diff options
| -rw-r--r-- | Zend/zend-parser.y | 20 | ||||
| -rw-r--r-- | Zend/zend.h | 20 | ||||
| -rw-r--r-- | Zend/zend_API.c | 74 | ||||
| -rw-r--r-- | Zend/zend_API.h | 12 | ||||
| -rw-r--r-- | Zend/zend_compile.c | 18 | ||||
| -rw-r--r-- | Zend/zend_compile.h | 10 | ||||
| -rw-r--r-- | Zend/zend_execute.c | 85 | ||||
| -rw-r--r-- | Zend/zend_execute_API.c | 26 | ||||
| -rw-r--r-- | Zend/zend_opcode.c | 4 | ||||
| -rw-r--r-- | Zend/zend_operators.c | 3 | ||||
| -rw-r--r-- | Zend/zend_variables.c | 12 | 
11 files changed, 151 insertions, 133 deletions
| diff --git a/Zend/zend-parser.y b/Zend/zend-parser.y index 1a0b3c32d6..b172509e79 100644 --- a/Zend/zend-parser.y +++ b/Zend/zend-parser.y @@ -272,11 +272,11 @@ parameter_list:  non_empty_parameter_list: -		T_VARIABLE						{ znode tmp;  fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.EA=0; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); } -	|	'&' T_VARIABLE					{ znode tmp;  fetch_simple_variable(&tmp, &$2, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.EA=0; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_FORCE CLS_CC); } -	|	T_CONST T_VARIABLE 			{ znode tmp;  fetch_simple_variable(&tmp, &$2, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.EA=0; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); } -	|	T_VARIABLE '=' static_scalar		{ znode tmp;  fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.EA=0; do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$3, BYREF_NONE CLS_CC); } -	|	T_VARIABLE '=' T_UNSET 		{ znode tmp;  fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.EA=0; do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, NULL, BYREF_NONE CLS_CC); } +		T_VARIABLE						{ znode tmp;  fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); } +	|	'&' T_VARIABLE					{ znode tmp;  fetch_simple_variable(&tmp, &$2, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_FORCE CLS_CC); } +	|	T_CONST T_VARIABLE 			{ znode tmp;  fetch_simple_variable(&tmp, &$2, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); } +	|	T_VARIABLE '=' static_scalar		{ znode tmp;  fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$3, BYREF_NONE CLS_CC); } +	|	T_VARIABLE '=' T_UNSET 		{ znode tmp;  fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=1; $$.u.constant.type=IS_LONG; INIT_PZVAL(&$$.u.constant); do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, NULL, BYREF_NONE CLS_CC); }  	|	non_empty_parameter_list ',' T_VARIABLE 						{ znode tmp;  fetch_simple_variable(&tmp, &$3, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); }  	|	non_empty_parameter_list ',' '&' T_VARIABLE					{ znode tmp;  fetch_simple_variable(&tmp, &$4, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_FORCE CLS_CC); }  	|	non_empty_parameter_list ',' T_CONST T_VARIABLE			{ znode tmp;  fetch_simple_variable(&tmp, &$4, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); } @@ -396,8 +396,8 @@ expr_without_variable:  	|	expr '%' expr 	{ do_binary_op(ZEND_MOD,&$$,&$1,&$3 CLS_CC); }  	| 	expr T_SL expr { do_binary_op(ZEND_SL, &$$, &$1, &$3 CLS_CC); }  	|	expr T_SR expr { do_binary_op(ZEND_SR, &$$, &$1, &$3 CLS_CC); } -	|	'+' expr { $1.u.constant.value.lval=0; $1.u.constant.type=IS_LONG; $1.op_type = IS_CONST; $1.u.constant.refcount=1; do_binary_op(ZEND_ADD, &$$, &$1, &$2 CLS_CC); } -	|	'-' expr { $1.u.constant.value.lval=0; $1.u.constant.type=IS_LONG; $1.op_type = IS_CONST; $1.u.constant.refcount=1; do_binary_op(ZEND_SUB, &$$, &$1, &$2 CLS_CC); } +	|	'+' expr { $1.u.constant.value.lval=0; $1.u.constant.type=IS_LONG; $1.op_type = IS_CONST; INIT_PZVAL(&$1.u.constant); do_binary_op(ZEND_ADD, &$$, &$1, &$2 CLS_CC); } +	|	'-' expr { $1.u.constant.value.lval=0; $1.u.constant.type=IS_LONG; $1.op_type = IS_CONST; INIT_PZVAL(&$1.u.constant); do_binary_op(ZEND_SUB, &$$, &$1, &$2 CLS_CC); }  	|	'!' expr { do_unary_op(ZEND_BOOL_NOT, &$$, &$2 CLS_CC); }  	|	'~' expr { do_unary_op(ZEND_BW_NOT, &$$, &$2 CLS_CC); }  	|	expr T_IS_EQUAL expr				{ do_binary_op(ZEND_IS_EQUAL, &$$, &$1, &$3 CLS_CC); } @@ -484,7 +484,7 @@ scalar:  static_array_pair_list: -		/* empty */ 						{ $$.op_type = IS_CONST; $$.u.constant.refcount=1; $$.u.constant.EA=0; array_init(&$$.u.constant); } +		/* empty */ 						{ $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); }  	|	non_empty_static_array_pair_list	{ $$ = $1; }  ; @@ -492,8 +492,8 @@ static_array_pair_list:  non_empty_static_array_pair_list:  		non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW static_scalar	{ do_add_static_array_element(&$$, &$3, &$5); }  	|	non_empty_static_array_pair_list ',' static_scalar		{ do_add_static_array_element(&$$, NULL, &$3); } -	|	static_scalar T_DOUBLE_ARROW static_scalar	{ $$.op_type = IS_CONST; $$.u.constant.refcount=1; $$.u.constant.EA=0; array_init(&$$.u.constant); do_add_static_array_element(&$$, &$1, &$3); } -	|	static_scalar 									{ $$.op_type = IS_CONST; $$.u.constant.refcount=1; $$.u.constant.EA=0; array_init(&$$.u.constant); do_add_static_array_element(&$$, NULL, &$1); } +	|	static_scalar T_DOUBLE_ARROW static_scalar	{ $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); do_add_static_array_element(&$$, &$1, &$3); } +	|	static_scalar 									{ $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); array_init(&$$.u.constant); do_add_static_array_element(&$$, NULL, &$1); }  ;  expr: diff --git a/Zend/zend.h b/Zend/zend.h index 571802fbf0..cc5921162a 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -91,7 +91,10 @@ struct _zval_struct {  	/* Variable information */  	zvalue_value value;		/* value */  	unsigned char type;	/* active type */ -	unsigned char EA; +	struct { +		unsigned int locks:7; +		unsigned int is_ref:1; +	} EA;  	short refcount;  }; @@ -172,12 +175,6 @@ typedef struct _zend_utility_values {  #define IS_CONSTANT	9  #define IS_METHOD	10 /* for overloaded function calls */ -#define MAKE_STD_ZVAL(zv) \ -	zv = (zval *) emalloc(sizeof(zval)); \ -	zv->refcount = 1; \ -	zv->EA = 0; - -  int zend_startup(zend_utility_functions *utility_functions, char **extensions);  void zend_shutdown(); @@ -235,4 +232,13 @@ extern zend_utility_values zend_uv;  #define ZMSG_MEMORY_LEAK_REPEATED		6L  #define ZMSG_LOG_SCRIPT_NAME		7L +#define INIT_PZVAL(z)		\ +	(z)->refcount = 1;		\ +	(z)->EA.is_ref = 0;		\ +	(z)->EA.locks = 0; + +#define MAKE_STD_ZVAL(zv) \ +	zv = (zval *) emalloc(sizeof(zval)); \ +	INIT_PZVAL(zv); +  #endif /* _ZEND_H */ diff --git a/Zend/zend_API.c b/Zend/zend_API.c index c348497f40..26a8efdad3 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -58,8 +58,7 @@ ZEND_API int getParameters(int ht, int param_count,...)  			new_tmp = (zval *) emalloc(sizeof(zval));  			*new_tmp = *param_ptr;  			zval_copy_ctor(new_tmp); -			new_tmp->refcount = 1; -			new_tmp->EA = 0; +			INIT_PZVAL(new_tmp);  			param_ptr = new_tmp;  			((zval *) *(p-param_count))->refcount--;  			*(p-param_count) = param_ptr; @@ -96,8 +95,7 @@ ZEND_API int getParametersArray(int ht, int param_count, zval **argument_array)  			new_tmp = (zval *) emalloc(sizeof(zval));  			*new_tmp = *param_ptr;  			zval_copy_ctor(new_tmp); -			new_tmp->refcount = 1; -			new_tmp->EA = 0; +			INIT_PZVAL(new_tmp);  			param_ptr = new_tmp;  			((zval *) *(p-param_count))->refcount--;  			*(p-param_count) = param_ptr; @@ -230,8 +228,7 @@ ZEND_API inline int add_assoc_long(zval *arg, char *key, long n)  	tmp->type = IS_LONG;  	tmp->value.lval = n; -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_update(arg->value.ht, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL);  } @@ -242,8 +239,7 @@ ZEND_API inline int add_assoc_double(zval *arg, char *key, double d)  	tmp->type = IS_DOUBLE;  	tmp->value.dval = d; -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_update(arg->value.ht, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL);  } @@ -259,8 +255,7 @@ ZEND_API inline int add_assoc_string(zval *arg, char *key, char *str, int duplic  	} else {  		tmp->value.str.val = str;  	} -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_update(arg->value.ht, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL);  } @@ -276,8 +271,7 @@ ZEND_API inline int add_assoc_stringl(zval *arg, char *key, char *str, uint leng  	} else {  		tmp->value.str.val = str;  	} -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_update(arg->value.ht, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL);  } @@ -295,8 +289,7 @@ ZEND_API inline int add_index_long(zval *arg, uint index, long n)  	tmp->type = IS_LONG;  	tmp->value.lval = n; -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),NULL);  } @@ -307,8 +300,7 @@ ZEND_API inline int add_index_double(zval *arg, uint index, double d)  	tmp->type = IS_DOUBLE;  	tmp->value.dval = d; -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),NULL);  } @@ -324,8 +316,7 @@ ZEND_API inline int add_index_string(zval *arg, uint index, char *str, int dupli  	} else {  		tmp->value.str.val = str;  	} -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *), NULL);  } @@ -341,8 +332,7 @@ ZEND_API inline int add_index_stringl(zval *arg, uint index, char *str, uint len  	} else {  		tmp->value.str.val = str;  	} -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),NULL);  } @@ -353,8 +343,7 @@ ZEND_API inline int add_next_index_long(zval *arg, long n)  	tmp->type = IS_LONG;  	tmp->value.lval = n; -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_next_index_insert(arg->value.ht, &tmp, sizeof(zval *), NULL);  } @@ -365,8 +354,7 @@ ZEND_API inline int add_next_index_double(zval *arg, double d)  	tmp->type = IS_DOUBLE;  	tmp->value.dval = d; -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_next_index_insert(arg->value.ht, &tmp, sizeof(zval *), NULL);  } @@ -382,8 +370,7 @@ ZEND_API inline int add_next_index_string(zval *arg, char *str, int duplicate)  	} else {  		tmp->value.str.val = str;  	} -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_next_index_insert(arg->value.ht, &tmp, sizeof(zval *),NULL);  } @@ -399,8 +386,7 @@ ZEND_API inline int add_next_index_stringl(zval *arg, char *str, uint length, in  	} else {  		tmp->value.str.val = str;  	} -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_next_index_insert(arg->value.ht, &tmp, sizeof(zval *),NULL);  } @@ -416,8 +402,7 @@ ZEND_API inline int add_get_assoc_string(zval *arg, char *key, char *str, void *  	} else {  		tmp->value.str.val = str;  	} -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_update(arg->value.ht, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), dest);  } @@ -433,8 +418,7 @@ ZEND_API inline int add_get_assoc_stringl(zval *arg, char *key, char *str, uint  	} else {  		tmp->value.str.val = str;  	} -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_update(arg->value.ht, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), dest);  } @@ -444,9 +428,8 @@ ZEND_API inline int add_get_index_long(zval *arg, uint index, long l, void **des  	zval *tmp = (zval *) emalloc(sizeof(zval));  	tmp->type = IS_LONG; -	tmp->value.lval= l; -	tmp->refcount=1; -	tmp->EA=0; +	tmp->value.lval = l; +	INIT_PZVAL(tmp);  	return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),dest);  } @@ -457,8 +440,7 @@ ZEND_API inline int add_get_index_double(zval *arg, uint index, double d, void *  	tmp->type = IS_DOUBLE;  	tmp->value.dval= d; -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),dest);  } @@ -474,8 +456,7 @@ ZEND_API inline int add_get_index_string(zval *arg, uint index, char *str, void  	} else {  		tmp->value.str.val = str;  	} -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),dest);  } @@ -491,8 +472,7 @@ ZEND_API inline int add_get_index_stringl(zval *arg, uint index, char *str, uint  	} else {  		tmp->value.str.val = str;  	} -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),dest);  } @@ -503,8 +483,7 @@ ZEND_API inline int add_property_long(zval *arg, char *key, long n)  	tmp->type = IS_LONG;  	tmp->value.lval = n; -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_update(arg->value.obj.properties, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL);  } @@ -515,8 +494,7 @@ ZEND_API inline int add_property_double(zval *arg, char *key, double d)  	tmp->type = IS_DOUBLE;  	tmp->value.dval = d; -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_update(arg->value.obj.properties, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL);  } @@ -532,8 +510,7 @@ ZEND_API inline int add_property_string(zval *arg, char *key, char *str, int dup  	} else {  		tmp->value.str.val = str;  	} -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_update(arg->value.obj.properties, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL);  } @@ -549,8 +526,7 @@ ZEND_API inline int add_property_stringl(zval *arg, char *key, char *str, uint l  	} else {  		tmp->value.str.val = str;  	} -	tmp->refcount=1; -	tmp->EA=0; +	INIT_PZVAL(tmp);  	return zend_hash_update(arg->value.obj.properties, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL);  } diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 85eb885de3..dc9f85b929 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -186,8 +186,7 @@ ZEND_API int add_property_stringl(zval *arg, char *key, char *str, uint length,  									var->value.str.val = (str); \  									var->value.str.len = strlen((str)); \  									var->type = IS_STRING; \ -									var->EA=0; \ -									var->refcount=1; \ +									INIT_PZVAL(var); \  									zend_hash_update(&EG(symbol_table), (n), strlen((n))+1, &var, sizeof(zval *), NULL); \  								} \  							} @@ -199,8 +198,7 @@ ZEND_API int add_property_stringl(zval *arg, char *key, char *str, uint length,  										var->value.str.val = (v); \  										var->value.str.len = (l); \  										var->type = IS_STRING; \ -										var->EA=0; \ -										var->refcount=1; \ +										INIT_PZVAL(var); \  										zend_hash_update(&EG(symbol_table), name, strlen(name)+1, &var, sizeof(zval *), NULL); \  									} \  								} @@ -210,8 +208,7 @@ ZEND_API int add_property_stringl(zval *arg, char *key, char *str, uint length,  									\  									var->value.lval = (v); \  									var->type = IS_LONG; \ -									var->EA=0; \ -									var->refcount=1; \ +									INIT_PZVAL(var); \  									zend_hash_update(&EG(symbol_table), (n), strlen((n))+1, &var, sizeof(zval *), NULL); \  								} \  							} @@ -221,8 +218,7 @@ ZEND_API int add_property_stringl(zval *arg, char *key, char *str, uint length,  									\  									var->value.dval = (v); \  									var->type = IS_DOUBLE; \ -									var->EA=0; \ -									var->refcount=1; \ +									INIT_PZVAL(var); \  									zend_hash_update(&EG(symbol_table)), (n), strlen((n))+1, &var, sizeof(zval *), NULL); \  								} \  							} diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index d12b504a2d..619bb8cc1b 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -839,8 +839,7 @@ void do_return(znode *expr CLS_DC)  	} else {  		var_uninit(&opline->op1.u.constant);  		opline->op1.op_type = IS_CONST; -		opline->op1.u.constant.refcount=1; -		opline->op1.u.constant.EA=0; +		INIT_PZVAL(&opline->op1.u.constant);  	}  	SET_UNUSED(opline->op2);  } @@ -1038,8 +1037,7 @@ void do_brk_cont(int op, znode *expr CLS_DC)  	} else {  		opline->op2.u.constant.type = IS_LONG;  		opline->op2.u.constant.value.lval = 1; -		opline->op2.u.constant.refcount=1; -		opline->op2.u.constant.EA=0; +		INIT_PZVAL(&opline->op2.u.constant);  		opline->op2.op_type = IS_CONST;  	}  } @@ -1189,8 +1187,7 @@ void do_default_before_statement(znode *case_list, znode *default_token CLS_DC)  	opline->op1.op_type = IS_CONST;  	opline->op1.u.constant.type = IS_LONG;  	opline->op1.u.constant.value.lval = 1; -	opline->op1.u.constant.refcount=1; -	opline->op1.u.constant.EA=0; +	INIT_PZVAL(&opline->op1.u.constant);  	SET_UNUSED(opline->op2);  	switch_entry_ptr->default_case = next_op_number; @@ -1422,8 +1419,7 @@ void do_shell_exec(znode *result, znode *cmd CLS_DC)  	opline->result.op_type = IS_TMP_VAR;  	opline->op1.u.constant.value.str.val = estrndup("shell_exec",sizeof("shell_exec")-1);  	opline->op1.u.constant.value.str.len = sizeof("shell_exec")-1; -	opline->op1.u.constant.refcount = 1; -	opline->op1.u.constant.EA = 0; +	INIT_PZVAL(&opline->op1.u.constant);  	opline->op1.u.constant.type = IS_STRING;  	opline->op1.op_type = IS_CONST;  	opline->extended_value = 1; @@ -1561,8 +1557,7 @@ void do_list_end(znode *result, znode *expr CLS_DC)  			opline->op2.op_type = IS_CONST;  			opline->op2.u.constant.type = IS_LONG;  			opline->op2.u.constant.value.lval = *((int *) dimension->data); -			opline->op2.u.constant.refcount = 1; -			opline->op2.u.constant.EA = 0; +			INIT_PZVAL(&opline->op2.u.constant);  			if (le == CG(list_llist).tail) {  				opline->extended_value = ZEND_FETCH_STANDARD;  			} else { @@ -1972,8 +1967,7 @@ int zendlex(znode *zendlval CLS_DC)  			break;  	} -	zendlval->u.constant.refcount = 1; -	zendlval->u.constant.EA = 0; +	INIT_PZVAL(&zendlval->u.constant);  	zendlval->op_type = IS_CONST;  	return retval;  } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 806ce24fac..1ed2b1b644 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -545,11 +545,11 @@ int zendlex(znode *zendlval CLS_DC);  #define ZEND_CTOR_CALL			1<<1 -/* Extended attributes for zval */ -#define ZEND_EA_IS_REF		(0<<1L) -#define ZEND_EA_LOCKED		(0<<2L) +#define PZVAL_IS_REF(z)		((z)->EA.is_ref) +#define PZVAL_IS_LOCKED(z)	((z)->EA.locks>0) + +#define PZVAL_LOCK(z)	(z)->EA.locks++ +#define PZVAL_UNLOCK(z)	(z)->EA.locks-- -#define PZVAL_IS_REF(z)		((z)->EA & ZEND_EA_IS_REF) -#define PZVAL_IS_LOCKED(z)	((z)->EA & ZEND_EA_LOCKED)  #endif /* _COMPILE_H */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index b53cb5621a..c6551253c1 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -86,6 +86,7 @@ static inline zval *_get_zval_ptr(znode *node, temp_variable *Ts, int *should_fr  		case IS_VAR:  			if (Ts[node->u.var].var) {  				DEC_AI_COUNT(); +				PZVAL_UNLOCK(*Ts[node->u.var].var);  				*should_free = 0;  				return *Ts[node->u.var].var;  			} else { @@ -95,7 +96,8 @@ static inline zval *_get_zval_ptr(znode *node, temp_variable *Ts, int *should_fr  					case IS_OVERLOADED_OBJECT:  						Ts[node->u.var].tmp_var = get_overloaded_property(ELS_C);  						Ts[node->u.var].tmp_var.refcount=1; -						Ts[node->u.var].tmp_var.EA=1; +						Ts[node->u.var].tmp_var.EA.is_ref=1; +						Ts[node->u.var].tmp_var.EA.locks=0;  						return &Ts[node->u.var].tmp_var;  						break;  					case IS_STRING_OFFSET: { @@ -114,7 +116,8 @@ static inline zval *_get_zval_ptr(znode *node, temp_variable *Ts, int *should_fr  							}  							zval_ptr_dtor(&str);  							T->tmp_var.refcount=1; -							T->tmp_var.EA=1; +							T->tmp_var.EA.is_ref=1; +							T->tmp_var.EA.locks=0;  							T->tmp_var.type = IS_STRING;  							return &T->tmp_var;  						} @@ -141,6 +144,7 @@ static inline zval **_get_zval_ptr_ptr(znode *node, temp_variable *Ts ELS_DC)  		case IS_VAR:  			if (Ts[node->u.var].var) {  				DEC_AI_COUNT(); +				PZVAL_UNLOCK(*Ts[node->u.var].var);  			}  			return Ts[node->u.var].var;  			break; @@ -207,6 +211,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2  {  	zval **variable_ptr_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W);  	zval *variable_ptr; +	int previous_lock_count;  	if (!variable_ptr_ptr) {  		switch (Ts[op1->u.var].EA.type) { @@ -251,6 +256,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2  		}  		Ts[result->u.var].var = &EG(uninitialized_zval_ptr);  		INC_AI_COUNT(result); +		/* No need to lock anything */  		return;  	} @@ -260,6 +266,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2  		if (result) {  			Ts[result->u.var].var = &EG(uninitialized_zval_ptr);  			INC_AI_COUNT(result); +			/* No need to lock anything */  		}  		return;  	} @@ -268,10 +275,12 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2  		if (variable_ptr!=value) {  			short refcount=variable_ptr->refcount; +			previous_lock_count = variable_ptr->EA.locks;  			zendi_zval_dtor(*variable_ptr);  			*variable_ptr = *value;  			variable_ptr->refcount = refcount; -			variable_ptr->EA = ZEND_EA_IS_REF; +			variable_ptr->EA.is_ref = 1; +			variable_ptr->EA.locks = previous_lock_count;  			if (type!=IS_TMP_VAR) {  				zendi_zval_copy_ctor(*variable_ptr);  			} @@ -287,9 +296,11 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2  					} else if (PZVAL_IS_REF(value)) {  						zval tmp = *value; +						previous_lock_count = variable_ptr->EA.locks;  						tmp = *value;  						zval_copy_ctor(&tmp);  						tmp.refcount=1; +						tmp.EA.locks = previous_lock_count;  						zendi_zval_dtor(*variable_ptr);  						*variable_ptr = tmp;  					} else { @@ -303,6 +314,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2  					zendi_zval_dtor(*variable_ptr);  					value->refcount=1;  					*variable_ptr = *value; +					variable_ptr->EA.locks = previous_lock_count;  					break;  			}  		} else { /* we need to split */ @@ -314,6 +326,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2  						*variable_ptr = *value;  						zval_copy_ctor(variable_ptr);  						variable_ptr->refcount=1; +						variable_ptr->EA.locks = previous_lock_count;  						break;  					}  					*variable_ptr_ptr = value; @@ -322,16 +335,18 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2  				case IS_TMP_VAR:  					(*variable_ptr_ptr) = (zval *) emalloc(sizeof(zval));  					value->refcount=1; +					value->EA.locks = 0;  					**variable_ptr_ptr = *value;  					break;  			}  		} -		(*variable_ptr_ptr)->EA=0; +		(*variable_ptr_ptr)->EA.is_ref=0;  	}  	if (result) {  		Ts[result->u.var].var = variable_ptr_ptr;  		INC_AI_COUNT(result); -	} +		PZVAL_LOCK(*variable_ptr_ptr); +	}   } @@ -431,6 +446,7 @@ static inline void zend_fetch_var_address(znode *result, znode *op1, znode *op2,  	}  	Ts[result->u.var].var = retval;	  	INC_AI_COUNT(result); +	PZVAL_LOCK(*retval);  } @@ -550,6 +566,7 @@ static inline void zend_fetch_dimension_address(znode *result, znode *op1, znode  	if (container == EG(error_zval_ptr)) {  		INC_AI_COUNT(result); +		/* No need to lock anything */  		*retval = &EG(error_zval_ptr);  		return;  	} @@ -562,7 +579,8 @@ static inline void zend_fetch_dimension_address(znode *result, znode *op1, znode  					container->refcount--;  					if (container->refcount>0) {  						container = *container_ptr = (zval *) emalloc(sizeof(zval)); -						container->EA=0; +						container->EA.is_ref=0; +						container->EA.locks = 0;  					}  					container->refcount=1;  				} @@ -578,8 +596,7 @@ static inline void zend_fetch_dimension_address(znode *result, znode *op1, znode  				*container_ptr = (zval *) emalloc(sizeof(zval));  				**container_ptr = *container;  				container = *container_ptr; -				container->refcount=1; -				container->EA=0; +				INIT_PZVAL(container);  				zendi_zval_copy_ctor(*container);  			}  			if (op2->op_type == IS_UNUSED) { @@ -590,6 +607,7 @@ static inline void zend_fetch_dimension_address(znode *result, znode *op1, znode  			} else {  				*retval = zend_fetch_dimension_address_inner(container->value.ht, op2, Ts, type ELS_CC);  			} +			PZVAL_LOCK(**retval);  			break;  		case IS_STRING: {  				zval *offset; @@ -632,6 +650,7 @@ static inline void zend_fetch_dimension_address(znode *result, znode *op1, znode  			break;  	}  	INC_AI_COUNT(result); +	/* Relevant cases handled above */  } @@ -642,12 +661,14 @@ static inline void zend_fetch_dimension_address_from_tmp_var(znode *result, znod  	if (container->type != IS_ARRAY) {  		INC_AI_COUNT(result); +		/* No need to lock anything */  		Ts[result->u.var].var = &EG(uninitialized_zval_ptr);  		return;  	}  	INC_AI_COUNT(result);  	Ts[result->u.var].var = zend_fetch_dimension_address_inner(container->value.ht, op2, Ts, BP_VAR_R ELS_CC); +	PZVAL_LOCK(*Ts[result->u.var].var);  } @@ -695,6 +716,7 @@ static inline void zend_fetch_property_address(znode *result, znode *op1, znode  	container = *container_ptr;  	if (container == EG(error_zval_ptr)) {  		INC_AI_COUNT(result); +		/* No need to lock anything */  		*retval = &EG(error_zval_ptr);  		return;  	} @@ -729,7 +751,8 @@ static inline void zend_fetch_property_address(znode *result, znode *op1, znode  					container->refcount--;  					if (container->refcount>0) {  						container = *container_ptr = (zval *) emalloc(sizeof(zval)); -						container->EA=0; +						container->EA.is_ref=0; +						container->EA.locks = 0;  					}  					container->refcount=1;  				} @@ -744,6 +767,7 @@ static inline void zend_fetch_property_address(znode *result, znode *op1, znode  		offset = get_zval_ptr(op2, Ts, &free_op2, BP_VAR_R);  		FREE_OP(op2, free_op2);  		INC_AI_COUNT(result); +		/* No need to lock anything */  		if (type==BP_VAR_R || type==BP_VAR_IS) {  			*retval = &EG(uninitialized_zval_ptr);  			return; @@ -759,12 +783,12 @@ static inline void zend_fetch_property_address(znode *result, znode *op1, znode  		*container_ptr = (zval *) emalloc(sizeof(zval));  		**container_ptr = *container;  		container = *container_ptr; -		container->refcount=1; -		container->EA=0; +		INIT_PZVAL(container);  		zendi_zval_copy_ctor(*container);  	} -	INC_AI_COUNT(result);  	*retval = zend_fetch_property_address_inner(container->value.obj.properties, op2, Ts, type ELS_CC); +	INC_AI_COUNT(result); +	PZVAL_LOCK(**retval);  } @@ -856,7 +880,8 @@ void execute(zend_op_array *op_array ELS_DC)  		zval *globals = (zval *) emalloc(sizeof(zval));  		globals->refcount=1; -		globals->EA=ZEND_EA_IS_REF; +		globals->EA.is_ref=1; +		globals->EA.locks = 0;  		globals->type = IS_ARRAY;  		globals->value.ht = &EG(symbol_table);  		if (zend_hash_add(EG(active_symbol_table), "GLOBALS", sizeof("GLOBALS"), &globals, sizeof(zval *), NULL)==FAILURE) { @@ -971,6 +996,7 @@ binary_assign_op_addr: {  					if (*var_ptr == EG(error_zval_ptr)) {  						Ts[opline->result.u.var].var = &EG(uninitialized_zval_ptr);  						INC_AI_COUNT(&opline->result); +						/* No need to lock anything */  						opline++;  						continue;  					} @@ -988,6 +1014,7 @@ binary_assign_op_addr: {  					binary_op(*var_ptr, *var_ptr, get_zval_ptr(&opline->op2, Ts, &free_op2, BP_VAR_R));  					Ts[opline->result.u.var].var = var_ptr;  					INC_AI_COUNT(&opline->result); +					PZVAL_LOCK(*var_ptr);  					FREE_OP(&opline->op2, free_op2);  				}  				break; @@ -1004,6 +1031,7 @@ binary_assign_op_addr: {  					if (*var_ptr == EG(error_zval_ptr)) {  						Ts[opline->result.u.var].var = &EG(uninitialized_zval_ptr);  						INC_AI_COUNT(&opline->result); +						/* No need to lock anything */  						opline++;  						continue;  					} @@ -1034,6 +1062,7 @@ binary_assign_op_addr: {  						case ZEND_PRE_DEC:  							Ts[opline->result.u.var].var = var_ptr;  							INC_AI_COUNT(&opline->result); +							PZVAL_LOCK(*var_ptr);  							break;  					}  				} @@ -1100,6 +1129,7 @@ binary_assign_op_addr: {  			case ZEND_ASSIGN_REF:  				zend_assign_to_variable_reference(&opline->result, get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_W), get_zval_ptr_ptr(&opline->op2, Ts, BP_VAR_W), Ts ELS_CC);  				INC_AI_COUNT(&opline->result); +				/* Handled inside zend_assign_to_variable_reference() now */  				break;  			case ZEND_JMP:  #if DEBUG_ZEND>=2 @@ -1358,8 +1388,7 @@ do_fcall_common:  							zval *dummy = (zval *) emalloc(sizeof(zval)), **this_ptr;  							var_uninit(dummy); -							dummy->refcount=1; -							dummy->EA=0; +							INIT_PZVAL(dummy);  							zend_hash_update_ptr(function_state.function_symbol_table, "this", sizeof("this"), dummy, sizeof(zval *), (void **) &this_ptr);  							zend_assign_to_variable_reference(NULL, this_ptr, object_ptr, NULL ELS_CC);  							object_ptr = NULL; @@ -1419,8 +1448,7 @@ do_fcall_common:  					zval *valptr = (zval *) emalloc(sizeof(zval));  					*valptr = Ts[opline->op1.u.var].tmp_var; -					valptr->refcount=1; -					valptr->EA=0; +					INIT_PZVAL(valptr);  					zend_ptr_stack_push(&EG(argument_stack), valptr);  				}  				break; @@ -1439,13 +1467,15 @@ do_fcall_common:  						varptr = (zval *) emalloc(sizeof(zval));  						var_uninit(varptr);  						varptr->refcount=0; -						varptr->EA=0; +						varptr->EA.is_ref=0; +						varptr->EA.locks = 0;  					} else if (PZVAL_IS_REF(varptr)) {  						zval *original_var = varptr;  						varptr = (zval *) emalloc(sizeof(zval));  						*varptr = *original_var; -						varptr->EA = 0; +						varptr->EA.is_ref = 0; +						varptr->EA.locks = 0;  						varptr->refcount = 0;  						zval_copy_ctor(varptr);  					} @@ -1469,7 +1499,8 @@ send_by_ref:  							varptr->refcount = 1;  							zval_copy_ctor(varptr);  						} -						varptr->EA = ZEND_EA_IS_REF; +						varptr->EA.is_ref = 1; +						varptr->EA.locks = 0;  						/* at the end of this code refcount is always 1 */  					}  					varptr->refcount++; @@ -1482,6 +1513,7 @@ send_by_ref:  					if (zend_ptr_stack_get_arg(opline->op1.u.constant.value.lval, (void **) ¶m ELS_CC)==FAILURE) {  						zend_error(E_NOTICE, "Missing argument %d for %s()\n", opline->op1.u.constant.value.lval, get_active_function_name());  						DEC_AI_COUNT(); +						/* No need to unlock anything, I think */  					} else if (PZVAL_IS_REF(*param)) {  						zend_assign_to_variable_reference(NULL, get_zval_ptr_ptr(&opline->result, Ts, BP_VAR_W), param, NULL ELS_CC);  					} else { @@ -1495,6 +1527,7 @@ send_by_ref:  					if (zend_ptr_stack_get_arg(opline->op1.u.constant.value.lval, (void **) ¶m ELS_CC)==FAILURE) {  						if (opline->op2.op_type == IS_UNUSED) {  							DEC_AI_COUNT(); +							/* No need to unlock anything, I think */  							break;  						}  						if (opline->op2.u.constant.type == IS_CONSTANT) { @@ -1509,7 +1542,8 @@ send_by_ref:  								*default_value = tmp;  							}  							default_value->refcount=0; -							default_value->EA=0; +							default_value->EA.is_ref=0; +							default_value->EA.locks = 0;  							param = &default_value;  							assignment_value = default_value;  						} else { @@ -1621,8 +1655,7 @@ send_by_ref:  						*new_expr = *expr;  						expr = new_expr; -						expr->refcount=1; -						expr->EA=0; +						INIT_PZVAL(expr);  					} else {  						if (PZVAL_IS_REF(expr)) {  							zval *new_expr = (zval *) emalloc(sizeof(zval)); @@ -1630,8 +1663,7 @@ send_by_ref:  							*new_expr = *expr;  							expr = new_expr;  							zendi_zval_copy_ctor(*expr); -							expr->refcount=1; -							expr->EA=0; +							INIT_PZVAL(expr);  						} else {  							expr->refcount++;  						} @@ -1809,8 +1841,7 @@ send_by_ref:  					zend_hash_index_update(result->value.ht, 0, value, sizeof(zval *), NULL);  					key = (zval *) emalloc(sizeof(zval)); -					key->refcount=1; -					key->EA=0; +					INIT_PZVAL(key);  					switch (zend_hash_get_current_key(array->value.ht, &str_key, &int_key)) {  						case HASH_KEY_IS_STRING:  							key->value.str.val = str_key; diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index c07ba96c9e..d7c9affcc2 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -80,10 +80,12 @@ void init_executor(CLS_D ELS_DC)  	var_uninit(&EG(uninitialized_zval));  	var_uninit(&EG(error_zval));  	EG(uninitialized_zval).refcount = 1; -	EG(uninitialized_zval).EA=0; +	EG(uninitialized_zval).EA.is_ref=0; +	EG(uninitialized_zval).EA.locks = 0;  	EG(uninitialized_zval_ptr)=&EG(uninitialized_zval);  	EG(error_zval).refcount = 1; -	EG(error_zval).EA=0; +	EG(error_zval).EA.is_ref=0; +	EG(error_zval).EA.locks = 0;  	EG(error_zval_ptr)=&EG(error_zval);  	zend_ptr_stack_init(&EG(arg_types_stack));  	zend_stack_init(&EG(overloaded_objects_stack)); @@ -197,6 +199,8 @@ ZEND_API inline void safe_free_zval_ptr(zval *p)  ZEND_API int zval_ptr_dtor(zval **zval_ptr)  { +	int locked = PZVAL_IS_LOCKED(*zval_ptr); +  #if DEBUG_ZEND>=2  	printf("Reducing refcount for %x (%x):  %d->%d\n", *zval_ptr, zval_ptr, (*zval_ptr)->refcount, (*zval_ptr)->refcount-1);  #endif @@ -205,7 +209,11 @@ ZEND_API int zval_ptr_dtor(zval **zval_ptr)  		zval_dtor(*zval_ptr);  		safe_free_zval_ptr(*zval_ptr);  	} -	return 1; +	if (locked) { +		return 0; /* don't kill the container bucket */ +	} else { +		return 1; +	}  } @@ -264,8 +272,7 @@ ZEND_API void zval_update_constant(zval *p)  			STR_FREE(p->value.str.val);  			*p = c;  		} -		p->refcount = 1; -		p->EA = 0; +		INIT_PZVAL(p);  	}  } @@ -299,8 +306,7 @@ int call_user_function(HashTable *function_table, zval *object, zval *function_n  		param = (zval *) emalloc(sizeof(zval));  		*param = *(params[i]); -		param->refcount=1; -		param->EA=0; +		INIT_PZVAL(param);  		zval_copy_ctor(param);  		//zend_hash_next_index_insert_ptr(function_state.function_symbol_table, param, sizeof(zval *), NULL);  		zend_ptr_stack_push(&EG(argument_stack), param); @@ -317,8 +323,7 @@ int call_user_function(HashTable *function_table, zval *object, zval *function_n  			zval *dummy = (zval *) emalloc(sizeof(zval)), **this_ptr;  			var_uninit(dummy); -			dummy->refcount=1; -			dummy->EA=0; +			INIT_PZVAL(dummy);  			zend_hash_update_ptr(EG(active_symbol_table), "this", sizeof("this"), dummy, sizeof(zval *), (void **) &this_ptr);  			zend_assign_to_variable_reference(NULL, this_ptr, &object, NULL ELS_CC);  		} @@ -429,7 +434,7 @@ ZEND_API inline void zend_assign_to_variable_reference(znode *result, zval **var  				zendi_zval_copy_ctor(*value_ptr);  			}  			value_ptr->refcount = 1; -			value_ptr->EA = ZEND_EA_IS_REF; +			INIT_PZVAL(value_ptr);  		}  		*variable_ptr_ptr = value_ptr; @@ -440,6 +445,7 @@ ZEND_API inline void zend_assign_to_variable_reference(znode *result, zval **var  	if (result && (result->op_type != IS_UNUSED)) {  		Ts[result->u.var].var = variable_ptr_ptr; +		PZVAL_LOCK(*variable_ptr_ptr);  	}  } diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index fe3e7171ea..946e165b53 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -294,10 +294,10 @@ void pass_include_eval(zend_op_array *op_array)  	while (opline<end) {  		if (opline->op1.op_type==IS_CONST) { -			opline->op1.u.constant.EA = ZEND_EA_IS_REF; +			opline->op1.u.constant.EA.is_ref = 1;  		}  		if (opline->op2.op_type==IS_CONST) { -			opline->op2.u.constant.EA = ZEND_EA_IS_REF; +			opline->op2.u.constant.EA.is_ref = 1;  		}  		opline++;  	} diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 35ab1c0197..38963c8c61 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -332,8 +332,7 @@ static void convert_scalar_to_array(zval *op, int type)  	zval *entry = (zval *) emalloc(sizeof(zval));  	*entry = *op; -	entry->refcount = 1; -	entry->EA = 0; +	INIT_PZVAL(entry);  	switch (type) {  		case IS_ARRAY: diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index 713c4a469b..49c9c53df3 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -61,17 +61,23 @@ ZEND_API int zval_dtor(zval *zvalue)  				ELS_FETCH();  				if (zvalue->value.ht && (zvalue->value.ht != &EG(symbol_table))) { +#ifdef USE_AI_COUNT  					if (EG(AiCount)==0) {  						zend_hash_destroy(zvalue->value.ht);  						efree(zvalue->value.ht);  					} else {  						zend_ptr_stack_push(&EG(garbage), zvalue->value.ht);  					} +#else +					zend_hash_destroy(zvalue->value.ht); +					efree(zvalue->value.ht); +#endif  				}  			}  			break;  		case IS_OBJECT: { -				ELS_FETCH(); +#ifdef USE_AI_COUNT +			ELS_FETCH();  				if (EG(AiCount)==0) {  					zend_hash_destroy(zvalue->value.obj.properties); @@ -79,6 +85,10 @@ ZEND_API int zval_dtor(zval *zvalue)  				} else {  					zend_ptr_stack_push(&EG(garbage), zvalue->value.obj.properties);  				} +#else +				zend_hash_destroy(zvalue->value.obj.properties); +				efree(zvalue->value.obj.properties); +#endif  			}  			break;  		case IS_RESOURCE: | 
