Hi Sara,
I fixed one error in your patch, so now it passes all tests.
BTW I am against this patch.
1) It adds sloppily built functionality into the core and slowdowns EACH
dimension or property fetch both at run-time and compilation-time. I think
it is a big cost for $_GET/$_POST encoding-conversion, but it is only my
opinion.
2) It adds pointer to zend_auto_global into zend_compiled_variable. This
makes troubles for opcode caches - zend_compiled_variable(s) may lay in
shared memory, so they cannot point to process specific data. I think this
issue can be fixed using indirect pointer (index).
I would prefer rollback "auto-globals CV" patch and commit (or not) the
whole patch after conclusion.
Why did you reject auto-globals as overloaded arrays?
Thanks. Dmitry.
> -----Original Message-----
> From: Sara Golemon [mailto:[EMAIL PROTECTED]
> Sent: Wednesday, January 24, 2007 10:58 PM
> To: [email protected]; Dmitry Stogov; Andi Gutmans;
> Andrei Zmievski
> Subject: [PHP-DEV] Runtime-JIT, the whole enchilada
>
>
> Dmitry-
>
> You asked for it, you get it :) Hopefully it'll be
> self-explanatory,
> the one part I hope you don't notice is that I put the
> auto_global check
> back into fetch_simple_variable_ex in order to force direct access to
> autoglobals ($foo = $_GET; foreach($_POST as ...) etc...) as
> non-auto-globals. Ultimately this made catching the
> difference between
> a whole var access and a dim/obj access much more
> straight-forward and
> computationally cheap. It comes at a slight cost for those
> fetches, but
> hopefully they're in the minority.
>
> Bench numbers with this patch:
> simple 0.461
> simplecall 1.985
> simpleucall 2.900
> simpleudcall 3.488
> mandel 2.136
> mandel2 3.192
> ackermann(7) 3.490
> ary(50000) 0.154
> ary2(50000) 0.137
> ary3(2000) 1.076
> fibo(30) 9.766
> hash1(50000) 0.423
> hash2(500) 0.307
> heapsort(20000) 0.799
> matrix(20) 0.526
> nestedloop(12) 0.866
> sieve(30) 0.630
> strcat(200000) 0.303
> ------------------------
> Total 32.639
>
> -Sara
>
>
Index: main/php_variables.c
===================================================================
RCS file: /repository/php-src/main/php_variables.c,v
retrieving revision 1.136
diff -u -p -d -r1.136 php_variables.c
--- main/php_variables.c 1 Jan 2007 09:29:35 -0000 1.136
+++ main/php_variables.c 26 Jan 2007 10:23:11 -0000
@@ -628,9 +628,9 @@ void _php_import_environment_variables(z
}
}
-zend_bool php_std_auto_global_callback(char *name, uint name_len TSRMLS_DC)
+zend_bool php_std_auto_global_callback(zend_auto_global *auto_global, int
stage, zval *ag_val, int fetch_op, zval *member TSRMLS_DC)
{
- zend_printf("%s\n", name);
+ zend_printf("%s\n", auto_global->name);
return 0; /* don't rearm */
}
@@ -802,9 +802,13 @@ static void php_autoglobal_merge(HashTab
}
/* }}} */
-static zend_bool php_auto_globals_create_server(char *name, uint name_len
TSRMLS_DC);
-static zend_bool php_auto_globals_create_env(char *name, uint name_len
TSRMLS_DC);
-static zend_bool php_auto_globals_create_request(char *name, uint name_len
TSRMLS_DC);
+static zend_auto_global *php_server_auto_global = NULL;
+static zend_auto_global *php_env_auto_global = NULL;
+static zend_auto_global *php_request_auto_global = NULL;
+
+static zend_bool php_auto_globals_create_server(zend_auto_global *auto_global,
int stage, zval *ag_val, int fetch_op, zval *member TSRMLS_DC);
+static zend_bool php_auto_globals_create_env(zend_auto_global *auto_global,
int stage, zval *ag_val, int fetch_op, zval *member TSRMLS_DC);
+static zend_bool php_auto_globals_create_request(zend_auto_global
*auto_global, int stage, zval *ag_val, int fetch_op, zval *member TSRMLS_DC);
/* {{{ php_hash_environment
*/
@@ -861,16 +865,14 @@ int php_hash_environment(TSRMLS_D)
case 'e':
case 'E':
if (!jit_initialization && !_gpc_flags[3]) {
- zend_auto_global_disable_jit("_ENV",
sizeof("_ENV")-1 TSRMLS_CC);
- php_auto_globals_create_env("_ENV",
sizeof("_ENV")-1 TSRMLS_CC);
+ php_env_auto_global->armed =
php_auto_globals_create_env(php_env_auto_global, ZEND_RT, NULL, ZEND_FETCH_R,
NULL TSRMLS_CC);
_gpc_flags[3] = 1;
}
break;
case 's':
case 'S':
if (!jit_initialization && !_gpc_flags[4]) {
- zend_auto_global_disable_jit("_SERVER",
sizeof("_SERVER")-1 TSRMLS_CC);
- php_register_server_variables(TSRMLS_C);
+ php_server_auto_global->armed =
php_auto_globals_create_server(php_server_auto_global, ZEND_RT, NULL,
ZEND_FETCH_R, NULL TSRMLS_CC);
_gpc_flags[4] = 1;
}
break;
@@ -904,15 +906,14 @@ int php_hash_environment(TSRMLS_D)
/* Create _REQUEST */
if (!jit_initialization) {
- zend_auto_global_disable_jit("_REQUEST", sizeof("_REQUEST")-1
TSRMLS_CC);
- php_auto_globals_create_request("_REQUEST",
sizeof("_REQUEST")-1 TSRMLS_CC);
+ php_request_auto_global->armed =
php_auto_globals_create_request(php_request_auto_global, ZEND_RT, NULL,
ZEND_FETCH_R, NULL TSRMLS_CC);
}
return SUCCESS;
}
/* }}} */
-static zend_bool php_auto_globals_create_server(char *name, uint name_len
TSRMLS_DC)
+static zend_bool php_auto_globals_create_server(zend_auto_global *auto_global,
int stage, zval *ag_val, int fetch_op, zval *member TSRMLS_DC)
{
if (PG(variables_order) && (strchr(PG(variables_order),'S') ||
strchr(PG(variables_order),'s'))) {
php_register_server_variables(TSRMLS_C);
@@ -944,13 +945,13 @@ static zend_bool php_auto_globals_create
PG(http_globals)[TRACK_VARS_SERVER] = server_vars;
}
- zend_ascii_hash_update(&EG(symbol_table), name, name_len + 1,
&PG(http_globals)[TRACK_VARS_SERVER], sizeof(zval *), NULL);
+ zend_ascii_hash_update(&EG(symbol_table), auto_global->name,
auto_global->name_len + 1, &PG(http_globals)[TRACK_VARS_SERVER], sizeof(zval
*), NULL);
PG(http_globals)[TRACK_VARS_SERVER]->refcount++;
return 0; /* don't rearm */
}
-static zend_bool php_auto_globals_create_env(char *name, uint name_len
TSRMLS_DC)
+static zend_bool php_auto_globals_create_env(zend_auto_global *auto_global,
int stage, zval *ag_val, int fetch_op, zval *member TSRMLS_DC)
{
zval *env_vars = NULL;
ALLOC_ZVAL(env_vars);
@@ -965,13 +966,13 @@ static zend_bool php_auto_globals_create
php_import_environment_variables(PG(http_globals)[TRACK_VARS_ENV] TSRMLS_CC);
}
- zend_ascii_hash_update(&EG(symbol_table), name, name_len + 1,
&PG(http_globals)[TRACK_VARS_ENV], sizeof(zval *), NULL);
+ zend_ascii_hash_update(&EG(symbol_table), auto_global->name,
auto_global->name_len + 1, &PG(http_globals)[TRACK_VARS_ENV], sizeof(zval *),
NULL);
PG(http_globals)[TRACK_VARS_ENV]->refcount++;
return 0; /* don't rearm */
}
-static zend_bool php_auto_globals_create_request(char *name, uint name_len
TSRMLS_DC)
+static zend_bool php_auto_globals_create_request(zend_auto_global
*auto_global, int stage, zval *ag_val, int fetch_op, zval *member TSRMLS_DC)
{
zval *form_variables;
unsigned char _gpc_flags[3] = {0, 0, 0};
@@ -1007,7 +1008,7 @@ static zend_bool php_auto_globals_create
}
}
- zend_ascii_hash_update(&EG(symbol_table), "_REQUEST",
sizeof("_REQUEST"), &form_variables, sizeof(zval *), NULL);
+ zend_ascii_hash_update(&EG(symbol_table), auto_global->name,
auto_global->name_len + 1, &form_variables, sizeof(zval *), NULL);
return 0;
}
@@ -1016,9 +1017,9 @@ void php_startup_auto_globals(TSRMLS_D)
zend_register_auto_global("_GET", sizeof("_GET")-1, NULL TSRMLS_CC);
zend_register_auto_global("_POST", sizeof("_POST")-1, NULL TSRMLS_CC);
zend_register_auto_global("_COOKIE", sizeof("_COOKIE")-1, NULL
TSRMLS_CC);
- zend_register_auto_global("_SERVER", sizeof("_SERVER")-1,
php_auto_globals_create_server TSRMLS_CC);
- zend_register_auto_global("_ENV", sizeof("_ENV")-1,
php_auto_globals_create_env TSRMLS_CC);
- zend_register_auto_global("_REQUEST", sizeof("_REQUEST")-1,
php_auto_globals_create_request TSRMLS_CC);
+ zend_register_auto_global_ex("_SERVER", sizeof("_SERVER")-1,
php_auto_globals_create_server, &php_server_auto_global TSRMLS_CC);
+ zend_register_auto_global_ex("_ENV", sizeof("_ENV")-1,
php_auto_globals_create_env, &php_env_auto_global TSRMLS_CC);
+ zend_register_auto_global_ex("_REQUEST", sizeof("_REQUEST")-1,
php_auto_globals_create_request, &php_request_auto_global TSRMLS_CC);
zend_register_auto_global("_FILES", sizeof("_FILES")-1, NULL TSRMLS_CC);
}
Index: Zend/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.736
diff -u -p -d -r1.736 zend_compile.c
--- Zend/zend_compile.c 20 Jan 2007 20:36:55 -0000 1.736
+++ Zend/zend_compile.c 26 Jan 2007 10:23:12 -0000
@@ -290,7 +290,8 @@ 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;
+ op_array->vars[i].auto_global = NULL;
+ op_array->vars[i].fetch_type = zend_u_is_auto_global(type, name,
name_len, &(op_array->vars[i].auto_global) TSRMLS_CC) ? ZEND_FETCH_AUTO_GLOBAL
: ZEND_FETCH_LOCAL;
return i;
}
@@ -377,18 +378,22 @@ void fetch_simple_variable_ex(znode *res
zend_op opline;
zend_op *opline_ptr;
zend_llist *fetch_list_ptr;
+ long fetch_type = ZEND_FETCH_LOCAL;
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;
+ ZEND_U_EQUAL(Z_TYPE(varname->u.constant),
Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant), "this",
sizeof("this")-1))) {
+ if (zend_u_is_auto_global(Z_TYPE(varname->u.constant),
Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant), NULL TSRMLS_CC)) {
+ fetch_type = ZEND_FETCH_AUTO_GLOBAL;
+ } else if (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;
+ }
}
if (bp) {
@@ -405,15 +410,7 @@ void fetch_simple_variable_ex(znode *res
opline_ptr->op1 = *varname;
*result = opline_ptr->result;
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;
- }
- }
+ opline_ptr->op2.u.EA.type = fetch_type;
if (bp) {
zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
@@ -492,6 +489,31 @@ void fetch_array_dim(znode *result, znod
zend_op opline;
zend_llist *fetch_list_ptr;
+ zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
+ if (fetch_list_ptr->count == 1) {
+ zend_llist_element *le = fetch_list_ptr->head;
+ zend_op *parentop = (zend_op*)le->data;
+
+ if (parentop && parentop->opcode == ZEND_FETCH_W &&
+ (parentop->op2.u.EA.type == ZEND_FETCH_LOCAL ||
+ parentop->op2.u.EA.type == ZEND_FETCH_AUTO_GLOBAL) &&
+ parent->op_type == IS_VAR && parentop->result.op_type
== IS_VAR && parent->u.var == parentop->result.u.var &&
+ parentop->op1.op_type == IS_CONST &&
+ (Z_TYPE(parentop->op1.u.constant) == IS_STRING ||
Z_TYPE(parentop->op1.u.constant) == IS_UNICODE) &&
+ !(Z_UNILEN(parentop->op1.u.constant) ==
(sizeof("this")-1) && ZEND_U_EQUAL(Z_TYPE(parentop->op1.u.constant),
Z_UNIVAL(parentop->op1.u.constant), Z_UNILEN(parentop->op1.u.constant), "this",
sizeof("this")-1)) ) {
+ /* Recompile CV and rewrite previous op to direct
FETCH_DIM */
+ zval tmp = parentop->op1.u.constant;
+ parentop->opcode = ZEND_FETCH_DIM_W;
+ parentop->op1.op_type = IS_CV;
+ parentop->op1.u.var = lookup_cv(CG(active_op_array),
Z_TYPE(tmp), Z_UNIVAL(tmp), Z_UNILEN(tmp) TSRMLS_CC);
+ parentop->op1.u.EA.type = 0;
+ parentop->op2 = *dim;
+ parentop->extended_value = ZEND_FETCH_STANDARD;
+ *result = parentop->result;
+ return;
+ }
+ }
+
init_op(&opline TSRMLS_CC);
opline.opcode = ZEND_FETCH_DIM_W; /* the backpatching routine
assumes W */
opline.result.op_type = IS_VAR;
@@ -502,7 +524,6 @@ void fetch_array_dim(znode *result, znod
opline.extended_value = ZEND_FETCH_STANDARD;
*result = opline.result;
- zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
zend_llist_add_element(fetch_list_ptr, &opline);
}
@@ -3261,7 +3282,6 @@ void zend_do_fetch_property(znode *resul
zend_op *opline_ptr=NULL;
zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
-
if (fetch_list_ptr->count == 1) {
zend_llist_element *le;
@@ -3295,6 +3315,21 @@ void zend_do_fetch_property(znode *resul
}
*result = opline_ptr->result;
return;
+ } else if (opline_ptr && opline_ptr->opcode == ZEND_FETCH_W &&
+ (opline_ptr->op2.u.EA.type == ZEND_FETCH_LOCAL ||
+ opline_ptr->op2.u.EA.type == ZEND_FETCH_AUTO_GLOBAL) &&
+ object->op_type == IS_VAR && opline_ptr->result.op_type
== IS_VAR && object->u.var == opline_ptr->result.u.var &&
+ opline_ptr->op1.op_type == IS_CONST &&
+ (Z_TYPE(opline_ptr->op1.u.constant) == IS_STRING ||
Z_TYPE(opline_ptr->op1.u.constant) == IS_UNICODE) ) {
+ /* Recompile CV and rewrite previous op to direct
FETCH_OBJ */
+ zval tmp = opline_ptr->op1.u.constant;
+ opline_ptr->opcode = ZEND_FETCH_OBJ_W;
+ opline_ptr->op1.op_type = IS_CV;
+ opline_ptr->op1.u.var = lookup_cv(CG(active_op_array),
Z_TYPE(tmp), Z_UNIVAL(tmp), Z_UNILEN(tmp) TSRMLS_CC);
+ opline_ptr->op1.u.EA.type = 0;
+ opline_ptr->op2 = *property;
+ *result = opline_ptr->result;
+ return;
}
}
@@ -4312,13 +4347,16 @@ 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(zend_uchar type, zstr name, uint name_len,
zend_auto_global **pauto 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) {
- auto_global->armed =
auto_global->auto_global_callback(auto_global->name, auto_global->name_len
TSRMLS_CC);
+ auto_global->armed =
auto_global->auto_global_callback(auto_global, ZEND_CT, NULL, 0, NULL
TSRMLS_CC);
+ }
+ if (pauto) {
+ *pauto = auto_global;
}
return 1;
}
@@ -4327,21 +4365,26 @@ zend_bool zend_u_is_auto_global(zend_uch
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(IS_STRING, ZSTR(name), name_len, 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_auto_global **pauto
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.armed = auto_global_callback ? 1 : 0;
- return zend_hash_add(CG(auto_globals), name, name_len+1, &auto_global,
sizeof(zend_auto_global), NULL);
+ return zend_hash_add(CG(auto_globals), name, name_len+1, &auto_global,
sizeof(zend_auto_global), (void**)pauto);
}
+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, NULL 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 26 Jan 2007 10:23:12 -0000
@@ -51,6 +51,7 @@
typedef struct _zend_op_array zend_op_array;
typedef struct _zend_op zend_op;
+typedef struct _zend_auto_global zend_auto_global;
typedef struct _znode {
int op_type;
@@ -175,6 +176,7 @@ typedef struct _zend_compiled_variable {
int name_len;
ulong hash_value;
zend_uint fetch_type;
+ zend_auto_global *auto_global;
} zend_compiled_variable;
struct _zend_op_array {
@@ -575,18 +577,19 @@ ZEND_API char *zend_make_compiled_string
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool
nullify_handlers TSRMLS_DC);
int zend_get_class_fetch_type(zend_uchar type, zstr class_name, uint
class_name_len);
-typedef zend_bool (*zend_auto_global_callback)(char *name, uint name_len
TSRMLS_DC);
-typedef struct _zend_auto_global {
+typedef zend_bool (*zend_auto_global_callback)(zend_auto_global *auto_global,
int stage, zval *ag_val, int fetch_op, zval *member TSRMLS_DC);
+struct _zend_auto_global {
char *name;
uint name_len;
zend_auto_global_callback auto_global_callback;
zend_bool armed;
-} zend_auto_global;
+};
void zend_auto_global_dtor(zend_auto_global *auto_global);
+ZEND_API int zend_register_auto_global_ex(char *name, uint name_len,
zend_auto_global_callback auto_global_callback, zend_auto_global **pauto
TSRMLS_DC);
ZEND_API int zend_register_auto_global(char *name, uint name_len,
zend_auto_global_callback auto_global_callback 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(zend_uchar type, zstr name, uint
name_len, zend_auto_global **pauto 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 26 Jan 2007 10:23:13 -0000
@@ -226,7 +226,7 @@ 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);
+ HashTable *symbol_table = (cv->fetch_type ==
ZEND_FETCH_AUTO_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) {
switch (type) {
@@ -297,7 +297,7 @@ 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);
+ HashTable *symbol_table = (cv->fetch_type ==
ZEND_FETCH_AUTO_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) {
switch (type) {
@@ -905,6 +905,17 @@ static inline HashTable *zend_get_target
case ZEND_FETCH_GLOBAL_LOCK:
return &EG(symbol_table);
break;
+ case ZEND_FETCH_AUTO_GLOBAL:
+ {
+ zend_auto_global *auto_global;
+
+ if (SUCCESS == zend_u_hash_find(CG(auto_globals),
Z_TYPE_P(variable), Z_UNIVAL_P(variable), Z_UNILEN_P(variable) + 1, (void **)
&auto_global) &&
+ auto_global->armed &&
auto_global->auto_global_callback) {
+ auto_global->armed =
auto_global->auto_global_callback(auto_global, ZEND_RT, NULL, ZEND_FETCH_R + (3
* type), NULL TSRMLS_CC);
+ }
+ return &EG(symbol_table);
+ break;
+ }
case ZEND_FETCH_STATIC:
if (!EG(active_op_array)->static_variables) {
ALLOC_HASHTABLE(EG(active_op_array)->static_variables);
@@ -1030,7 +1041,7 @@ fetch_string_dim:
return retval;
}
-static void zend_fetch_dimension_address(temp_variable *result, zval
**container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC)
+static void zend_fetch_dimension_address(znode *container_node, temp_variable
*result, zval **container_ptr, zval *dim, int dim_is_tmp_var, int type
TSRMLS_DC)
{
zval *container;
@@ -1039,6 +1050,13 @@ static void zend_fetch_dimension_address
}
container = *container_ptr;
+ if (container_node->op_type == IS_CV) {
+ zend_auto_global *auto_global =
CV_DEF_OF(container_node->u.var).auto_global;
+
+ if (auto_global && auto_global->armed &&
auto_global->auto_global_callback) {
+ auto_global->armed =
auto_global->auto_global_callback(auto_global, ZEND_RT, container,
ZEND_FETCH_DIM_R + (3 * type), dim TSRMLS_CC);
+ }
+ }
if (container == EG(error_zval_ptr)) {
if (result) {
@@ -1232,11 +1250,19 @@ static void zend_fetch_dimension_address
}
}
-static void zend_fetch_property_address(temp_variable *result, zval
**container_ptr, zval *prop_ptr, int type TSRMLS_DC)
+static void zend_fetch_property_address(znode *container_node, temp_variable
*result, zval **container_ptr, zval *prop_ptr, int type TSRMLS_DC)
{
zval *container;
container = *container_ptr;
+ if (container_node->op_type == IS_CV) {
+ zend_auto_global *auto_global =
CV_DEF_OF(container_node->u.var).auto_global;
+
+ if (auto_global && auto_global->armed &&
auto_global->auto_global_callback) {
+ auto_global->armed =
auto_global->auto_global_callback(auto_global, ZEND_RT, container,
ZEND_FETCH_OBJ_R + (3 * type), prop_ptr TSRMLS_CC);
+ }
+ }
+
if (container == EG(error_zval_ptr)) {
if (result) {
result->var.ptr_ptr = &EG(error_zval_ptr);
Index: Zend/zend_vm_def.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_def.h,v
retrieving revision 1.155
diff -u -p -d -r1.155 zend_vm_def.h
--- Zend/zend_vm_def.h 11 Jan 2007 22:35:36 -0000 1.155
+++ Zend/zend_vm_def.h 26 Jan 2007 10:23:13 -0000
@@ -418,7 +418,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_
zend_op *op_data = opline+1;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
-
zend_fetch_dimension_address(&EX_T(op_data->op2.u.var),
GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW), dim, IS_OP2_TMP_FREE(), BP_VAR_RW TSRMLS_CC);
+
zend_fetch_dimension_address(&opline->op1, &EX_T(op_data->op2.u.var),
GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW), dim, IS_OP2_TMP_FREE(), BP_VAR_RW TSRMLS_CC);
value = get_zval_ptr(&op_data->op1,
EX(Ts), &free_op_data1, BP_VAR_R);
var_ptr =
get_zval_ptr_ptr(&op_data->op2, EX(Ts), &free_op_data2, BP_VAR_RW);
increment_opline = 1;
@@ -978,6 +978,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address
}
switch (opline->op2.u.EA.type) {
case ZEND_FETCH_GLOBAL:
+ case ZEND_FETCH_AUTO_GLOBAL:
if (OP1_TYPE != IS_TMP_VAR) {
FREE_OP1();
}
@@ -1066,7 +1067,7 @@ ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, VA
EX_T(opline->op1.u.var).var.ptr_ptr) {
PZVAL_LOCK(*EX_T(opline->op1.u.var).var.ptr_ptr);
}
-
zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_ZVAL_PTR_PTR(BP_VAR_R), dim, IS_OP2_TMP_FREE(), BP_VAR_R TSRMLS_CC);
+ zend_fetch_dimension_address(&opline->op1,
RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_ZVAL_PTR_PTR(BP_VAR_R), dim, IS_OP2_TMP_FREE(), BP_VAR_R TSRMLS_CC);
FREE_OP2();
FREE_OP1_VAR_PTR();
ZEND_VM_NEXT_OPCODE();
@@ -1078,7 +1079,7 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VA
zend_free_op free_op1, free_op2;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
-
zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_ZVAL_PTR_PTR(BP_VAR_W), dim, IS_OP2_TMP_FREE(), BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&opline->op1,
RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_ZVAL_PTR_PTR(BP_VAR_W), dim, IS_OP2_TMP_FREE(), BP_VAR_W TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && OP1_FREE &&
READY_TO_DESTROY(free_op1.var) &&
@@ -1095,7 +1096,7 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, V
zend_free_op free_op1, free_op2;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
-
zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW), dim, IS_OP2_TMP_FREE(), BP_VAR_RW TSRMLS_CC);
+ zend_fetch_dimension_address(&opline->op1,
RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW), dim, IS_OP2_TMP_FREE(), BP_VAR_RW TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && OP1_FREE &&
READY_TO_DESTROY(free_op1.var) &&
@@ -1112,7 +1113,7 @@ ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, V
zend_free_op free_op1, free_op2;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
-
zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_ZVAL_PTR_PTR(BP_VAR_IS), dim, IS_OP2_TMP_FREE(), BP_VAR_IS TSRMLS_CC);
+ zend_fetch_dimension_address(&opline->op1,
RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_ZVAL_PTR_PTR(BP_VAR_IS), dim, IS_OP2_TMP_FREE(), BP_VAR_IS TSRMLS_CC);
FREE_OP2();
FREE_OP1_VAR_PTR();
ZEND_VM_NEXT_OPCODE();
@@ -1129,7 +1130,7 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
-
zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_ZVAL_PTR_PTR(type), dim, IS_OP2_TMP_FREE(), type TSRMLS_CC);
+ zend_fetch_dimension_address(&opline->op1,
RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_ZVAL_PTR_PTR(type), dim, IS_OP2_TMP_FREE(), type TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && type == BP_VAR_W && OP1_FREE &&
READY_TO_DESTROY(free_op1.var) &&
@@ -1157,7 +1158,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET
SEPARATE_ZVAL_IF_NOT_REF(container);
}
}
-
zend_fetch_dimension_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
container, dim, IS_OP2_TMP_FREE(), BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_dimension_address(&opline->op1,
RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
container, dim, IS_OP2_TMP_FREE(), BP_VAR_UNSET TSRMLS_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR && OP1_FREE &&
READY_TO_DESTROY(free_op1.var) &&
@@ -1218,6 +1219,14 @@ ZEND_VM_HELPER_EX(zend_fetch_property_ad
MAKE_REAL_ZVAL_PTR(offset);
}
+ if (opline->op1.op_type == IS_CV) {
+ zend_auto_global *auto_global =
CV_DEF_OF(opline->op1.u.var).auto_global;
+
+ if (auto_global && auto_global->armed &&
auto_global->auto_global_callback) {
+ auto_global->armed =
auto_global->auto_global_callback(auto_global, ZEND_RT, container,
ZEND_FETCH_OBJ_R + (3 * type), offset TSRMLS_CC);
+ }
+ }
+
/* here we are sure we are dealing with an object */
*retval = Z_OBJ_HT_P(container)->read_property(container,
offset, type TSRMLS_CC);
@@ -1259,7 +1268,7 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VA
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
-
zend_fetch_property_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W), property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&opline->op1,
RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W), property, BP_VAR_W TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(&property);
} else {
@@ -1283,7 +1292,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, V
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
-
zend_fetch_property_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW), property, BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(&opline->op1,
RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW), property, BP_VAR_RW TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(&property);
} else {
@@ -1315,7 +1324,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
-
zend_fetch_property_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W), property, BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(&opline->op1,
RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W), property, BP_VAR_W TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(&property);
} else {
@@ -1348,7 +1357,7 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET
if (IS_OP2_TMP_FREE()) {
MAKE_REAL_ZVAL_PTR(property);
}
-
zend_fetch_property_address(RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
container, property, BP_VAR_R TSRMLS_CC);
+ zend_fetch_property_address(&opline->op1,
RETURN_VALUE_UNUSED(&opline->result)?NULL:&EX_T(opline->result.u.var),
container, property, BP_VAR_R TSRMLS_CC);
if (IS_OP2_TMP_FREE()) {
zval_ptr_dtor(&property);
} else {
@@ -1428,7 +1437,7 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VA
zval *value;
zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
- zend_fetch_dimension_address(&EX_T(op_data->op2.u.var),
object_ptr, dim, IS_OP2_TMP_FREE(), BP_VAR_W TSRMLS_CC);
+ zend_fetch_dimension_address(&opline->op1,
&EX_T(op_data->op2.u.var), object_ptr, dim, IS_OP2_TMP_FREE(), BP_VAR_W
TSRMLS_CC);
FREE_OP2();
value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1,
BP_VAR_R);
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php