From: Zeev Suraski Date: Fri, 9 Jul 1999 20:43:59 +0000 (+0000) Subject: Step 4: X-Git-Tag: BEFORE_REMOVING_AI_COUNT_FINAL_STEP~6 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2a6da7814c27a7e851c8c7a883441ae9d34cd95c;p=php Step 4: Move to a 7-bit counter (not fully implemented yet) --- 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 (oplineop1.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: