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