Encapsulate reference-counting primitives.

Prohibit direct update of GC_REFCOUNT(), GC_SET_REFCOUNT(), GC_ADDREF() and GC_DELREF() shoukf be instead.
Added mactros to validate reference-counting (disabled for now).
These macros are going to be used to eliminate race-condintions during reference-counting on data shared between threads.
This commit is contained in:
Dmitry Stogov 2017-10-27 01:28:58 +03:00
parent 1ab0d820da
commit 49ea143bbd
66 changed files with 408 additions and 345 deletions

View file

@ -83,6 +83,10 @@ void (*zend_on_timeout)(int seconds);
static void (*zend_message_dispatcher_p)(zend_long message, const void *data); static void (*zend_message_dispatcher_p)(zend_long message, const void *data);
static zval *(*zend_get_configuration_directive_p)(zend_string *name); static zval *(*zend_get_configuration_directive_p)(zend_string *name);
#if ZEND_RC_DEBUG
ZEND_API zend_bool zend_rc_debug = 0;
#endif
static ZEND_INI_MH(OnUpdateErrorReporting) /* {{{ */ static ZEND_INI_MH(OnUpdateErrorReporting) /* {{{ */
{ {
if (!new_value) { if (!new_value) {

View file

@ -1250,7 +1250,7 @@ static zend_always_inline int zend_parse_arg_array_ht(zval *arg, HashTable **des
&& Z_OBJ_P(arg)->properties && Z_OBJ_P(arg)->properties
&& UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(arg)->properties) > 1)) { && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(arg)->properties) > 1)) {
if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(arg)->properties) & IS_ARRAY_IMMUTABLE))) { if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(arg)->properties) & IS_ARRAY_IMMUTABLE))) {
GC_REFCOUNT(Z_OBJ_P(arg)->properties)--; GC_DELREF(Z_OBJ_P(arg)->properties);
} }
Z_OBJ_P(arg)->properties = zend_array_dup(Z_OBJ_P(arg)->properties); Z_OBJ_P(arg)->properties = zend_array_dup(Z_OBJ_P(arg)->properties);
} }

View file

@ -559,7 +559,7 @@ ZEND_API zend_ast_ref *zend_ast_copy(zend_ast *ast)
tree_size = zend_ast_tree_size(ast) + sizeof(zend_ast_ref); tree_size = zend_ast_tree_size(ast) + sizeof(zend_ast_ref);
ref = emalloc(tree_size); ref = emalloc(tree_size);
zend_ast_tree_copy(ast, GC_AST(ref)); zend_ast_tree_copy(ast, GC_AST(ref));
GC_REFCOUNT(ref) = 1; GC_SET_REFCOUNT(ref, 1);
GC_TYPE_INFO(ref) = IS_CONSTANT_AST; GC_TYPE_INFO(ref) = IS_CONSTANT_AST;
return ref; return ref;
} }

View file

@ -171,7 +171,7 @@ ZEND_METHOD(Closure, call)
if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) { if (fci_cache.function_handler->common.fn_flags & ZEND_ACC_GENERATOR) {
/* copied upon generator creation */ /* copied upon generator creation */
--GC_REFCOUNT(&closure->std); GC_DELREF(&closure->std);
} else if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) { } else if (ZEND_USER_CODE(my_function.type) && closure->func.common.scope != Z_OBJCE_P(newthis)) {
efree(my_function.op_array.run_time_cache); efree(my_function.op_array.run_time_cache);
} }

View file

@ -1061,7 +1061,7 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
} }
if (op_array->static_variables) { if (op_array->static_variables) {
if (!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { if (!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
GC_REFCOUNT(op_array->static_variables)++; GC_ADDREF(op_array->static_variables);
} }
} }
op_array->run_time_cache = NULL; op_array->run_time_cache = NULL;
@ -4256,7 +4256,7 @@ static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, zend_
if (GC_REFCOUNT(CG(active_op_array)->static_variables) > 1) { if (GC_REFCOUNT(CG(active_op_array)->static_variables) > 1) {
if (!(GC_FLAGS(CG(active_op_array)->static_variables) & IS_ARRAY_IMMUTABLE)) { if (!(GC_FLAGS(CG(active_op_array)->static_variables) & IS_ARRAY_IMMUTABLE)) {
GC_REFCOUNT(CG(active_op_array)->static_variables)--; GC_DELREF(CG(active_op_array)->static_variables);
} }
CG(active_op_array)->static_variables = zend_array_dup(CG(active_op_array)->static_variables); CG(active_op_array)->static_variables = zend_array_dup(CG(active_op_array)->static_variables);
} }

View file

@ -100,7 +100,7 @@ void zend_exception_set_previous(zend_object *exception, zend_object *add_previo
previous = zend_read_property_ex(base_ce, ex, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv); previous = zend_read_property_ex(base_ce, ex, ZSTR_KNOWN(ZEND_STR_PREVIOUS), 1, &rv);
if (Z_TYPE_P(previous) == IS_NULL) { if (Z_TYPE_P(previous) == IS_NULL) {
zend_update_property_ex(base_ce, ex, ZSTR_KNOWN(ZEND_STR_PREVIOUS), &pv); zend_update_property_ex(base_ce, ex, ZSTR_KNOWN(ZEND_STR_PREVIOUS), &pv);
GC_REFCOUNT(add_previous)--; GC_DELREF(add_previous);
return; return;
} }
ex = previous; ex = previous;

View file

@ -593,11 +593,11 @@ static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *v
} }
ref = Z_REF_P(value_ptr); ref = Z_REF_P(value_ptr);
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
if (Z_REFCOUNTED_P(variable_ptr)) { if (Z_REFCOUNTED_P(variable_ptr)) {
zend_refcounted *garbage = Z_COUNTED_P(variable_ptr); zend_refcounted *garbage = Z_COUNTED_P(variable_ptr);
if (--GC_REFCOUNT(garbage) == 0) { if (GC_DELREF(garbage) == 0) {
ZVAL_REF(variable_ptr, ref); ZVAL_REF(variable_ptr, ref);
zval_dtor_func(garbage); zval_dtor_func(garbage);
return; return;
@ -1894,7 +1894,7 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
} else if (EXPECTED(zobj->properties != NULL)) { } else if (EXPECTED(zobj->properties != NULL)) {
if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
GC_REFCOUNT(zobj->properties)--; GC_DELREF(zobj->properties);
} }
zobj->properties = zend_array_dup(zobj->properties); zobj->properties = zend_array_dup(zobj->properties);
} }
@ -2080,7 +2080,7 @@ static zend_always_inline void i_free_compiled_variables(zend_execute_data *exec
while (EXPECTED(cv != end)) { while (EXPECTED(cv != end)) {
if (Z_REFCOUNTED_P(cv)) { if (Z_REFCOUNTED_P(cv)) {
zend_refcounted *r = Z_COUNTED_P(cv); zend_refcounted *r = Z_COUNTED_P(cv);
if (!--GC_REFCOUNT(r)) { if (!GC_DELREF(r)) {
ZVAL_NULL(cv); ZVAL_NULL(cv);
zval_dtor_func(r); zval_dtor_func(r);
} else { } else {
@ -2428,7 +2428,7 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o
if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) { if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) { if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) {
GC_REFCOUNT(Z_OBJ(call->This))--; GC_DELREF(Z_OBJ(call->This));
if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) { if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) {
zend_object_store_ctor_failed(Z_OBJ(call->This)); zend_object_store_ctor_failed(Z_OBJ(call->This));
} }
@ -2618,14 +2618,14 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zval *
if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) { if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */ /* Delay closure destruction until its invocation */
ZEND_ASSERT(GC_TYPE((zend_object*)fbc->common.prototype) == IS_OBJECT); ZEND_ASSERT(GC_TYPE((zend_object*)fbc->common.prototype) == IS_OBJECT);
GC_REFCOUNT((zend_object*)fbc->common.prototype)++; GC_ADDREF((zend_object*)fbc->common.prototype);
call_info |= ZEND_CALL_CLOSURE; call_info |= ZEND_CALL_CLOSURE;
if (fbc->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { if (fbc->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
call_info |= ZEND_CALL_FAKE_CLOSURE; call_info |= ZEND_CALL_FAKE_CLOSURE;
} }
} else if (object) { } else if (object) {
call_info |= ZEND_CALL_RELEASE_THIS; call_info |= ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(object)++; /* For $this pointer */ GC_ADDREF(object); /* For $this pointer */
} }
} else { } else {
zend_throw_error(NULL, "Function name must be a string"); zend_throw_error(NULL, "Function name must be a string");
@ -2721,7 +2721,7 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar
object = NULL; object = NULL;
} else { } else {
call_info |= ZEND_CALL_RELEASE_THIS; call_info |= ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(object)++; /* For $this pointer */ GC_ADDREF(object); /* For $this pointer */
} }
} }
} else { } else {

View file

@ -85,19 +85,19 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval
if (ZEND_CONST_COND(value_type & (IS_VAR|IS_CV), 1) && variable_ptr == value) { if (ZEND_CONST_COND(value_type & (IS_VAR|IS_CV), 1) && variable_ptr == value) {
if (value_type == IS_VAR && ref) { if (value_type == IS_VAR && ref) {
ZEND_ASSERT(GC_REFCOUNT(ref) > 1); ZEND_ASSERT(GC_REFCOUNT(ref) > 1);
--GC_REFCOUNT(ref); GC_DELREF(ref);
} }
return variable_ptr; return variable_ptr;
} }
garbage = Z_COUNTED_P(variable_ptr); garbage = Z_COUNTED_P(variable_ptr);
if (--GC_REFCOUNT(garbage) == 0) { if (GC_DELREF(garbage) == 0) {
ZVAL_COPY_VALUE(variable_ptr, value); ZVAL_COPY_VALUE(variable_ptr, value);
if (value_type & (IS_CONST|IS_CV)) { if (value_type & (IS_CONST|IS_CV)) {
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) { if (UNEXPECTED(Z_OPT_REFCOUNTED_P(variable_ptr))) {
Z_ADDREF_P(variable_ptr); Z_ADDREF_P(variable_ptr);
} }
} else if (ZEND_CONST_COND(value_type == IS_VAR, 1) && UNEXPECTED(ref)) { } else if (ZEND_CONST_COND(value_type == IS_VAR, 1) && UNEXPECTED(ref)) {
if (UNEXPECTED(--GC_REFCOUNT(ref) == 0)) { if (UNEXPECTED(GC_DELREF(ref) == 0)) {
efree_size(ref, sizeof(zend_reference)); efree_size(ref, sizeof(zend_reference));
} else if (Z_OPT_REFCOUNTED_P(variable_ptr)) { } else if (Z_OPT_REFCOUNTED_P(variable_ptr)) {
Z_ADDREF_P(variable_ptr); Z_ADDREF_P(variable_ptr);
@ -120,7 +120,7 @@ static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval
Z_ADDREF_P(variable_ptr); Z_ADDREF_P(variable_ptr);
} }
} else if (ZEND_CONST_COND(value_type == IS_VAR, 1) && UNEXPECTED(ref)) { } else if (ZEND_CONST_COND(value_type == IS_VAR, 1) && UNEXPECTED(ref)) {
if (UNEXPECTED(--GC_REFCOUNT(ref) == 0)) { if (UNEXPECTED(GC_DELREF(ref) == 0)) {
efree_size(ref, sizeof(zend_reference)); efree_size(ref, sizeof(zend_reference));
} else if (Z_OPT_REFCOUNTED_P(variable_ptr)) { } else if (Z_OPT_REFCOUNTED_P(variable_ptr)) {
Z_ADDREF_P(variable_ptr); Z_ADDREF_P(variable_ptr);
@ -223,7 +223,7 @@ static zend_always_inline void zend_vm_stack_free_extra_args_ex(uint32_t call_in
p--; p--;
if (Z_REFCOUNTED_P(p)) { if (Z_REFCOUNTED_P(p)) {
zend_refcounted *r = Z_COUNTED_P(p); zend_refcounted *r = Z_COUNTED_P(p);
if (!--GC_REFCOUNT(r)) { if (!GC_DELREF(r)) {
ZVAL_NULL(p); ZVAL_NULL(p);
zval_dtor_func(r); zval_dtor_func(r);
} else { } else {

View file

@ -774,7 +774,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
uint32_t call_info; uint32_t call_info;
ZEND_ASSERT(GC_TYPE((zend_object*)func->op_array.prototype) == IS_OBJECT); ZEND_ASSERT(GC_TYPE((zend_object*)func->op_array.prototype) == IS_OBJECT);
GC_REFCOUNT((zend_object*)func->op_array.prototype)++; GC_ADDREF((zend_object*)func->op_array.prototype);
call_info = ZEND_CALL_CLOSURE; call_info = ZEND_CALL_CLOSURE;
if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
call_info |= ZEND_CALL_FAKE_CLOSURE; call_info |= ZEND_CALL_FAKE_CLOSURE;

View file

@ -282,9 +282,9 @@ ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted *ref)
if (!GC_G(gc_enabled)) { if (!GC_G(gc_enabled)) {
return; return;
} }
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
gc_collect_cycles(); gc_collect_cycles();
GC_REFCOUNT(ref)--; GC_DELREF(ref);
if (UNEXPECTED(GC_REFCOUNT(ref)) == 0) { if (UNEXPECTED(GC_REFCOUNT(ref)) == 0) {
zval_dtor_func(ref); zval_dtor_func(ref);
return; return;
@ -397,7 +397,7 @@ tail_call:
while (zv != end) { while (zv != end) {
if (Z_REFCOUNTED_P(zv)) { if (Z_REFCOUNTED_P(zv)) {
ref = Z_COUNTED_P(zv); ref = Z_COUNTED_P(zv);
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
if (GC_REF_GET_COLOR(ref) != GC_BLACK) { if (GC_REF_GET_COLOR(ref) != GC_BLACK) {
gc_scan_black(ref); gc_scan_black(ref);
} }
@ -406,7 +406,7 @@ tail_call:
} }
if (EXPECTED(!ht)) { if (EXPECTED(!ht)) {
ref = Z_COUNTED_P(zv); ref = Z_COUNTED_P(zv);
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
if (GC_REF_GET_COLOR(ref) != GC_BLACK) { if (GC_REF_GET_COLOR(ref) != GC_BLACK) {
goto tail_call; goto tail_call;
} }
@ -424,7 +424,7 @@ tail_call:
} else if (GC_TYPE(ref) == IS_REFERENCE) { } else if (GC_TYPE(ref) == IS_REFERENCE) {
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) { if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
ref = Z_COUNTED(((zend_reference*)ref)->val); ref = Z_COUNTED(((zend_reference*)ref)->val);
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
if (GC_REF_GET_COLOR(ref) != GC_BLACK) { if (GC_REF_GET_COLOR(ref) != GC_BLACK) {
goto tail_call; goto tail_call;
} }
@ -455,7 +455,7 @@ tail_call:
} }
if (Z_REFCOUNTED_P(zv)) { if (Z_REFCOUNTED_P(zv)) {
ref = Z_COUNTED_P(zv); ref = Z_COUNTED_P(zv);
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
if (GC_REF_GET_COLOR(ref) != GC_BLACK) { if (GC_REF_GET_COLOR(ref) != GC_BLACK) {
gc_scan_black(ref); gc_scan_black(ref);
} }
@ -467,7 +467,7 @@ tail_call:
zv = Z_INDIRECT_P(zv); zv = Z_INDIRECT_P(zv);
} }
ref = Z_COUNTED_P(zv); ref = Z_COUNTED_P(zv);
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
if (GC_REF_GET_COLOR(ref) != GC_BLACK) { if (GC_REF_GET_COLOR(ref) != GC_BLACK) {
goto tail_call; goto tail_call;
} }
@ -507,14 +507,14 @@ tail_call:
while (zv != end) { while (zv != end) {
if (Z_REFCOUNTED_P(zv)) { if (Z_REFCOUNTED_P(zv)) {
ref = Z_COUNTED_P(zv); ref = Z_COUNTED_P(zv);
GC_REFCOUNT(ref)--; GC_DELREF(ref);
gc_mark_grey(ref); gc_mark_grey(ref);
} }
zv++; zv++;
} }
if (EXPECTED(!ht)) { if (EXPECTED(!ht)) {
ref = Z_COUNTED_P(zv); ref = Z_COUNTED_P(zv);
GC_REFCOUNT(ref)--; GC_DELREF(ref);
goto tail_call; goto tail_call;
} }
} else { } else {
@ -530,7 +530,7 @@ tail_call:
} else if (GC_TYPE(ref) == IS_REFERENCE) { } else if (GC_TYPE(ref) == IS_REFERENCE) {
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) { if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
ref = Z_COUNTED(((zend_reference*)ref)->val); ref = Z_COUNTED(((zend_reference*)ref)->val);
GC_REFCOUNT(ref)--; GC_DELREF(ref);
goto tail_call; goto tail_call;
} }
return; return;
@ -559,7 +559,7 @@ tail_call:
} }
if (Z_REFCOUNTED_P(zv)) { if (Z_REFCOUNTED_P(zv)) {
ref = Z_COUNTED_P(zv); ref = Z_COUNTED_P(zv);
GC_REFCOUNT(ref)--; GC_DELREF(ref);
gc_mark_grey(ref); gc_mark_grey(ref);
} }
p++; p++;
@ -569,7 +569,7 @@ tail_call:
zv = Z_INDIRECT_P(zv); zv = Z_INDIRECT_P(zv);
} }
ref = Z_COUNTED_P(zv); ref = Z_COUNTED_P(zv);
GC_REFCOUNT(ref)--; GC_DELREF(ref);
goto tail_call; goto tail_call;
} }
} }
@ -799,7 +799,7 @@ tail_call:
while (zv != end) { while (zv != end) {
if (Z_REFCOUNTED_P(zv)) { if (Z_REFCOUNTED_P(zv)) {
ref = Z_COUNTED_P(zv); ref = Z_COUNTED_P(zv);
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
count += gc_collect_white(ref, flags); count += gc_collect_white(ref, flags);
/* count non-refcounted for compatibility ??? */ /* count non-refcounted for compatibility ??? */
} else if (Z_TYPE_P(zv) != IS_UNDEF) { } else if (Z_TYPE_P(zv) != IS_UNDEF) {
@ -809,7 +809,7 @@ tail_call:
} }
if (EXPECTED(!ht)) { if (EXPECTED(!ht)) {
ref = Z_COUNTED_P(zv); ref = Z_COUNTED_P(zv);
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
goto tail_call; goto tail_call;
} }
} else { } else {
@ -828,7 +828,7 @@ tail_call:
} else if (GC_TYPE(ref) == IS_REFERENCE) { } else if (GC_TYPE(ref) == IS_REFERENCE) {
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) { if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
ref = Z_COUNTED(((zend_reference*)ref)->val); ref = Z_COUNTED(((zend_reference*)ref)->val);
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
goto tail_call; goto tail_call;
} }
return count; return count;
@ -861,7 +861,7 @@ tail_call:
} }
if (Z_REFCOUNTED_P(zv)) { if (Z_REFCOUNTED_P(zv)) {
ref = Z_COUNTED_P(zv); ref = Z_COUNTED_P(zv);
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
count += gc_collect_white(ref, flags); count += gc_collect_white(ref, flags);
/* count non-refcounted for compatibility ??? */ /* count non-refcounted for compatibility ??? */
} else if (Z_TYPE_P(zv) != IS_UNDEF) { } else if (Z_TYPE_P(zv) != IS_UNDEF) {
@ -874,7 +874,7 @@ tail_call:
zv = Z_INDIRECT_P(zv); zv = Z_INDIRECT_P(zv);
} }
ref = Z_COUNTED_P(zv); ref = Z_COUNTED_P(zv);
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
goto tail_call; goto tail_call;
} }
return count; return count;
@ -1118,9 +1118,9 @@ ZEND_API int zend_gc_collect_cycles(void)
if (obj->handlers->dtor_obj if (obj->handlers->dtor_obj
&& (obj->handlers->dtor_obj != zend_objects_destroy_object && (obj->handlers->dtor_obj != zend_objects_destroy_object
|| obj->ce->destructor)) { || obj->ce->destructor)) {
GC_REFCOUNT(obj)++; GC_ADDREF(obj);
obj->handlers->dtor_obj(obj); obj->handlers->dtor_obj(obj);
GC_REFCOUNT(obj)--; GC_DELREF(obj);
} }
} }
} }
@ -1154,9 +1154,9 @@ ZEND_API int zend_gc_collect_cycles(void)
if (!(GC_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { if (!(GC_FLAGS(obj) & IS_OBJ_FREE_CALLED)) {
GC_FLAGS(obj) |= IS_OBJ_FREE_CALLED; GC_FLAGS(obj) |= IS_OBJ_FREE_CALLED;
if (obj->handlers->free_obj) { if (obj->handlers->free_obj) {
GC_REFCOUNT(obj)++; GC_ADDREF(obj);
obj->handlers->free_obj(obj); obj->handlers->free_obj(obj);
GC_REFCOUNT(obj)--; GC_DELREF(obj);
} }
} }
SET_OBJ_BUCKET_NUMBER(EG(objects_store).object_buckets[obj->handle], EG(objects_store).free_list_head); SET_OBJ_BUCKET_NUMBER(EG(objects_store).object_buckets[obj->handle], EG(objects_store).free_list_head);

View file

@ -514,7 +514,7 @@ static void zend_generator_add_child(zend_generator *generator, zend_generator *
if (was_leaf) { if (was_leaf) {
zend_generator *next = generator->node.parent; zend_generator *next = generator->node.parent;
leaf->node.ptr.root = generator->node.ptr.root; leaf->node.ptr.root = generator->node.ptr.root;
++GC_REFCOUNT(&generator->std); /* we need to increment the generator refcount here as it became integrated into the tree (no leaf), but we must not increment the refcount of the *whole* path in tree */ GC_ADDREF(&generator->std); /* we need to increment the generator refcount here as it became integrated into the tree (no leaf), but we must not increment the refcount of the *whole* path in tree */
generator->node.ptr.leaf = leaf; generator->node.ptr.leaf = leaf;
while (next) { while (next) {
@ -592,7 +592,7 @@ void zend_generator_yield_from(zend_generator *generator, zend_generator *from)
generator->node.parent = from; generator->node.parent = from;
zend_generator_get_current(generator); zend_generator_get_current(generator);
--GC_REFCOUNT(&from->std); GC_DELREF(&from->std);
} }
ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator, zend_generator *leaf) ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator, zend_generator *leaf)
@ -658,7 +658,7 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
} else { } else {
do { do {
root = root->node.parent; root = root->node.parent;
++GC_REFCOUNT(&root->std); GC_ADDREF(&root->std);
} while (root->node.parent); } while (root->node.parent);
} }
} }

View file

@ -173,7 +173,7 @@ ZEND_API const HashTable zend_empty_array = {
static zend_always_inline void _zend_hash_init_int(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent) static zend_always_inline void _zend_hash_init_int(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent)
{ {
GC_REFCOUNT(ht) = 1; GC_SET_REFCOUNT(ht, 1);
GC_TYPE_INFO(ht) = IS_ARRAY | (persistent ? (GC_PERSISTENT << GC_FLAGS_SHIFT) : (GC_COLLECTABLE << GC_FLAGS_SHIFT)); GC_TYPE_INFO(ht) = IS_ARRAY | (persistent ? (GC_PERSISTENT << GC_FLAGS_SHIFT) : (GC_COLLECTABLE << GC_FLAGS_SHIFT));
ht->u.flags = HASH_FLAG_STATIC_KEYS; ht->u.flags = HASH_FLAG_STATIC_KEYS;
ht->nTableMask = HT_MIN_MASK; ht->nTableMask = HT_MIN_MASK;
@ -1746,7 +1746,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source)
IS_CONSISTENT(source); IS_CONSISTENT(source);
ALLOC_HASHTABLE(target); ALLOC_HASHTABLE(target);
GC_REFCOUNT(target) = 1; GC_SET_REFCOUNT(target, 1);
GC_TYPE_INFO(target) = IS_ARRAY | (GC_COLLECTABLE << GC_FLAGS_SHIFT); GC_TYPE_INFO(target) = IS_ARRAY | (GC_COLLECTABLE << GC_FLAGS_SHIFT);
target->nTableSize = source->nTableSize; target->nTableSize = source->nTableSize;
@ -2500,7 +2500,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_symtable_to_proptable(HashTable *ht)
} ZEND_HASH_FOREACH_END(); } ZEND_HASH_FOREACH_END();
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
GC_REFCOUNT(ht)++; GC_ADDREF(ht);
} }
return ht; return ht;
@ -2558,7 +2558,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_proptable_to_symtable(HashTable *ht, zend
} }
if (EXPECTED(!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE))) { if (EXPECTED(!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE))) {
GC_REFCOUNT(ht)++; GC_ADDREF(ht);
} }
return ht; return ht;

View file

@ -79,7 +79,7 @@ static zend_function *zend_duplicate_function(zend_function *func, zend_class_en
return func; return func;
} }
if (!(GC_FLAGS(func->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) { if (!(GC_FLAGS(func->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
GC_REFCOUNT(func->op_array.static_variables)++; GC_ADDREF(func->op_array.static_variables);
} }
new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
memcpy(new_function, func, sizeof(zend_op_array)); memcpy(new_function, func, sizeof(zend_op_array));

View file

@ -81,7 +81,7 @@ ZEND_API void zend_iterator_init(zend_object_iterator *iter)
ZEND_API void zend_iterator_dtor(zend_object_iterator *iter) ZEND_API void zend_iterator_dtor(zend_object_iterator *iter)
{ {
if (--GC_REFCOUNT(&iter->std) > 0) { if (GC_DELREF(&iter->std) > 0) {
return; return;
} }

View file

@ -46,7 +46,7 @@ ZEND_API zval *zend_list_insert(void *ptr, int type)
ZEND_API int zend_list_delete(zend_resource *res) ZEND_API int zend_list_delete(zend_resource *res)
{ {
if (--GC_REFCOUNT(res) <= 0) { if (GC_DELREF(res) <= 0) {
return zend_hash_index_del(&EG(regular_list), res->handle); return zend_hash_index_del(&EG(regular_list), res->handle);
} else { } else {
return SUCCESS; return SUCCESS;

View file

@ -713,7 +713,7 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, v
if (EXPECTED(zobj->properties != NULL)) { if (EXPECTED(zobj->properties != NULL)) {
if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
GC_REFCOUNT(zobj->properties)--; GC_DELREF(zobj->properties);
} }
zobj->properties = zend_array_dup(zobj->properties); zobj->properties = zend_array_dup(zobj->properties);
} }
@ -923,7 +923,7 @@ static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type,
if (EXPECTED(zobj->properties)) { if (EXPECTED(zobj->properties)) {
if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
GC_REFCOUNT(zobj->properties)--; GC_DELREF(zobj->properties);
} }
zobj->properties = zend_array_dup(zobj->properties); zobj->properties = zend_array_dup(zobj->properties);
} }
@ -987,7 +987,7 @@ static void zend_std_unset_property(zval *object, zval *member, void **cache_slo
&& EXPECTED(zobj->properties != NULL)) { && EXPECTED(zobj->properties != NULL)) {
if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
GC_REFCOUNT(zobj->properties)--; GC_DELREF(zobj->properties);
} }
zobj->properties = zend_array_dup(zobj->properties); zobj->properties = zend_array_dup(zobj->properties);
} }

View file

@ -29,7 +29,7 @@
ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce) ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce)
{ {
GC_REFCOUNT(object) = 1; GC_SET_REFCOUNT(object, 1);
GC_TYPE_INFO(object) = IS_OBJECT | (GC_COLLECTABLE << GC_FLAGS_SHIFT); GC_TYPE_INFO(object) = IS_OBJECT | (GC_COLLECTABLE << GC_FLAGS_SHIFT);
object->ce = ce; object->ce = ce;
object->properties = NULL; object->properties = NULL;
@ -46,7 +46,7 @@ ZEND_API void zend_object_std_dtor(zend_object *object)
if (object->properties) { if (object->properties) {
if (EXPECTED(!(GC_FLAGS(object->properties) & IS_ARRAY_IMMUTABLE))) { if (EXPECTED(!(GC_FLAGS(object->properties) & IS_ARRAY_IMMUTABLE))) {
if (EXPECTED(--GC_REFCOUNT(object->properties) == 0)) { if (EXPECTED(GC_DELREF(object->properties) == 0)) {
zend_array_destroy(object->properties); zend_array_destroy(object->properties);
} }
} }
@ -125,7 +125,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
} }
} }
GC_REFCOUNT(object)++; GC_ADDREF(object);
ZVAL_OBJ(&obj, object); ZVAL_OBJ(&obj, object);
/* Make sure that destructors are protected from previously thrown exceptions. /* Make sure that destructors are protected from previously thrown exceptions.
@ -183,7 +183,7 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *o
/* fast copy */ /* fast copy */
if (EXPECTED(old_object->handlers == &std_object_handlers)) { if (EXPECTED(old_object->handlers == &std_object_handlers)) {
if (EXPECTED(!(GC_FLAGS(old_object->properties) & IS_ARRAY_IMMUTABLE))) { if (EXPECTED(!(GC_FLAGS(old_object->properties) & IS_ARRAY_IMMUTABLE))) {
GC_REFCOUNT(old_object->properties)++; GC_ADDREF(old_object->properties);
} }
new_object->properties = old_object->properties; new_object->properties = old_object->properties;
return; return;

View file

@ -54,9 +54,9 @@ ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects)
if (obj->handlers->dtor_obj if (obj->handlers->dtor_obj
&& (obj->handlers->dtor_obj != zend_objects_destroy_object && (obj->handlers->dtor_obj != zend_objects_destroy_object
|| obj->ce->destructor)) { || obj->ce->destructor)) {
GC_REFCOUNT(obj)++; GC_ADDREF(obj);
obj->handlers->dtor_obj(obj); obj->handlers->dtor_obj(obj);
GC_REFCOUNT(obj)--; GC_DELREF(obj);
} }
} }
} }
@ -101,9 +101,9 @@ ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects
if (!(GC_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { if (!(GC_FLAGS(obj) & IS_OBJ_FREE_CALLED)) {
GC_FLAGS(obj) |= IS_OBJ_FREE_CALLED; GC_FLAGS(obj) |= IS_OBJ_FREE_CALLED;
if (obj->handlers->free_obj && obj->handlers->free_obj != zend_object_std_dtor) { if (obj->handlers->free_obj && obj->handlers->free_obj != zend_object_std_dtor) {
GC_REFCOUNT(obj)++; GC_ADDREF(obj);
obj->handlers->free_obj(obj); obj->handlers->free_obj(obj);
GC_REFCOUNT(obj)--; GC_DELREF(obj);
} }
} }
} }
@ -116,9 +116,9 @@ ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects
if (!(GC_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { if (!(GC_FLAGS(obj) & IS_OBJ_FREE_CALLED)) {
GC_FLAGS(obj) |= IS_OBJ_FREE_CALLED; GC_FLAGS(obj) |= IS_OBJ_FREE_CALLED;
if (obj->handlers->free_obj) { if (obj->handlers->free_obj) {
GC_REFCOUNT(obj)++; GC_ADDREF(obj);
obj->handlers->free_obj(obj); obj->handlers->free_obj(obj);
GC_REFCOUNT(obj)--; GC_DELREF(obj);
} }
} }
} }
@ -169,9 +169,9 @@ ZEND_API void zend_objects_store_del(zend_object *object) /* {{{ */
if (object->handlers->dtor_obj if (object->handlers->dtor_obj
&& (object->handlers->dtor_obj != zend_objects_destroy_object && (object->handlers->dtor_obj != zend_objects_destroy_object
|| object->ce->destructor)) { || object->ce->destructor)) {
GC_REFCOUNT(object)++; GC_ADDREF(object);
object->handlers->dtor_obj(object); object->handlers->dtor_obj(object);
GC_REFCOUNT(object)--; GC_DELREF(object);
} }
} }
@ -183,9 +183,9 @@ ZEND_API void zend_objects_store_del(zend_object *object) /* {{{ */
if (!(GC_FLAGS(object) & IS_OBJ_FREE_CALLED)) { if (!(GC_FLAGS(object) & IS_OBJ_FREE_CALLED)) {
GC_FLAGS(object) |= IS_OBJ_FREE_CALLED; GC_FLAGS(object) |= IS_OBJ_FREE_CALLED;
if (object->handlers->free_obj) { if (object->handlers->free_obj) {
GC_REFCOUNT(object)++; GC_ADDREF(object);
object->handlers->free_obj(object); object->handlers->free_obj(object);
GC_REFCOUNT(object)--; GC_DELREF(object);
} }
} }
ptr = ((char*)object) - object->handlers->offset; ptr = ((char*)object) - object->handlers->offset;
@ -194,7 +194,7 @@ ZEND_API void zend_objects_store_del(zend_object *object) /* {{{ */
ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle); ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle);
} }
} else { } else {
GC_REFCOUNT(object)--; GC_DELREF(object);
} }
} }
} }

View file

@ -72,7 +72,7 @@ END_EXTERN_C()
static zend_always_inline void zend_object_release(zend_object *obj) static zend_always_inline void zend_object_release(zend_object *obj)
{ {
if (--GC_REFCOUNT(obj) == 0) { if (GC_DELREF(obj) == 0) {
zend_objects_store_del(obj); zend_objects_store_del(obj);
} else if (UNEXPECTED(GC_MAY_LEAK((zend_refcounted*)obj))) { } else if (UNEXPECTED(GC_MAY_LEAK((zend_refcounted*)obj))) {
gc_possible_root((zend_refcounted*)obj); gc_possible_root((zend_refcounted*)obj);

View file

@ -376,7 +376,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array)
if (op_array->static_variables && if (op_array->static_variables &&
!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) { !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
if (--GC_REFCOUNT(op_array->static_variables) == 0) { if (GC_DELREF(op_array->static_variables) == 0) {
zend_array_destroy(op_array->static_variables); zend_array_destroy(op_array->static_variables);
} }
} }

View file

@ -137,7 +137,7 @@ static zend_always_inline zend_string *zend_add_interned_string(zend_string *str
{ {
zval val; zval val;
GC_REFCOUNT(str) = 1; GC_SET_REFCOUNT(str, 1);
GC_FLAGS(str) |= IS_STR_INTERNED | flags; GC_FLAGS(str) |= IS_STR_INTERNED | flags;
ZVAL_INTERNED_STR(&val, str); ZVAL_INTERNED_STR(&val, str);

View file

@ -78,7 +78,7 @@ END_EXTERN_C()
#define ZSTR_ALLOCA_ALLOC(str, _len, use_heap) do { \ #define ZSTR_ALLOCA_ALLOC(str, _len, use_heap) do { \
(str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(_len), 8), (use_heap)); \ (str) = (zend_string *)do_alloca(ZEND_MM_ALIGNED_SIZE_EX(_ZSTR_STRUCT_SIZE(_len), 8), (use_heap)); \
GC_REFCOUNT(str) = 1; \ GC_SET_REFCOUNT(str, 1); \
GC_TYPE_INFO(str) = IS_STRING; \ GC_TYPE_INFO(str) = IS_STRING; \
zend_string_forget_hash_val(str); \ zend_string_forget_hash_val(str); \
ZSTR_LEN(str) = _len; \ ZSTR_LEN(str) = _len; \
@ -118,7 +118,7 @@ static zend_always_inline uint32_t zend_string_refcount(const zend_string *s)
static zend_always_inline uint32_t zend_string_addref(zend_string *s) static zend_always_inline uint32_t zend_string_addref(zend_string *s)
{ {
if (!ZSTR_IS_INTERNED(s)) { if (!ZSTR_IS_INTERNED(s)) {
return ++GC_REFCOUNT(s); return GC_ADDREF(s);
} }
return 1; return 1;
} }
@ -126,7 +126,7 @@ static zend_always_inline uint32_t zend_string_addref(zend_string *s)
static zend_always_inline uint32_t zend_string_delref(zend_string *s) static zend_always_inline uint32_t zend_string_delref(zend_string *s)
{ {
if (!ZSTR_IS_INTERNED(s)) { if (!ZSTR_IS_INTERNED(s)) {
return --GC_REFCOUNT(s); return GC_DELREF(s);
} }
return 1; return 1;
} }
@ -135,7 +135,7 @@ static zend_always_inline zend_string *zend_string_alloc(size_t len, int persist
{ {
zend_string *ret = (zend_string *)pemalloc(ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(len)), persistent); zend_string *ret = (zend_string *)pemalloc(ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(len)), persistent);
GC_REFCOUNT(ret) = 1; GC_SET_REFCOUNT(ret, 1);
#if 1 #if 1
/* optimized single assignment */ /* optimized single assignment */
GC_TYPE_INFO(ret) = IS_STRING | ((persistent ? IS_STR_PERSISTENT : 0) << 8); GC_TYPE_INFO(ret) = IS_STRING | ((persistent ? IS_STR_PERSISTENT : 0) << 8);
@ -153,7 +153,7 @@ static zend_always_inline zend_string *zend_string_safe_alloc(size_t n, size_t m
{ {
zend_string *ret = (zend_string *)safe_pemalloc(n, m, ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(l)), persistent); zend_string *ret = (zend_string *)safe_pemalloc(n, m, ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(l)), persistent);
GC_REFCOUNT(ret) = 1; GC_SET_REFCOUNT(ret, 1);
#if 1 #if 1
/* optimized single assignment */ /* optimized single assignment */
GC_TYPE_INFO(ret) = IS_STRING | ((persistent ? IS_STR_PERSISTENT : 0) << 8); GC_TYPE_INFO(ret) = IS_STRING | ((persistent ? IS_STR_PERSISTENT : 0) << 8);
@ -179,7 +179,7 @@ static zend_always_inline zend_string *zend_string_init(const char *str, size_t
static zend_always_inline zend_string *zend_string_copy(zend_string *s) static zend_always_inline zend_string *zend_string_copy(zend_string *s)
{ {
if (!ZSTR_IS_INTERNED(s)) { if (!ZSTR_IS_INTERNED(s)) {
GC_REFCOUNT(s)++; GC_ADDREF(s);
} }
return s; return s;
} }
@ -204,7 +204,7 @@ static zend_always_inline zend_string *zend_string_realloc(zend_string *s, size_
zend_string_forget_hash_val(ret); zend_string_forget_hash_val(ret);
return ret; return ret;
} else { } else {
GC_REFCOUNT(s)--; GC_DELREF(s);
} }
} }
ret = zend_string_alloc(len, persistent); ret = zend_string_alloc(len, persistent);
@ -224,7 +224,7 @@ static zend_always_inline zend_string *zend_string_extend(zend_string *s, size_t
zend_string_forget_hash_val(ret); zend_string_forget_hash_val(ret);
return ret; return ret;
} else { } else {
GC_REFCOUNT(s)--; GC_DELREF(s);
} }
} }
ret = zend_string_alloc(len, persistent); ret = zend_string_alloc(len, persistent);
@ -244,7 +244,7 @@ static zend_always_inline zend_string *zend_string_truncate(zend_string *s, size
zend_string_forget_hash_val(ret); zend_string_forget_hash_val(ret);
return ret; return ret;
} else { } else {
GC_REFCOUNT(s)--; GC_DELREF(s);
} }
} }
ret = zend_string_alloc(len, persistent); ret = zend_string_alloc(len, persistent);
@ -263,7 +263,7 @@ static zend_always_inline zend_string *zend_string_safe_realloc(zend_string *s,
zend_string_forget_hash_val(ret); zend_string_forget_hash_val(ret);
return ret; return ret;
} else { } else {
GC_REFCOUNT(s)--; GC_DELREF(s);
} }
} }
ret = zend_string_safe_alloc(n, m, l, persistent); ret = zend_string_safe_alloc(n, m, l, persistent);
@ -282,7 +282,7 @@ static zend_always_inline void zend_string_free(zend_string *s)
static zend_always_inline void zend_string_release(zend_string *s) static zend_always_inline void zend_string_release(zend_string *s)
{ {
if (!ZSTR_IS_INTERNED(s)) { if (!ZSTR_IS_INTERNED(s)) {
if (--GC_REFCOUNT(s) == 0) { if (GC_DELREF(s) == 0) {
pefree(s, GC_FLAGS(s) & IS_STR_PERSISTENT); pefree(s, GC_FLAGS(s) & IS_STR_PERSISTENT);
} }
} }

View file

@ -431,7 +431,13 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
#define Z_TYPE_FLAGS_SHIFT 8 #define Z_TYPE_FLAGS_SHIFT 8
#define GC_REFCOUNT(p) (p)->gc.refcount #define GC_REFCOUNT(p) zend_gc_refcount(&(p)->gc)
#define GC_SET_REFCOUNT(p, rc) zend_gc_set_refcount(&(p)->gc, rc)
#define GC_ADDREF(p) zend_gc_addref(&(p)->gc)
#define GC_DELREF(p) zend_gc_delref(&(p)->gc)
#define GC_ADDREF_EX(p, rc) zend_gc_addref_ex(&(p)->gc, rc)
#define GC_DELREF_EX(p, rc) zend_gc_delref_ex(&(p)->gc, rc)
#define GC_TYPE(p) (p)->gc.u.v.type #define GC_TYPE(p) (p)->gc.u.v.type
#define GC_FLAGS(p) (p)->gc.u.v.flags #define GC_FLAGS(p) (p)->gc.u.v.flags
#define GC_INFO(p) (p)->gc.u.v.gc_info #define GC_INFO(p) (p)->gc.u.v.gc_info
@ -707,7 +713,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
if (ZSTR_IS_INTERNED(__s)) { \ if (ZSTR_IS_INTERNED(__s)) { \
Z_TYPE_INFO_P(__z) = IS_INTERNED_STRING_EX; \ Z_TYPE_INFO_P(__z) = IS_INTERNED_STRING_EX; \
} else { \ } else { \
GC_REFCOUNT(__s)++; \ GC_ADDREF(__s); \
Z_TYPE_INFO_P(__z) = IS_STRING_EX; \ Z_TYPE_INFO_P(__z) = IS_STRING_EX; \
} \ } \
} while (0) } while (0)
@ -751,7 +757,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
zend_resource *_res = \ zend_resource *_res = \
(zend_resource *) emalloc(sizeof(zend_resource)); \ (zend_resource *) emalloc(sizeof(zend_resource)); \
zval *__z; \ zval *__z; \
GC_REFCOUNT(_res) = 1; \ GC_SET_REFCOUNT(_res, 1); \
GC_TYPE_INFO(_res) = IS_RESOURCE; \ GC_TYPE_INFO(_res) = IS_RESOURCE; \
_res->handle = (h); \ _res->handle = (h); \
_res->type = (t); \ _res->type = (t); \
@ -765,7 +771,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
zend_resource *_res = \ zend_resource *_res = \
(zend_resource *) malloc(sizeof(zend_resource)); \ (zend_resource *) malloc(sizeof(zend_resource)); \
zval *__z; \ zval *__z; \
GC_REFCOUNT(_res) = 1; \ GC_SET_REFCOUNT(_res, 1); \
GC_TYPE_INFO(_res) = IS_RESOURCE; \ GC_TYPE_INFO(_res) = IS_RESOURCE; \
_res->handle = (h); \ _res->handle = (h); \
_res->type = (t); \ _res->type = (t); \
@ -784,7 +790,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
#define ZVAL_NEW_EMPTY_REF(z) do { \ #define ZVAL_NEW_EMPTY_REF(z) do { \
zend_reference *_ref = \ zend_reference *_ref = \
(zend_reference *) emalloc(sizeof(zend_reference)); \ (zend_reference *) emalloc(sizeof(zend_reference)); \
GC_REFCOUNT(_ref) = 1; \ GC_SET_REFCOUNT(_ref, 1); \
GC_TYPE_INFO(_ref) = IS_REFERENCE; \ GC_TYPE_INFO(_ref) = IS_REFERENCE; \
Z_REF_P(z) = _ref; \ Z_REF_P(z) = _ref; \
Z_TYPE_INFO_P(z) = IS_REFERENCE_EX; \ Z_TYPE_INFO_P(z) = IS_REFERENCE_EX; \
@ -793,7 +799,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
#define ZVAL_NEW_REF(z, r) do { \ #define ZVAL_NEW_REF(z, r) do { \
zend_reference *_ref = \ zend_reference *_ref = \
(zend_reference *) emalloc(sizeof(zend_reference)); \ (zend_reference *) emalloc(sizeof(zend_reference)); \
GC_REFCOUNT(_ref) = 1; \ GC_SET_REFCOUNT(_ref, 1); \
GC_TYPE_INFO(_ref) = IS_REFERENCE; \ GC_TYPE_INFO(_ref) = IS_REFERENCE; \
ZVAL_COPY_VALUE(&_ref->val, r); \ ZVAL_COPY_VALUE(&_ref->val, r); \
Z_REF_P(z) = _ref; \ Z_REF_P(z) = _ref; \
@ -803,7 +809,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
#define ZVAL_NEW_PERSISTENT_REF(z, r) do { \ #define ZVAL_NEW_PERSISTENT_REF(z, r) do { \
zend_reference *_ref = \ zend_reference *_ref = \
(zend_reference *) malloc(sizeof(zend_reference)); \ (zend_reference *) malloc(sizeof(zend_reference)); \
GC_REFCOUNT(_ref) = 1; \ GC_SET_REFCOUNT(_ref, 1); \
GC_TYPE_INFO(_ref) = IS_REFERENCE; \ GC_TYPE_INFO(_ref) = IS_REFERENCE; \
ZVAL_COPY_VALUE(&_ref->val, r); \ ZVAL_COPY_VALUE(&_ref->val, r); \
Z_REF_P(z) = _ref; \ Z_REF_P(z) = _ref; \
@ -865,24 +871,69 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
#define Z_TRY_ADDREF(z) Z_TRY_ADDREF_P(&(z)) #define Z_TRY_ADDREF(z) Z_TRY_ADDREF_P(&(z))
#define Z_TRY_DELREF(z) Z_TRY_DELREF_P(&(z)) #define Z_TRY_DELREF(z) Z_TRY_DELREF_P(&(z))
static zend_always_inline uint32_t zval_refcount_p(zval* pz) { #ifndef ZEND_RC_DEBUG
# define ZEND_RC_DEBUG 0
#endif
#if ZEND_RC_DEBUG
extern ZEND_API zend_bool zend_rc_debug;
# define ZEND_RC_MOD_CHECK(p) \
ZEND_ASSERT(!zend_rc_debug || \
((p)->u.v.flags & (GC_IMMUTABLE | GC_PERSISTENT)) == 0)
#else
# define ZEND_RC_MOD_CHECK(p) \
do { } while (0)
#endif
static zend_always_inline uint32_t zend_gc_refcount(const zend_refcounted_h *p) {
return p->refcount;
}
static zend_always_inline uint32_t zend_gc_set_refcount(zend_refcounted_h *p, uint32_t rc) {
p->refcount = rc;
return p->refcount;
}
static zend_always_inline uint32_t zend_gc_addref(zend_refcounted_h *p) {
ZEND_RC_MOD_CHECK(p);
return ++(p->refcount);
}
static zend_always_inline uint32_t zend_gc_delref(zend_refcounted_h *p) {
ZEND_RC_MOD_CHECK(p);
return --(p->refcount);
}
static zend_always_inline uint32_t zend_gc_addref_ex(zend_refcounted_h *p, uint32_t rc) {
ZEND_RC_MOD_CHECK(p);
p->refcount += rc;
return p->refcount;
}
static zend_always_inline uint32_t zend_gc_delref_ex(zend_refcounted_h *p, uint32_t rc) {
ZEND_RC_MOD_CHECK(p);
p->refcount -= rc;
return p->refcount;
}
static zend_always_inline uint32_t zval_refcount_p(const zval* pz) {
ZEND_ASSERT(Z_REFCOUNTED_P(pz) || Z_COPYABLE_P(pz)); ZEND_ASSERT(Z_REFCOUNTED_P(pz) || Z_COPYABLE_P(pz));
return GC_REFCOUNT(Z_COUNTED_P(pz)); return GC_REFCOUNT(Z_COUNTED_P(pz));
} }
static zend_always_inline uint32_t zval_set_refcount_p(zval* pz, uint32_t rc) { static zend_always_inline uint32_t zval_set_refcount_p(zval* pz, uint32_t rc) {
ZEND_ASSERT(Z_REFCOUNTED_P(pz)); ZEND_ASSERT(Z_REFCOUNTED_P(pz));
return GC_REFCOUNT(Z_COUNTED_P(pz)) = rc; return GC_SET_REFCOUNT(Z_COUNTED_P(pz), rc);
} }
static zend_always_inline uint32_t zval_addref_p(zval* pz) { static zend_always_inline uint32_t zval_addref_p(zval* pz) {
ZEND_ASSERT(Z_REFCOUNTED_P(pz)); ZEND_ASSERT(Z_REFCOUNTED_P(pz));
return ++GC_REFCOUNT(Z_COUNTED_P(pz)); return GC_ADDREF(Z_COUNTED_P(pz));
} }
static zend_always_inline uint32_t zval_delref_p(zval* pz) { static zend_always_inline uint32_t zval_delref_p(zval* pz) {
ZEND_ASSERT(Z_REFCOUNTED_P(pz)); ZEND_ASSERT(Z_REFCOUNTED_P(pz));
return --GC_REFCOUNT(Z_COUNTED_P(pz)); return GC_DELREF(Z_COUNTED_P(pz));
} }
#if SIZEOF_SIZE_T == 4 #if SIZEOF_SIZE_T == 4
@ -920,7 +971,7 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) {
uint32_t _t = Z_TYPE_INFO_P(_z2); \ uint32_t _t = Z_TYPE_INFO_P(_z2); \
ZVAL_COPY_VALUE_EX(_z1, _z2, _gc, _t); \ ZVAL_COPY_VALUE_EX(_z1, _z2, _gc, _t); \
if ((_t & (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT)) != 0) { \ if ((_t & (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT)) != 0) { \
GC_REFCOUNT(_gc)++; \ GC_ADDREF(_gc); \
} \ } \
} while (0) } while (0)
@ -935,7 +986,7 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) {
if ((_t & (IS_TYPE_COPYABLE << Z_TYPE_FLAGS_SHIFT)) != 0) { \ if ((_t & (IS_TYPE_COPYABLE << Z_TYPE_FLAGS_SHIFT)) != 0) { \
_zval_copy_ctor_func(_z1 ZEND_FILE_LINE_CC); \ _zval_copy_ctor_func(_z1 ZEND_FILE_LINE_CC); \
} else { \ } else { \
GC_REFCOUNT(_gc)++; \ GC_ADDREF(_gc); \
} \ } \
} \ } \
} while (0) } while (0)
@ -1000,7 +1051,7 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) {
zend_array *_arr = Z_ARR_P(_zv); \ zend_array *_arr = Z_ARR_P(_zv); \
if (UNEXPECTED(GC_REFCOUNT(_arr) > 1)) { \ if (UNEXPECTED(GC_REFCOUNT(_arr) > 1)) { \
if (Z_REFCOUNTED_P(_zv)) { \ if (Z_REFCOUNTED_P(_zv)) { \
GC_REFCOUNT(_arr)--; \ GC_DELREF(_arr); \
} \ } \
ZVAL_ARR(_zv, zend_array_dup(_arr)); \ ZVAL_ARR(_zv, zend_array_dup(_arr)); \
} \ } \

View file

@ -45,7 +45,7 @@ static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC)
{ {
if (Z_REFCOUNTED_P(zval_ptr)) { if (Z_REFCOUNTED_P(zval_ptr)) {
zend_refcounted *ref = Z_COUNTED_P(zval_ptr); zend_refcounted *ref = Z_COUNTED_P(zval_ptr);
if (!--GC_REFCOUNT(ref)) { if (!GC_DELREF(ref)) {
_zval_dtor_func(ref ZEND_FILE_LINE_RELAY_CC); _zval_dtor_func(ref ZEND_FILE_LINE_RELAY_CC);
} else { } else {
gc_check_possible_root(ref); gc_check_possible_root(ref);

View file

@ -2138,7 +2138,7 @@ ZEND_VM_C_LABEL(fast_assign_obj):
if (EXPECTED(zobj->properties != NULL)) { if (EXPECTED(zobj->properties != NULL)) {
if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
GC_REFCOUNT(zobj->properties)--; GC_DELREF(zobj->properties);
} }
zobj->properties = zend_array_dup(zobj->properties); zobj->properties = zend_array_dup(zobj->properties);
} }
@ -2161,7 +2161,7 @@ ZEND_VM_C_LABEL(fast_assign_obj):
if (Z_ISREF_P(value)) { if (Z_ISREF_P(value)) {
if (OP_DATA_TYPE == IS_VAR) { if (OP_DATA_TYPE == IS_VAR) {
zend_reference *ref = Z_REF_P(value); zend_reference *ref = Z_REF_P(value);
if (--GC_REFCOUNT(ref) == 0) { if (GC_DELREF(ref) == 0) {
ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value));
efree_size(ref, sizeof(zend_reference)); efree_size(ref, sizeof(zend_reference));
value = &tmp; value = &tmp;
@ -2412,7 +2412,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
#else #else
if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) { if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) {
#endif #endif
GC_REFCOUNT(object)--; GC_DELREF(object);
zend_object_store_ctor_failed(object); zend_object_store_ctor_failed(object);
} }
OBJ_RELEASE(object); OBJ_RELEASE(object);
@ -2443,7 +2443,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
#else #else
if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) { if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) {
#endif #endif
GC_REFCOUNT(object)--; GC_DELREF(object);
zend_object_store_ctor_failed(object); zend_object_store_ctor_failed(object);
} }
OBJ_RELEASE(object); OBJ_RELEASE(object);
@ -3096,7 +3096,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, CONST|T
} else if (OP1_TYPE & (IS_VAR|IS_TMP_VAR|IS_CV)) { } else if (OP1_TYPE & (IS_VAR|IS_TMP_VAR|IS_CV)) {
/* CV may be changed indirectly (e.g. when it's a reference) */ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS; call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */ GC_ADDREF(obj); /* For $this pointer */
} }
FREE_OP2(); FREE_OP2();
@ -3389,14 +3389,14 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
if (func->common.fn_flags & ZEND_ACC_CLOSURE) { if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */ /* Delay closure destruction until its invocation */
ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT); ZEND_ASSERT(GC_TYPE((zend_object*)func->common.prototype) == IS_OBJECT);
GC_REFCOUNT((zend_object*)func->common.prototype)++; GC_ADDREF((zend_object*)func->common.prototype);
call_info |= ZEND_CALL_CLOSURE; call_info |= ZEND_CALL_CLOSURE;
if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) { if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
call_info |= ZEND_CALL_FAKE_CLOSURE; call_info |= ZEND_CALL_FAKE_CLOSURE;
} }
} else if (object) { } else if (object) {
call_info |= ZEND_CALL_RELEASE_THIS; call_info |= ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(object)++; /* For $this pointer */ GC_ADDREF(object); /* For $this pointer */
} }
FREE_OP2(); FREE_OP2();
@ -3756,7 +3756,7 @@ ZEND_VM_C_LABEL(fcall_end):
#else #else
if (UNEXPECTED(EG(exception) != NULL) && (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR)) { if (UNEXPECTED(EG(exception) != NULL) && (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR)) {
#endif #endif
GC_REFCOUNT(object)--; GC_DELREF(object);
zend_object_store_ctor_failed(object); zend_object_store_ctor_failed(object);
} }
OBJ_RELEASE(object); OBJ_RELEASE(object);
@ -3874,7 +3874,7 @@ ZEND_VM_HOT_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
retval_ptr = Z_REFVAL_P(retval_ptr); retval_ptr = Z_REFVAL_P(retval_ptr);
ZVAL_COPY_VALUE(return_value, retval_ptr); ZVAL_COPY_VALUE(return_value, retval_ptr);
if (UNEXPECTED(--GC_REFCOUNT(ref) == 0)) { if (UNEXPECTED(GC_DELREF(ref) == 0)) {
efree_size(ref, sizeof(zend_reference)); efree_size(ref, sizeof(zend_reference));
} else if (Z_OPT_REFCOUNTED_P(retval_ptr)) { } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) {
Z_ADDREF_P(retval_ptr); Z_ADDREF_P(retval_ptr);
@ -4049,7 +4049,7 @@ ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, CONST|TMP|VAR|CV, ANY)
retval = Z_REFVAL_P(retval); retval = Z_REFVAL_P(retval);
ZVAL_COPY_VALUE(&generator->retval, retval); ZVAL_COPY_VALUE(&generator->retval, retval);
if (UNEXPECTED(--GC_REFCOUNT(ref) == 0)) { if (UNEXPECTED(GC_DELREF(ref) == 0)) {
efree_size(ref, sizeof(zend_reference)); efree_size(ref, sizeof(zend_reference));
} else if (Z_OPT_REFCOUNTED_P(retval)) { } else if (Z_OPT_REFCOUNTED_P(retval)) {
Z_ADDREF_P(retval); Z_ADDREF_P(retval);
@ -4153,7 +4153,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV, JMP_ADDR)
zval_ptr_dtor(ex); zval_ptr_dtor(ex);
ZVAL_OBJ(ex, EG(exception)); ZVAL_OBJ(ex, EG(exception));
if (UNEXPECTED(EG(exception) != exception)) { if (UNEXPECTED(EG(exception) != exception)) {
GC_REFCOUNT(EG(exception))++; GC_ADDREF(EG(exception));
HANDLE_EXCEPTION(); HANDLE_EXCEPTION();
} else { } else {
EG(exception) = NULL; EG(exception) = NULL;
@ -4235,7 +4235,7 @@ ZEND_VM_HOT_HANDLER(117, ZEND_SEND_VAR, VAR|CV, NUM)
varptr = Z_REFVAL_P(varptr); varptr = Z_REFVAL_P(varptr);
ZVAL_COPY_VALUE(arg, varptr); ZVAL_COPY_VALUE(arg, varptr);
if (UNEXPECTED(--GC_REFCOUNT(ref) == 0)) { if (UNEXPECTED(GC_DELREF(ref) == 0)) {
efree_size(ref, sizeof(zend_reference)); efree_size(ref, sizeof(zend_reference));
} else if (Z_OPT_REFCOUNTED_P(arg)) { } else if (Z_OPT_REFCOUNTED_P(arg)) {
Z_ADDREF_P(arg); Z_ADDREF_P(arg);
@ -4372,7 +4372,7 @@ ZEND_VM_C_LABEL(send_var_by_ref):
varptr = Z_REFVAL_P(varptr); varptr = Z_REFVAL_P(varptr);
ZVAL_COPY_VALUE(arg, varptr); ZVAL_COPY_VALUE(arg, varptr);
if (UNEXPECTED(--GC_REFCOUNT(ref) == 0)) { if (UNEXPECTED(GC_DELREF(ref) == 0)) {
efree_size(ref, sizeof(zend_reference)); efree_size(ref, sizeof(zend_reference));
} else if (Z_OPT_REFCOUNTED_P(arg)) { } else if (Z_OPT_REFCOUNTED_P(arg)) {
Z_ADDREF_P(arg); Z_ADDREF_P(arg);
@ -5184,7 +5184,7 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSE
zend_refcounted *ref = Z_COUNTED_P(expr_ptr); zend_refcounted *ref = Z_COUNTED_P(expr_ptr);
expr_ptr = Z_REFVAL_P(expr_ptr); expr_ptr = Z_REFVAL_P(expr_ptr);
if (UNEXPECTED(--GC_REFCOUNT(ref) == 0)) { if (UNEXPECTED(GC_DELREF(ref) == 0)) {
ZVAL_COPY_VALUE(&new_expr, expr_ptr); ZVAL_COPY_VALUE(&new_expr, expr_ptr);
expr_ptr = &new_expr; expr_ptr = &new_expr;
efree_size(ref, sizeof(zend_reference)); efree_size(ref, sizeof(zend_reference));
@ -5430,7 +5430,7 @@ ZEND_VM_HANDLER(196, ZEND_UNSET_CV, CV, UNUSED)
ZVAL_UNDEF(var); ZVAL_UNDEF(var);
SAVE_OPLINE(); SAVE_OPLINE();
if (!--GC_REFCOUNT(garbage)) { if (!GC_DELREF(garbage)) {
zval_dtor_func(garbage); zval_dtor_func(garbage);
} else { } else {
gc_check_possible_root(garbage); gc_check_possible_root(garbage);
@ -5688,7 +5688,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR)
if (Z_OBJ_P(array_ptr)->properties if (Z_OBJ_P(array_ptr)->properties
&& UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties)--; GC_DELREF(Z_OBJ_P(array_ptr)->properties);
} }
Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
} }
@ -5811,7 +5811,7 @@ ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, JMP_ADDR)
if (Z_OBJ_P(array_ptr)->properties if (Z_OBJ_P(array_ptr)->properties
&& UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties)--; GC_DELREF(Z_OBJ_P(array_ptr)->properties);
} }
Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
} }
@ -6050,7 +6050,7 @@ ZEND_VM_C_LABEL(fe_fetch_r_exit):
ZVAL_COPY_VALUE_EX(res, value, gc, value_type); ZVAL_COPY_VALUE_EX(res, value, gc, value_type);
if (EXPECTED((value_type & (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT)) != 0)) { if (EXPECTED((value_type & (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT)) != 0)) {
GC_REFCOUNT(gc)++; GC_ADDREF(gc);
} }
} }
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@ -6219,7 +6219,7 @@ ZEND_VM_C_LABEL(fe_fetch_w_exit):
zend_reference *ref; zend_reference *ref;
ref = Z_REF_P(value); ref = Z_REF_P(value);
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
zval_ptr_dtor(variable_ptr); zval_ptr_dtor(variable_ptr);
ZVAL_REF(variable_ptr, ref); ZVAL_REF(variable_ptr, ref);
} }
@ -6669,7 +6669,7 @@ ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, JMP_ADDR)
} else if (OP1_TYPE == IS_VAR && ref) { } else if (OP1_TYPE == IS_VAR && ref) {
zend_reference *r = Z_REF_P(ref); zend_reference *r = Z_REF_P(ref);
if (UNEXPECTED(--GC_REFCOUNT(r) == 0)) { if (UNEXPECTED(GC_DELREF(r) == 0)) {
efree_size(r, sizeof(zend_reference)); efree_size(r, sizeof(zend_reference));
} else if (Z_OPT_REFCOUNTED_P(result)) { } else if (Z_OPT_REFCOUNTED_P(result)) {
Z_ADDREF_P(result); Z_ADDREF_P(result);
@ -6710,7 +6710,7 @@ ZEND_VM_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR)
} else if (OP1_TYPE == IS_VAR && ref) { } else if (OP1_TYPE == IS_VAR && ref) {
zend_reference *r = Z_REF_P(ref); zend_reference *r = Z_REF_P(ref);
if (UNEXPECTED(--GC_REFCOUNT(r) == 0)) { if (UNEXPECTED(GC_DELREF(r) == 0)) {
efree_size(r, sizeof(zend_reference)); efree_size(r, sizeof(zend_reference));
} else if (Z_OPT_REFCOUNTED_P(result)) { } else if (Z_OPT_REFCOUNTED_P(result)) {
Z_ADDREF_P(result); Z_ADDREF_P(result);
@ -7607,21 +7607,21 @@ ZEND_VM_C_LABEL(check_indirect):
if (UNEXPECTED(!Z_ISREF_P(value))) { if (UNEXPECTED(!Z_ISREF_P(value))) {
ref = (zend_reference*)emalloc(sizeof(zend_reference)); ref = (zend_reference*)emalloc(sizeof(zend_reference));
GC_REFCOUNT(ref) = 2; GC_SET_REFCOUNT(ref, 2);
GC_TYPE_INFO(ref) = IS_REFERENCE; GC_TYPE_INFO(ref) = IS_REFERENCE;
ZVAL_COPY_VALUE(&ref->val, value); ZVAL_COPY_VALUE(&ref->val, value);
Z_REF_P(value) = ref; Z_REF_P(value) = ref;
Z_TYPE_INFO_P(value) = IS_REFERENCE_EX; Z_TYPE_INFO_P(value) = IS_REFERENCE_EX;
} else { } else {
ref = Z_REF_P(value); ref = Z_REF_P(value);
GC_REFCOUNT(ref)++; GC_ADDREF(ref);
} }
variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) { if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
zend_refcounted *ref = Z_COUNTED_P(variable_ptr); zend_refcounted *ref = Z_COUNTED_P(variable_ptr);
uint32_t refcnt = --GC_REFCOUNT(ref); uint32_t refcnt = GC_DELREF(ref);
if (EXPECTED(variable_ptr != value)) { if (EXPECTED(variable_ptr != value)) {
if (refcnt == 0) { if (refcnt == 0) {
@ -7971,7 +7971,7 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, CONST, REF)
ZEND_ASSERT(ht != NULL); ZEND_ASSERT(ht != NULL);
if (GC_REFCOUNT(ht) > 1) { if (GC_REFCOUNT(ht) > 1) {
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
GC_REFCOUNT(ht)--; GC_DELREF(ht);
} }
EX(func)->op_array.static_variables = ht = zend_array_dup(ht); EX(func)->op_array.static_variables = ht = zend_array_dup(ht);
} }
@ -7989,7 +7989,7 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, CONST, REF)
} }
if (UNEXPECTED(!Z_ISREF_P(value))) { if (UNEXPECTED(!Z_ISREF_P(value))) {
zend_reference *ref = (zend_reference*)emalloc(sizeof(zend_reference)); zend_reference *ref = (zend_reference*)emalloc(sizeof(zend_reference));
GC_REFCOUNT(ref) = 2; GC_SET_REFCOUNT(ref, 2);
GC_TYPE_INFO(ref) = IS_REFERENCE; GC_TYPE_INFO(ref) = IS_REFERENCE;
ZVAL_COPY_VALUE(&ref->val, value); ZVAL_COPY_VALUE(&ref->val, value);
Z_REF_P(value) = ref; Z_REF_P(value) = ref;
@ -8065,7 +8065,7 @@ ZEND_VM_HANDLER(51, ZEND_MAKE_REF, VAR|CV, UNUSED)
if (EXPECTED(!Z_ISREF_P(op1))) { if (EXPECTED(!Z_ISREF_P(op1))) {
ZVAL_MAKE_REF(op1); ZVAL_MAKE_REF(op1);
} }
GC_REFCOUNT(Z_REF_P(op1))++; GC_ADDREF(Z_REF_P(op1));
ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1)); ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1));
} else { } else {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), op1); ZVAL_COPY_VALUE(EX_VAR(opline->result.var), op1);

File diff suppressed because it is too large Load diff

View file

@ -231,7 +231,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz,
self->stream = innerstream; self->stream = innerstream;
if (innerstream) { if (innerstream) {
GC_REFCOUNT(innerstream->res)++; GC_ADDREF(innerstream->res);
} }
self->bz_file = bz; self->bz_file = bz;

View file

@ -281,7 +281,7 @@ PHP_COM_DOTNET_API IStream *php_com_wrapper_export_stream(php_stream *stream)
stm->refcount = 1; stm->refcount = 1;
stm->stream = stream; stm->stream = stream;
GC_REFCOUNT(stream->res)++; GC_ADDREF(stream->res);
tmp = zend_list_insert(stm, le_istream); tmp = zend_list_insert(stm, le_istream);
stm->res = Z_RES_P(tmp); stm->res = Z_RES_P(tmp);

View file

@ -695,7 +695,7 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
info = (dba_info *)le->ptr; info = (dba_info *)le->ptr;
GC_REFCOUNT(le)++; GC_ADDREF(le);
RETURN_RES(zend_register_resource(info, le_pdb)); RETURN_RES(zend_register_resource(info, le_pdb));
return; return;
} }

View file

@ -1199,7 +1199,7 @@ PHP_DOM_EXPORT zend_bool php_dom_create_object(xmlNodePtr obj, zval *return_valu
} }
if ((intern = (dom_object *) php_dom_object_get_data((void *) obj))) { if ((intern = (dom_object *) php_dom_object_get_data((void *) obj))) {
GC_REFCOUNT(&intern->std)++; GC_ADDREF(&intern->std);
ZVAL_OBJ(return_value, &intern->std); ZVAL_OBJ(return_value, &intern->std);
return 1; return 1;
} }

View file

@ -567,7 +567,7 @@ PHP_FUNCTION(enchant_broker_request_dict)
pbroker->dict[pos] = dict; pbroker->dict[pos] = dict;
dict->rsrc = zend_register_resource(dict, le_enchant_dict); dict->rsrc = zend_register_resource(dict, le_enchant_dict);
pbroker->rsrc->gc.refcount++; GC_ADDREF(pbroker->rsrc);
RETURN_RES(dict->rsrc); RETURN_RES(dict->rsrc);
} else { } else {
RETURN_FALSE; RETURN_FALSE;
@ -614,7 +614,7 @@ PHP_FUNCTION(enchant_broker_request_pwl_dict)
pbroker->dict[pos] = dict; pbroker->dict[pos] = dict;
dict->rsrc = zend_register_resource(dict, le_enchant_dict); dict->rsrc = zend_register_resource(dict, le_enchant_dict);
pbroker->rsrc->gc.refcount++; GC_ADDREF(pbroker->rsrc);
RETURN_RES(dict->rsrc); RETURN_RES(dict->rsrc);
} else { } else {
RETURN_FALSE; RETURN_FALSE;

View file

@ -328,7 +328,7 @@ PHP_FUNCTION(ibase_set_event_handler)
event = (ibase_event *) safe_emalloc(sizeof(ibase_event), 1, 0); event = (ibase_event *) safe_emalloc(sizeof(ibase_event), 1, 0);
TSRMLS_SET_CTX(event->thread_ctx); TSRMLS_SET_CTX(event->thread_ctx);
event->link_res = link_res; event->link_res = link_res;
GC_REFCOUNT(link_res)++; GC_ADDREF(link_res);
event->link = ib_link; event->link = ib_link;
event->event_count = 0; event->event_count = 0;
event->state = NEW; event->state = NEW;

View file

@ -183,7 +183,7 @@ static zend_object_iterator *IntlIterator_get_iterator(
return NULL; return NULL;
} }
++GC_REFCOUNT(&ii->iterator->std); GC_ADDREF(&ii->iterator->std);
return ii->iterator; return ii->iterator;
} }

View file

@ -58,7 +58,7 @@ int transliterator_object_construct( zval *object,
ZVAL_NEW_STR(&tmp, u8str); ZVAL_NEW_STR(&tmp, u8str);
zend_update_property(Transliterator_ce_ptr, object, zend_update_property(Transliterator_ce_ptr, object,
"id", sizeof( "id" ) - 1, &tmp ); "id", sizeof( "id" ) - 1, &tmp );
GC_REFCOUNT(u8str)--; GC_DELREF(u8str);
return SUCCESS; return SUCCESS;
} }
/* }}} */ /* }}} */

View file

@ -654,7 +654,7 @@ is_string:
"input buffer"); "input buffer");
} else { } else {
/* make stream not being closed when the zval is freed */ /* make stream not being closed when the zval is freed */
++GC_REFCOUNT(stream->res); GC_ADDREF(stream->res);
pib->context = stream; pib->context = stream;
pib->readcallback = php_libxml_streams_IO_read; pib->readcallback = php_libxml_streams_IO_read;
pib->closecallback = php_libxml_streams_IO_close; pib->closecallback = php_libxml_streams_IO_close;

View file

@ -1456,7 +1456,7 @@ void php_oci_column_hash_dtor(zval *data)
if (GC_REFCOUNT(column->descid) == 1) if (GC_REFCOUNT(column->descid) == 1)
zend_list_close(column->descid); zend_list_close(column->descid);
else else
GC_REFCOUNT(column->descid)--; GC_DELREF(column->descid);
} }
if (column->data) { if (column->data) {
@ -1878,7 +1878,7 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char
(memcmp(ZSTR_VAL(tmp->hash_key), ZSTR_VAL(hashed_details.s), (memcmp(ZSTR_VAL(tmp->hash_key), ZSTR_VAL(hashed_details.s),
ZSTR_LEN(tmp->hash_key)) == 0)) { ZSTR_LEN(tmp->hash_key)) == 0)) {
connection = tmp; connection = tmp;
++GC_REFCOUNT(connection->id); GC_ADDREF(connection->id);
} }
} else { } else {
PHP_OCI_REGISTER_RESOURCE(connection, le_pconnection); PHP_OCI_REGISTER_RESOURCE(connection, le_pconnection);
@ -1888,7 +1888,7 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char
* decremented in the persistent helper * decremented in the persistent helper
*/ */
if (OCI_G(old_oci_close_semantics)) { if (OCI_G(old_oci_close_semantics)) {
++GC_REFCOUNT(connection->id); GC_ADDREF(connection->id);
} }
} }
smart_str_free(&hashed_details); smart_str_free(&hashed_details);
@ -1899,7 +1899,7 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char
} else { } else {
/* we do not ping non-persistent connections */ /* we do not ping non-persistent connections */
smart_str_free(&hashed_details); smart_str_free(&hashed_details);
++GC_REFCOUNT(connection->id); GC_ADDREF(connection->id);
return connection; return connection;
} }
} /* is_open is true? */ } /* is_open is true? */
@ -2051,7 +2051,7 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char
* refcount is decremented in the persistent helper * refcount is decremented in the persistent helper
*/ */
if (OCI_G(old_oci_close_semantics)) { if (OCI_G(old_oci_close_semantics)) {
++GC_REFCOUNT(connection->id); GC_ADDREF(connection->id);
} }
zend_hash_update_mem(&EG(persistent_list), connection->hash_key, (void *)&new_le, sizeof(zend_resource)); zend_hash_update_mem(&EG(persistent_list), connection->hash_key, (void *)&new_le, sizeof(zend_resource));
OCI_G(num_persistent)++; OCI_G(num_persistent)++;
@ -2448,7 +2448,7 @@ int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode)
if (column->is_cursor) { /* REFCURSOR -> simply return the statement id */ if (column->is_cursor) { /* REFCURSOR -> simply return the statement id */
ZVAL_RES(value, column->stmtid); ZVAL_RES(value, column->stmtid);
++GC_REFCOUNT(column->stmtid); GC_ADDREF(column->stmtid);
} else if (column->is_descr) { } else if (column->is_descr) {
if (column->data_type != SQLT_RDD) { if (column->data_type != SQLT_RDD) {
@ -2492,7 +2492,7 @@ int php_oci_column_to_zval(php_oci_out_column *column, zval *value, int mode)
/* return the locator */ /* return the locator */
object_init_ex(value, oci_lob_class_entry_ptr); object_init_ex(value, oci_lob_class_entry_ptr);
add_property_resource(value, "descriptor", column->descid); add_property_resource(value, "descriptor", column->descid);
++GC_REFCOUNT(column->descid); GC_ADDREF(column->descid);
} }
} else { } else {
switch (column->retcode) { switch (column->retcode) {

View file

@ -52,7 +52,7 @@ php_oci_collection *php_oci_collection_create(php_oci_connection *connection, ch
collection->connection = connection; collection->connection = connection;
collection->collection = NULL; collection->collection = NULL;
++GC_REFCOUNT(collection->connection->id); GC_ADDREF(collection->connection->id);
/* get type handle by name */ /* get type handle by name */
PHP_OCI_CALL_RETURN(errstatus, OCITypeByName, PHP_OCI_CALL_RETURN(errstatus, OCITypeByName,

View file

@ -67,7 +67,7 @@ php_oci_descriptor *php_oci_lob_create (php_oci_connection *connection, zend_lon
descriptor = ecalloc(1, sizeof(php_oci_descriptor)); descriptor = ecalloc(1, sizeof(php_oci_descriptor));
descriptor->type = (ub4) type; descriptor->type = (ub4) type;
descriptor->connection = connection; descriptor->connection = connection;
++GC_REFCOUNT(descriptor->connection->id); GC_ADDREF(descriptor->connection->id);
PHP_OCI_CALL_RETURN(errstatus, OCIDescriptorAlloc, (connection->env, (dvoid*)&(descriptor->descriptor), descriptor->type, (size_t) 0, (dvoid **) 0)); PHP_OCI_CALL_RETURN(errstatus, OCIDescriptorAlloc, (connection->env, (dvoid*)&(descriptor->descriptor), descriptor->type, (size_t) 0, (dvoid **) 0));

View file

@ -111,7 +111,7 @@ php_oci_statement *php_oci_statement_create(php_oci_connection *connection, char
statement->impres_child_stmt = NULL; statement->impres_child_stmt = NULL;
statement->impres_count = 0; statement->impres_count = 0;
statement->impres_flag = PHP_OCI_IMPRES_UNKNOWN; /* may or may not have Implicit Result Set children */ statement->impres_flag = PHP_OCI_IMPRES_UNKNOWN; /* may or may not have Implicit Result Set children */
++GC_REFCOUNT(statement->connection->id); GC_ADDREF(statement->connection->id);
if (OCI_G(default_prefetch) >= 0) { if (OCI_G(default_prefetch) >= 0) {
php_oci_statement_set_prefetch(statement, (ub4)OCI_G(default_prefetch)); php_oci_statement_set_prefetch(statement, (ub4)OCI_G(default_prefetch));
@ -171,8 +171,8 @@ php_oci_statement *php_oci_get_implicit_resultset(php_oci_statement *statement)
statement2->has_descr = 0; statement2->has_descr = 0;
statement2->stmttype = 0; statement2->stmttype = 0;
GC_REFCOUNT(statement->id)++; GC_ADDREF(statement->id);
GC_REFCOUNT(statement2->connection->id)++; GC_ADDREF(statement2->connection->id);
php_oci_statement_set_prefetch(statement2, statement->prefetch_count); php_oci_statement_set_prefetch(statement2, statement->prefetch_count);
@ -433,7 +433,7 @@ sb4 php_oci_define_callback(dvoid *ctx, OCIDefine *define, ub4 iter, dvoid **buf
return OCI_ERROR; return OCI_ERROR;
} }
nested_stmt->parent_stmtid = outcol->statement->id; nested_stmt->parent_stmtid = outcol->statement->id;
++GC_REFCOUNT(outcol->statement->id); GC_ADDREF(outcol->statement->id);
outcol->nested_statement = nested_stmt; outcol->nested_statement = nested_stmt;
outcol->stmtid = nested_stmt->id; outcol->stmtid = nested_stmt->id;

View file

@ -2652,7 +2652,7 @@ try_and_get_another_connection:
p = zend_hash_index_find_ptr(&EG(regular_list), conn_id); /* check if the connection is still there */ p = zend_hash_index_find_ptr(&EG(regular_list), conn_id); /* check if the connection is still there */
if (p && p->ptr && (p->type == le_conn || p->type == le_pconn)) { if (p && p->ptr && (p->type == le_conn || p->type == le_pconn)) {
GC_REFCOUNT(p)++; GC_ADDREF(p);
RETVAL_RES(p); RETVAL_RES(p);
efree(hashed_details); efree(hashed_details);
return; return;

View file

@ -471,7 +471,7 @@ zend_string *accel_new_interned_string(zend_string *str)
p->key = (zend_string*) ZCSG(interned_strings_top); p->key = (zend_string*) ZCSG(interned_strings_top);
ZCSG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); ZCSG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(_ZSTR_STRUCT_SIZE(ZSTR_LEN(str)));
p->h = h; p->h = h;
GC_REFCOUNT(p->key) = 1; GC_SET_REFCOUNT(p->key, 1);
#if 1 #if 1
/* optimized single assignment */ /* optimized single assignment */
GC_TYPE_INFO(p->key) = IS_STRING | ((IS_STR_INTERNED | IS_STR_PERMANENT) << 8); GC_TYPE_INFO(p->key) = IS_STRING | ((IS_STR_INTERNED | IS_STR_PERMANENT) << 8);

View file

@ -47,7 +47,7 @@ static void zend_accel_destroy_zend_function(zval *zv)
if (function->type == ZEND_USER_FUNCTION) { if (function->type == ZEND_USER_FUNCTION) {
if (function->op_array.static_variables) { if (function->op_array.static_variables) {
if (!(GC_FLAGS(function->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) { if (!(GC_FLAGS(function->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
if (--GC_REFCOUNT(function->op_array.static_variables) == 0) { if (GC_DELREF(function->op_array.static_variables) == 0) {
FREE_HASHTABLE(function->op_array.static_variables); FREE_HASHTABLE(function->op_array.static_variables);
} }
} }

View file

@ -300,7 +300,7 @@ static void zend_persist_zval(zval *z)
zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval); zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval);
/* make immutable array */ /* make immutable array */
Z_TYPE_FLAGS_P(z) = IS_TYPE_COPYABLE; Z_TYPE_FLAGS_P(z) = IS_TYPE_COPYABLE;
GC_REFCOUNT(Z_COUNTED_P(z)) = 2; GC_SET_REFCOUNT(Z_COUNTED_P(z), 2);
GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE; GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE;
Z_ARRVAL_P(z)->u.flags |= HASH_FLAG_STATIC_KEYS; Z_ARRVAL_P(z)->u.flags |= HASH_FLAG_STATIC_KEYS;
} }
@ -325,7 +325,7 @@ static void zend_persist_zval(zval *z)
Z_ARR_P(z) = zend_accel_memdup(Z_AST_P(z), sizeof(zend_ast_ref)); Z_ARR_P(z) = zend_accel_memdup(Z_AST_P(z), sizeof(zend_ast_ref));
zend_persist_ast(GC_AST(old_ref)); zend_persist_ast(GC_AST(old_ref));
Z_TYPE_FLAGS_P(z) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE); Z_TYPE_FLAGS_P(z) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
GC_REFCOUNT(Z_COUNTED_P(z)) = 2; GC_SET_REFCOUNT(Z_COUNTED_P(z), 2);
efree(old_ref); efree(old_ref);
} }
break; break;
@ -370,7 +370,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
zend_hash_persist(op_array->static_variables, zend_persist_zval); zend_hash_persist(op_array->static_variables, zend_persist_zval);
zend_accel_store(op_array->static_variables, sizeof(HashTable)); zend_accel_store(op_array->static_variables, sizeof(HashTable));
/* make immutable array */ /* make immutable array */
GC_REFCOUNT(op_array->static_variables) = 2; GC_SET_REFCOUNT(op_array->static_variables, 2);
GC_TYPE_INFO(op_array->static_variables) = IS_ARRAY | (IS_ARRAY_IMMUTABLE << 8); GC_TYPE_INFO(op_array->static_variables) = IS_ARRAY | (IS_ARRAY_IMMUTABLE << 8);
op_array->static_variables->u.flags |= HASH_FLAG_STATIC_KEYS; op_array->static_variables->u.flags |= HASH_FLAG_STATIC_KEYS;
} }

View file

@ -2291,7 +2291,7 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_
if (xparam->outputs.client) { if (xparam->outputs.client) {
xparam->outputs.client->ctx = stream->ctx; xparam->outputs.client->ctx = stream->ctx;
if (stream->ctx) { if (stream->ctx) {
GC_REFCOUNT(stream->ctx)++; GC_ADDREF(stream->ctx);
} }
} }

View file

@ -367,7 +367,7 @@ static PHP_METHOD(PDO, dbh_constructor)
le.type = php_pdo_list_entry(); le.type = php_pdo_list_entry();
le.ptr = dbh; le.ptr = dbh;
GC_REFCOUNT(&le) = 1; GC_SET_REFCOUNT(&le, 1);
if ((zend_hash_str_update_mem(&EG(persistent_list), if ((zend_hash_str_update_mem(&EG(persistent_list),
(char*)dbh->persistent_id, dbh->persistent_id_len, &le, sizeof(le))) == NULL) { (char*)dbh->persistent_id, dbh->persistent_id_len, &le, sizeof(le))) == NULL) {

View file

@ -246,8 +246,8 @@ static void get_lazy_object(pdo_stmt_t *stmt, zval *return_value) /* {{{ */
zend_object_std_init(&row->std, pdo_row_ce); zend_object_std_init(&row->std, pdo_row_ce);
ZVAL_OBJ(&stmt->lazy_object_ref, &row->std); ZVAL_OBJ(&stmt->lazy_object_ref, &row->std);
row->std.handlers = &pdo_row_object_handlers; row->std.handlers = &pdo_row_object_handlers;
GC_REFCOUNT(&stmt->std)++; GC_ADDREF(&stmt->std);
GC_REFCOUNT(&row->std)--; GC_DELREF(&row->std);
} }
ZVAL_COPY(return_value, &stmt->lazy_object_ref); ZVAL_COPY(return_value, &stmt->lazy_object_ref);
} }

View file

@ -691,7 +691,7 @@ static int oci_blob_close(php_stream *stream, int close_handle)
OCILobClose(self->E->svc, self->E->err, self->lob); OCILobClose(self->E->svc, self->E->err, self->lob);
zval_ptr_dtor(&self->dbh); zval_ptr_dtor(&self->dbh);
GC_REFCOUNT(obj)--; GC_DELREF(obj);
efree(self->E); efree(self->E);
efree(self); efree(self);
} }
@ -751,7 +751,7 @@ static php_stream *oci_create_lob_stream(zval *dbh, pdo_stmt_t *stmt, OCILobLoca
zend_object *obj; zend_object *obj;
obj = &stmt->std; obj = &stmt->std;
Z_ADDREF(self->dbh); Z_ADDREF(self->dbh);
GC_REFCOUNT(obj)++; GC_ADDREF(obj);
return stm; return stm;
} }

View file

@ -346,7 +346,7 @@ static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
ZVAL_NULL(&zargs[0]); ZVAL_NULL(&zargs[0]);
} else { } else {
if (Z_ISUNDEF(agg_context->val)) { if (Z_ISUNDEF(agg_context->val)) {
GC_REFCOUNT(agg_context) = 1; GC_SET_REFCOUNT(agg_context, 1);
GC_TYPE_INFO(agg_context) = IS_REFERENCE; GC_TYPE_INFO(agg_context) = IS_REFERENCE;
ZVAL_NULL(&agg_context->val); ZVAL_NULL(&agg_context->val);
} }

View file

@ -923,7 +923,7 @@ static inline char * _php_pgsql_trim_result(PGconn * pgsql, char **buf)
*/ */
static void php_pgsql_set_default_link(zend_resource *res) static void php_pgsql_set_default_link(zend_resource *res)
{ {
GC_REFCOUNT(res)++; GC_ADDREF(res);
if (PGG(default_link) != NULL) { if (PGG(default_link) != NULL) {
zend_list_delete(PGG(default_link)); zend_list_delete(PGG(default_link));
@ -1451,7 +1451,7 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
link = (zend_resource *)index_ptr->ptr; link = (zend_resource *)index_ptr->ptr;
if (link->ptr && (link->type == le_link || link->type == le_plink)) { if (link->ptr && (link->type == le_link || link->type == le_plink)) {
php_pgsql_set_default_link(link); php_pgsql_set_default_link(link);
GC_REFCOUNT(link)++; GC_ADDREF(link);
RETVAL_RES(link); RETVAL_RES(link);
goto cleanup; goto cleanup;
} else { } else {

View file

@ -1850,7 +1850,7 @@ ZEND_METHOD(reflection_function, getStaticVariables)
array_init(return_value); array_init(return_value);
if (GC_REFCOUNT(fptr->op_array.static_variables) > 1) { if (GC_REFCOUNT(fptr->op_array.static_variables) > 1) {
if (!(GC_FLAGS(fptr->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) { if (!(GC_FLAGS(fptr->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
GC_REFCOUNT(fptr->op_array.static_variables)--; GC_DELREF(fptr->op_array.static_variables);
} }
fptr->op_array.static_variables = zend_array_dup(fptr->op_array.static_variables); fptr->op_array.static_variables = zend_array_dup(fptr->op_array.static_variables);
} }
@ -2278,7 +2278,7 @@ ZEND_METHOD(reflection_generator, getExecutingGenerator)
REFLECTION_CHECK_VALID_GENERATOR(ex) REFLECTION_CHECK_VALID_GENERATOR(ex)
current = zend_generator_get_current(generator); current = zend_generator_get_current(generator);
++GC_REFCOUNT(&current->std); GC_ADDREF(&current->std);
ZVAL_OBJ(return_value, (zend_object *) current); ZVAL_OBJ(return_value, (zend_object *) current);
} }

View file

@ -519,7 +519,7 @@ try_again:
if (stream) { if (stream) {
php_stream_auto_cleanup(stream); php_stream_auto_cleanup(stream);
add_property_resource(this_ptr, "httpsocket", stream->res); add_property_resource(this_ptr, "httpsocket", stream->res);
GC_REFCOUNT(stream->res)++; GC_ADDREF(stream->res);
add_property_long(this_ptr, "_use_proxy", use_proxy); add_property_long(this_ptr, "_use_proxy", use_proxy);
} else { } else {
php_url_free(phpurl); php_url_free(phpurl);
@ -539,7 +539,7 @@ try_again:
zend_resource *ret = zend_register_resource(phpurl, le_url); zend_resource *ret = zend_register_resource(phpurl, le_url);
add_property_resource(this_ptr, "httpurl", ret); add_property_resource(this_ptr, "httpurl", ret);
GC_REFCOUNT(ret)++; GC_ADDREF(ret);
/*zend_list_addref(ret);*/ /*zend_list_addref(ret);*/
if (context && if (context &&
@ -1014,7 +1014,7 @@ try_again:
} }
if (!zend_hash_index_exists(Z_ARRVAL(zcookie), 2)) { if (!zend_hash_index_exists(Z_ARRVAL(zcookie), 2)) {
add_index_str(&zcookie, 2, phpurl->host); add_index_str(&zcookie, 2, phpurl->host);
GC_REFCOUNT(phpurl->host)++; GC_ADDREF(phpurl->host);
} }
zend_symtable_update(Z_ARRVAL_P(cookies), name.s, &zcookie); zend_symtable_update(Z_ARRVAL_P(cookies), name.s, &zcookie);

View file

@ -100,7 +100,7 @@ static inline HashTable **spl_array_get_hash_table_ptr(spl_array_object* intern)
rebuild_object_properties(obj); rebuild_object_properties(obj);
} else if (GC_REFCOUNT(obj->properties) > 1) { } else if (GC_REFCOUNT(obj->properties) > 1) {
if (EXPECTED(!(GC_FLAGS(obj->properties) & IS_ARRAY_IMMUTABLE))) { if (EXPECTED(!(GC_FLAGS(obj->properties) & IS_ARRAY_IMMUTABLE))) {
GC_REFCOUNT(obj->properties)--; GC_DELREF(obj->properties);
} }
obj->properties = zend_array_dup(obj->properties); obj->properties = zend_array_dup(obj->properties);
} }
@ -1473,7 +1473,7 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam
ZVAL_NEW_EMPTY_REF(&params[0]); ZVAL_NEW_EMPTY_REF(&params[0]);
ZVAL_ARR(Z_REFVAL(params[0]), aht); ZVAL_ARR(Z_REFVAL(params[0]), aht);
GC_REFCOUNT(aht)++; GC_ADDREF(aht);
if (!use_arg) { if (!use_arg) {
intern->nApplyCount++; intern->nApplyCount++;
@ -1507,7 +1507,7 @@ exit:
if (aht != new_ht) { if (aht != new_ht) {
spl_array_replace_hash_table(intern, new_ht); spl_array_replace_hash_table(intern, new_ht);
} else { } else {
GC_REFCOUNT(aht)--; GC_DELREF(aht);
} }
efree(Z_REF(params[0])); efree(Z_REF(params[0]));
zend_string_free(Z_STR(function_name)); zend_string_free(Z_STR(function_name));

View file

@ -1583,7 +1583,7 @@ static spl_dual_it_object* spl_dual_it_construct(INTERNAL_FUNCTION_PARAMETERS, z
Z_ADDREF(cfi->fci.function_name); Z_ADDREF(cfi->fci.function_name);
} }
cfi->object = cfi->fcc.object; cfi->object = cfi->fcc.object;
if (cfi->object) GC_REFCOUNT(cfi->object)++; if (cfi->object) GC_ADDREF(cfi->object);
intern->u.cbfilter = cfi; intern->u.cbfilter = cfi;
break; break;
} }

View file

@ -2567,7 +2567,7 @@ static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_valu
if (zend_string_equals_literal(Z_STR_P(entry), "this")) { if (zend_string_equals_literal(Z_STR_P(entry), "this")) {
zend_object *object = zend_get_this_object(EG(current_execute_data)); zend_object *object = zend_get_this_object(EG(current_execute_data));
if (object) { if (object) {
GC_REFCOUNT(object)++; GC_ADDREF(object);
ZVAL_OBJ(&data, object); ZVAL_OBJ(&data, object);
zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data); zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data);
} }
@ -2659,7 +2659,7 @@ PHP_FUNCTION(array_fill)
Z_ARRVAL_P(return_value)->nNextFreeElement = (zend_long)(start_key + num); Z_ARRVAL_P(return_value)->nNextFreeElement = (zend_long)(start_key + num);
if (Z_REFCOUNTED_P(val)) { if (Z_REFCOUNTED_P(val)) {
GC_REFCOUNT(Z_COUNTED_P(val)) += (uint32_t)num; GC_ADDREF_EX(Z_COUNTED_P(val), (uint32_t)num);
} }
p = Z_ARRVAL_P(return_value)->arData; p = Z_ARRVAL_P(return_value)->arData;
@ -2680,7 +2680,7 @@ PHP_FUNCTION(array_fill)
array_init_size(return_value, (uint32_t)num); array_init_size(return_value, (uint32_t)num);
zend_hash_real_init(Z_ARRVAL_P(return_value), 0); zend_hash_real_init(Z_ARRVAL_P(return_value), 0);
if (Z_REFCOUNTED_P(val)) { if (Z_REFCOUNTED_P(val)) {
GC_REFCOUNT(Z_COUNTED_P(val)) += (uint32_t)num; GC_ADDREF_EX(Z_COUNTED_P(val), (uint32_t)num);
} }
zend_hash_index_add_new(Z_ARRVAL_P(return_value), start_key, val); zend_hash_index_add_new(Z_ARRVAL_P(return_value), start_key, val);
while (--num) { while (--num) {
@ -4311,7 +4311,7 @@ PHP_FUNCTION(array_pad)
num_pads = pad_size_abs - input_size; num_pads = pad_size_abs - input_size;
if (Z_REFCOUNTED_P(pad_value)) { if (Z_REFCOUNTED_P(pad_value)) {
GC_REFCOUNT(Z_COUNTED_P(pad_value)) += num_pads; GC_ADDREF_EX(Z_COUNTED_P(pad_value), num_pads);
} }
array_init_size(return_value, pad_size_abs); array_init_size(return_value, pad_size_abs);

View file

@ -113,7 +113,7 @@ static void php_set_default_dir(zend_resource *res)
} }
if (res) { if (res) {
GC_REFCOUNT(res)++; GC_ADDREF(res);
} }
DIRG(default_dir) = res; DIRG(default_dir) = res;

View file

@ -447,7 +447,7 @@ finish:
if (ZSTR_IS_INTERNED(tmp)) { if (ZSTR_IS_INTERNED(tmp)) {
tmp = zend_string_init(ZSTR_VAL(tmp), ZSTR_LEN(tmp), 0); tmp = zend_string_init(ZSTR_VAL(tmp), ZSTR_LEN(tmp), 0);
} else if (GC_REFCOUNT(tmp) > 1) { } else if (GC_REFCOUNT(tmp) > 1) {
GC_REFCOUNT(tmp)--; GC_DELREF(tmp);
tmp = zend_string_init(ZSTR_VAL(tmp), ZSTR_LEN(tmp), 0); tmp = zend_string_init(ZSTR_VAL(tmp), ZSTR_LEN(tmp), 0);
} }

View file

@ -185,7 +185,7 @@ static void proc_open_rsrc_dtor(zend_resource *rsrc)
/* Close all handles to avoid a deadlock */ /* Close all handles to avoid a deadlock */
for (i = 0; i < proc->npipes; i++) { for (i = 0; i < proc->npipes; i++) {
if (proc->pipes[i] != 0) { if (proc->pipes[i] != 0) {
GC_REFCOUNT(proc->pipes[i])--; GC_DELREF(proc->pipes[i]);
zend_list_close(proc->pipes[i]); zend_list_close(proc->pipes[i]);
proc->pipes[i] = 0; proc->pipes[i] = 0;
} }

View file

@ -208,7 +208,7 @@ PHP_FUNCTION(stream_socket_server)
context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT); context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
if (context) { if (context) {
GC_REFCOUNT(context->res)++; GC_ADDREF(context->res);
} }
if (zerrno) { if (zerrno) {
@ -1229,7 +1229,7 @@ static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS)
if (filter) { if (filter) {
filter->res = zend_register_resource(filter, php_file_le_stream_filter()); filter->res = zend_register_resource(filter, php_file_le_stream_filter());
GC_REFCOUNT(filter->res)++; GC_ADDREF(filter->res);
RETURN_RES(filter->res); RETURN_RES(filter->res);
} else { } else {
RETURN_FALSE; RETURN_FALSE;

View file

@ -279,9 +279,9 @@ static void destroy_server_data(xmlrpc_server_data *server)
static void xmlrpc_server_destructor(zend_resource *rsrc) static void xmlrpc_server_destructor(zend_resource *rsrc)
{ {
if (rsrc && rsrc->ptr) { if (rsrc && rsrc->ptr) {
rsrc->gc.refcount++; GC_ADDREF(rsrc);
destroy_server_data((xmlrpc_server_data*) rsrc->ptr); destroy_server_data((xmlrpc_server_data*) rsrc->ptr);
rsrc->gc.refcount--; GC_DELREF(rsrc);
} }
} }

View file

@ -1596,6 +1596,10 @@ int php_request_startup(void)
{ {
int retval = SUCCESS; int retval = SUCCESS;
#if ZEND_RC_DEBUG
zend_rc_debug = 1;
#endif
zend_interned_strings_activate(); zend_interned_strings_activate();
#ifdef HAVE_DTRACE #ifdef HAVE_DTRACE
@ -1805,6 +1809,10 @@ void php_request_shutdown(void *dummy)
#ifdef HAVE_DTRACE #ifdef HAVE_DTRACE
DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method)); DTRACE_REQUEST_SHUTDOWN(SAFE_FILENAME(SG(request_info).path_translated), SAFE_FILENAME(SG(request_info).request_uri), (char *)SAFE_FILENAME(SG(request_info).request_method));
#endif /* HAVE_DTRACE */ #endif /* HAVE_DTRACE */
#if ZEND_RC_DEBUG
zend_rc_debug = 0;
#endif
} }
/* }}} */ /* }}} */

View file

@ -38,7 +38,7 @@ typedef void (*php_stream_notification_func)(php_stream_context *context,
FG(default_context) ? FG(default_context) : \ FG(default_context) ? FG(default_context) : \
(FG(default_context) = php_stream_context_alloc()) ) (FG(default_context) = php_stream_context_alloc()) )
#define php_stream_context_to_zval(context, zval) { ZVAL_RES(zval, (context)->res); GC_REFCOUNT((context)->res)++; } #define php_stream_context_to_zval(context, zval) { ZVAL_RES(zval, (context)->res); GC_ADDREF((context)->res); }
typedef struct _php_stream_notifier php_stream_notifier; typedef struct _php_stream_notifier php_stream_notifier;

View file

@ -120,12 +120,12 @@ PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream *
*stream = (php_stream*)le->ptr; *stream = (php_stream*)le->ptr;
ZEND_HASH_FOREACH_PTR(&EG(regular_list), regentry) { ZEND_HASH_FOREACH_PTR(&EG(regular_list), regentry) {
if (regentry->ptr == le->ptr) { if (regentry->ptr == le->ptr) {
GC_REFCOUNT(regentry)++; GC_ADDREF(regentry);
(*stream)->res = regentry; (*stream)->res = regentry;
return PHP_STREAM_PERSISTENT_SUCCESS; return PHP_STREAM_PERSISTENT_SUCCESS;
} }
} ZEND_HASH_FOREACH_END(); } ZEND_HASH_FOREACH_END();
GC_REFCOUNT(le)++; GC_ADDREF(le);
(*stream)->res = zend_register_resource(*stream, le_pstream); (*stream)->res = zend_register_resource(*stream, le_pstream);
} }
return PHP_STREAM_PERSISTENT_SUCCESS; return PHP_STREAM_PERSISTENT_SUCCESS;
@ -2127,7 +2127,7 @@ PHPAPI php_stream_context *php_stream_context_set(php_stream *stream, php_stream
if (context) { if (context) {
stream->ctx = context->res; stream->ctx = context->res;
GC_REFCOUNT(context->res)++; GC_ADDREF(context->res);
} else { } else {
stream->ctx = NULL; stream->ctx = NULL;
} }

View file

@ -293,7 +293,7 @@ static void user_stream_create_object(struct php_user_stream_wrapper *uwrap, php
if (context) { if (context) {
add_property_resource(object, "context", context->res); add_property_resource(object, "context", context->res);
GC_REFCOUNT(context->res)++; GC_ADDREF(context->res);
} else { } else {
add_property_null(object, "context"); add_property_null(object, "context");
} }

View file

@ -835,7 +835,7 @@ static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t
if (xparam->outputs.client) { if (xparam->outputs.client) {
xparam->outputs.client->ctx = stream->ctx; xparam->outputs.client->ctx = stream->ctx;
if (stream->ctx) { if (stream->ctx) {
GC_REFCOUNT(stream->ctx)++; GC_ADDREF(stream->ctx);
} }
} }
} }

View file

@ -580,10 +580,10 @@ static PHP_FUNCTION(phpdbg_get_executable)
zend_hash_add_empty_element(files, zval_get_string(filename)); zend_hash_add_empty_element(files, zval_get_string(filename));
} ZEND_HASH_FOREACH_END(); } ZEND_HASH_FOREACH_END();
} else { } else {
GC_REFCOUNT(files)++; GC_ADDREF(files);
} }
} else { } else {
GC_REFCOUNT(files)++; GC_ADDREF(files);
} }
array_init(return_value); array_init(return_value);
@ -632,7 +632,7 @@ static PHP_FUNCTION(phpdbg_get_executable)
} }
} ZEND_HASH_FOREACH_END(); } ZEND_HASH_FOREACH_END();
if (!--GC_REFCOUNT(files)) { if (!GC_DELREF(files)) {
zend_hash_destroy(files); zend_hash_destroy(files);
} }
} }

View file

@ -1692,7 +1692,7 @@ int phpdbg_interactive(zend_bool allow_async_unsafe, char *input) /* {{{ */
backup_opline = EG(current_execute_data)->opline; \ backup_opline = EG(current_execute_data)->opline; \
} \ } \
before_ex = EG(opline_before_exception); \ before_ex = EG(opline_before_exception); \
++GC_REFCOUNT(exception); \ GC_ADDREF(exception); \
zend_clear_exception(); \ zend_clear_exception(); \
} \ } \
if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) { \ if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) { \