From e3832fa17fdedba9e5f08ef5e1750fbf2f6ab564 Mon Sep 17 00:00:00 2001 From: Per Hedbor <ph@opera.com> Date: Thu, 2 Oct 2014 19:55:28 +0200 Subject: [PATCH] Added a simple append_mapping instruction. Much like append_array, but for mappings. This speeds up the append mapping benchmark by about (currently) 1000x. However, that is somewhat misleading since the refs optimization is not done currently since the wrong assignment operator ends up being used. Even when that is fixed the speedup should is still more than 2x, however. --- src/docode.c | 11 +++++++++++ src/interpret_functions.h | 4 ++++ src/las.c | 14 +++++++++++++- src/mapping.c | 33 +++++++++++++++++++++++++++++++++ src/mapping.h | 1 + src/treeopt.in | 15 +++++++++++++++ 6 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/docode.c b/src/docode.c index a7e8b70db2..f12a32d1d7 100644 --- a/src/docode.c +++ b/src/docode.c @@ -1149,6 +1149,17 @@ static int do_docode2(node *n, int flags) return 1; } + case F_APPEND_MAPPING: { + emit0(F_MARK); + PUSH_CLEANUP_FRAME(do_pop_mark, 0); + do_docode(CAR(n),DO_LVALUE); + emit0(F_CONST0); /* Reserved for svalue. */ + do_docode(CDR(n),0); + emit0(F_APPEND_MAPPING); + POP_AND_DONT_CLEANUP; + return 1; + } + case '?': { INT32 *prev_switch_jumptable = current_switch.jumptable; diff --git a/src/interpret_functions.h b/src/interpret_functions.h index e67e12c7ac..bfffd60b8c 100644 --- a/src/interpret_functions.h +++ b/src/interpret_functions.h @@ -2021,6 +2021,10 @@ OPCODE0(F_APPEND_ARRAY, "append array", I_UPDATE_SP|I_UPDATE_M_SP, { o_append_array(Pike_sp - *(--Pike_mark_sp)); }); +OPCODE0(F_APPEND_MAPPING, "append mapping", I_UPDATE_SP|I_UPDATE_M_SP, { + o_append_mapping(Pike_sp - *(--Pike_mark_sp)); + }); + OPCODE2(F_LOCAL_LOCAL_INDEX, "local[local]", I_UPDATE_SP, { LOCAL_VAR(struct svalue *s); s = Pike_fp->locals + arg1; diff --git a/src/las.c b/src/las.c index c4d4e2ab2e..ba0ae0e11c 100644 --- a/src/las.c +++ b/src/las.c @@ -919,6 +919,7 @@ node *debug_mknode(int token, node *a, node *b) break; case F_APPEND_ARRAY: + case F_APPEND_MAPPING: case F_MULTI_ASSIGN: case F_ASSIGN: case F_ASSIGN_SELF: @@ -2742,7 +2743,8 @@ static void find_written_vars(node *n, find_written_vars(CDR(n), p, 1); break; - case F_APPEND_ARRAY: + case F_APPEND_MAPPING: + case F_APPEND_ARRAY: find_written_vars(CAR(n), p, 1); find_written_vars(CDR(n), p, 0); break; @@ -3199,6 +3201,16 @@ void fix_type_field(node *n) } break; + case F_APPEND_MAPPING: + if (!CAR(n) || (CAR(n)->type == void_type_string)) { + yyerror("Assigning a void expression."); + copy_pike_type(n->type, void_type_string); + } + else + /* FIXME: Not really correct, should calculate type of RHS. */ + copy_pike_type(n->type, CAR(n)->type); + break; + case F_APPEND_ARRAY: if (!CAR(n) || (CAR(n)->type == void_type_string)) { yyerror("Assigning a void expression."); diff --git a/src/mapping.c b/src/mapping.c index cfe0e2afaf..7421b4d55f 100644 --- a/src/mapping.c +++ b/src/mapping.c @@ -1856,6 +1856,39 @@ PMOD_EXPORT struct mapping *merge_mapping_array_unordered(struct mapping *a, return m; } +void o_append_mapping( INT32 args ) +{ + struct svalue *lval = Pike_sp - args; + struct svalue *val = lval + 2; +#ifdef PIKE_DEBUG + if (args < 3) { + Pike_fatal("Too few arguments to o_append_mapping(): %d\n", args); + } +#endif + args -= 3; + /* Note: val should always be a zero here! */ + lvalue_to_svalue_no_free(val, lval); + + if (TYPEOF(*val) == T_MAPPING) + { + struct mapping *m = val->u.mapping; + if( m->refs == 2 ) + { + int i; + /* fprintf( stderr, "map_refs==2\n" ); */ + for( i=0; i<args; i+=2 ) + low_mapping_insert( m, Pike_sp-(i+2), Pike_sp-(i+1), 0 ); + stack_pop_n_elems_keep_top(2+args); + return; + } + } + + f_aggregate_mapping(args); + f_add(2); + assign_lvalue(lval, val); + stack_pop_2_elems_keep_top(); +} + /* NOTE: May perform destructive operations on either of the arguments * if it has only a single reference. */ diff --git a/src/mapping.h b/src/mapping.h index f4e11165c5..62c790bcd1 100644 --- a/src/mapping.h +++ b/src/mapping.h @@ -390,6 +390,7 @@ int mapping_is_constant(struct mapping *m, struct processing *p); void free_all_mapping_blocks(void); +void o_append_mapping( INT32 args ); /* Prototypes end here */ #define allocate_mapping(X) dmalloc_touch(struct mapping *,debug_allocate_mapping(X)) diff --git a/src/treeopt.in b/src/treeopt.in index a66af5c311..4115308a46 100644 --- a/src/treeopt.in +++ b/src/treeopt.in @@ -995,6 +995,21 @@ F_ADD_EQ(0, F_APPLY(F_CONSTANT [$$->u.sval.u.efun->function == debug_f_aggregate], 1)): F_APPEND_ARRAY($0, $1); + +// a += ([ args... ]) -> F_APPEND_MAPPING(a, args...) +F_ADD_EQ(0, F_APPLY(F_CONSTANT + [TYPEOF($$->u.sval) == T_FUNCTION] + [SUBTYPEOF($$->u.sval) == FUNCTION_BUILTIN] + [$$->u.sval.u.efun->function == f_aggregate_mapping], 1)): + F_APPEND_MAPPING($0, $1); + +// a += ([ args... ]) -> F_APPEND_MAPPING(a, args...) +F_OR_EQ(0, F_APPLY(F_CONSTANT + [TYPEOF($$->u.sval) == T_FUNCTION] + [SUBTYPEOF($$->u.sval) == FUNCTION_BUILTIN] + [$$->u.sval.u.efun->function == f_aggregate_mapping], 1)): + F_APPEND_MAPPING($0, $1); + F_INDEX(-, 0 = *): F_COMMA_EXPR(F_POP_VALUE($0, -), 0); -- GitLab