From: Dmitry Stogov Date: Tue, 29 Apr 2008 08:15:49 +0000 (+0000) Subject: Lazy EG(active_symbol_table) initialization X-Git-Tag: RELEASE_2_0_0b1~152 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1d0f893b491d925771f459351aed560f050edfb3;p=php Lazy EG(active_symbol_table) initialization --- diff --git a/Zend/zend.c b/Zend/zend.c index 64bf6c1ca3..7910265d13 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1589,6 +1589,9 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ Z_LVAL_P(z_error_lineno) = error_lineno; Z_TYPE_P(z_error_lineno) = IS_LONG; + if (!EG(active_symbol_table)) { + zend_rebuild_symbol_table(TSRMLS_C); + } Z_ARRVAL_P(z_context) = EG(active_symbol_table); Z_TYPE_P(z_context) = IS_ARRAY; zval_copy_ctor(z_context); diff --git a/Zend/zend_API.h b/Zend/zend_API.h index fc6d0638b2..45c7676013 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -1591,6 +1591,8 @@ ZEND_API int zend_u_delete_global_variable(zend_uchar type, zstr name, int name_ ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC); +ZEND_API void zend_rebuild_symbol_table(TSRMLS_D); + #define add_method(arg, key, method) add_assoc_function((arg), (key), (method)) ZEND_API ZEND_FUNCTION(display_disabled_function); diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 10644661f1..f8ffebfa26 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1501,6 +1501,10 @@ ZEND_FUNCTION(get_defined_vars) array_init(return_value); + if (!EG(active_symbol_table)) { + zend_rebuild_symbol_table(TSRMLS_C); + } + zend_hash_copy(Z_ARRVAL_P(return_value), EG(active_symbol_table), (copy_ctor_func_t)zval_add_ref, &tmp, sizeof(zval *)); } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index b7b4c40584..a8ac9ebde1 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2282,7 +2282,9 @@ void zend_do_begin_catch(znode *try_token, znode *class_name, znode *catch_var, opline->opcode = ZEND_CATCH; opline->op1 = catch_class; /* SET_UNUSED(opline->op1); */ /* FIXME: Define IS_CLASS or something like that */ - opline->op2 = *catch_var; + opline->op2.op_type = IS_CV; + opline->op2.u.var = lookup_cv(CG(active_op_array), Z_TYPE(catch_var->u.constant), Z_UNIVAL(catch_var->u.constant), Z_UNILEN(catch_var->u.constant)); + opline->op2.u.EA.type = 0; opline->op1.u.EA.type = 0; /* 1 means it's the last catch in the block */ try_token->u.opline_num = catch_op_number; @@ -2660,7 +2662,7 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro if (zend_u_hash_quick_find(&parent_ce->default_properties, utype, parent_info->name, parent_info->name_length+1, parent_info->h, (void **) &pvalue) == SUCCESS) { Z_ADDREF_PP(pvalue); - zend_u_hash_del(&ce->default_properties, utype, child_info->name, child_info->name_length+1); + zend_u_hash_quick_del(&ce->default_properties, utype, child_info->name, child_info->name_length+1, parent_info->h); zend_u_hash_quick_update(&ce->default_properties, utype, parent_info->name, parent_info->name_length+1, parent_info->h, pvalue, sizeof(zval *), NULL); } } @@ -4366,18 +4368,12 @@ void zend_do_unset(znode *variable TSRMLS_DC) /* {{{ */ zend_check_writable_variable(variable); if (variable->op_type == IS_CV) { - zstr name; - int name_len; zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - name = CG(active_op_array)->vars[variable->u.var].name; - name_len = CG(active_op_array)->vars[variable->u.var].name_len; - opline->opcode = ZEND_UNSET_VAR; - opline->op1.op_type = IS_CONST; - ZVAL_TEXTL(&opline->op1.u.constant, name, name_len, 1); + opline->op1 = *variable; SET_UNUSED(opline->op2); - opline->op2.u.EA.type = zend_u_is_auto_global(ZEND_STR_TYPE, name, name_len TSRMLS_CC) ? ZEND_FETCH_GLOBAL : ZEND_FETCH_LOCAL;; + opline->op2.u.EA.type = ZEND_FETCH_LOCAL; SET_UNUSED(opline->result); } else { last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1]; @@ -4407,19 +4403,11 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC zend_check_writable_variable(variable); if (variable->op_type == IS_CV) { - zstr name; - int name_len; - last_op = get_next_op(CG(active_op_array) TSRMLS_CC); - - name = CG(active_op_array)->vars[variable->u.var].name; - name_len = CG(active_op_array)->vars[variable->u.var].name_len; - last_op->opcode = ZEND_ISSET_ISEMPTY_VAR; - last_op->op1.op_type = IS_CONST; - ZVAL_TEXTL(&last_op->op1.u.constant, name, name_len, 1); + last_op->op1 = *variable; SET_UNUSED(last_op->op2); - last_op->op2.u.EA.type = zend_u_is_auto_global(ZEND_STR_TYPE, name, name_len TSRMLS_CC) ? ZEND_FETCH_GLOBAL : ZEND_FETCH_LOCAL;; + last_op->op2.u.EA.type = ZEND_FETCH_LOCAL; last_op->result.u.var = get_temporary_variable(CG(active_op_array)); } else { last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1]; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 1e3654e6d2..ce7a511b5c 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -173,15 +173,6 @@ ZEND_API zval** zend_get_compiled_variable_value(zend_execute_data *execute_data } /* }}} */ -static inline void zend_get_cv_address(zend_uchar utype, zend_compiled_variable *cv, zval ***ptr, temp_variable *Ts TSRMLS_DC) /* {{{ */ -{ - zval *new_zval = &EG(uninitialized_zval); - - Z_ADDREF_P(new_zval); - zend_u_hash_quick_update(EG(active_symbol_table), utype, cv->name, cv->name_len+1, cv->hash_value, &new_zval, sizeof(zval *), (void **)ptr); -} -/* }}} */ - static inline zval *_get_zval_ptr_tmp(znode *node, temp_variable *Ts, zend_free_op *should_free TSRMLS_DC) /* {{{ */ { return should_free->var = &T(node->u.var).tmp_var; @@ -246,7 +237,8 @@ static inline zval *_get_zval_ptr_cv(znode *node, temp_variable *Ts, int type TS zend_compiled_variable *cv = &CV_DEF_OF(node->u.var); zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING; - if (zend_u_hash_quick_find(EG(active_symbol_table), utype, cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) { + if (!EG(active_symbol_table) || + zend_u_hash_quick_find(EG(active_symbol_table), utype, cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) { switch (type) { case BP_VAR_R: case BP_VAR_UNSET: @@ -259,7 +251,13 @@ static inline zval *_get_zval_ptr_cv(znode *node, temp_variable *Ts, int type TS zend_error(E_NOTICE, "Undefined variable: %v", cv->name); /* break missing intentionally */ case BP_VAR_W: - zend_get_cv_address(utype, cv, ptr, Ts TSRMLS_CC); + Z_ADDREF(EG(uninitialized_zval)); + if (!EG(active_symbol_table)) { + *ptr = (zval**)EG(current_execute_data)->CVs + (EG(active_op_array)->last_var + node->u.var); + **ptr = &EG(uninitialized_zval); + } else { + zend_u_hash_quick_update(EG(active_symbol_table), utype, cv->name, cv->name_len+1, cv->hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **)ptr); + } break; } } @@ -319,7 +317,8 @@ static inline zval **_get_zval_ptr_ptr_cv(znode *node, temp_variable *Ts, int ty zend_compiled_variable *cv = &CV_DEF_OF(node->u.var); zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING; - if (zend_u_hash_quick_find(EG(active_symbol_table), utype, cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) { + if (!EG(active_symbol_table) || + zend_u_hash_quick_find(EG(active_symbol_table), utype, cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) { switch (type) { case BP_VAR_R: case BP_VAR_UNSET: @@ -332,7 +331,13 @@ static inline zval **_get_zval_ptr_ptr_cv(znode *node, temp_variable *Ts, int ty zend_error(E_NOTICE, "Undefined variable: %v", cv->name); /* break missing intentionally */ case BP_VAR_W: - zend_get_cv_address(utype, cv, ptr, Ts TSRMLS_CC); + Z_ADDREF(EG(uninitialized_zval)); + if (!EG(active_symbol_table)) { + *ptr = (zval**)EG(current_execute_data)->CVs + (EG(active_op_array)->last_var + node->u.var); + **ptr = &EG(uninitialized_zval); + } else { + zend_u_hash_quick_update(EG(active_symbol_table), utype, cv->name, cv->name_len+1, cv->hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **)ptr); + } break; } } @@ -843,6 +848,9 @@ static inline HashTable *zend_get_target_symbol_table(zend_op *opline, temp_vari { switch (opline->op2.u.EA.type) { case ZEND_FETCH_LOCAL: + if (!EG(active_symbol_table)) { + zend_rebuild_symbol_table(TSRMLS_C); + } return EG(active_symbol_table); break; case ZEND_FETCH_GLOBAL: @@ -1408,11 +1416,21 @@ ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_v #define ZEND_VM_INC_OPCODE() \ EX(opline)++ -#define ZEND_VM_EXIT_FROM_EXECUTE_LOOP() \ - EG(in_execution) = EX(original_in_execution); \ - EG(current_execute_data) = EX(prev_execute_data); \ - EG(opline_ptr) = NULL; \ - zend_vm_stack_free(execute_data TSRMLS_CC); +#define ZEND_VM_EXIT_FROM_EXECUTE_LOOP() do { \ + EG(in_execution) = EX(original_in_execution); \ + EG(current_execute_data) = EX(prev_execute_data); \ + EG(opline_ptr) = NULL; \ + if (!EG(active_symbol_table)) { \ + int n = EX(op_array)->last_var; \ + while (n > 0) { \ + --n; \ + if (EX(CVs)[n]) { \ + zval_ptr_dtor(EX(CVs)[n]); \ + } \ + } \ + } \ + zend_vm_stack_free(execute_data TSRMLS_CC); \ + } while (0); #define ZEND_VM_RETURN_FROM_EXECUTE_LOOP() \ ZEND_VM_EXIT_FROM_EXECUTE_LOOP(); \ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index ae76c28bf0..b3a329b05f 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1996,7 +1996,7 @@ ZEND_API int zend_u_delete_global_variable(zend_uchar type, zstr name, int name_ } } } - return zend_u_hash_del(&EG(symbol_table), type, name, name_len + 1); + return zend_u_hash_quick_del(&EG(symbol_table), type, name, name_len + 1, hash_value); } return FAILURE; } @@ -2008,6 +2008,45 @@ ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC) /* } /* }}} */ +ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */ +{ + zend_uchar type = ZEND_STR_TYPE; + zend_uint i; + + if (!EG(active_symbol_table)) { + if (EG(symtable_cache_ptr)>=EG(symtable_cache)) { + /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/ + EG(active_symbol_table) = *(EG(symtable_cache_ptr)--); + } else { + ALLOC_HASHTABLE(EG(active_symbol_table)); + zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0); + /*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/ + } + if (EG(current_execute_data) && EG(current_execute_data)->op_array) { + EG(current_execute_data)->symbol_table = EG(active_symbol_table); + if (EG(current_execute_data)->op_array->uses_this && EG(This)) { + Z_ADDREF_P(EG(This)); /* For $this pointer */ + if (zend_ascii_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL)==FAILURE) { + Z_DELREF_P(EG(This)); + } + } + for (i = 0; i < EG(current_execute_data)->op_array->last_var; i++) { + if (EG(current_execute_data)->CVs[i]) { + zend_u_hash_quick_update(EG(active_symbol_table), + type, + EG(current_execute_data)->op_array->vars[i].name, + EG(current_execute_data)->op_array->vars[i].name_len + 1, + EG(current_execute_data)->op_array->vars[i].hash_value, + (void**)EG(current_execute_data)->CVs[i], + sizeof(zval*), + (void**)&EG(current_execute_data)->CVs[i]); + } + } + } + } +} +/* }}} */ + /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index bf65381bec..3445560246 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -36,6 +36,7 @@ #define HASH_DEL_KEY 0 #define HASH_DEL_INDEX 1 +#define HASH_DEL_KEY_QUICK 2 @@ -195,8 +196,12 @@ ZEND_API int zend_utf8_hash_del(HashTable *ht, const char *arKey, uint nKeyLengt ZEND_API int zend_u_hash_del_key_or_index(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, ulong h, int flag); #define zend_hash_del(ht, arKey, nKeyLength) \ zend_hash_del_key_or_index(ht, arKey, nKeyLength, 0, HASH_DEL_KEY) +#define zend_hash_quick_del(ht, arKey, nKeyLength, h) \ + zend_hash_del_key_or_index(ht, arKey, nKeyLength, h, HASH_DEL_KEY_QUICK) #define zend_u_hash_del(ht, type, arKey, nKeyLength) \ zend_u_hash_del_key_or_index(ht, type, arKey, nKeyLength, 0, HASH_DEL_KEY) +#define zend_u_hash_quick_del(ht, type, arKey, nKeyLength, h) \ + zend_u_hash_del_key_or_index(ht, type, arKey, nKeyLength, h, HASH_DEL_KEY_QUICK) #define zend_hash_index_del(ht, h) \ zend_hash_del_key_or_index(ht, NULL, 0, h, HASH_DEL_INDEX) diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 21c77f3824..a57883f807 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -620,7 +620,7 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC) /* {{{ property_info = zend_get_property_info(zobj->ce, member, (zobj->ce->__unset != NULL) TSRMLS_CC); - if (!property_info || zend_u_hash_del(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1)) { + if (!property_info || zend_u_hash_quick_del(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1, property_info->h)) { zend_guard *guard; if (zobj->ce->__unset && diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index fad07c3e73..287543fc76 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2212,14 +2212,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY) } else if (EX(function_state).function->type == ZEND_USER_FUNCTION) { zval **original_return_value = EG(return_value_ptr_ptr); - if (EG(symtable_cache_ptr)>=EG(symtable_cache)) { - /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/ - EG(active_symbol_table) = *(EG(symtable_cache_ptr)--); - } else { - ALLOC_HASHTABLE(EG(active_symbol_table)); - zend_u_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode)); - /*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/ - } + EG(active_symbol_table) = NULL; EG(active_op_array) = &EX(function_state).function->op_array; EG(return_value_ptr_ptr) = NULL; if (RETURN_VALUE_USED(opline)) { @@ -2234,14 +2227,16 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY) EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); EG(return_value_ptr_ptr)=original_return_value; - if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { - zend_hash_destroy(EG(active_symbol_table)); - FREE_HASHTABLE(EG(active_symbol_table)); - } else { - /* clean before putting into the cache, since clean - could call dtors, which could use cached hash */ - zend_hash_clean(EG(active_symbol_table)); - *(++EG(symtable_cache_ptr)) = EG(active_symbol_table); + if (EG(active_symbol_table)) { + if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { + zend_hash_destroy(EG(active_symbol_table)); + FREE_HASHTABLE(EG(active_symbol_table)); + } else { + /* clean before putting into the cache, since clean + could call dtors, which could use cached hash */ + zend_hash_clean(EG(active_symbol_table)); + *(++EG(symtable_cache_ptr)) = EG(active_symbol_table); + } } EG(active_symbol_table) = EX(symbol_table); } else { /* ZEND_OVERLOADED_FUNCTION */ @@ -2427,7 +2422,7 @@ ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(107, ZEND_CATCH, ANY, ANY) +ZEND_VM_HANDLER(107, ZEND_CATCH, ANY, CV) { zend_op *opline = EX(opline); zend_class_entry *ce; @@ -2449,8 +2444,17 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, ANY, ANY) } } - zend_u_hash_update(EG(active_symbol_table), Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), - Z_UNILEN(opline->op2.u.constant)+1, &EG(exception), sizeof(zval *), (void **) NULL); + if (!EG(active_symbol_table)) { + if (EX(CVs)[opline->op2.u.var]) { + zval_ptr_dtor(EX(CVs)[opline->op2.u.var]); + } + EX(CVs)[opline->op2.u.var] = (zval**)EX(CVs) + (EX(op_array)->last_var + opline->op2.u.var); + *EX(CVs)[opline->op2.u.var] = EG(exception); + } else { + zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.u.var); + zend_u_hash_quick_update(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value, + &EG(exception), sizeof(zval *), NULL); + } EG(exception) = NULL; ZEND_VM_NEXT_OPCODE(); } @@ -3203,6 +3207,10 @@ skip_compile: EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; + if (!EG(active_symbol_table)) { + zend_rebuild_symbol_table(TSRMLS_C); + } + zend_execute(new_op_array TSRMLS_CC); EX(function_state).function = saved_function; @@ -3244,6 +3252,36 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, ANY) HashTable *target_symbol_table; zend_free_op free_op1; + if (OP1_TYPE == IS_CV) { + if (EG(active_symbol_table)) { + zend_execute_data *ex = EX(prev_execute_data); + zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var); + + if (zend_u_hash_quick_del(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value) == SUCCESS) { + while (ex && ex->symbol_table == EG(active_symbol_table)) { + int i; + + if (ex->op_array) { + for (i = 0; i < ex->op_array->last_var; i++) { + if (ex->op_array->vars[i].hash_value == cv->hash_value && + ex->op_array->vars[i].name_len == cv->name_len && + !memcmp(ex->op_array->vars[i].name.v, cv->name.v, USTR_BYTES(ZEND_STR_TYPE, cv->name_len))) { + ex->CVs[i] = NULL; + break; + } + } + } + ex = ex->prev_execute_data; + } + } + EX(CVs)[opline->op1.u.var] = NULL; + } else if (EX(CVs)[opline->op1.u.var]) { + zval_ptr_dtor(EX(CVs)[opline->op1.u.var]); + EX(CVs)[opline->op1.u.var] = NULL; + } + ZEND_VM_NEXT_OPCODE(); + } + varname = GET_OP1_ZVAL_PTR(BP_VAR_R); if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { @@ -3251,17 +3289,18 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, ANY) zval_copy_ctor(&tmp); convert_to_text(&tmp); varname = &tmp; - } else if (OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) { + } else if (OP1_TYPE == IS_VAR) { Z_ADDREF_P(varname); } if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname) TSRMLS_CC); } else { + ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1); + target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); - if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) { + if (zend_u_hash_quick_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, hash_value) == SUCCESS) { zend_execute_data *ex = EXECUTE_DATA; - ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1); zend_auto_global *auto_global; if (zend_u_hash_quick_find(CG(auto_globals), Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, hash_value, (void**)&auto_global) == SUCCESS) { @@ -3287,7 +3326,7 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, ANY) if (varname == &tmp) { zval_dtor(&tmp); - } else if (OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) { + } else if (OP1_TYPE == IS_VAR) { zval_ptr_dtor(&varname); } FREE_OP1(); @@ -3754,29 +3793,49 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY) ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, ANY) { zend_op *opline = EX(opline); - zend_free_op free_op1; - zval tmp, *varname = GET_OP1_ZVAL_PTR(BP_VAR_IS); zval **value; zend_bool isset = 1; - HashTable *target_symbol_table; - if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { - tmp = *varname; - zval_copy_ctor(&tmp); - convert_to_text(&tmp); - varname = &tmp; - } + if (OP1_TYPE == IS_CV) { + if (EX(CVs)[opline->op1.u.var]) { + value = EX(CVs)[opline->op1.u.var]; + } else if (EG(active_symbol_table)) { + zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var); - if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { - value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1 TSRMLS_CC); - if (!value) { - isset = 0; + if (zend_u_hash_quick_find(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) { + isset = 0; + } + } else { + isset = 0; + } + } else { + HashTable *target_symbol_table; + zend_free_op free_op1; + zval tmp, *varname = GET_OP1_ZVAL_PTR(BP_VAR_IS); + + if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { + tmp = *varname; + zval_copy_ctor(&tmp); + convert_to_text(&tmp); + varname = &tmp; } - } else { - target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); - if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) { - isset = 0; + + if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { + value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1 TSRMLS_CC); + if (!value) { + isset = 0; + } + } else { + target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); + if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) { + isset = 0; + } + } + + if (varname == &tmp) { + zval_dtor(&tmp); } + FREE_OP1(); } Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL; @@ -3798,11 +3857,6 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, ANY) break; } - if (varname == &tmp) { - zval_dtor(&tmp); - } - FREE_OP1(); - ZEND_VM_NEXT_OPCODE(); } @@ -4187,10 +4241,8 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) int catched = 0; zval restored_error_reporting; - void **stack_frame = (void**)execute_data + - (sizeof(zend_execute_data) + - sizeof(zval**) * EX(op_array)->last_var + - sizeof(temp_variable) * EX(op_array)->T) / sizeof(void*); + void **stack_frame = (void**)EX(Ts) + + (sizeof(temp_variable) * EX(op_array)->T) / sizeof(void*); while (zend_vm_stack_top(TSRMLS_C) != stack_frame) { zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index b7a7aa4d0e..933f06b821 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -46,12 +46,12 @@ ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) /* Initialize execute_data */ execute_data = (zend_execute_data *)zend_vm_stack_alloc( sizeof(zend_execute_data) + - sizeof(zval**) * op_array->last_var + + sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2) + sizeof(temp_variable) * op_array->T TSRMLS_CC); EX(CVs) = (zval***)((char*)execute_data + sizeof(zend_execute_data)); memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); - EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var); + EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var * (EG(active_symbol_table) ? 1 : 2)); EX(fbc) = NULL; EX(called_scope) = NULL; EX(object) = NULL; @@ -69,7 +69,7 @@ ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) ZEND_VM_SET_OPCODE(op_array->opcodes); } - if (op_array->uses_this && EG(This)) { + if (op_array->uses_this && EG(This) && EG(active_symbol_table)) { Z_ADDREF_P(EG(This)); /* For $this pointer */ if (zend_ascii_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL)==FAILURE) { Z_DELREF_P(EG(This)); @@ -205,14 +205,7 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) } else if (EX(function_state).function->type == ZEND_USER_FUNCTION) { zval **original_return_value = EG(return_value_ptr_ptr); - if (EG(symtable_cache_ptr)>=EG(symtable_cache)) { - /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/ - EG(active_symbol_table) = *(EG(symtable_cache_ptr)--); - } else { - ALLOC_HASHTABLE(EG(active_symbol_table)); - zend_u_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode)); - /*printf("Cache miss! Initialized %x\n", EG(active_symbol_table));*/ - } + EG(active_symbol_table) = NULL; EG(active_op_array) = &EX(function_state).function->op_array; EG(return_value_ptr_ptr) = NULL; if (RETURN_VALUE_USED(opline)) { @@ -227,14 +220,16 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); EG(return_value_ptr_ptr)=original_return_value; - if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { - zend_hash_destroy(EG(active_symbol_table)); - FREE_HASHTABLE(EG(active_symbol_table)); - } else { - /* clean before putting into the cache, since clean - could call dtors, which could use cached hash */ - zend_hash_clean(EG(active_symbol_table)); - *(++EG(symtable_cache_ptr)) = EG(active_symbol_table); + if (EG(active_symbol_table)) { + if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { + zend_hash_destroy(EG(active_symbol_table)); + FREE_HASHTABLE(EG(active_symbol_table)); + } else { + /* clean before putting into the cache, since clean + could call dtors, which could use cached hash */ + zend_hash_clean(EG(active_symbol_table)); + *(++EG(symtable_cache_ptr)) = EG(active_symbol_table); + } } EG(active_symbol_table) = EX(symbol_table); } else { /* ZEND_OVERLOADED_FUNCTION */ @@ -303,34 +298,6 @@ static int ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } -static int ZEND_CATCH_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zend_op *opline = EX(opline); - zend_class_entry *ce; - - /* Check whether an exception has been thrown, if not, jump over code */ - if (EG(exception) == NULL) { - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]); - ZEND_VM_CONTINUE(); /* CHECK_ME */ - } - ce = Z_OBJCE_P(EG(exception)); - if (ce != EX_T(opline->op1.u.var).class_entry) { - if (!instanceof_function(ce, EX_T(opline->op1.u.var).class_entry TSRMLS_CC)) { - if (opline->op1.u.EA.type) { - zend_throw_exception_internal(NULL TSRMLS_CC); - ZEND_VM_NEXT_OPCODE(); - } - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]); - ZEND_VM_CONTINUE(); /* CHECK_ME */ - } - } - - zend_u_hash_update(EG(active_symbol_table), Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), - Z_UNILEN(opline->op2.u.constant)+1, &EG(exception), sizeof(zval *), (void **) NULL); - EG(exception) = NULL; - ZEND_VM_NEXT_OPCODE(); -} - static int ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -511,10 +478,8 @@ static int ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int catched = 0; zval restored_error_reporting; - void **stack_frame = (void**)execute_data + - (sizeof(zend_execute_data) + - sizeof(zval**) * EX(op_array)->last_var + - sizeof(temp_variable) * EX(op_array)->T) / sizeof(void*); + void **stack_frame = (void**)EX(Ts) + + (sizeof(temp_variable) * EX(op_array)->T) / sizeof(void*); while (zend_vm_stack_top(TSRMLS_C) != stack_frame) { zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C); @@ -1055,6 +1020,43 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_NEXT_OPCODE(); } +static int ZEND_CATCH_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *opline = EX(opline); + zend_class_entry *ce; + + /* Check whether an exception has been thrown, if not, jump over code */ + if (EG(exception) == NULL) { + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]); + ZEND_VM_CONTINUE(); /* CHECK_ME */ + } + ce = Z_OBJCE_P(EG(exception)); + if (ce != EX_T(opline->op1.u.var).class_entry) { + if (!instanceof_function(ce, EX_T(opline->op1.u.var).class_entry TSRMLS_CC)) { + if (opline->op1.u.EA.type) { + zend_throw_exception_internal(NULL TSRMLS_CC); + ZEND_VM_NEXT_OPCODE(); + } + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]); + ZEND_VM_CONTINUE(); /* CHECK_ME */ + } + } + + if (!EG(active_symbol_table)) { + if (EX(CVs)[opline->op2.u.var]) { + zval_ptr_dtor(EX(CVs)[opline->op2.u.var]); + } + EX(CVs)[opline->op2.u.var] = (zval**)EX(CVs) + (EX(op_array)->last_var + opline->op2.u.var); + *EX(CVs)[opline->op2.u.var] = EG(exception); + } else { + zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.u.var); + zend_u_hash_quick_update(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value, + &EG(exception), sizeof(zval *), NULL); + } + EG(exception) = NULL; + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_BW_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); @@ -1757,6 +1759,10 @@ skip_compile: EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; + if (!EG(active_symbol_table)) { + zend_rebuild_symbol_table(TSRMLS_C); + } + zend_execute(new_op_array TSRMLS_CC); EX(function_state).function = saved_function; @@ -1798,6 +1804,36 @@ static int ZEND_UNSET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) HashTable *target_symbol_table; + if (IS_CONST == IS_CV) { + if (EG(active_symbol_table)) { + zend_execute_data *ex = EX(prev_execute_data); + zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var); + + if (zend_u_hash_quick_del(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value) == SUCCESS) { + while (ex && ex->symbol_table == EG(active_symbol_table)) { + int i; + + if (ex->op_array) { + for (i = 0; i < ex->op_array->last_var; i++) { + if (ex->op_array->vars[i].hash_value == cv->hash_value && + ex->op_array->vars[i].name_len == cv->name_len && + !memcmp(ex->op_array->vars[i].name.v, cv->name.v, USTR_BYTES(ZEND_STR_TYPE, cv->name_len))) { + ex->CVs[i] = NULL; + break; + } + } + } + ex = ex->prev_execute_data; + } + } + EX(CVs)[opline->op1.u.var] = NULL; + } else if (EX(CVs)[opline->op1.u.var]) { + zval_ptr_dtor(EX(CVs)[opline->op1.u.var]); + EX(CVs)[opline->op1.u.var] = NULL; + } + ZEND_VM_NEXT_OPCODE(); + } + varname = &opline->op1.u.constant; if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { @@ -1805,17 +1841,18 @@ static int ZEND_UNSET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval_copy_ctor(&tmp); convert_to_text(&tmp); varname = &tmp; - } else if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + } else if (IS_CONST == IS_VAR) { Z_ADDREF_P(varname); } if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname) TSRMLS_CC); } else { + ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1); + target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); - if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) { + if (zend_u_hash_quick_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, hash_value) == SUCCESS) { zend_execute_data *ex = execute_data; - ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1); zend_auto_global *auto_global; if (zend_u_hash_quick_find(CG(auto_globals), Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, hash_value, (void**)&auto_global) == SUCCESS) { @@ -1841,7 +1878,7 @@ static int ZEND_UNSET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (varname == &tmp) { zval_dtor(&tmp); - } else if (IS_CONST == IS_CV || IS_CONST == IS_VAR) { + } else if (IS_CONST == IS_VAR) { zval_ptr_dtor(&varname); } @@ -2003,29 +2040,49 @@ static int ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - - zval tmp, *varname = &opline->op1.u.constant; zval **value; zend_bool isset = 1; - HashTable *target_symbol_table; - if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { - tmp = *varname; - zval_copy_ctor(&tmp); - convert_to_text(&tmp); - varname = &tmp; - } + if (IS_CONST == IS_CV) { + if (EX(CVs)[opline->op1.u.var]) { + value = EX(CVs)[opline->op1.u.var]; + } else if (EG(active_symbol_table)) { + zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var); - if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { - value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1 TSRMLS_CC); - if (!value) { - isset = 0; + if (zend_u_hash_quick_find(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) { + isset = 0; + } + } else { + isset = 0; + } + } else { + HashTable *target_symbol_table; + + zval tmp, *varname = &opline->op1.u.constant; + + if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { + tmp = *varname; + zval_copy_ctor(&tmp); + convert_to_text(&tmp); + varname = &tmp; } - } else { - target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); - if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) { - isset = 0; + + if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { + value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1 TSRMLS_CC); + if (!value) { + isset = 0; + } + } else { + target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); + if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) { + isset = 0; + } } + + if (varname == &tmp) { + zval_dtor(&tmp); + } + } Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL; @@ -2047,10 +2104,6 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) break; } - if (varname == &tmp) { - zval_dtor(&tmp); - } - ZEND_VM_NEXT_OPCODE(); } @@ -5066,6 +5119,10 @@ skip_compile: EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; + if (!EG(active_symbol_table)) { + zend_rebuild_symbol_table(TSRMLS_C); + } + zend_execute(new_op_array TSRMLS_CC); EX(function_state).function = saved_function; @@ -5107,6 +5164,36 @@ static int ZEND_UNSET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) HashTable *target_symbol_table; zend_free_op free_op1; + if (IS_TMP_VAR == IS_CV) { + if (EG(active_symbol_table)) { + zend_execute_data *ex = EX(prev_execute_data); + zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var); + + if (zend_u_hash_quick_del(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value) == SUCCESS) { + while (ex && ex->symbol_table == EG(active_symbol_table)) { + int i; + + if (ex->op_array) { + for (i = 0; i < ex->op_array->last_var; i++) { + if (ex->op_array->vars[i].hash_value == cv->hash_value && + ex->op_array->vars[i].name_len == cv->name_len && + !memcmp(ex->op_array->vars[i].name.v, cv->name.v, USTR_BYTES(ZEND_STR_TYPE, cv->name_len))) { + ex->CVs[i] = NULL; + break; + } + } + } + ex = ex->prev_execute_data; + } + } + EX(CVs)[opline->op1.u.var] = NULL; + } else if (EX(CVs)[opline->op1.u.var]) { + zval_ptr_dtor(EX(CVs)[opline->op1.u.var]); + EX(CVs)[opline->op1.u.var] = NULL; + } + ZEND_VM_NEXT_OPCODE(); + } + varname = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { @@ -5114,17 +5201,18 @@ static int ZEND_UNSET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval_copy_ctor(&tmp); convert_to_text(&tmp); varname = &tmp; - } else if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + } else if (IS_TMP_VAR == IS_VAR) { Z_ADDREF_P(varname); } if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname) TSRMLS_CC); } else { + ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1); + target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); - if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) { + if (zend_u_hash_quick_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, hash_value) == SUCCESS) { zend_execute_data *ex = execute_data; - ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1); zend_auto_global *auto_global; if (zend_u_hash_quick_find(CG(auto_globals), Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, hash_value, (void**)&auto_global) == SUCCESS) { @@ -5150,7 +5238,7 @@ static int ZEND_UNSET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (varname == &tmp) { zval_dtor(&tmp); - } else if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) { + } else if (IS_TMP_VAR == IS_VAR) { zval_ptr_dtor(&varname); } zval_dtor(free_op1.var); @@ -5312,29 +5400,49 @@ static int ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); zval **value; zend_bool isset = 1; - HashTable *target_symbol_table; - if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { - tmp = *varname; - zval_copy_ctor(&tmp); - convert_to_text(&tmp); - varname = &tmp; - } + if (IS_TMP_VAR == IS_CV) { + if (EX(CVs)[opline->op1.u.var]) { + value = EX(CVs)[opline->op1.u.var]; + } else if (EG(active_symbol_table)) { + zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var); - if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { - value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1 TSRMLS_CC); - if (!value) { - isset = 0; + if (zend_u_hash_quick_find(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) { + isset = 0; + } + } else { + isset = 0; + } + } else { + HashTable *target_symbol_table; + zend_free_op free_op1; + zval tmp, *varname = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + + if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { + tmp = *varname; + zval_copy_ctor(&tmp); + convert_to_text(&tmp); + varname = &tmp; } - } else { - target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); - if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) { - isset = 0; + + if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { + value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1 TSRMLS_CC); + if (!value) { + isset = 0; + } + } else { + target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); + if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) { + isset = 0; + } + } + + if (varname == &tmp) { + zval_dtor(&tmp); } + zval_dtor(free_op1.var); } Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL; @@ -5356,11 +5464,6 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) break; } - if (varname == &tmp) { - zval_dtor(&tmp); - } - zval_dtor(free_op1.var); - ZEND_VM_NEXT_OPCODE(); } @@ -8409,6 +8512,10 @@ skip_compile: EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; + if (!EG(active_symbol_table)) { + zend_rebuild_symbol_table(TSRMLS_C); + } + zend_execute(new_op_array TSRMLS_CC); EX(function_state).function = saved_function; @@ -8450,6 +8557,36 @@ static int ZEND_UNSET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) HashTable *target_symbol_table; zend_free_op free_op1; + if (IS_VAR == IS_CV) { + if (EG(active_symbol_table)) { + zend_execute_data *ex = EX(prev_execute_data); + zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var); + + if (zend_u_hash_quick_del(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value) == SUCCESS) { + while (ex && ex->symbol_table == EG(active_symbol_table)) { + int i; + + if (ex->op_array) { + for (i = 0; i < ex->op_array->last_var; i++) { + if (ex->op_array->vars[i].hash_value == cv->hash_value && + ex->op_array->vars[i].name_len == cv->name_len && + !memcmp(ex->op_array->vars[i].name.v, cv->name.v, USTR_BYTES(ZEND_STR_TYPE, cv->name_len))) { + ex->CVs[i] = NULL; + break; + } + } + } + ex = ex->prev_execute_data; + } + } + EX(CVs)[opline->op1.u.var] = NULL; + } else if (EX(CVs)[opline->op1.u.var]) { + zval_ptr_dtor(EX(CVs)[opline->op1.u.var]); + EX(CVs)[opline->op1.u.var] = NULL; + } + ZEND_VM_NEXT_OPCODE(); + } + varname = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { @@ -8457,17 +8594,18 @@ static int ZEND_UNSET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval_copy_ctor(&tmp); convert_to_text(&tmp); varname = &tmp; - } else if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + } else if (IS_VAR == IS_VAR) { Z_ADDREF_P(varname); } if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname) TSRMLS_CC); } else { + ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1); + target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); - if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) { + if (zend_u_hash_quick_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, hash_value) == SUCCESS) { zend_execute_data *ex = execute_data; - ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1); zend_auto_global *auto_global; if (zend_u_hash_quick_find(CG(auto_globals), Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, hash_value, (void**)&auto_global) == SUCCESS) { @@ -8493,7 +8631,7 @@ static int ZEND_UNSET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (varname == &tmp) { zval_dtor(&tmp); - } else if (IS_VAR == IS_CV || IS_VAR == IS_VAR) { + } else if (IS_VAR == IS_VAR) { zval_ptr_dtor(&varname); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -8811,29 +8949,49 @@ static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); zval **value; zend_bool isset = 1; - HashTable *target_symbol_table; - if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { - tmp = *varname; - zval_copy_ctor(&tmp); - convert_to_text(&tmp); - varname = &tmp; - } + if (IS_VAR == IS_CV) { + if (EX(CVs)[opline->op1.u.var]) { + value = EX(CVs)[opline->op1.u.var]; + } else if (EG(active_symbol_table)) { + zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var); - if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { - value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1 TSRMLS_CC); - if (!value) { - isset = 0; + if (zend_u_hash_quick_find(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) { + isset = 0; + } + } else { + isset = 0; + } + } else { + HashTable *target_symbol_table; + zend_free_op free_op1; + zval tmp, *varname = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + + if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { + tmp = *varname; + zval_copy_ctor(&tmp); + convert_to_text(&tmp); + varname = &tmp; } - } else { - target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); - if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) { - isset = 0; + + if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { + value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1 TSRMLS_CC); + if (!value) { + isset = 0; + } + } else { + target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); + if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) { + isset = 0; + } + } + + if (varname == &tmp) { + zval_dtor(&tmp); } + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; } Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL; @@ -8855,11 +9013,6 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) break; } - if (varname == &tmp) { - zval_dtor(&tmp); - } - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - ZEND_VM_NEXT_OPCODE(); } @@ -22667,6 +22820,10 @@ skip_compile: EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; + if (!EG(active_symbol_table)) { + zend_rebuild_symbol_table(TSRMLS_C); + } + zend_execute(new_op_array TSRMLS_CC); EX(function_state).function = saved_function; @@ -22708,6 +22865,36 @@ static int ZEND_UNSET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) HashTable *target_symbol_table; + if (IS_CV == IS_CV) { + if (EG(active_symbol_table)) { + zend_execute_data *ex = EX(prev_execute_data); + zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var); + + if (zend_u_hash_quick_del(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value) == SUCCESS) { + while (ex && ex->symbol_table == EG(active_symbol_table)) { + int i; + + if (ex->op_array) { + for (i = 0; i < ex->op_array->last_var; i++) { + if (ex->op_array->vars[i].hash_value == cv->hash_value && + ex->op_array->vars[i].name_len == cv->name_len && + !memcmp(ex->op_array->vars[i].name.v, cv->name.v, USTR_BYTES(ZEND_STR_TYPE, cv->name_len))) { + ex->CVs[i] = NULL; + break; + } + } + } + ex = ex->prev_execute_data; + } + } + EX(CVs)[opline->op1.u.var] = NULL; + } else if (EX(CVs)[opline->op1.u.var]) { + zval_ptr_dtor(EX(CVs)[opline->op1.u.var]); + EX(CVs)[opline->op1.u.var] = NULL; + } + ZEND_VM_NEXT_OPCODE(); + } + varname = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC); if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { @@ -22715,17 +22902,18 @@ static int ZEND_UNSET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval_copy_ctor(&tmp); convert_to_text(&tmp); varname = &tmp; - } else if (IS_CV == IS_CV || IS_CV == IS_VAR) { + } else if (IS_CV == IS_VAR) { Z_ADDREF_P(varname); } if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname) TSRMLS_CC); } else { + ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1); + target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); - if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) { + if (zend_u_hash_quick_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, hash_value) == SUCCESS) { zend_execute_data *ex = execute_data; - ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1); zend_auto_global *auto_global; if (zend_u_hash_quick_find(CG(auto_globals), Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, hash_value, (void**)&auto_global) == SUCCESS) { @@ -22751,7 +22939,7 @@ static int ZEND_UNSET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (varname == &tmp) { zval_dtor(&tmp); - } else if (IS_CV == IS_CV || IS_CV == IS_VAR) { + } else if (IS_CV == IS_VAR) { zval_ptr_dtor(&varname); } @@ -22913,29 +23101,49 @@ static int ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - - zval tmp, *varname = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC); zval **value; zend_bool isset = 1; - HashTable *target_symbol_table; - if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { - tmp = *varname; - zval_copy_ctor(&tmp); - convert_to_text(&tmp); - varname = &tmp; - } + if (IS_CV == IS_CV) { + if (EX(CVs)[opline->op1.u.var]) { + value = EX(CVs)[opline->op1.u.var]; + } else if (EG(active_symbol_table)) { + zend_compiled_variable *cv = &CV_DEF_OF(opline->op1.u.var); - if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { - value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1 TSRMLS_CC); - if (!value) { - isset = 0; + if (zend_u_hash_quick_find(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value, (void **) &value) == FAILURE) { + isset = 0; + } + } else { + isset = 0; + } + } else { + HashTable *target_symbol_table; + + zval tmp, *varname = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_IS TSRMLS_CC); + + if (Z_TYPE_P(varname) != IS_STRING && Z_TYPE_P(varname) != IS_UNICODE) { + tmp = *varname; + zval_copy_ctor(&tmp); + convert_to_text(&tmp); + varname = &tmp; } - } else { - target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); - if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) { - isset = 0; + + if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { + value = zend_std_get_static_property(EX_T(opline->op2.u.var).class_entry, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1 TSRMLS_CC); + if (!value) { + isset = 0; + } + } else { + target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC); + if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) { + isset = 0; + } } + + if (varname == &tmp) { + zval_dtor(&tmp); + } + } Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_BOOL; @@ -22957,10 +23165,6 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) break; } - if (varname == &tmp) { - zval_dtor(&tmp); - } - ZEND_VM_NEXT_OPCODE(); } @@ -33185,31 +33389,31 @@ void zend_init_opcodes_handlers(void) ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER, ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER, ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, - ZEND_CATCH_SPEC_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CATCH_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CATCH_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CATCH_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CATCH_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CATCH_SPEC_CV_HANDLER, ZEND_THROW_SPEC_CONST_HANDLER, ZEND_THROW_SPEC_CONST_HANDLER, ZEND_THROW_SPEC_CONST_HANDLER, diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index dce15d9f4f..911b01f7f3 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -14,12 +14,12 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC) /* Initialize execute_data */ execute_data = (zend_execute_data *)zend_vm_stack_alloc( sizeof(zend_execute_data) + - sizeof(zval**) * op_array->last_var + + sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2) + sizeof(temp_variable) * op_array->T TSRMLS_CC); EX(CVs) = (zval***)((char*)execute_data + sizeof(zend_execute_data)); memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); - EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var); + EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var * (EG(active_symbol_table) ? 1 : 2)); EX(fbc) = NULL; EX(called_scope) = NULL; EX(object) = NULL; @@ -37,7 +37,7 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC) ZEND_VM_SET_OPCODE(op_array->opcodes); } - if (op_array->uses_this && EG(This)) { + if (op_array->uses_this && EG(This) && EG(active_symbol_table)) { Z_ADDREF_P(EG(This)); /* For $this pointer */ if (zend_ascii_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL)==FAILURE) { Z_DELREF_P(EG(This)); diff --git a/ext/curl/streams.c b/ext/curl/streams.c index 1271bfcf60..d55d946475 100644 --- a/ext/curl/streams.c +++ b/ext/curl/streams.c @@ -64,6 +64,9 @@ static size_t on_data_available(char *data, size_t size, size_t nmemb, void *ctx if (curlstream->readbuffer.writepos == 0) { zval *sym; + if (!EG(active_symbol_table)) { + zend_rebuild_symbol_table(TSRMLS_C); + } MAKE_STD_ZVAL(sym); *sym = *curlstream->headers; zval_copy_ctor(sym); diff --git a/ext/standard/array.c b/ext/standard/array.c index 1a4e9d4f41..5a26eea0e5 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1420,6 +1420,10 @@ PHP_FUNCTION(extract) } } + if (!EG(active_symbol_table)) { + zend_rebuild_symbol_table(TSRMLS_C); + } + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(var_array), &pos); while (zend_hash_get_current_data_ex(Z_ARRVAL_P(var_array), (void **)&entry, &pos) == SUCCESS) { zval final_name; @@ -1617,6 +1621,10 @@ PHP_FUNCTION(compact) WRONG_PARAM_COUNT; } + if (!EG(active_symbol_table)) { + zend_rebuild_symbol_table(TSRMLS_C); + } + array_init(return_value); for (i=0; i