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); }
| 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); }
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; }
;
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:
/* 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;
};
#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();
#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 */
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;
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;
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);
}
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);
}
} 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);
}
} 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);
}
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);
}
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);
}
} 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);
}
} 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);
}
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);
}
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);
}
} 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);
}
} 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);
}
} 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);
}
} 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);
}
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);
}
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);
}
} 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);
}
} 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);
}
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);
}
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);
}
} 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);
}
} 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);
}
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); \
} \
}
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); \
} \
}
\
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); \
} \
}
\
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); \
} \
}
} 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);
}
} 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;
}
}
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;
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;
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 {
break;
}
- zendlval->u.constant.refcount = 1;
- zendlval->u.constant.EA = 0;
+ INIT_PZVAL(&zendlval->u.constant);
zendlval->op_type = IS_CONST;
return retval;
}
#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 */
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 {
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: {
}
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;
}
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;
{
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) {
}
Ts[result->u.var].var = &EG(uninitialized_zval_ptr);
INC_AI_COUNT(result);
+ /* No need to lock anything */
return;
}
if (result) {
Ts[result->u.var].var = &EG(uninitialized_zval_ptr);
INC_AI_COUNT(result);
+ /* No need to lock anything */
}
return;
}
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);
}
} 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 {
zendi_zval_dtor(*variable_ptr);
value->refcount=1;
*variable_ptr = *value;
+ variable_ptr->EA.locks = previous_lock_count;
break;
}
} else { /* we need to split */
*variable_ptr = *value;
zval_copy_ctor(variable_ptr);
variable_ptr->refcount=1;
+ variable_ptr->EA.locks = previous_lock_count;
break;
}
*variable_ptr_ptr = value;
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);
+ }
}
}
Ts[result->u.var].var = retval;
INC_AI_COUNT(result);
+ PZVAL_LOCK(*retval);
}
if (container == EG(error_zval_ptr)) {
INC_AI_COUNT(result);
+ /* No need to lock anything */
*retval = &EG(error_zval_ptr);
return;
}
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;
}
*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) {
} else {
*retval = zend_fetch_dimension_address_inner(container->value.ht, op2, Ts, type ELS_CC);
}
+ PZVAL_LOCK(**retval);
break;
case IS_STRING: {
zval *offset;
break;
}
INC_AI_COUNT(result);
+ /* Relevant cases handled above */
}
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);
}
container = *container_ptr;
if (container == EG(error_zval_ptr)) {
INC_AI_COUNT(result);
+ /* No need to lock anything */
*retval = &EG(error_zval_ptr);
return;
}
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;
}
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;
*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);
}
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) {
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;
}
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;
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;
}
case ZEND_PRE_DEC:
Ts[opline->result.u.var].var = var_ptr;
INC_AI_COUNT(&opline->result);
+ PZVAL_LOCK(*var_ptr);
break;
}
}
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
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;
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;
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);
}
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++;
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 {
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) {
*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 {
*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));
*new_expr = *expr;
expr = new_expr;
zendi_zval_copy_ctor(*expr);
- expr->refcount=1;
- expr->EA=0;
+ INIT_PZVAL(expr);
} else {
expr->refcount++;
}
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;
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));
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
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;
+ }
}
STR_FREE(p->value.str.val);
*p = c;
}
- p->refcount = 1;
- p->EA = 0;
+ INIT_PZVAL(p);
}
}
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);
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);
}
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;
if (result && (result->op_type != IS_UNUSED)) {
Ts[result->u.var].var = variable_ptr_ptr;
+ PZVAL_LOCK(*variable_ptr_ptr);
}
}
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++;
}
zval *entry = (zval *) emalloc(sizeof(zval));
*entry = *op;
- entry->refcount = 1;
- entry->EA = 0;
+ INIT_PZVAL(entry);
switch (type) {
case IS_ARRAY:
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);
} 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: