The patch is attached. To use runtime JIT you will need to change zend_register_auto_global() to zend_register_auto_global_ex() with "1" as the last argument. Compile-time JIT is still supported too.
Note that the significant part of the patch is reverting of "autoglobals CV" patch, that is reimplemented using CG(auto_globals_cache). Any objections? Thanks. Dmitry. > -----Original Message----- > From: Dmitry Stogov [mailto:[EMAIL PROTECTED] > Sent: Tuesday, February 13, 2007 10:35 PM > To: 'Sara Golemon'; '[EMAIL PROTECTED]'; 'Andrei Zmievski' > Cc: 'Andi Gutmans'; 'Rasmus Lerdorf' > Subject: RE: runtime JIT > > > Hi, > > I see the following simple decision: > > PHP compiler compiles accesses to autoglobals into > ZEND_FETCH_x "name" with flag ZEND_FETCH_AUTOGLOBAL instead > of ZEND_FETCH_GLOBAL. Also this opcode contains an index of > autoglobal descriptor (for fast access during execution). > > During execution of ZEND_FETCH_x with ZEND_FETCH_AUTOGLOBAL, > it looks into autoglobal descriptor, checks if JIT was > already called, and calls autoglobal JIT callback if need. > > The decision walso removes (or modifys) CV autoglobals patch. > We don't need to mix local and autoglobal CV in one array. > Autoglobals zvals are cached in autoglobal desriptors. > > Is this OK? > > Dmitry. > > > > -----Original Message----- > > From: Sara Golemon [mailto:[EMAIL PROTECTED] > > Sent: Tuesday, February 13, 2007 7:14 PM > > To: [EMAIL PROTECTED] > > Cc: Dmitry Stogov; Andrei Zmievski; Andi Gutmans; Rasmus Lerdorf > > Subject: Re: runtime JIT > > > > > > >> > We've discussed it all a number of times on the list. Do > > you have > > >> > access to archives? > > >> > > >> I have, but extracting requirements from the list will take huge > > >> amount of time. > > >> Could you point me into the key problems and ideas > > > > > Key Problems: > > > > 1) Scripts need an opportunity to do some processing *prior* > > to the GPC > > values being decoded to unicode so that the script can specify what > > encoding the data is likely to be coming in. > > > > 2) Decoding an entire GPC array at once opens the door to potential > > attack vectors by injecting deliberately invalid data, so > > we'd *like* to > > be able to only decode elements on an as-requested basis (the > > also means > > less-work for the runtime). > > > > Ideas: > > > > 1) Make JIT happen at Runtime (Possibly allowing it to happen on a > > per-element basis) > > > > 2) Wrap GPC arrays in over-loaded objects. Not a *bad* > solution IMO, > > but not without it's problems. (I've explained the BC issues > > surrounding > > this too many times to do it again) > > > > > JIT is now done at compile time, it has to be done at > > runtime instead. > > > That's the key problem/change. What do you mean by "good way"? > > > > > I presume he's referring to the numerous hooks my last > patch put into > > the various FETCH ops as a not-good way. Taking the per-element > > component out of the picture would reduce that somewhat, but > > the need to > > catch all the various fetches would still exist. > > > > -Sara > > >
Index: Zend/zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.737 diff -u -p -d -r1.737 zend_compile.c --- Zend/zend_compile.c 1 Feb 2007 15:24:10 -0000 1.737 +++ Zend/zend_compile.c 14 Feb 2007 11:40:21 -0000 @@ -160,6 +161,7 @@ void zend_init_compiler_data_structures( CG(in_compilation) = 0; CG(start_lineno) = 0; init_compiler_declarables(TSRMLS_C); + memset(CG(auto_globals_cache), 0, sizeof(zval**) * zend_hash_num_elements(CG(auto_globals))); zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_arm TSRMLS_CC); zend_stack_init(&CG(labels_stack)); CG(labels) = NULL; @@ -168,6 +170,7 @@ void zend_init_compiler_data_structures( void init_compiler(TSRMLS_D) { + CG(auto_globals_cache) = emalloc(sizeof(zval**) * zend_hash_num_elements(CG(auto_globals))); CG(active_op_array) = NULL; zend_init_compiler_data_structures(TSRMLS_C); zend_init_rsrc_list(TSRMLS_C); @@ -180,6 +183,8 @@ void init_compiler(TSRMLS_D) void shutdown_compiler(TSRMLS_D) { + efree(CG(auto_globals_cache)); + CG(auto_globals_cache) = NULL; zend_stack_destroy(&CG(bp_stack)); zend_stack_destroy(&CG(function_call_stack)); zend_stack_destroy(&CG(switch_cond_stack)); @@ -267,7 +272,7 @@ static zend_uint get_temporary_variable( return (op_array->T)++ * sizeof(temp_variable); } -static int lookup_cv(zend_op_array *op_array, zend_uchar type, zstr name, int name_len TSRMLS_DC) +static int lookup_cv(zend_op_array *op_array, zend_uchar type, zstr name, int name_len) { int i = 0; ulong hash_value = zend_u_inline_hash_func(type, name, name_len+1); @@ -290,7 +295,6 @@ static int lookup_cv(zend_op_array *op_a op_array->vars[i].name = name; /* estrndup(name, name_len); */ op_array->vars[i].name_len = name_len; op_array->vars[i].hash_value = hash_value; - op_array->vars[i].fetch_type = zend_u_is_auto_global(type, name, name_len TSRMLS_CC) ? ZEND_FETCH_GLOBAL : ZEND_FETCH_LOCAL; return i; } @@ -377,18 +381,23 @@ void fetch_simple_variable_ex(znode *res zend_op opline; zend_op *opline_ptr; zend_llist *fetch_list_ptr; + zend_bool is_auto_global = 0; + zend_auto_global *auto_global; if (varname->op_type == IS_CONST && (Z_TYPE(varname->u.constant) == IS_STRING || - Z_TYPE(varname->u.constant) == IS_UNICODE) && - !(Z_UNILEN(varname->u.constant) == (sizeof("this")-1) && - ZEND_U_EQUAL(Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant), "this", sizeof("this")-1)) && - (CG(active_op_array)->last == 0 || - CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) { - result->op_type = IS_CV; - result->u.var = lookup_cv(CG(active_op_array), Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant) TSRMLS_CC); - result->u.EA.type = 0; - return; + Z_TYPE(varname->u.constant) == IS_UNICODE)) { + is_auto_global = zend_u_is_auto_global_ex(Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant), 0, &auto_global TSRMLS_CC); + if (!is_auto_global && + !(Z_UNILEN(varname->u.constant) == (sizeof("this")-1) && + ZEND_U_EQUAL(Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant), "this", sizeof("this")-1)) && + (CG(active_op_array)->last == 0 || + CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) { + result->op_type = IS_CV; + result->u.var = lookup_cv(CG(active_op_array), Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant)); + result->u.EA.type = 0; + return; + } } if (bp) { @@ -407,12 +416,9 @@ void fetch_simple_variable_ex(znode *res SET_UNUSED(opline_ptr->op2); opline_ptr->op2.u.EA.type = ZEND_FETCH_LOCAL; - if (varname->op_type == IS_CONST && - (Z_TYPE(varname->u.constant) == IS_STRING || - Z_TYPE(varname->u.constant) == IS_UNICODE)) { - if (zend_u_is_auto_global(Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant) TSRMLS_CC)) { - opline_ptr->op2.u.EA.type = ZEND_FETCH_GLOBAL; - } + if (is_auto_global) { + opline_ptr->op2.u.var = auto_global->index; + opline_ptr->op2.u.EA.type = ZEND_FETCH_AUTO_GLOBAL; } if (bp) { @@ -4310,36 +4316,50 @@ void zend_auto_global_dtor(zend_auto_glo } -zend_bool zend_u_is_auto_global(zend_uchar type, zstr name, uint name_len TSRMLS_DC) +zend_bool zend_u_is_auto_global_ex(zend_uchar type, zstr name, uint name_len, zend_bool runtime, zend_auto_global **ret TSRMLS_DC) { zend_auto_global *auto_global; if (zend_u_hash_find(CG(auto_globals), type, name, name_len+1, (void **) &auto_global)==SUCCESS) { - if (auto_global->armed) { + if (auto_global->runtime == runtime && auto_global->armed) { auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC); } + if (ret) { + *ret = auto_global; + } return 1; } return 0; } +zend_bool zend_u_is_auto_global(zend_uchar type, zstr name, uint name_len TSRMLS_DC) +{ + return zend_u_is_auto_global_ex(type, name, name_len, 0, NULL TSRMLS_CC); +} + zend_bool zend_is_auto_global(char *name, uint name_len TSRMLS_DC) { - return zend_u_is_auto_global(IS_STRING, ZSTR(name), name_len TSRMLS_CC); + return zend_u_is_auto_global_ex(IS_STRING, ZSTR(name), name_len, 0, NULL TSRMLS_CC); } -int zend_register_auto_global(char *name, uint name_len, zend_auto_global_callback auto_global_callback TSRMLS_DC) +int zend_register_auto_global_ex(char *name, uint name_len, zend_auto_global_callback auto_global_callback, zend_bool runtime TSRMLS_DC) { zend_auto_global auto_global; auto_global.name = zend_strndup(name, name_len); auto_global.name_len = name_len; auto_global.auto_global_callback = auto_global_callback; + auto_global.runtime = runtime; + auto_global.index = zend_hash_num_elements(CG(auto_globals)); return zend_hash_add(CG(auto_globals), name, name_len+1, &auto_global, sizeof(zend_auto_global), NULL); } +int zend_register_auto_global(char *name, uint name_len, zend_auto_global_callback auto_global_callback TSRMLS_DC) +{ + return zend_register_auto_global_ex(name, name_len, auto_global_callback, 0 TSRMLS_CC); +} int zendlex(znode *zendlval TSRMLS_DC) { Index: Zend/zend_compile.h =================================================================== RCS file: /repository/ZendEngine2/zend_compile.h,v retrieving revision 1.353 diff -u -p -d -r1.353 zend_compile.h --- Zend/zend_compile.h 20 Jan 2007 20:36:55 -0000 1.353 +++ Zend/zend_compile.h 14 Feb 2007 11:40:24 -0000 @@ -174,7 +174,6 @@ typedef struct _zend_compiled_variable { zstr name; int name_len; ulong hash_value; - zend_uint fetch_type; } zend_compiled_variable; struct _zend_op_array { @@ -581,12 +580,16 @@ typedef struct _zend_auto_global { uint name_len; zend_auto_global_callback auto_global_callback; zend_bool armed; + zend_bool runtime; + zend_uchar index; } zend_auto_global; void zend_auto_global_dtor(zend_auto_global *auto_global); ZEND_API int zend_register_auto_global(char *name, uint name_len, zend_auto_global_callback auto_global_callback TSRMLS_DC); +ZEND_API int zend_register_auto_global_ex(char *name, uint name_len, zend_auto_global_callback auto_global_callback, zend_bool runtime TSRMLS_DC); ZEND_API zend_bool zend_is_auto_global(char *name, uint name_len TSRMLS_DC); ZEND_API zend_bool zend_u_is_auto_global(zend_uchar type, zstr name, uint name_len TSRMLS_DC); +ZEND_API zend_bool zend_u_is_auto_global_ex(zend_uchar type, zstr name, uint name_len, zend_bool runtime, zend_auto_global **ret TSRMLS_DC); ZEND_API int zend_auto_global_disable_jit(char *varname, zend_uint varname_length TSRMLS_DC); int zendlex(znode *zendlval TSRMLS_DC); @@ -607,7 +610,8 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_FETCH_LOCAL 1 #define ZEND_FETCH_STATIC 2 #define ZEND_FETCH_STATIC_MEMBER 3 -#define ZEND_FETCH_GLOBAL_LOCK 4 +#define ZEND_FETCH_GLOBAL_LOCK 4 +#define ZEND_FETCH_AUTO_GLOBAL 5 /* class fetches */ Index: Zend/zend_execute.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute.c,v retrieving revision 1.758 diff -u -p -d -r1.758 zend_execute.c --- Zend/zend_execute.c 20 Jan 2007 20:36:55 -0000 1.758 +++ Zend/zend_execute.c 14 Feb 2007 11:40:28 -0000 @@ -226,9 +226,8 @@ static inline zval *_get_zval_ptr_cv(zno if (!*ptr) { zend_compiled_variable *cv = &CV_DEF_OF(node->u.var); zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING; - HashTable *symbol_table = (cv->fetch_type == ZEND_FETCH_GLOBAL) ? &EG(symbol_table) : EG(active_symbol_table); - if (zend_u_hash_quick_find(symbol_table, utype, cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) { + if (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: @@ -297,9 +296,8 @@ static inline zval **_get_zval_ptr_ptr_c if (!*ptr) { zend_compiled_variable *cv = &CV_DEF_OF(node->u.var); zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING; - HashTable *symbol_table = (cv->fetch_type == ZEND_FETCH_GLOBAL) ? &EG(symbol_table) : EG(active_symbol_table); - if (zend_u_hash_quick_find(symbol_table, utype, cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) { + if (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: @@ -903,6 +901,7 @@ static inline HashTable *zend_get_target break; case ZEND_FETCH_GLOBAL: case ZEND_FETCH_GLOBAL_LOCK: + case ZEND_FETCH_AUTO_GLOBAL: return &EG(symbol_table); break; case ZEND_FETCH_STATIC: Index: Zend/zend_execute_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute_API.c,v retrieving revision 1.392 diff -u -p -d -r1.392 zend_execute_API.c --- Zend/zend_execute_API.c 1 Jan 2007 09:29:20 -0000 1.392 +++ Zend/zend_execute_API.c 14 Feb 2007 11:40:33 -0000 @@ -1706,6 +1706,7 @@ ZEND_API void zend_reset_all_cv(HashTabl zend_execute_data *ex; int i; + memset(CG(auto_globals_cache), 0, sizeof(zval**) * zend_hash_num_elements(CG(auto_globals))); for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) { if (ex->op_array && ex->symbol_table == symbol_table) { for (i = 0; i < ex->op_array->last_var; i++) { @@ -1719,7 +1720,11 @@ ZEND_API int zend_u_delete_global_variab { zend_execute_data *ex; ulong hash_value = zend_u_inline_hash_func(type, name, name_len+1); + zend_auto_global *auto_global; + if (zend_u_hash_quick_find(CG(auto_globals), type, name, name_len+1, hash_value, (void**)&auto_global) == SUCCESS) { + CG(auto_globals_cache)[auto_global->index] = NULL; + } if (zend_u_hash_quick_exists(&EG(symbol_table), type, name, name_len+1, hash_value)) { for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) { if (ex->op_array && ex->symbol_table == &EG(symbol_table)) { Index: Zend/zend_globals.h =================================================================== RCS file: /repository/ZendEngine2/zend_globals.h,v retrieving revision 1.166 diff -u -p -d -r1.166 zend_globals.h --- Zend/zend_globals.h 1 Jan 2007 09:29:21 -0000 1.166 +++ Zend/zend_globals.h 14 Feb 2007 11:40:34 -0000 @@ -96,6 +96,7 @@ struct _zend_compiler_globals { HashTable filenames_table; HashTable *auto_globals; + zval ***auto_globals_cache; zend_bool in_compilation; zend_bool short_tags; Index: Zend/zend_vm_def.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_def.h,v retrieving revision 1.156 diff -u -p -d -r1.156 zend_vm_def.h --- Zend/zend_vm_def.h 1 Feb 2007 16:38:15 -0000 1.156 +++ Zend/zend_vm_def.h 14 Feb 2007 11:41:03 -0000 @@ -945,9 +945,17 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address varname = &tmp_varname; } - if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { + if (opline->op2.u.EA.type == ZEND_FETCH_AUTO_GLOBAL && + CG(auto_globals_cache)[opline->op2.u.var]) { + retval = CG(auto_globals_cache)[opline->op2.u.var]; + } else if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { retval = 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), 0 TSRMLS_CC); } else { + zend_auto_global *auto_global = NULL; + + if (opline->op2.u.EA.type == ZEND_FETCH_AUTO_GLOBAL) { + zend_u_is_auto_global_ex(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1, &auto_global TSRMLS_CC); + } target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), type, varname TSRMLS_CC); /* if (!target_symbol_table) { @@ -977,6 +985,11 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address } } switch (opline->op2.u.EA.type) { + case ZEND_FETCH_AUTO_GLOBAL: + if (auto_global && (!auto_global->armed || !auto_global->runtime)) { + CG(auto_globals_cache)[opline->op2.u.var] = retval; + } + /* break missing intentionally */ case ZEND_FETCH_GLOBAL: if (OP1_TYPE != IS_TMP_VAR) { FREE_OP1(); @@ -2987,7 +3000,11 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONS if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == 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) { + CG(auto_globals_cache)[auto_global->index] = NULL; + } do { int i; Index: Zend/zend_vm_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_execute.h,v retrieving revision 1.159 diff -u -p -d -r1.159 zend_vm_execute.h --- Zend/zend_vm_execute.h 1 Feb 2007 16:38:15 -0000 1.159 +++ Zend/zend_vm_execute.h 14 Feb 2007 11:41:38 -0000 @@ -1443,9 +1443,17 @@ static int zend_fetch_var_address_helper varname = &tmp_varname; } - if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { + if (opline->op2.u.EA.type == ZEND_FETCH_AUTO_GLOBAL && + CG(auto_globals_cache)[opline->op2.u.var]) { + retval = CG(auto_globals_cache)[opline->op2.u.var]; + } else if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { retval = 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), 0 TSRMLS_CC); } else { + zend_auto_global *auto_global = NULL; + + if (opline->op2.u.EA.type == ZEND_FETCH_AUTO_GLOBAL) { + zend_u_is_auto_global_ex(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1, &auto_global TSRMLS_CC); + } target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), type, varname TSRMLS_CC); /* if (!target_symbol_table) { @@ -1475,6 +1483,11 @@ static int zend_fetch_var_address_helper } } switch (opline->op2.u.EA.type) { + case ZEND_FETCH_AUTO_GLOBAL: + if (auto_global && (!auto_global->armed || !auto_global->runtime)) { + CG(auto_globals_cache)[opline->op2.u.var] = retval; + } + /* break missing intentionally */ case ZEND_FETCH_GLOBAL: if (IS_CONST != IS_TMP_VAR) { @@ -2079,7 +2092,11 @@ static int ZEND_UNSET_VAR_SPEC_CONST_HAN if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == 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) { + CG(auto_globals_cache)[auto_global->index] = NULL; + } do { int i; @@ -4057,9 +4074,17 @@ static int zend_fetch_var_address_helper varname = &tmp_varname; } - if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { + if (opline->op2.u.EA.type == ZEND_FETCH_AUTO_GLOBAL && + CG(auto_globals_cache)[opline->op2.u.var]) { + retval = CG(auto_globals_cache)[opline->op2.u.var]; + } else if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { retval = 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), 0 TSRMLS_CC); } else { + zend_auto_global *auto_global = NULL; + + if (opline->op2.u.EA.type == ZEND_FETCH_AUTO_GLOBAL) { + zend_u_is_auto_global_ex(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1, &auto_global TSRMLS_CC); + } target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), type, varname TSRMLS_CC); /* if (!target_symbol_table) { @@ -4089,6 +4114,11 @@ static int zend_fetch_var_address_helper } } switch (opline->op2.u.EA.type) { + case ZEND_FETCH_AUTO_GLOBAL: + if (auto_global && (!auto_global->armed || !auto_global->runtime)) { + CG(auto_globals_cache)[opline->op2.u.var] = retval; + } + /* break missing intentionally */ case ZEND_FETCH_GLOBAL: if (IS_TMP_VAR != IS_TMP_VAR) { zval_dtor(free_op1.var); @@ -4694,7 +4724,11 @@ static int ZEND_UNSET_VAR_SPEC_TMP_HANDL if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == 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) { + CG(auto_globals_cache)[auto_global->index] = NULL; + } do { int i; @@ -7178,9 +7212,17 @@ static int zend_fetch_var_address_helper varname = &tmp_varname; } - if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { + if (opline->op2.u.EA.type == ZEND_FETCH_AUTO_GLOBAL && + CG(auto_globals_cache)[opline->op2.u.var]) { + retval = CG(auto_globals_cache)[opline->op2.u.var]; + } else if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { retval = 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), 0 TSRMLS_CC); } else { + zend_auto_global *auto_global = NULL; + + if (opline->op2.u.EA.type == ZEND_FETCH_AUTO_GLOBAL) { + zend_u_is_auto_global_ex(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1, &auto_global TSRMLS_CC); + } target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), type, varname TSRMLS_CC); /* if (!target_symbol_table) { @@ -7210,6 +7252,11 @@ static int zend_fetch_var_address_helper } } switch (opline->op2.u.EA.type) { + case ZEND_FETCH_AUTO_GLOBAL: + if (auto_global && (!auto_global->armed || !auto_global->runtime)) { + CG(auto_globals_cache)[opline->op2.u.var] = retval; + } + /* break missing intentionally */ case ZEND_FETCH_GLOBAL: if (IS_VAR != IS_TMP_VAR) { if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -7914,7 +7961,11 @@ static int ZEND_UNSET_VAR_SPEC_VAR_HANDL if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == 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) { + CG(auto_globals_cache)[auto_global->index] = NULL; + } do { int i; @@ -19760,9 +19811,17 @@ static int zend_fetch_var_address_helper varname = &tmp_varname; } - if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { + if (opline->op2.u.EA.type == ZEND_FETCH_AUTO_GLOBAL && + CG(auto_globals_cache)[opline->op2.u.var]) { + retval = CG(auto_globals_cache)[opline->op2.u.var]; + } else if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { retval = 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), 0 TSRMLS_CC); } else { + zend_auto_global *auto_global = NULL; + + if (opline->op2.u.EA.type == ZEND_FETCH_AUTO_GLOBAL) { + zend_u_is_auto_global_ex(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname), 1, &auto_global TSRMLS_CC); + } target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), type, varname TSRMLS_CC); /* if (!target_symbol_table) { @@ -19792,6 +19851,11 @@ static int zend_fetch_var_address_helper } } switch (opline->op2.u.EA.type) { + case ZEND_FETCH_AUTO_GLOBAL: + if (auto_global && (!auto_global->armed || !auto_global->runtime)) { + CG(auto_globals_cache)[opline->op2.u.var] = retval; + } + /* break missing intentionally */ case ZEND_FETCH_GLOBAL: if (IS_CV != IS_TMP_VAR) { @@ -20483,7 +20547,11 @@ static int ZEND_UNSET_VAR_SPEC_CV_HANDLE if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == 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) { + CG(auto_globals_cache)[auto_global->index] = NULL; + } do { int i;
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php