# Runtime-JIT, the whole enchilada

- Thread: https://externals.io/message/27639
- Original archive: https://news-web.php.net/php.internals/27639
- Started by Sara Golemon on 2007-01-24T19:58:14+00:00
- Messages: 6
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #27639 — Sara Golemon — 2007-01-24T19:58:14+00:00

URL: https://externals.io/message/27639#27639

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

---

## #27640 — Ilia Alshanetsky — 2007-01-24T21:27:44+00:00

URL: https://externals.io/message/27639#27640 · In reply to: #27639

What are the numbers before the patch?



> 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: Zend/zend_compile.c
> ===================================================================
> RCS file: /repository/ZendEngine2/zend_compile.c,v
> retrieving revision 1.736
> diff -u -p -r1.736 zend_compile.c
> --- Zend/zend_compile.c	20 Jan 2007 20:36:55 -0000	1.736
> +++ Zend/zend_compile.c	24 Jan 2007 19:50:52 -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_GLOBAL : ZEND_FETCH_LOCAL;
>  	return i;
>  }
>
> @@ -383,6 +384,7 @@ void fetch_simple_variable_ex(znode *res
>  	     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- 
> > […]
> ("this")-1)) &&
> +	    !zend_u_is_auto_global(Z_TYPE(varname->u.constant), Z_UNIVAL 
> (varname->u.constant), Z_UNILEN(varname->u.constant), `NULL`  
> TSRMLS_CC) &&
>  	    (CG(active_op_array)->last == 0 ||
>  	     CG(active_op_array)->opcodes[CG(active_op_array)- 
> > […]
>  		result->op_type = IS_CV;
> @@ -410,7 +412,7 @@ void fetch_simple_variable_ex(znode *res
>  	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)) {
> +		if (zend_u_is_auto_global(Z_TYPE(varname->u.constant), Z_UNIVAL 
> (varname->u.constant), Z_UNILEN(varname->u.constant), `NULL`  
> TSRMLS_CC)) {
>  			opline_ptr->op2.u.EA.type = ZEND_FETCH_GLOBAL;
>  		}
>  	}
> @@ -492,6 +494,29 @@ 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 &&
> +			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- 
> > […]
> ("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 +527,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 +3285,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 +3318,19 @@ void zend_do_fetch_property(znode *resul
>  			}
>  			*result = opline_ptr->result;
>  			return;
> +		} else if (opline_ptr && opline_ptr->opcode == ZEND_FETCH_W &&
> +			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 +4348,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 +4366,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 -r1.353 zend_compile.h
> --- Zend/zend_compile.h	20 Jan 2007 20:36:55 -0000	1.353
> +++ Zend/zend_compile.h	24 Jan 2007 19:50:52 -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);
> Index: Zend/zend_execute.c
> ===================================================================
> RCS file: /repository/ZendEngine2/zend_execute.c,v
> retrieving revision 1.758
> diff -u -p -r1.758 zend_execute.c
> --- Zend/zend_execute.c	20 Jan 2007 20:36:55 -0000	1.758
> +++ Zend/zend_execute.c	24 Jan 2007 19:50:52 -0000
> @@ -903,8 +903,17 @@ static inline HashTable *zend_get_target
>  			break;
>  		case ZEND_FETCH_GLOBAL:
>  		case ZEND_FETCH_GLOBAL_LOCK:
> +		{
> +			zend_auto_global *auto_global;
> +
> +			if ((Z_TYPE_P(variable) == IS_STRING || Z_TYPE_P(variable) ==  
> IS_UNICODE) &&
> +				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 +1039,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 +1048,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- 
> > […]
> +
> +		if (auto_global && auto_global->armed && auto_global- 
> > […]
> +			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 +1248,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- 
> > […]
> +
> +		if (auto_global && auto_global->armed && auto_global- 
> > […]
> +			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 -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	24 Jan 2007 19:50:52 -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- 
> > […]
> (), 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;
> @@ -1066,7 +1066,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 +1078,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 +1095,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 +1112,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 +1129,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 +1157,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 +1218,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- 
> > […]
> +
> +			if (auto_global && auto_global->armed && auto_global- 
> > […]
> +				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 +1267,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 +1291,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 +1323,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 +1356,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 +1436,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- 
> > […]
>  		FREE_OP2();
>
>  		value = get_zval_ptr(&op_data->op1, EX(Ts), &free_op_data1,  
> BP_VAR_R);
> Index: main/php_variables.c
> ===================================================================
> RCS file: /repository/php-src/main/php_variables.c,v
> retrieving revision 1.136
> diff -u -p -r1.136 php_variables.c
> --- main/php_variables.c	1 Jan 2007 09:29:35 -0000	1.136
> +++ main/php_variables.c	24 Jan 2007 19:50:52 -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);
>  }
>
>
> -- 
> 
> 

Ilia Alshanetsky

---

## #27668 — Dmitry Stogov — 2007-01-26T14:32:05+00:00

URL: https://externals.io/message/27639#27668 · In reply to: #27639

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:pollita@php.net] 
> Sent: Wednesday, January 24, 2007 10:58 PM
> To: internals@lists.php.net; 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

---

## #27669 — Pierre — 2007-01-26T14:37:57+00:00

URL: https://externals.io/message/27639#27669 · In reply to: #27668

Hi Dmitry,


> 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?

As I already told you in my initial proposal (which is simpler than
this solution), they do not work in all cases (check the various bugs
about them) and they will bring a huge breakage as is_array($objarray)
returns false. The later is certainly fixable (with slowness too), I'm
not sure about the other issues.

--Pierre

---

## #27675 — Sara Golemon — 2007-01-26T17:10:14+00:00

URL: https://externals.io/message/27639#27675 · In reply to: #27668

> I fixed one error in your patch, so now it passes all tests.
> 
Which error?  I notice some changes related to minimizing performance 
impact, but I'm not seeing what I did wrong.  Just curious for my own 
benefit on that one.

> BTW I am against this patch.
> 
Fair enough.

> 1) It adds sloppily built functionality into the core 
Well, you sure know how to sweet-talk a gal.

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.
> 
For disarmed callbacks, it amounts to a vector lookup and a couple 
integer compares, I'd hardly call that a "big cost".  As to armed 
callbacks, well, if they're still armed then they still have some work 
to do.  Refer to prior posts in the thread as to why this work would 
(and should) be deferred.

> 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).
> 
Excellent point.  That will need to be addressed....

> Why did you reject auto-globals as overloaded arrays?
>
See earlier posts in this thread, such as the one I sent you less than a 
week ago and to which you replied indicating you understood it.

If you thinking breaking BC is preferable to this "sloppy" approach, 
then we can reexamine that.  If you have a better, third approach, which 
solves all of the issues already outlined, then I'd love to hear it.

-Sara

---

## #27676 — Sara Golemon — 2007-01-26T17:10:35+00:00

URL: https://externals.io/message/27639#27676 · In reply to: #27668

> I fixed one error in your patch, so now it passes all tests.
> 
Which error?  I notice some changes related to minimizing performance 
impact, but I'm not seeing what I did wrong.  Just curious for my own 
benefit on that one.

> BTW I am against this patch.
> 
Fair enough.

> 1) It adds sloppily built functionality into the core 
Well, you sure know how to sweet-talk a gal.

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.
> 
For disarmed callbacks, it amounts to a vector lookup and a couple 
integer compares, I'd hardly call that a "big cost".  As to armed 
callbacks, well, if they're still armed then they still have some work 
to do.  Refer to prior posts in the thread as to why this work would 
(and should) be deferred.

> 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).
> 
Excellent point.  That will need to be addressed....

> Why did you reject auto-globals as overloaded arrays?
>
See earlier posts in this thread, such as the one I sent you less than a 
week ago and to which you replied indicating you understood it.

If you thinking breaking BC is preferable to this "sloppy" approach, 
then we can reexamine that.  If you have a better, third approach, which 
solves all of the issues already outlined, then I'd love to hear it.

-Sara
