From: Dmitry Stogov Date: Thu, 28 Apr 2016 12:17:24 +0000 (+0300) Subject: Don't initialize EX(call)->symbol_table on each function call. X-Git-Tag: php-7.1.0alpha1~251 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=747a482b9c011b33d3e61823d3291c2258eaec9e;p=php Don't initialize EX(call)->symbol_table on each function call. Keep it uninitialized, and check ZEND_CALL_HAS_SYMBOL_TABLE flag when necessary. --- diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 20a622f4d8..6cc16c61b3 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -467,7 +467,7 @@ struct _zend_execute_data { #define ZEND_CALL_TOP (1 << 1) #define ZEND_CALL_FREE_EXTRA_ARGS (1 << 2) /* equal to IS_TYPE_REFCOUNTED */ #define ZEND_CALL_CTOR (1 << 3) -#define ZEND_CALL_FREE_SYMBOL_TABLE (1 << 4) +#define ZEND_CALL_HAS_SYMBOL_TABLE (1 << 4) #define ZEND_CALL_CLOSURE (1 << 5) #define ZEND_CALL_RELEASE_THIS (1 << 6) #define ZEND_CALL_ALLOCATED (1 << 7) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 95aea65ac8..c6bca19684 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1540,7 +1540,7 @@ static zend_always_inline HashTable *zend_get_target_symbol_table(zend_execute_d ht = &EG(symbol_table); } else { ZEND_ASSERT(fetch_type == ZEND_FETCH_LOCAL); - if (!EX(symbol_table)) { + if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_rebuild_symbol_table(); } ht = EX(symbol_table); @@ -2252,7 +2252,7 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da EX(call) = NULL; EX(return_value) = return_value; - if (UNEXPECTED(EX(symbol_table) != NULL)) { + if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { if (UNEXPECTED(op_array->this_var != (uint32_t)-1) && EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) { GC_REFCOUNT(Z_OBJ(EX(This)))++; if (!zend_hash_str_add(EX(symbol_table), "this", sizeof("this")-1, &EX(This))) { @@ -2381,8 +2381,6 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data } while (arg_src != end); } - EX(symbol_table) = NULL; - if (UNEXPECTED(!op_array->run_time_cache)) { init_func_run_time_cache(op_array); } diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 023b341f21..6bb833fd99 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -853,7 +853,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) / if (func->type == ZEND_USER_FUNCTION) { int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0; - call->symbol_table = NULL; if (EXPECTED((func->op_array.fn_flags & ZEND_ACC_GENERATOR) == 0)) { zend_init_execute_data(call, &func->op_array, fci->retval); zend_execute_ex(call); @@ -1535,11 +1534,11 @@ ZEND_API zend_array *zend_rebuild_symbol_table(void) /* {{{ */ if (!ex) { return NULL; } - if (ex->symbol_table) { + if (ZEND_CALL_INFO(ex) & ZEND_CALL_HAS_SYMBOL_TABLE) { return ex->symbol_table; } - ZEND_ADD_CALL_FLAG(ex, ZEND_CALL_FREE_SYMBOL_TABLE); + ZEND_ADD_CALL_FLAG(ex, ZEND_CALL_HAS_SYMBOL_TABLE); if (EG(symtable_cache_ptr) >= EG(symtable_cache)) { /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/ symbol_table = ex->symbol_table = *(EG(symtable_cache_ptr)--); @@ -1640,7 +1639,7 @@ ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force) /* {{ } if (execute_data) { - if (!execute_data->symbol_table) { + if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_ulong h = zend_string_hash_val(name); zend_op_array *op_array = &execute_data->func->op_array; @@ -1682,7 +1681,7 @@ ZEND_API int zend_set_local_var_str(const char *name, size_t len, zval *value, i } if (execute_data) { - if (!execute_data->symbol_table) { + if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_ulong h = zend_hash_func(name, len); zend_op_array *op_array = &execute_data->func->op_array; if (EXPECTED(op_array->last_var)) { diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 5524a165fa..457cea9f53 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -64,7 +64,7 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished if (EXPECTED(generator->execute_data)) { zend_execute_data *execute_data = generator->execute_data; - if (execute_data->symbol_table) { + if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { zend_clean_and_cache_symbol_table(execute_data->symbol_table); } /* always free the CV's, in the symtable are only not-free'd IS_INDIRECT's */ @@ -208,7 +208,7 @@ static uint32_t calc_gc_buffer_size(zend_generator *generator) /* {{{ */ zend_op_array *op_array = &EX(func)->op_array; /* Compiled variables */ - if (!execute_data->symbol_table) { + if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) { size += op_array->last_var; } /* Extra args */ @@ -262,7 +262,7 @@ static HashTable *zend_generator_get_gc(zval *object, zval **table, int *n) /* { ZVAL_COPY_VALUE(gc_buffer++, &generator->retval); ZVAL_COPY_VALUE(gc_buffer++, &generator->values); - if (!execute_data->symbol_table) { + if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) { uint32_t i, num_cvs = EX(func)->op_array.last_var; for (i = 0; i < num_cvs; i++) { ZVAL_COPY_VALUE(gc_buffer++, EX_VAR_NUM(i)); @@ -292,7 +292,11 @@ static HashTable *zend_generator_get_gc(zval *object, zval **table, int *n) /* { } } - return execute_data->symbol_table; + if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { + return execute_data->symbol_table; + } else { + return NULL; + } } /* }}} */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 2b29e62887..ed579b125d 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2489,8 +2489,8 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) if (EXPECTED(ZEND_CALL_KIND_EX(call_info) == ZEND_CALL_NESTED_FUNCTION)) { i_free_compiled_variables(execute_data); - if (UNEXPECTED(call_info & (ZEND_CALL_FREE_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED))) { - if (UNEXPECTED(call_info & ZEND_CALL_FREE_SYMBOL_TABLE)) { + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED))) { + if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_clean_and_cache_symbol_table(EX(symbol_table)); } EG(current_execute_data) = EX(prev_execute_data); @@ -2567,8 +2567,8 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) } else { if (ZEND_CALL_KIND_EX(call_info) == ZEND_CALL_TOP_FUNCTION) { i_free_compiled_variables(execute_data); - if (UNEXPECTED(call_info & (ZEND_CALL_FREE_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS))) { - if (UNEXPECTED(call_info & ZEND_CALL_FREE_SYMBOL_TABLE)) { + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS))) { + if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_clean_and_cache_symbol_table(EX(symbol_table)); } zend_vm_stack_free_extra_args_ex(call_info, execute_data); @@ -2584,7 +2584,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) zend_detach_symbol_table(execute_data); old_execute_data = EX(prev_execute_data); while (old_execute_data) { - if (old_execute_data->func && ZEND_USER_CODE(old_execute_data->func->op_array.type)) { + if (old_execute_data->func && (ZEND_CALL_INFO(old_execute_data) & ZEND_CALL_HAS_SYMBOL_TABLE)) { if (old_execute_data->symbol_table == symbol_table) { zend_attach_symbol_table(old_execute_data); } @@ -3590,7 +3590,6 @@ ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL)) EX(call) = call->prev_execute_data; ret = NULL; - call->symbol_table = NULL; if (RETURN_VALUE_USED(opline)) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); @@ -3624,7 +3623,6 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) zend_vm_stack_free_call_frame(call); } else { ret = NULL; - call->symbol_table = NULL; if (RETURN_VALUE_USED(opline)) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); @@ -3734,7 +3732,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) } } else { ret = NULL; - call->symbol_table = NULL; if (RETURN_VALUE_USED(opline)) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); @@ -5348,12 +5345,12 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL) new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE, + call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); - if (EX(symbol_table)) { + if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); } else { call->symbol_table = zend_rebuild_symbol_table(); @@ -7837,7 +7834,6 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) ZEND_ASSERT(!(fbc->common.fn_flags & ZEND_ACC_GENERATOR)); - call->symbol_table = NULL; if (UNEXPECTED(!fbc->op_array.run_time_cache)) { init_func_run_time_cache(&fbc->op_array); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index cd7965bc56..a17fc6cf34 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -458,7 +458,7 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value) return; } - execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE, + execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data))); if (EG(current_execute_data)) { execute_data->symbol_table = zend_rebuild_symbol_table(); @@ -478,8 +478,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_ if (EXPECTED(ZEND_CALL_KIND_EX(call_info) == ZEND_CALL_NESTED_FUNCTION)) { i_free_compiled_variables(execute_data); - if (UNEXPECTED(call_info & (ZEND_CALL_FREE_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED))) { - if (UNEXPECTED(call_info & ZEND_CALL_FREE_SYMBOL_TABLE)) { + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED))) { + if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_clean_and_cache_symbol_table(EX(symbol_table)); } EG(current_execute_data) = EX(prev_execute_data); @@ -556,8 +556,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_ } else { if (ZEND_CALL_KIND_EX(call_info) == ZEND_CALL_TOP_FUNCTION) { i_free_compiled_variables(execute_data); - if (UNEXPECTED(call_info & (ZEND_CALL_FREE_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS))) { - if (UNEXPECTED(call_info & ZEND_CALL_FREE_SYMBOL_TABLE)) { + if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS))) { + if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_clean_and_cache_symbol_table(EX(symbol_table)); } zend_vm_stack_free_extra_args_ex(call_info, execute_data); @@ -573,7 +573,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_ zend_detach_symbol_table(execute_data); old_execute_data = EX(prev_execute_data); while (old_execute_data) { - if (old_execute_data->func && ZEND_USER_CODE(old_execute_data->func->op_array.type)) { + if (old_execute_data->func && (ZEND_CALL_INFO(old_execute_data) & ZEND_CALL_HAS_SYMBOL_TABLE)) { if (old_execute_data->symbol_table == symbol_table) { zend_attach_symbol_table(old_execute_data); } @@ -700,7 +700,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_HA EX(call) = call->prev_execute_data; ret = NULL; - call->symbol_table = NULL; if (0) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); @@ -723,7 +722,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_USED_HAND EX(call) = call->prev_execute_data; ret = NULL; - call->symbol_table = NULL; if (1) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); @@ -757,7 +755,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U zend_vm_stack_free_call_frame(call); } else { ret = NULL; - call->symbol_table = NULL; if (0) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); @@ -848,7 +845,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U zend_vm_stack_free_call_frame(call); } else { ret = NULL; - call->symbol_table = NULL; if (1) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); @@ -958,7 +954,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA } } else { ret = NULL; - call->symbol_table = NULL; if (0) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); @@ -1100,7 +1095,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND } } else { ret = NULL; - call->symbol_table = NULL; if (1) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); @@ -1969,7 +1963,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z ZEND_ASSERT(!(fbc->common.fn_flags & ZEND_ACC_GENERATOR)); - call->symbol_table = NULL; if (UNEXPECTED(!fbc->op_array.run_time_cache)) { init_func_run_time_cache(&fbc->op_array); } @@ -3380,12 +3373,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE, + call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); - if (EX(symbol_table)) { + if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); } else { call->symbol_table = zend_rebuild_symbol_table(); @@ -35453,12 +35446,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE, + call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); - if (EX(symbol_table)) { + if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); } else { call->symbol_table = zend_rebuild_symbol_table(); @@ -50202,12 +50195,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA new_op_array->scope = EX(func)->op_array.scope; - call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE, + call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)new_op_array, 0, Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL, Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL); - if (EX(symbol_table)) { + if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) { call->symbol_table = EX(symbol_table); } else { call->symbol_table = zend_rebuild_symbol_table(); diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 50c9178bc4..ebc6474ae5 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -29,7 +29,7 @@ ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value return; } - execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE, + execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE | ZEND_CALL_HAS_SYMBOL_TABLE, (zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data))); if (EG(current_execute_data)) { execute_data->symbol_table = zend_rebuild_symbol_table(); diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 787517dd9d..3b7274a997 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -687,7 +687,7 @@ PHPDBG_COMMAND(run) /* {{{ */ } /* clean up from last execution */ - if (ex && ex->symbol_table) { + if (ex && (ZEND_CALL_INFO(ex) & ZEND_CALL_HAS_SYMBOL_TABLE)) { zend_hash_clean(ex->symbol_table); } else { zend_rebuild_symbol_table();