summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2014-03-19 17:00:28 +0400
committerDmitry Stogov <dmitry@zend.com>2014-03-19 17:00:28 +0400
commitb7938ab1bd765897bd6f08a48a8aea494a961ea9 (patch)
tree22f8034d42dfac8f03b4bb6d6573e5a7f6361ac8
parent2e3e96b24bb1c547362af53b952f823f451e6bce (diff)
downloadphp-git-b7938ab1bd765897bd6f08a48a8aea494a961ea9.tar.gz
Refactored GC (incomplete)
-rw-r--r--Zend/zend.h14
-rw-r--r--Zend/zend_closures.c1
-rw-r--r--Zend/zend_execute.c26
-rw-r--r--Zend/zend_execute.h6
-rw-r--r--Zend/zend_gc.c894
-rw-r--r--Zend/zend_gc.h48
-rw-r--r--Zend/zend_generators.c2
-rw-r--r--Zend/zend_objects.c3
-rw-r--r--Zend/zend_objects_API.c19
-rw-r--r--Zend/zend_objects_API.h1
-rw-r--r--Zend/zend_operators.c5
-rw-r--r--Zend/zend_string.h2
-rw-r--r--Zend/zend_types.h22
-rw-r--r--Zend/zend_variables.c155
-rw-r--r--Zend/zend_variables.h6
-rw-r--r--Zend/zend_vm_def.h12
-rw-r--r--Zend/zend_vm_execute.h75
-rw-r--r--ext/date/php_date.c4
-rw-r--r--ext/reflection/php_reflection.c1
-rw-r--r--ext/spl/spl_array.c1
-rw-r--r--ext/spl/spl_directory.c1
-rw-r--r--ext/spl/spl_dllist.c1
-rw-r--r--ext/spl/spl_fixedarray.c1
-rw-r--r--ext/spl/spl_heap.c1
-rw-r--r--ext/spl/spl_iterators.c2
-rw-r--r--ext/spl/spl_observer.c1
-rw-r--r--ext/standard/array.c4
27 files changed, 548 insertions, 760 deletions
diff --git a/Zend/zend.h b/Zend/zend.h
index 261a77bd9a..90cf94d8f2 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -681,6 +681,16 @@ END_EXTERN_C()
zval_copy_ctor(__z1); \
} while (0)
+#define ZVAL_UNREF(z) do { \
+ zval *_z = (z); \
+ zend_reference *ref; \
+ ZEND_ASSERT(Z_ISREF_P(_z)); \
+ ref = Z_REF_P(_z); \
+ ZVAL_COPY_VALUE(_z, &ref->val); \
+ GC_REMOVE_FROM_BUFFER(ref); \
+ efree(ref); \
+ } while (0)
+
// TODO: invalud ???
#define INIT_PZVAL_COPY(z, v) \
do { \
@@ -720,9 +730,7 @@ END_EXTERN_C()
zval *__zv = (zv); \
if (Z_ISREF_P(__zv)) { \
if (Z_REFCOUNT_P(__zv) == 1) { \
- zend_reference *ref = Z_REF_P(__zv); \
- ZVAL_COPY_VALUE(__zv, &ref->val); \
- efree(ref); \
+ ZVAL_UNREF(__zv); \
} else { \
zval *ref = Z_REFVAL_P(__zv); \
Z_DELREF_P(__zv); \
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index 8f60e670e5..61808927f1 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -242,6 +242,7 @@ static void zend_closure_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
zval_ptr_dtor(&closure->this_ptr);
}
+ GC_REMOVE_FROM_BUFFER(closure);
efree(closure);
}
/* }}} */
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 5176817041..12c7625744 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -96,9 +96,7 @@ static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC)
if (Z_REFCOUNTED_P(z)) {
if (!Z_DELREF_P(z)) {
ZEND_ASSERT(z != &EG(uninitialized_zval));
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
- efree(z);
}
}
}
@@ -911,11 +909,10 @@ static inline zval* zend_assign_tmp_to_variable(zval *variable_ptr, zval *value
GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
ZVAL_COPY_VALUE(variable_ptr, value);
} else {
- zval garbage;
+ zend_refcounted *garbage = Z_COUNTED_P(variable_ptr);
- ZVAL_COPY_VALUE(&garbage, variable_ptr);
ZVAL_COPY_VALUE(variable_ptr, value);
- _zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
+ _zval_dtor_func(garbage ZEND_FILE_LINE_CC);
}
return variable_ptr;
}
@@ -946,21 +943,20 @@ static inline zval* zend_assign_const_to_variable(zval *variable_ptr, zval *valu
zval_copy_ctor(variable_ptr);
}
} else {
- zval garbage;
+ zend_refcounted *garbage = Z_COUNTED_P(variable_ptr);
- ZVAL_COPY_VALUE(&garbage, variable_ptr);
ZVAL_COPY_VALUE(variable_ptr, value);
if (Z_REFCOUNTED_P(value)) {
zval_copy_ctor(variable_ptr);
}
- _zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
+ _zval_dtor_func(garbage ZEND_FILE_LINE_CC);
}
return variable_ptr;
}
static inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value TSRMLS_DC)
{
- zval garbage;
+ zend_refcounted *garbage;
int is_ref = 0;
if (EXPECTED(!Z_REFCOUNTED_P(variable_ptr))) {
@@ -982,7 +978,7 @@ static inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value TSRM
Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr, value TSRMLS_CC);
} else if (EXPECTED(variable_ptr != value)) {
if (Z_REFCOUNT_P(variable_ptr)==1) {
- ZVAL_COPY_VALUE(&garbage, variable_ptr);
+ garbage = Z_COUNTED_P(variable_ptr);
if (EXPECTED(!Z_ISREF_P(value))) {
if (!is_ref) {
ZVAL_COPY(variable_ptr, value);
@@ -992,15 +988,13 @@ static inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value TSRM
} else {
if (Z_REFCOUNT_P(value) == 1) {
//??? auto dereferencing
- zend_reference *ref = Z_REF_P(value);
- ZVAL_COPY_VALUE(value, Z_REFVAL_P(value));
+ ZVAL_UNREF(value);
ZVAL_COPY(variable_ptr, value);
- efree(ref);
} else {
ZVAL_DUP(variable_ptr, Z_REFVAL_P(value));
}
}
- _zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
+ _zval_dtor_func(garbage ZEND_FILE_LINE_CC);
} else { /* we need to split */
Z_DELREF_P(variable_ptr);
GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
@@ -1015,10 +1009,8 @@ assign_simple:
assign_ref:
if (Z_REFCOUNT_P(value) == 1) {
//??? auto dereferencing
- zend_reference *ref = Z_REF_P(value);
- ZVAL_COPY_VALUE(value, Z_REFVAL_P(value));
+ ZVAL_UNREF(value);
ZVAL_COPY(variable_ptr, value);
- efree(ref);
} else {
ZVAL_DUP(variable_ptr, Z_REFVAL_P(value));
}
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h
index 5c9651feb8..10bc3f8c23 100644
--- a/Zend/zend_execute.h
+++ b/Zend/zend_execute.h
@@ -79,8 +79,7 @@ static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC
(type != IS_STRING || !IS_INTERNED(Z_STR_P(zval_ptr)))) {
if (!Z_DELREF_P(zval_ptr)) {
ZEND_ASSERT(zval_ptr != &EG(uninitialized_zval));
- GC_REMOVE_ZVAL_FROM_BUFFER(zval_ptr);
- _zval_dtor_func_for_ptr(zval_ptr ZEND_FILE_LINE_CC);
+ _zval_dtor_func_for_ptr(Z_COUNTED_P(zval_ptr) ZEND_FILE_LINE_CC);
} else {
if (Z_REFCOUNT_P(zval_ptr) == 1 && Z_TYPE_P(zval_ptr) == IS_REFERENCE) {
/* convert reference to regular value */
@@ -98,8 +97,7 @@ static zend_always_inline void i_zval_ptr_dtor_nogc(zval *zval_ptr ZEND_FILE_LIN
if (Z_REFCOUNTED_P(zval_ptr)) {
if (!Z_DELREF_P(zval_ptr)) {
ZEND_ASSERT(zval_ptr != &EG(uninitialized_zval));
- GC_REMOVE_ZVAL_FROM_BUFFER(zval_ptr);
- _zval_dtor_func_for_ptr(zval_ptr ZEND_FILE_LINE_CC);
+ _zval_dtor_func_for_ptr(Z_COUNTED_P(zval_ptr) ZEND_FILE_LINE_CC);
} else {
if (Z_REFCOUNT_P(zval_ptr) == 1 && Z_TYPE_P(zval_ptr) == IS_REFERENCE) {
/* convert reference to regular value */
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c
index 4b31f979da..57f9455fd1 100644
--- a/Zend/zend_gc.c
+++ b/Zend/zend_gc.c
@@ -30,10 +30,10 @@ ZEND_API int gc_globals_id;
ZEND_API zend_gc_globals gc_globals;
#endif
-#define GC_REMOVE_FROM_BUFFER(current) \
- gc_remove_from_buffer((current) TSRMLS_CC)
+#define GC_REMOVE_FROM_ROOTS(current) \
+ gc_remove_from_roots((current) TSRMLS_CC)
-static zend_always_inline void gc_remove_from_buffer(gc_root_buffer *root TSRMLS_DC)
+static zend_always_inline void gc_remove_from_roots(gc_root_buffer *root TSRMLS_DC)
{
root->next->prev = root->prev;
root->prev->next = root->next;
@@ -60,10 +60,13 @@ static void gc_globals_ctor_ex(zend_gc_globals *gc_globals TSRMLS_DC)
gc_globals->roots.next = &gc_globals->roots;
gc_globals->roots.prev = &gc_globals->roots;
gc_globals->unused = NULL;
- gc_globals->zval_to_free = NULL;
- gc_globals->free_list = NULL;
+//??? gc_globals->zval_to_free = NULL;
+//??? gc_globals->free_list = NULL;
gc_globals->next_to_free = NULL;
+ gc_globals->to_free.next = &gc_globals->to_free;
+ gc_globals->to_free.prev = &gc_globals->to_free;
+
gc_globals->gc_runs = 0;
gc_globals->collected = 0;
@@ -71,13 +74,9 @@ static void gc_globals_ctor_ex(zend_gc_globals *gc_globals TSRMLS_DC)
gc_globals->root_buf_length = 0;
gc_globals->root_buf_peak = 0;
gc_globals->zval_possible_root = 0;
- gc_globals->zobj_possible_root = 0;
gc_globals->zval_buffered = 0;
- gc_globals->zobj_buffered = 0;
gc_globals->zval_remove_from_buffer = 0;
- gc_globals->zobj_remove_from_buffer = 0;
gc_globals->zval_marked_grey = 0;
- gc_globals->zobj_marked_grey = 0;
#endif
}
@@ -106,23 +105,22 @@ ZEND_API void gc_reset(TSRMLS_D)
GC_G(root_buf_length) = 0;
GC_G(root_buf_peak) = 0;
GC_G(zval_possible_root) = 0;
- GC_G(zobj_possible_root) = 0;
GC_G(zval_buffered) = 0;
- GC_G(zobj_buffered) = 0;
GC_G(zval_remove_from_buffer) = 0;
- GC_G(zobj_remove_from_buffer) = 0;
GC_G(zval_marked_grey) = 0;
- GC_G(zobj_marked_grey) = 0;
#endif
GC_G(roots).next = &GC_G(roots);
GC_G(roots).prev = &GC_G(roots);
+ GC_G(to_free).next = &GC_G(to_free);
+ GC_G(to_free).prev = &GC_G(to_free);
+
if (GC_G(buf)) {
GC_G(unused) = NULL;
GC_G(first_unused) = GC_G(buf) + 1;
- GC_G(zval_to_free) = NULL;
+//??? GC_G(zval_to_free) = NULL;
} else {
GC_G(unused) = NULL;
GC_G(first_unused) = NULL;
@@ -139,12 +137,17 @@ ZEND_API void gc_init(TSRMLS_D)
}
}
-ZEND_API void gc_zval_possible_root(zend_refcounted *ref TSRMLS_DC)
+ZEND_API void gc_possible_root(zend_refcounted *ref TSRMLS_DC)
{
- if (UNEXPECTED(GC_G(free_list) != NULL &&
- GC_ADDRESS(ref->u.v.buffer) &&
- GC_GET_COLOR(ref->u.v.buffer) == GC_BLACK &&
- GC_ADDRESS(ref->u.v.buffer) >= GC_G(last_unused) - GC_G(buf))) {
+ /* don't colect references (collext arrays and objects) */
+//??? if (ref->u.v.type == IS_REFERENCE) {
+//??? ZEND_ASSERT(Z_REFCOUNTED(((zend_reference*)ref)->val));
+//??? ref = Z_COUNTED(((zend_reference*)ref)->val);
+//??? }
+
+ if (UNEXPECTED(GC_ADDRESS(ref->u.v.gc_info) &&
+ GC_GET_COLOR(ref->u.v.gc_info) == GC_BLACK &&
+ GC_ADDRESS(ref->u.v.gc_info) >= GC_G(last_unused) - GC_G(buf))) {
/* The given zval is a garbage that is going to be deleted by
* currently running GC */
return;
@@ -152,10 +155,10 @@ ZEND_API void gc_zval_possible_root(zend_refcounted *ref TSRMLS_DC)
GC_BENCH_INC(zval_possible_root);
- if (GC_GET_COLOR(ref->u.v.buffer) != GC_PURPLE) {
- GC_SET_PURPLE(ref->u.v.buffer);
+ if (GC_GET_COLOR(ref->u.v.gc_info) != GC_PURPLE) {
+ GC_SET_PURPLE(ref->u.v.gc_info);
- if (!GC_ADDRESS(ref->u.v.buffer)) {
+ if (!GC_ADDRESS(ref->u.v.gc_info)) {
gc_root_buffer *newRoot = GC_G(unused);
if (newRoot) {
@@ -165,7 +168,7 @@ ZEND_API void gc_zval_possible_root(zend_refcounted *ref TSRMLS_DC)
GC_G(first_unused)++;
} else {
if (!GC_G(gc_enabled)) {
- GC_SET_BLACK(ref->u.v.buffer);
+ GC_SET_BLACK(ref->u.v.gc_info);
return;
}
ref->refcount++;
@@ -175,7 +178,7 @@ ZEND_API void gc_zval_possible_root(zend_refcounted *ref TSRMLS_DC)
if (!newRoot) {
return;
}
- GC_SET_PURPLE(ref->u.v.buffer);
+ GC_SET_PURPLE(ref->u.v.gc_info);
GC_G(unused) = newRoot->prev;
}
@@ -184,7 +187,7 @@ ZEND_API void gc_zval_possible_root(zend_refcounted *ref TSRMLS_DC)
GC_G(roots).next->prev = newRoot;
GC_G(roots).next = newRoot;
- GC_SET_ADDRESS(ref->u.v.buffer, newRoot - GC_G(buf));
+ GC_SET_ADDRESS(ref->u.v.gc_info, newRoot - GC_G(buf));
newRoot->ref = ref;
@@ -195,87 +198,27 @@ ZEND_API void gc_zval_possible_root(zend_refcounted *ref TSRMLS_DC)
}
}
-//???
-#if 0
-ZEND_API void gc_zobj_possible_root(zval *zv TSRMLS_DC)
+ZEND_API void gc_remove_from_buffer(zend_refcounted *ref TSRMLS_DC)
{
- struct _store_object *obj;
-
- if (UNEXPECTED(Z_OBJ_HT_P(zv)->get_gc == NULL ||
- EG(objects_store).object_buckets == NULL)) {
- return;
- }
-
- GC_BENCH_INC(zobj_possible_root);
-
- obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zv)].bucket.obj;
- if (GC_GET_COLOR(obj->buffered) != GC_PURPLE) {
- GC_SET_PURPLE(obj->buffered);
- if (!GC_ADDRESS(obj->buffered)) {
- gc_root_buffer *newRoot = GC_G(unused);
-
- if (newRoot) {
- GC_G(unused) = newRoot->prev;
- } else if (GC_G(first_unused) != GC_G(last_unused)) {
- newRoot = GC_G(first_unused);
- GC_G(first_unused)++;
- } else {
- if (!GC_G(gc_enabled)) {
- GC_ZVAL_SET_BLACK(zv);
- return;
- }
- zv->refcount__gc++;
- gc_collect_cycles(TSRMLS_C);
- zv->refcount__gc--;
- newRoot = GC_G(unused);
- if (!newRoot) {
- return;
- }
- obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zv)].bucket.obj;
- GC_SET_PURPLE(obj->buffered);
- GC_G(unused) = newRoot->prev;
- }
-
- newRoot->next = GC_G(roots).next;
- newRoot->prev = &GC_G(roots);
- GC_G(roots).next->prev = newRoot;
- GC_G(roots).next = newRoot;
-
- GC_SET_ADDRESS(obj->buffered, newRoot);
-
- newRoot->handle = Z_OBJ_HANDLE_P(zv);
- newRoot->u.handlers = Z_OBJ_HT_P(zv);
+ gc_root_buffer *root;
- GC_BENCH_INC(zobj_buffered);
- GC_BENCH_INC(root_buf_length);
- GC_BENCH_PEAK(root_buf_peak, root_buf_length);
- }
- }
-}
-#endif
-
-ZEND_API void gc_remove_zval_from_buffer(zend_refcounted *ref TSRMLS_DC)
-{
-//??? gc_root_buffer* root_buffer = GC_ADDRESS(ref->u.v.buffer);
-
- if (UNEXPECTED(GC_G(free_list) != NULL &&
- GC_GET_COLOR(ref->u.v.buffer) == GC_BLACK &&
- GC_ADDRESS(ref->u.v.buffer) >= GC_G(last_unused) - GC_G(buf))) {
+ if (UNEXPECTED(GC_GET_COLOR(ref->u.v.gc_info) == GC_BLACK &&
+ GC_ADDRESS(ref->u.v.gc_info) >= GC_G(last_unused) - GC_G(buf))) {
/* The given zval is a garbage that is going to be deleted by
* currently running GC */
-//??? if (GC_G(next_to_free) == (zval_gc_info*)zv) {
-//??? GC_G(next_to_free) = ((zval_gc_info*)zv)->u.next;
-//??? }
return;
}
+//???
+ root = GC_G(buf) + GC_ADDRESS(ref->u.v.gc_info);
+ if (GC_G(next_to_free) == root) {
+ GC_G(next_to_free) = root->next;
+ }
GC_BENCH_INC(zval_remove_from_buffer);
- GC_REMOVE_FROM_BUFFER(GC_G(buf) + GC_ADDRESS(ref->u.v.buffer));
- ref->u.v.buffer = 0;
+ GC_REMOVE_FROM_ROOTS(root);
+ ref->u.v.gc_info = 0;
}
-//???
-#if 0
-static void zval_scan_black(zval *pz TSRMLS_DC)
+static void gc_scan_black(zend_refcounted *ref TSRMLS_DC)
{
HashTable *ht;
uint idx;
@@ -283,212 +226,156 @@ static void zval_scan_black(zval *pz TSRMLS_DC)
tail_call:
ht = NULL;
- GC_ZVAL_SET_BLACK(pz);
+ GC_SET_BLACK(ref->u.v.gc_info);
- if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
+ if (ref->u.v.type == IS_OBJECT && EG(objects_store).object_buckets) {
zend_object_get_gc_t get_gc;
- struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
+ zend_object *obj = (zend_object*)ref;
- obj->refcount++;
- if (GC_GET_COLOR(obj->buffered) != GC_BLACK) {
- GC_SET_BLACK(obj->buffered);
- if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
- int i, n;
- zval **table;
- HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
+ if (EXPECTED(IS_VALID(EG(objects_store).object_buckets[obj->handle]) &&
+ (get_gc = obj->handlers->get_gc) != NULL)) {
+ int i, n;
+ zval *table;
+ zval tmp;
+ HashTable *props;
- while (n > 0 && !table[n-1]) n--;
- for (i = 0; i < n; i++) {
- if (table[i]) {
- pz = table[i];
- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
- pz->refcount__gc++;
- }
- if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) {
- if (!props && i == n - 1) {
- goto tail_call;
- } else {
- zval_scan_black(pz TSRMLS_CC);
- }
+ ZVAL_OBJ(&tmp, obj);
+ props = get_gc(&tmp, &table, &n TSRMLS_CC);
+ while (n > 0 && !Z_REFCOUNTED(table[n-1])) n--;
+ for (i = 0; i < n; i++) {
+ if (Z_REFCOUNTED(table[i])) {
+ ref = Z_COUNTED(table[i]);
+ if (ref->u.v.type != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
+ ref->refcount++;
+ }
+ if (GC_GET_COLOR(ref->u.v.gc_info) != GC_BLACK) {
+ if (!props && i == n - 1) {
+ goto tail_call;
+ } else {
+ gc_scan_black(ref TSRMLS_CC);
}
}
}
- if (!props) {
- return;
- }
- ht = props;
}
+ if (!props) {
+ return;
+ }
+ ht = props;
}
- } else if (Z_TYPE_P(pz) == IS_ARRAY) {
- if (Z_ARRVAL_P(pz) != &EG(symbol_table)) {
- ht = Z_ARRVAL_P(pz);
+ } else if (ref->u.v.type == IS_ARRAY) {
+ if ((zend_array*)ref != &EG(symbol_table)) {
+ ht = &((zend_array*)ref)->ht;
+ }
+ } else if (ref->u.v.type == IS_REFERENCE) {
+ if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
+ if (UNEXPECTED(!EG(objects_store).object_buckets) &&
+ Z_TYPE(((zend_reference*)ref)->val) == IS_OBJECT) {
+ return;
+ }
+ ref = Z_COUNTED(((zend_reference*)ref)->val);
+ if (ref->u.v.type != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
+ ref->refcount++;
+ }
+ if (GC_GET_COLOR(ref->u.v.gc_info) != GC_BLACK) {
+ goto tail_call;
+ }
}
+ return;
}
if (!ht) return;
for (idx = 0; idx < ht->nNumUsed; idx++) {
p = ht->arData + idx;
- if (!p->xData) continue;
- pz = (zval*)p->xData;
- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
- pz->refcount__gc++;
+ if (!Z_REFCOUNTED(p->val)) continue;
+ ref = Z_COUNTED(p->val);
+ if (ref->u.v.type != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
+ ref->refcount++;
}
- if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) {
+ if (GC_GET_COLOR(ref->u.v.gc_info) != GC_BLACK) {
if (idx == ht->nNumUsed-1) {
goto tail_call;
} else {
- zval_scan_black(pz TSRMLS_CC);
+ gc_scan_black(ref TSRMLS_CC);
}
}
}
}
-static void zobj_scan_black(struct _store_object *obj, zval *pz TSRMLS_DC)
-{
- uint idx;
- Bucket *p;
- zend_object_get_gc_t get_gc;
-
- GC_SET_BLACK(obj->buffered);
- if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
- int i, n;
- zval **table;
- HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
-
- for (i = 0; i < n; i++) {
- if (table[i]) {
- pz = table[i];
- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
- pz->refcount__gc++;
- }
- if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) {
- zval_scan_black(pz TSRMLS_CC);
- }
- }
- }
- if (!props) {
- return;
- }
- for (idx = 0; idx < props->nNumUsed; idx++) {
- p = props->arData + idx;
- if (!p->xData) continue;
- pz = (zval*)p->xData;
- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
- pz->refcount__gc++;
- }
- if (GC_ZVAL_GET_COLOR(pz) != GC_BLACK) {
- zval_scan_black(pz TSRMLS_CC);
- }
- }
- }
-}
-
-static void zval_mark_grey(zval *pz TSRMLS_DC)
+static void gc_mark_grey(zend_refcounted *ref TSRMLS_DC)
{
HashTable *ht;
uint idx;
Bucket *p;
tail_call:
- if (GC_ZVAL_GET_COLOR(pz) != GC_GREY) {
+ if (GC_GET_COLOR(ref->u.v.gc_info) != GC_GREY) {
ht = NULL;
GC_BENCH_INC(zval_marked_grey);
- GC_ZVAL_SET_COLOR(pz, GC_GREY);
+ GC_SET_COLOR(ref->u.v.gc_info, GC_GREY);
- if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
+ if (ref->u.v.type == IS_OBJECT && EG(objects_store).object_buckets) {
zend_object_get_gc_t get_gc;
- struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
-
- obj->refcount--;
- if (GC_GET_COLOR(obj->buffered) != GC_GREY) {
- GC_BENCH_INC(zobj_marked_grey);
- GC_SET_COLOR(obj->buffered, GC_GREY);
- if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
- int i, n;
- zval **table;
- HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
+ zend_object *obj = (zend_object*)ref;
- while (n > 0 && !table[n-1]) n--;
- for (i = 0; i < n; i++) {
- if (table[i]) {
- pz = table[i];
- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
- pz->refcount__gc--;
- }
- if (!props && i == n - 1) {
- goto tail_call;
- } else {
- zval_mark_grey(pz TSRMLS_CC);
- }
+ if (EXPECTED(IS_VALID(EG(objects_store).object_buckets[obj->handle]) &&
+ (get_gc = obj->handlers->get_gc) != NULL)) {
+ int i, n;
+ zval *table;
+ zval tmp;
+
+ ZVAL_OBJ(&tmp, obj);
+ HashTable *props = get_gc(&tmp, &table, &n TSRMLS_CC);
+
+ while (n > 0 && !Z_REFCOUNTED(table[n-1])) n--;
+ for (i = 0; i < n; i++) {
+ if (Z_REFCOUNTED(table[i])) {
+ ref = Z_COUNTED(table[i]);
+ if (ref->u.v.type != IS_ARRAY || ((zend_array*)ref) != &EG(symbol_table)) {
+ ref->refcount--;
+ }
+ if (!props && i == n - 1) {
+ goto tail_call;
+ } else {
+ gc_mark_grey(ref TSRMLS_CC);
}
}
- if (!props) {
- return;
- }
- ht = props;
}
+ if (!props) {
+ return;
+ }
+ ht = props;
}
- } else if (Z_TYPE_P(pz) == IS_ARRAY) {
- if (Z_ARRVAL_P(pz) == &EG(symbol_table)) {
- GC_ZVAL_SET_BLACK(pz);
+ } else if (ref->u.v.type == IS_ARRAY) {
+ if (((zend_array*)ref) == &EG(symbol_table)) {
+ GC_SET_BLACK(ref->u.v.gc_info);
} else {
- ht = Z_ARRVAL_P(pz);
+ ht = &((zend_array*)ref)->ht;
}
+ } else if (ref->u.v.type == IS_REFERENCE) {
+ if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
+ if (UNEXPECTED(!EG(objects_store).object_buckets) &&
+ Z_TYPE(((zend_reference*)ref)->val) == IS_OBJECT) {
+ return;
+ }
+ ref = Z_COUNTED(((zend_reference*)ref)->val);
+ if (ref->u.v.type != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
+ ref->refcount--;
+ }
+ goto tail_call;
+ }
+ return;
}
if (!ht) return;
for (idx = 0; idx < ht->nNumUsed; idx++) {
p = ht->arData + idx;
- if (!p->xData) continue;
- pz = (zval*)p->xData;
- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
- pz->refcount__gc--;
+ if (!Z_REFCOUNTED(p->val)) continue;
+ ref = Z_COUNTED(p->val);
+ if (ref->u.v.type != IS_ARRAY || ((zend_array*)ref) != &EG(symbol_table)) {
+ ref->refcount--;
}
if (idx == ht->nNumUsed-1) {
goto tail_call;
} else {
- zval_mark_grey(pz TSRMLS_CC);
- }
- }
- }
-}
-
-static void zobj_mark_grey(struct _store_object *obj, zval *pz TSRMLS_DC)
-{
- uint idx;
- Bucket *p;
- zend_object_get_gc_t get_gc;
-
- if (GC_GET_COLOR(obj->buffered) != GC_GREY) {
- GC_BENCH_INC(zobj_marked_grey);
- GC_SET_COLOR(obj->buffered, GC_GREY);
- if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
- int i, n;
- zval **table;
- HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
-
- for (i = 0; i < n; i++) {
- if (table[i]) {
- pz = table[i];
- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
- pz->refcount__gc--;
- }
- zval_mark_grey(pz TSRMLS_CC);
- }
- }
- if (!props) {
- return;
- }
- for (idx = 0; idx < props->nNumUsed; idx++) {
- p = props->arData + idx;
- if (!p->xData) continue;
- pz = (zval*)p->xData;
- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
- pz->refcount__gc--;
- }
- zval_mark_grey(pz TSRMLS_CC);
+ gc_mark_grey(ref TSRMLS_CC);
}
}
}
@@ -499,137 +386,85 @@ static void gc_mark_roots(TSRMLS_D)
gc_root_buffer *current = GC_G(roots).next;
while (current != &GC_G(roots)) {
- if (current->handle) {
- if (EG(objects_store).object_buckets) {
- struct _store_object *obj = &EG(objects_store).object_buckets[current->handle].bucket.obj;
-
- if (GC_GET_COLOR(obj->buffered) == GC_PURPLE) {
- zval z;
-
- INIT_PZVAL(&z);
- Z_OBJ_HANDLE(z) = current->handle;
- Z_OBJ_HT(z) = current->u.handlers;
- zobj_mark_grey(obj, &z TSRMLS_CC);
- } else {
- GC_SET_ADDRESS(obj->buffered, NULL);
- GC_REMOVE_FROM_BUFFER(current);
- }
- }
+ if (GC_GET_COLOR(current->ref->u.v.gc_info) == GC_PURPLE) {
+ gc_mark_grey(current->ref TSRMLS_CC);
} else {
- if (GC_ZVAL_GET_COLOR(current->u.pz) == GC_PURPLE) {
- zval_mark_grey(current->u.pz TSRMLS_CC);
- } else {
- GC_ZVAL_SET_ADDRESS(current->u.pz, NULL);
- GC_REMOVE_FROM_BUFFER(current);
- }
+ GC_SET_ADDRESS(current->ref->u.v.gc_info, 0);
+ GC_REMOVE_FROM_ROOTS(current);
}
current = current->next;
}
}
-static void zval_scan(zval *pz TSRMLS_DC)
+static void gc_scan(zend_refcounted *ref TSRMLS_DC)
{
HashTable *ht;
uint idx;
Bucket *p;
tail_call:
- if (GC_ZVAL_GET_COLOR(pz) == GC_GREY) {
+ if (GC_GET_COLOR(ref->u.v.gc_info) == GC_GREY) {
ht = NULL;
- if (pz->refcount__gc > 0) {
- zval_scan_black(pz TSRMLS_CC);
+ if (ref->refcount > 0) {
+ gc_scan_black(ref TSRMLS_CC);
} else {
- GC_ZVAL_SET_COLOR(pz, GC_WHITE);
- if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
+ GC_SET_COLOR(ref->u.v.gc_info, GC_WHITE);
+ if (ref->u.v.type == IS_OBJECT && EG(objects_store).object_buckets) {
zend_object_get_gc_t get_gc;
- struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
-
- if (GC_GET_COLOR(obj->buffered) == GC_GREY) {
- if (obj->refcount > 0) {
- zobj_scan_black(obj, pz TSRMLS_CC);
- } else {
- GC_SET_COLOR(obj->buffered, GC_WHITE);
- if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
- int i, n;
- zval **table;
- HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
-
- while (n > 0 && !table[n-1]) n--;
- for (i = 0; i < n; i++) {
- if (table[i]) {
- pz = table[i];
- if (!props && i == n - 1) {
- goto tail_call;
- } else {
- zval_scan(pz TSRMLS_CC);
- }
- }
- }
- if (!props) {
- return;
+ zend_object *obj = (zend_object*)ref;
+
+ if (EXPECTED(IS_VALID(EG(objects_store).object_buckets[obj->handle]) &&
+ (get_gc = obj->handlers->get_gc) != NULL)) {
+ int i, n;
+ zval *table;
+ zval tmp;
+ HashTable *props;
+
+ ZVAL_OBJ(&tmp, obj);
+ props = get_gc(&tmp, &table, &n TSRMLS_CC);
+ while (n > 0 && !Z_REFCOUNTED(table[n-1])) n--;
+ for (i = 0; i < n; i++) {
+ if (Z_REFCOUNTED(table[i])) {
+ ref = Z_COUNTED(table[i]);
+ if (!props && i == n - 1) {
+ goto tail_call;
+ } else {
+ gc_scan(ref TSRMLS_CC);
}
- ht = props;
}
}
+ if (!props) {
+ return;
+ }
+ ht = props;
}
- } else if (Z_TYPE_P(pz) == IS_ARRAY) {
- if (Z_ARRVAL_P(pz) == &EG(symbol_table)) {
- GC_ZVAL_SET_BLACK(pz);
+ } else if (ref->u.v.type == IS_ARRAY) {
+ if ((zend_array*)ref == &EG(symbol_table)) {
+ GC_SET_BLACK(ref->u.v.gc_info);
} else {
- ht = Z_ARRVAL_P(pz);
+ ht = &((zend_array*)ref)->ht;
+ }
+ } else if (ref->u.v.type == IS_REFERENCE) {
+ if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
+ if (UNEXPECTED(!EG(objects_store).object_buckets) &&
+ Z_TYPE(((zend_reference*)ref)->val) == IS_OBJECT) {
+ return;
+ }
+ ref = Z_COUNTED(((zend_reference*)ref)->val);
+ goto tail_call;
}
+ return;
}
}
if (!ht) return;
for (idx = 0; idx < ht->nNumUsed; idx++) {
p = ht->arData + idx;
- if (!p->xData) continue;
+ if (!Z_REFCOUNTED(p->val)) continue;
+ ref = Z_COUNTED(p->val);
if (idx == ht->nNumUsed-1) {
- pz = (zval*)p->xData;
goto tail_call;
} else {
- zval_scan((zval*)p->xData TSRMLS_CC);
- }
- }
- }
-}
-
-static void zobj_scan(zval *pz TSRMLS_DC)
-{
- uint idx;
- Bucket *p;
- zend_object_get_gc_t get_gc;
-
- if (EG(objects_store).object_buckets) {
- struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
-
- if (GC_GET_COLOR(obj->buffered) == GC_GREY) {
- if (obj->refcount > 0) {
- zobj_scan_black(obj, pz TSRMLS_CC);
- } else {
- GC_SET_COLOR(obj->buffered, GC_WHITE);
- if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
- int i, n;
- zval **table;
- HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
-
- for (i = 0; i < n; i++) {
- if (table[i]) {
- pz = table[i];
- zval_scan(pz TSRMLS_CC);
- }
- }
- if (!props) {
- return;
- }
- for (idx = 0; idx < props->nNumUsed; idx++) {
- p = props->arData + idx;
- if (!p->xData) continue;
- zval_scan((zval*)p->xData TSRMLS_CC);
- }
- }
+ gc_scan(ref TSRMLS_CC);
}
}
}
@@ -640,258 +475,253 @@ static void gc_scan_roots(TSRMLS_D)
gc_root_buffer *current = GC_G(roots).next;
while (current != &GC_G(roots)) {
- if (current->handle) {
- zval z;
-
- INIT_PZVAL(&z);
- Z_OBJ_HANDLE(z) = current->handle;
- Z_OBJ_HT(z) = current->u.handlers;
- zobj_scan(&z TSRMLS_CC);
- } else {
- zval_scan(current->u.pz TSRMLS_CC);
- }
+ gc_scan(current->ref TSRMLS_CC);
current = current->next;
}
}
-static void zval_collect_white(zval *pz TSRMLS_DC)
+static int gc_collect_white(zend_refcounted *ref TSRMLS_DC)
{
+ int count = 0;
HashTable *ht;
uint idx;
Bucket *p;
tail_call:
- if (((zval_gc_info*)(pz))->u.buffered == (gc_root_buffer*)GC_WHITE) {
+ if (ref->u.v.gc_info == GC_WHITE) {
ht = NULL;
- GC_ZVAL_SET_BLACK(pz);
+ GC_SET_BLACK(ref->u.v.gc_info);
- if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
+ /* don't count references for compatibilty */
+ if (ref->u.v.type != IS_REFERENCE) {
+ count++;
+ }
+ /* put into list to free */
+//???
+// ref->gc_next = GC_G(zval_to_free);
+// GC_G(zval_to_free) = ref;
+ if (ref->u.v.type == IS_OBJECT && EG(objects_store).object_buckets) {
zend_object_get_gc_t get_gc;
- struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
-
- if (obj->buffered == (gc_root_buffer*)GC_WHITE) {
- /* PURPLE instead of BLACK to prevent buffering in nested gc calls */
- GC_SET_PURPLE(obj->buffered);
-
- if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
- int i, n;
- zval **table, *zv;
- HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
+ zend_object *obj = (zend_object*)ref;
- if (!props) {
- /* restore refcount and put into list to free */
- pz->refcount__gc++;
- ((zval_gc_info*)pz)->u.next = GC_G(zval_to_free);
- GC_G(zval_to_free) = (zval_gc_info*)pz;
- }
+ /* PURPLE instead of BLACK to prevent buffering in nested gc calls */
+//??? GC_SET_PURPLE(obj->gc.u.v.gc_info);
- while (n > 0 && !table[n-1]) n--;
- for (i = 0; i < n; i++) {
- if (table[i]) {
- zv = table[i];
- if (Z_TYPE_P(zv) != IS_ARRAY || Z_ARRVAL_P(zv) != &EG(symbol_table)) {
- zv->refcount__gc++;
- }
- if (!props && i == n - 1) {
- pz = zv;
- goto tail_call;
- } else {
- zval_collect_white(zv TSRMLS_CC);
- }
+ if (EXPECTED(IS_VALID(EG(objects_store).object_buckets[obj->handle]) &&
+ (get_gc = obj->handlers->get_gc) != NULL)) {
+ int i, n;
+ zval *table;
+ zval tmp;
+ HashTable *props;
+
+ ZVAL_OBJ(&tmp, obj);
+ props = get_gc(&tmp, &table, &n TSRMLS_CC);
+ while (n > 0 && !Z_REFCOUNTED(table[n-1])) n--;
+ for (i = 0; i < n; i++) {
+ if (Z_REFCOUNTED(table[i])) {
+ ref = Z_COUNTED(table[i]);
+ if (ref->u.v.type != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
+ ref->refcount++;
+ }
+ if (!props && i == n - 1) {
+ goto tail_call;
+ } else {
+ count += gc_collect_white(ref TSRMLS_CC);
}
}
- if (!props) {
- return;
- }
- ht = props;
}
+ if (!props) {
+ return count;
+ }
+ ht = props;
}
- } else {
- if (Z_TYPE_P(pz) == IS_ARRAY) {
- ht = Z_ARRVAL_P(pz);
+ } else if (ref->u.v.type == IS_ARRAY) {
+ ht = &((zend_array*)ref)->ht;
+ } else if (ref->u.v.type == IS_REFERENCE) {
+ if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
+ if (UNEXPECTED(!EG(objects_store).object_buckets) &&
+ Z_TYPE(((zend_reference*)ref)->val) == IS_OBJECT) {
+ return count;
+ }
+ ref = Z_COUNTED(((zend_reference*)ref)->val);
+ if (ref->u.v.type != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
+ ref->refcount++;
+ }
+ goto tail_call;
}
+ return count;
}
- /* restore refcount and put into list to free */
- pz->refcount__gc++;
- ((zval_gc_info*)pz)->u.next = GC_G(zval_to_free);
- GC_G(zval_to_free) = (zval_gc_info*)pz;
-
- if (!ht) return;
-
+ if (!ht) return count;
for (idx = 0; idx < ht->nNumUsed; idx++) {
p = ht->arData + idx;
- if (!p->xData) continue;
- pz = (zval*)p->xData;
- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
- pz->refcount__gc++;
+ if (!Z_REFCOUNTED(p->val)) continue;
+ ref = Z_COUNTED(p->val);
+ if (ref->u.v.type != IS_ARRAY || (zend_array*)ref != &EG(symbol_table)) {
+ ref->refcount++;
}
if (idx == ht->nNumUsed-1) {
goto tail_call;
} else {
- zval_collect_white(pz TSRMLS_CC);
- }
- }
- }
-}
-
-static void zobj_collect_white(zval *pz TSRMLS_DC)
-{
- uint idx;
- Bucket *p;
-
- if (EG(objects_store).object_buckets) {
- zend_object_get_gc_t get_gc;
- struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
-
- if (obj->buffered == (gc_root_buffer*)GC_WHITE) {
- /* PURPLE instead of BLACK to prevent buffering in nested gc calls */
- GC_SET_PURPLE(obj->buffered);
-
- if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
- (get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
- int i, n;
- zval **table;
- HashTable *props = get_gc(pz, &table, &n TSRMLS_CC);
-
- for (i = 0; i < n; i++) {
- if (table[i]) {
- pz = table[i];
- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
- pz->refcount__gc++;
- }
- zval_collect_white(pz TSRMLS_CC);
- }
- }
- if (!props) {
- return;
- }
- for (idx = 0; idx < props->nNumUsed; idx++) {
- p = props->arData + idx;
- if (!p->xData) continue;
- pz = (zval*)p->xData;
- if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) {
- pz->refcount__gc++;
- }
- zval_collect_white(pz TSRMLS_CC);
- }
+ count += gc_collect_white(ref TSRMLS_CC);
}
}
}
+ return count;
}
-static void gc_collect_roots(TSRMLS_D)
+static int gc_collect_roots(TSRMLS_D)
{
+ int count = 0;
gc_root_buffer *current = GC_G(roots).next;
while (current != &GC_G(roots)) {
- if (current->handle) {
- if (EG(objects_store).object_buckets) {
- struct _store_object *obj = &EG(objects_store).object_buckets[current->handle].bucket.obj;
- zval z;
-
- GC_SET_ADDRESS(obj->buffered, NULL);
- INIT_PZVAL(&z);
- Z_OBJ_HANDLE(z) = current->handle;
- Z_OBJ_HT(z) = current->u.handlers;
- zobj_collect_white(&z TSRMLS_CC);
- }
+ GC_SET_ADDRESS(current->ref->u.v.gc_info, 0);
+ if (current->ref->u.v.gc_info == GC_WHITE) {
+ count += gc_collect_white(current->ref TSRMLS_CC);
+ GC_SET_ADDRESS(current->ref->u.v.gc_info, current - GC_G(buf));
} else {
- GC_ZVAL_SET_ADDRESS(current->u.pz, NULL);
- zval_collect_white(current->u.pz TSRMLS_CC);
+ GC_REMOVE_FROM_ROOTS(current);
}
-
- GC_REMOVE_FROM_BUFFER(current);
current = current->next;
}
+ /* relink remaining roots into list to free */
+ if (GC_G(roots).next != &GC_G(roots)) {
+ if (GC_G(to_free).next == &GC_G(to_free)) {
+ /* move roots into list to free */
+ GC_G(to_free).next = GC_G(roots).next;
+ GC_G(to_free).prev = GC_G(roots).prev;
+ GC_G(to_free).next->prev = &GC_G(to_free);
+ GC_G(to_free).prev->next = &GC_G(to_free);
+ } else {
+ /* add roots into list to free */
+//???
+ gc_root_buffer *p1 = GC_G(to_free).next;
+ gc_root_buffer *p2 = GC_G(to_free).prev;
+ gc_root_buffer *p3 = GC_G(roots).next;
+ gc_root_buffer *p4 = GC_G(roots).prev;
+
+ p2->next = p3;
+ p3->prev = p2;
+ p4->next = &GC_G(to_free);
+ GC_G(to_free).prev = p4;
+ }
+
+ GC_G(roots).next = &GC_G(roots);
+ GC_G(roots).prev = &GC_G(roots);
+ }
+ return count;
}
-#endif
-#define FREE_LIST_END ((zval_gc_info*)(~(zend_uintptr_t)GC_COLOR))
+//???#define FREE_LIST_END ((zend_refcounted*)(~(zend_uintptr_t)GC_COLOR))
+//???#define FREE_LIST_END NULL
ZEND_API int gc_collect_cycles(TSRMLS_D)
{
-//???
- return 0;
-#if 0
int count = 0;
if (GC_G(roots).next != &GC_G(roots)) {
- zval_gc_info *p, *q, *orig_free_list, *orig_next_to_free;
+ gc_root_buffer *current, *orig_next_to_free;
+ zend_refcounted *p;
+//??? zend_refcounted *p, *q, *orig_free_list, *orig_next_to_free;
if (GC_G(gc_active)) {
return 0;
}
GC_G(gc_runs)++;
- GC_G(zval_to_free) = FREE_LIST_END;
+//??? GC_G(zval_to_free) = FREE_LIST_END;
GC_G(gc_active) = 1;
gc_mark_roots(TSRMLS_C);
gc_scan_roots(TSRMLS_C);
- gc_collect_roots(TSRMLS_C);
+ count = gc_collect_roots(TSRMLS_C);
- orig_free_list = GC_G(free_list);
+//??? orig_free_list = GC_G(free_list);
orig_next_to_free = GC_G(next_to_free);
- p = GC_G(free_list) = GC_G(zval_to_free);
- GC_G(zval_to_free) = NULL;
+//??? p = GC_G(free_list) = GC_G(zval_to_free);
+//??? GC_G(zval_to_free) = NULL;
GC_G(gc_active) = 0;
/* First call destructors */
- while (p != FREE_LIST_END) {
- if (Z_TYPE(p->z) == IS_OBJECT) {
- if (EG(objects_store).object_buckets &&
- EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].valid &&
- EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount <= 0 &&
- EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.dtor &&
- !EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].destructor_called) {
-
- EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].destructor_called = 1;
- EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount++;
- EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.dtor(EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.object, Z_OBJ_HANDLE(p->z) TSRMLS_CC);
- EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount--;
+ current = GC_G(to_free).next;
+ while (current != &GC_G(to_free)) {
+ p = current->ref;
+ GC_G(next_to_free) = current->next;
+ if (p->u.v.type == IS_OBJECT) {
+ zend_object *obj = (zend_object*)p;
+
+ if (obj->handlers->dtor_obj &&
+ EG(objects_store).object_buckets &&
+ IS_VALID(EG(objects_store).object_buckets[obj->handle]) &&
+ !(obj->gc.u.v.flags & IS_OBJ_DESTRUCTOR_CALLED)) {
+
+ obj->gc.u.v.flags |= IS_OBJ_DESTRUCTOR_CALLED;
+ obj->gc.refcount++;
+ obj->handlers->dtor_obj(obj TSRMLS_CC);
+ obj->gc.refcount--;
}
}
- count++;
- p = p->u.next;
+//???
+ current = GC_G(next_to_free);
}
/* Destroy zvals */
- p = GC_G(free_list);
- while (p != FREE_LIST_END) {
- GC_G(next_to_free) = p->u.next;
- if (Z_TYPE(p->z) == IS_OBJECT) {
- if (EG(objects_store).object_buckets &&
- EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].valid &&
- EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount <= 0) {
- EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount = 1;
- Z_TYPE(p->z) = IS_NULL;
- zend_objects_store_del_ref_by_handle_ex(Z_OBJ_HANDLE(p->z), Z_OBJ_HT(p->z) TSRMLS_CC);
+//??? p = GC_G(free_list);
+ current = GC_G(to_free).next;
+ while (current != &GC_G(to_free)) {
+ p = current->ref;
+ GC_G(next_to_free) = current->next;
+//??? while (p != FREE_LIST_END) {
+//???
+//??? GC_G(next_to_free) = p->gc_next;
+ if (1 /*&& p->refcount <= 0 ???*/) {
+ if (p->u.v.type == IS_OBJECT) {
+ zend_object *obj = (zend_object*)p;
+
+ if (EG(objects_store).object_buckets &&
+ IS_VALID(EG(objects_store).object_buckets[obj->handle])) {
+//??? obj->gc.refcount = 0;
+//??? Z_TYPE(p->z) = IS_NULL;
+ obj->gc.u.v.type = IS_NULL;
+ zend_objects_store_free(obj TSRMLS_CC);
+ }
+ } else if (p->u.v.type == IS_ARRAY) {
+ zend_array *arr = (zend_array*)p;
+
+ arr->gc.u.v.type = IS_NULL;
+ zend_hash_destroy(&arr->ht);
+ efree(arr);
+ } else if (p->u.v.type == IS_REFERENCE) {
+ zend_reference *ref = (zend_reference*)p;
+
+ ref->gc.u.v.type = IS_NULL;
+ if (EXPECTED(EG(objects_store).object_buckets != NULL) ||
+ Z_TYPE(ref->val) != IS_OBJECT) {
+ zval_dtor(&ref->val);
+ }
+ efree(ref);
+ } else {
+//??? zval_dtor(&p->z);
+//??? Z_TYPE(p->z) = IS_NULL;
}
- } else if (Z_TYPE(p->z) == IS_ARRAY) {
- Z_TYPE(p->z) = IS_NULL;
- zend_hash_destroy(Z_ARRVAL(p->z));
- FREE_HASHTABLE(Z_ARRVAL(p->z));
- } else {
- zval_dtor(&p->z);
- Z_TYPE(p->z) = IS_NULL;
}
- p = GC_G(next_to_free);
+//???
+ current = GC_G(next_to_free);
}
/* Free zvals */
- p = GC_G(free_list);
- while (p != FREE_LIST_END) {
- q = p->u.next;
- FREE_ZVAL_EX(&p->z);
- p = q;
- }
+//??? p = GC_G(free_list);
+//??? while (p != FREE_LIST_END) {
+//??? q = p->gc_next;
+//??? efree(p);
+//??? p = q;
+//??? }
+
GC_G(collected) += count;
- GC_G(free_list) = orig_free_list;
+//??? GC_G(free_list) = orig_free_list;
GC_G(next_to_free) = orig_next_to_free;
}
return count;
-#endif
}
/*
diff --git a/Zend/zend_gc.h b/Zend/zend_gc.h
index f714033962..29e2ca6e02 100644
--- a/Zend/zend_gc.h
+++ b/Zend/zend_gc.h
@@ -61,17 +61,17 @@
do {(v) = (v) | GC_COLOR;} while (0)
#define GC_ZVAL_ADDRESS(v) \
- GC_ADDRESS(Z_GC_BUFFER_P(v))
+ GC_ADDRESS(Z_GC_INFO_P(v))
#define GC_ZVAL_SET_ADDRESS(v, a) \
- GC_SET_ADDRESS(Z_GC_BUFFER_P(v), (a))
+ GC_SET_ADDRESS(Z_GC_INFO_P(v), (a))
#define GC_ZVAL_GET_COLOR(v) \
- GC_GET_COLOR(Z_GC_BUFFER_P(v))
+ GC_GET_COLOR(Z_GC_INFO_P(v))
#define GC_ZVAL_SET_COLOR(v, c) \
- GC_SET_COLOR(Z_GC_BUFFER_P(v), (c))
+ GC_SET_COLOR(Z_GC_INFO_P(v), (c))
#define GC_ZVAL_SET_BLACK(v) \
- GC_SET_BLACK(Z_GC_BUFFER_P(v))
+ GC_SET_BLACK(Z_GC_INFO_P(v))
#define GC_ZVAL_SET_PURPLE(v) \
- GC_SET_PURPLE(Z_GC_BUFFER_P(v))
+ GC_SET_PURPLE(Z_GC_INFO_P(v))
typedef struct _gc_root_buffer {
struct _gc_root_buffer *prev; /* double-linked list */
@@ -89,9 +89,8 @@ typedef struct _zend_gc_globals {
gc_root_buffer *first_unused; /* pointer to first unused buffer */
gc_root_buffer *last_unused; /* pointer to last unused buffer */
- zend_refcounted *zval_to_free; /* temporary list of zvals to free */
- zend_refcounted *free_list;
- zend_refcounted *next_to_free;
+ gc_root_buffer to_free; /* list to free */
+ gc_root_buffer *next_to_free;
zend_uint gc_runs;
zend_uint collected;
@@ -100,13 +99,9 @@ typedef struct _zend_gc_globals {
zend_uint root_buf_length;
zend_uint root_buf_peak;
zend_uint zval_possible_root;
- zend_uint zobj_possible_root;
zend_uint zval_buffered;
- zend_uint zobj_buffered;
zend_uint zval_remove_from_buffer;
- zend_uint zobj_remove_from_buffer;
zend_uint zval_marked_grey;
- zend_uint zobj_marked_grey;
#endif
} zend_gc_globals;
@@ -123,8 +118,8 @@ extern ZEND_API zend_gc_globals gc_globals;
BEGIN_EXTERN_C()
ZEND_API int gc_collect_cycles(TSRMLS_D);
-ZEND_API void gc_zval_possible_root(zend_refcounted *ref TSRMLS_DC);
-ZEND_API void gc_remove_zval_from_buffer(zend_refcounted *ref TSRMLS_DC);
+ZEND_API void gc_possible_root(zend_refcounted *ref TSRMLS_DC);
+ZEND_API void gc_remove_from_buffer(zend_refcounted *ref TSRMLS_DC);
ZEND_API void gc_globals_ctor(TSRMLS_D);
ZEND_API void gc_globals_dtor(TSRMLS_D);
ZEND_API void gc_init(TSRMLS_D);
@@ -132,24 +127,21 @@ ZEND_API void gc_reset(TSRMLS_D);
END_EXTERN_C()
#define GC_ZVAL_CHECK_POSSIBLE_ROOT(z) \
- gc_zval_check_possible_root((z) TSRMLS_CC)
+ gc_check_possible_root((z) TSRMLS_CC)
-#define GC_REMOVE_ZVAL_FROM_BUFFER(z) do { \
- if (GC_ZVAL_ADDRESS(z)) { \
- gc_remove_zval_from_buffer(Z_COUNTED_P(z) TSRMLS_CC); \
+#define GC_REMOVE_FROM_BUFFER(p) do { \
+ zend_refcounted *_p = (zend_refcounted*)(p); \
+ if (GC_ADDRESS(_p->u.v.gc_info)) { \
+ gc_remove_from_buffer(_p TSRMLS_CC); \
} \
} while (0)
-#define GC_REMOVE_ZOBJ_FROM_BUFFER(z) do { \
- if (GC_ADDRESS((z)->gc.u.v.buffer)) { \
- gc_remove_zval_from_buffer(&(z)->gc TSRMLS_CC); \
- } \
- } while (0)
-
-static zend_always_inline void gc_zval_check_possible_root(zval *z TSRMLS_DC)
+static zend_always_inline void gc_check_possible_root(zval *z TSRMLS_DC)
{
- if (Z_TYPE_P(z) == IS_ARRAY || Z_TYPE_P(z) == IS_OBJECT) {
- gc_zval_possible_root(Z_COUNTED_P(z) TSRMLS_CC);
+ if (Z_TYPE_P(z) == IS_OBJECT ||
+ (Z_ISREF_P(z) &&
+ (Z_TYPE_P(Z_REFVAL_P(z)) == IS_ARRAY || Z_TYPE_P(Z_REFVAL_P(z)) == IS_OBJECT))) {
+ gc_possible_root(Z_COUNTED_P(z) TSRMLS_CC);
}
}
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index 483628dbaf..47a0797cf9 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -207,6 +207,8 @@ static void zend_generator_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
zend_generator_close(generator, 0 TSRMLS_CC);
zend_object_std_dtor(&generator->std TSRMLS_CC);
+
+ GC_REMOVE_FROM_BUFFER(generator);
efree(generator);
}
/* }}} */
diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c
index 27c9f6c5f6..50785b86ec 100644
--- a/Zend/zend_objects.c
+++ b/Zend/zend_objects.c
@@ -31,7 +31,7 @@ ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce TSR
object->gc.refcount = 1;
object->gc.u.v.type = IS_OBJECT;
object->gc.u.v.flags = 0;
- object->gc.u.v.buffer = 0;
+ object->gc.u.v.gc_info = 0;
object->ce = ce;
object->properties = NULL;
object->guards = NULL;
@@ -125,6 +125,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object TSRMLS_DC)
ZEND_API void zend_object_free(zend_object *object TSRMLS_DC)
{
zend_object_std_dtor(object TSRMLS_CC);
+ GC_REMOVE_FROM_BUFFER(object);
efree(object);
}
diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c
index a4a5055b70..77b7ee103a 100644
--- a/Zend/zend_objects_API.c
+++ b/Zend/zend_objects_API.c
@@ -53,10 +53,6 @@ ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects TS
obj->gc.refcount++;
obj->handlers->dtor_obj(obj TSRMLS_CC);
obj->gc.refcount--;
-
- if (obj->gc.refcount == 0) {
- GC_REMOVE_ZOBJ_FROM_BUFFER(obj TSRMLS_CC);
- }
}
}
}
@@ -86,7 +82,6 @@ ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects
zend_object *obj = objects->object_buckets[i];
if (IS_VALID(obj)) {
- GC_REMOVE_ZOBJ_FROM_BUFFER(obj TSRMLS_CC);
objects->object_buckets[i] = SET_INVALID(obj);
if (obj->handlers->free_obj) {
obj->handlers->free_obj(obj TSRMLS_CC);
@@ -121,6 +116,17 @@ ZEND_API void zend_objects_store_put(zend_object *object TSRMLS_DC)
SET_BUCKET_NUMBER(EG(objects_store).object_buckets[handle], EG(objects_store).free_list_head); \
EG(objects_store).free_list_head = handle;
+ZEND_API void zend_objects_store_free(zend_object *object TSRMLS_DC) /* {{{ */
+{
+ int handle = object->handle;
+
+ if (object->handlers->free_obj) {
+ object->handlers->free_obj(object TSRMLS_CC);
+ }
+ ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle);
+}
+/* }}} */
+
ZEND_API void zend_objects_store_del(zend_object *object TSRMLS_DC) /* {{{ */
{
/* Make sure we hold a reference count during the destructor call
@@ -149,7 +155,6 @@ ZEND_API void zend_objects_store_del(zend_object *object TSRMLS_DC) /* {{{ */
if (object->gc.refcount == 0) {
zend_uint handle = object->handle;
-//??? GC_REMOVE_ZOBJ_FROM_BUFFER(obj);
if (object->handlers->free_obj) {
zend_try {
object->handlers->free_obj(object TSRMLS_CC);
@@ -251,7 +256,7 @@ ZEND_API zend_object *zend_object_create_proxy(zval *object, zval *member TSRMLS
obj->std.gc.refcount = 1;
obj->std.gc.u.v.type = IS_OBJECT;
- obj->std.gc.u.v.buffer = 0;
+ obj->std.gc.u.v.gc_info = 0;
obj->std.ce = NULL;
obj->std.properties = NULL;
obj->std.guards = NULL;
diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h
index 647bfeaee5..61147dd8c6 100644
--- a/Zend/zend_objects_API.h
+++ b/Zend/zend_objects_API.h
@@ -88,6 +88,7 @@ ZEND_API void zend_objects_store_destroy(zend_objects_store *objects);
/* Store API functions */
ZEND_API void zend_objects_store_put(zend_object *object TSRMLS_DC);
ZEND_API void zend_objects_store_del(zend_object *object TSRMLS_DC);
+ZEND_API void zend_objects_store_free(zend_object *object TSRMLS_DC);
/* See comment in zend_objects_API.c before you use this */
ZEND_API void zend_object_store_set_object(zval *zobject, zend_object *object TSRMLS_DC);
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index fdfa5aba3b..514dbb1e2f 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -187,9 +187,7 @@ try_again:
switch (Z_TYPE_P(op)) {
case IS_REFERENCE:
if (Z_REFCOUNT_P(op) == 1) {
- zend_reference *ref = Z_REF_P(op);
- ZVAL_COPY_VALUE(op, Z_REFVAL_P(op));
- efree(ref);
+ ZVAL_UNREF(op);
} else {
Z_DELREF_P(op);
ZVAL_COPY_VALUE(op, Z_REFVAL_P(op));
@@ -1531,7 +1529,6 @@ static inline void zend_free_obj_get_result(zval *op TSRMLS_DC) /* {{{ */
{
if (Z_REFCOUNTED_P(op)) {
if (Z_REFCOUNT_P(op) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(op);
zval_dtor(op);
} else {
zval_ptr_dtor(op);
diff --git a/Zend/zend_string.h b/Zend/zend_string.h
index e3467a8b76..8c93ef48ac 100644
--- a/Zend/zend_string.h
+++ b/Zend/zend_string.h
@@ -100,7 +100,7 @@ static zend_always_inline zend_string *zend_str_alloc(int len, int persistent)
ret->gc.refcount = 1;
ret->gc.u.v.type = IS_STRING;
ret->gc.u.v.flags = (persistent ? IS_STR_PERSISTENT : 0);
- ret->gc.u.v.buffer = 0;
+ ret->gc.u.v.gc_info = 0;
ret->h = 0;
ret->len = len;
return ret;
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index f2361ef454..91c59c7679 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -103,10 +103,10 @@ struct _zend_refcounted {
struct {
zend_uchar type;
zend_uchar flags; /* used for strings & objects */
- zend_ushort buffer; /* keeps GC root number or 0 */
+ zend_ushort gc_info; /* keeps GC root number (or 0) and color */
} v;
zend_uint long_type;
- } u;
+ } u;
};
struct _zend_string {
@@ -271,8 +271,8 @@ struct _zend_ast_ref {
#define Z_GC_TYPE(zval) Z_COUNTED(zval)->type
#define Z_GC_TYPE_P(zval_p) Z_GC_TYPE(*(zval_p))
-#define Z_GC_BUFFER(zval) Z_COUNTED(zval)->u.v.buffer
-#define Z_GC_BUFFER_P(zval_p) Z_GC_BUFFER(*(zval_p))
+#define Z_GC_INFO(zval) Z_COUNTED(zval)->u.v.gc_info
+#define Z_GC_INFO_P(zval_p) Z_GC_INFO(*(zval_p))
#define Z_STR(zval) (zval).value.str
#define Z_STR_P(zval_p) Z_STR(*(zval_p))
@@ -395,7 +395,7 @@ struct _zend_ast_ref {
zend_array *_arr = emalloc(sizeof(zend_array)); \
_arr->gc.refcount = 1; \
_arr->gc.u.v.type = IS_ARRAY; \
- _arr->gc.u.v.buffer = 0; \
+ _arr->gc.u.v.gc_info = 0; \
Z_ARR_P(__z) = _arr; \
Z_TYPE_P(__z) = IS_ARRAY; \
} while (0)
@@ -405,7 +405,7 @@ struct _zend_ast_ref {
zend_array *_arr = malloc(sizeof(zend_array)); \
_arr->gc.refcount = 1; \
_arr->gc.u.v.type = IS_ARRAY; \
- _arr->gc.u.v.buffer = 0; \
+ _arr->gc.u.v.gc_info = 0; \
Z_ARR_P(__z) = _arr; \
Z_TYPE_P(__z) = IS_ARRAY; \
} while (0)
@@ -426,7 +426,7 @@ struct _zend_ast_ref {
zend_resource *_res = emalloc(sizeof(zend_resource)); \
_res->gc.refcount = 1; \
_res->gc.u.v.type = IS_RESOURCE; \
- _res->gc.u.v.buffer = 0; \
+ _res->gc.u.v.gc_info = 0; \
_res->handle = (h); \
_res->type = (t); \
_res->ptr = (p); \
@@ -439,7 +439,7 @@ struct _zend_ast_ref {
zend_resource *_res = malloc(sizeof(zend_resource)); \
_res->gc.refcount = 1; \
_res->gc.u.v.type = IS_RESOURCE; \
- _res->gc.u.v.buffer = 0; \
+ _res->gc.u.v.gc_info = 0; \
_res->handle = (h); \
_res->type = (t); \
_res->ptr = (p); \
@@ -458,7 +458,7 @@ struct _zend_ast_ref {
zend_reference *_ref = emalloc(sizeof(zend_reference)); \
_ref->gc.refcount = 1; \
_ref->gc.u.v.type = IS_REFERENCE; \
- _ref->gc.u.v.buffer = 0; \
+ _ref->gc.u.v.gc_info = 0; \
_ref->val = *(r); \
Z_REF_P(z) = _ref; \
Z_TYPE_P(z) = IS_REFERENCE; \
@@ -469,7 +469,7 @@ struct _zend_ast_ref {
zend_ast_ref *_ast = emalloc(sizeof(zend_ast_ref)); \
_ast->gc.refcount = 1; \
_ast->gc.u.v.type = IS_CONSTANT_AST; \
- _ast->gc.u.v.buffer = 0; \
+ _ast->gc.u.v.gc_info = 0; \
_ast->ast = (a); \
Z_AST_P(__z) = _ast; \
Z_TYPE_P(__z) = IS_CONSTANT_AST; \
@@ -499,7 +499,7 @@ struct _zend_ast_ref {
zend_str_offset *x = emalloc(sizeof(zend_str_offset)); \
x->gc.refcount = 1; \
x->gc.u.v.type = IS_STR_OFFSET; \
- x->gc.u.v.buffer = 0; \
+ x->gc.u.v.gc_info = 0; \
x->str = (s); \
x->offset = (o); \
Z_STR_OFFSET_P(z) = x; \
diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c
index f016f85f00..20f8b1adb6 100644
--- a/Zend/zend_variables.c
+++ b/Zend/zend_variables.c
@@ -27,114 +27,132 @@
#include "zend_constants.h"
#include "zend_list.h"
-ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
+ZEND_API void _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC)
{
- switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
+//??? switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
+ switch (p->u.v.type) {
case IS_STRING:
- case IS_CONSTANT:
- CHECK_ZVAL_STRING_REL(zvalue);
- STR_RELEASE(Z_STR_P(zvalue));
- break;
+ case IS_CONSTANT: {
+ zend_string *str = (zend_string*)p;
+//??? CHECK_ZVAL_STRING_REL(zvalue);
+ STR_RELEASE(str);
+ goto exit;
+ }
case IS_ARRAY:
case IS_CONSTANT_ARRAY: {
+ zend_array *arr =(zend_array*)p;
TSRMLS_FETCH();
- if (Z_ARRVAL_P(zvalue) != &EG(symbol_table).ht) {
+ if (arr != &EG(symbol_table)) {
/* break possible cycles */
- Z_TYPE_P(zvalue) = IS_NULL;
- zend_hash_destroy(Z_ARRVAL_P(zvalue));
- efree(Z_ARR_P(zvalue));
+ arr->gc.u.v.type = IS_NULL;
+ zend_hash_destroy(&arr->ht);
+ goto gc_exit;
}
+ goto exit;
}
- break;
- case IS_CONSTANT_AST:
- zend_ast_destroy(Z_AST_P(zvalue)->ast);
- efree(Z_AST_P(zvalue));
- break;
- case IS_OBJECT:
- {
+ case IS_CONSTANT_AST: {
+ zend_ast_ref *ast =(zend_ast_ref*)p;
+
+ zend_ast_destroy(ast->ast);
+ efree(ast);
+ goto exit;
+ }
+ case IS_OBJECT: {
+ zend_object *obj = (zend_object*)p;
TSRMLS_FETCH();
- OBJ_RELEASE(Z_OBJ_P(zvalue));
+ OBJ_RELEASE(obj);
+ goto exit;
}
- break;
- case IS_RESOURCE:
- {
+ case IS_RESOURCE: {
+ zend_resource *res = (zend_resource*)p;
TSRMLS_FETCH();
- if (Z_DELREF_P(zvalue) == 0) {
+ if (--res->gc.refcount == 0) {
/* destroy resource */
- zend_list_delete(Z_RES_P(zvalue));
+ zend_list_delete(res);
}
+ goto exit;
}
- break;
- case IS_REFERENCE:
- if (Z_DELREF_P(zvalue) == 0) {
- zval_dtor(Z_REFVAL_P(zvalue));
- efree(Z_REF_P(zvalue));
+ case IS_REFERENCE: {
+ zend_reference *ref = (zend_reference*)p;
+ if (--ref->gc.refcount == 0) {
+ zval_dtor(&ref->val);
+ goto gc_exit;
+ }
+ goto exit;
}
- break;
- case IS_LONG:
- case IS_DOUBLE:
- case IS_BOOL:
- case IS_NULL:
default:
- return;
- break;
+ goto exit;
}
+gc_exit:
+ GC_REMOVE_FROM_BUFFER(p);
+ efree(p);
+exit:
+ return;
}
-ZEND_API void _zval_dtor_func_for_ptr(zval *zvalue ZEND_FILE_LINE_DC)
+ZEND_API void _zval_dtor_func_for_ptr(zend_refcounted *p ZEND_FILE_LINE_DC)
{
- switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
+//??? switch (Z_TYPE_P(zvalue) & IS_CONSTANT_TYPE_MASK) {
+ switch (p->u.v.type) {
case IS_STRING:
- case IS_CONSTANT:
- CHECK_ZVAL_STRING_REL(zvalue);
- STR_FREE(Z_STR_P(zvalue));
- break;
+ case IS_CONSTANT: {
+ zend_string *str = (zend_string*)p;
+//??? CHECK_ZVAL_STRING_REL(zvalue);
+ STR_FREE(str);
+ goto exit;
+ }
case IS_ARRAY:
case IS_CONSTANT_ARRAY: {
+ zend_array *arr =(zend_array*)p;
TSRMLS_FETCH();
- if (Z_ARRVAL_P(zvalue) != &EG(symbol_table).ht) {
+ if (arr != &EG(symbol_table)) {
/* break possible cycles */
- Z_TYPE_P(zvalue) = IS_NULL;
- zend_hash_destroy(Z_ARRVAL_P(zvalue));
- efree(Z_ARR_P(zvalue));
+ arr->gc.u.v.type = IS_NULL;
+ zend_hash_destroy(&arr->ht);
+ goto gc_exit;
}
+ goto exit;
}
- break;
- case IS_CONSTANT_AST:
- zend_ast_destroy(Z_AST_P(zvalue)->ast);
- efree(Z_AST_P(zvalue));
- break;
- case IS_OBJECT:
- {
+ case IS_CONSTANT_AST: {
+ zend_ast_ref *ast =(zend_ast_ref*)p;
+
+ zend_ast_destroy(ast->ast);
+ efree(ast);
+ goto exit;
+ }
+ case IS_OBJECT: {
+ zend_object *obj = (zend_object*)p;
TSRMLS_FETCH();
- zend_objects_store_del(Z_OBJ_P(zvalue) TSRMLS_CC);
+ zend_objects_store_del(obj TSRMLS_CC);
+ goto exit;
}
- break;
- case IS_RESOURCE:
- {
+ case IS_RESOURCE: {
+ zend_resource *res = (zend_resource*)p;
TSRMLS_FETCH();
/* destroy resource */
- zend_list_delete(Z_RES_P(zvalue));
+ zend_list_delete(res);
+ goto exit;
+ }
+ case IS_REFERENCE: {
+ zend_reference *ref = (zend_reference*)p;
+
+ zval_dtor(&ref->val);
+ goto gc_exit;
}
- break;
- case IS_REFERENCE:
- zval_dtor(Z_REFVAL_P(zvalue));
- efree(Z_REF_P(zvalue));
- break;
- case IS_LONG:
- case IS_DOUBLE:
- case IS_BOOL:
- case IS_NULL:
default:
- return;
- break;
+ goto exit;
}
+gc_exit:
+ GC_REMOVE_FROM_BUFFER(p);
+ efree(p);
+exit:
+ return;
}
ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
@@ -264,7 +282,6 @@ ZEND_API void _zval_dtor_wrapper(zval *zvalue)
{
TSRMLS_FETCH();
- GC_REMOVE_ZVAL_FROM_BUFFER(zvalue);
zval_dtor(zvalue);
}
diff --git a/Zend/zend_variables.h b/Zend/zend_variables.h
index 2e2b183d76..c62a194e21 100644
--- a/Zend/zend_variables.h
+++ b/Zend/zend_variables.h
@@ -25,15 +25,15 @@
BEGIN_EXTERN_C()
-ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC);
-ZEND_API void _zval_dtor_func_for_ptr(zval *zvalue ZEND_FILE_LINE_DC);
+ZEND_API void _zval_dtor_func(zend_refcounted *p ZEND_FILE_LINE_DC);
+ZEND_API void _zval_dtor_func_for_ptr(zend_refcounted *p ZEND_FILE_LINE_DC);
static zend_always_inline void _zval_dtor(zval *zvalue ZEND_FILE_LINE_DC)
{
if (!Z_REFCOUNTED_P(zvalue)) {
return;
}
- _zval_dtor_func(zvalue ZEND_FILE_LINE_RELAY_CC);
+ _zval_dtor_func(Z_COUNTED_P(zvalue) ZEND_FILE_LINE_RELAY_CC);
}
ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC);
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 14483a427f..8076ba6caa 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -405,7 +405,6 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -652,7 +651,6 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -750,7 +748,6 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -4368,16 +4365,11 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
//??? dereference
if (Z_ISREF_P(array_ref)) {
if (Z_REFCOUNT_P(array_ref) == 1) {
- zend_reference *ref = Z_REF_P(array_ref);
- ZVAL_COPY(array_ref, &ref->val);
- efree(ref);
+ ZVAL_UNREF(array_ref);
array_ptr = array_ref;
- } else {
- Z_ADDREF_P(array_ref);
}
- } else {
- Z_ADDREF_P(array_ref);
}
+ Z_ADDREF_P(array_ref);
}
}
}
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index dc625815f4..c635d8a06d 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -3079,16 +3079,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
//??? dereference
if (Z_ISREF_P(array_ref)) {
if (Z_REFCOUNT_P(array_ref) == 1) {
- zend_reference *ref = Z_REF_P(array_ref);
- ZVAL_COPY(array_ref, &ref->val);
- efree(ref);
+ ZVAL_UNREF(array_ref);
array_ptr = array_ref;
- } else {
- Z_ADDREF_P(array_ref);
}
- } else {
- Z_ADDREF_P(array_ref);
}
+ Z_ADDREF_P(array_ref);
}
}
}
@@ -8180,16 +8175,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
//??? dereference
if (Z_ISREF_P(array_ref)) {
if (Z_REFCOUNT_P(array_ref) == 1) {
- zend_reference *ref = Z_REF_P(array_ref);
- ZVAL_COPY(array_ref, &ref->val);
- efree(ref);
+ ZVAL_UNREF(array_ref);
array_ptr = array_ref;
- } else {
- Z_ADDREF_P(array_ref);
}
- } else {
- Z_ADDREF_P(array_ref);
}
+ Z_ADDREF_P(array_ref);
}
}
}
@@ -13359,16 +13349,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
//??? dereference
if (Z_ISREF_P(array_ref)) {
if (Z_REFCOUNT_P(array_ref) == 1) {
- zend_reference *ref = Z_REF_P(array_ref);
- ZVAL_COPY(array_ref, &ref->val);
- efree(ref);
+ ZVAL_UNREF(array_ref);
array_ptr = array_ref;
- } else {
- Z_ADDREF_P(array_ref);
}
- } else {
- Z_ADDREF_P(array_ref);
}
+ Z_ADDREF_P(array_ref);
}
}
}
@@ -14079,7 +14064,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -14325,7 +14309,6 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -14423,7 +14406,6 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -16577,7 +16559,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -16824,7 +16805,6 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -16922,7 +16902,6 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -18653,7 +18632,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -18900,7 +18878,6 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -18998,7 +18975,6 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -20843,7 +20819,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -22264,7 +22239,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -22510,7 +22484,6 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -22608,7 +22581,6 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -24195,7 +24167,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -24440,7 +24411,6 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incde
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -24538,7 +24508,6 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incd
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -25599,7 +25568,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -25845,7 +25813,6 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -25943,7 +25910,6 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -26920,7 +26886,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -27166,7 +27131,6 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -27264,7 +27228,6 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -28242,7 +28205,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -28658,7 +28620,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -28903,7 +28864,6 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -29001,7 +28961,6 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -30907,16 +30866,11 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
//??? dereference
if (Z_ISREF_P(array_ref)) {
if (Z_REFCOUNT_P(array_ref) == 1) {
- zend_reference *ref = Z_REF_P(array_ref);
- ZVAL_COPY(array_ref, &ref->val);
- efree(ref);
+ ZVAL_UNREF(array_ref);
array_ptr = array_ref;
- } else {
- Z_ADDREF_P(array_ref);
}
- } else {
- Z_ADDREF_P(array_ref);
}
+ Z_ADDREF_P(array_ref);
}
}
}
@@ -31495,7 +31449,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -31740,7 +31693,6 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -31838,7 +31790,6 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -33775,7 +33726,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -34021,7 +33971,6 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -34119,7 +34068,6 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -35726,7 +35674,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -35972,7 +35919,6 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -36070,7 +36016,6 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -37790,7 +37735,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -39077,7 +39021,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -39322,7 +39265,6 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
@@ -39420,7 +39362,6 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in
zval *value = Z_OBJ_HT_P(z)->get(z TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- GC_REMOVE_ZVAL_FROM_BUFFER(z);
zval_dtor(z);
}
z = value;
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index 65fe5c46ed..8c08ddba20 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -2440,6 +2440,7 @@ static void date_object_free_storage_date(zend_object *object TSRMLS_DC) /* {{{
}
zend_object_std_dtor(&intern->std TSRMLS_CC);
+ GC_REMOVE_FROM_BUFFER(object);
efree(intern);
} /* }}} */
@@ -2451,6 +2452,7 @@ static void date_object_free_storage_timezone(zend_object *object TSRMLS_DC) /*
free(intern->tzi.z.abbr);
}
zend_object_std_dtor(&intern->std TSRMLS_CC);
+ GC_REMOVE_FROM_BUFFER(object);
efree(intern);
} /* }}} */
@@ -2460,6 +2462,7 @@ static void date_object_free_storage_interval(zend_object *object TSRMLS_DC) /*
timelib_rel_time_dtor(intern->diff);
zend_object_std_dtor(&intern->std TSRMLS_CC);
+ GC_REMOVE_FROM_BUFFER(object);
efree(intern);
} /* }}} */
@@ -2481,6 +2484,7 @@ static void date_object_free_storage_period(zend_object *object TSRMLS_DC) /* {{
timelib_rel_time_dtor(intern->interval);
zend_object_std_dtor(&intern->std TSRMLS_CC);
+ GC_REMOVE_FROM_BUFFER(object);
efree(intern);
} /* }}} */
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 9c822029fe..148dae4378 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -319,6 +319,7 @@ static void reflection_free_objects_storage(zend_object *object TSRMLS_DC) /* {{
intern->ptr = NULL;
zval_ptr_dtor(&intern->obj);
zend_object_std_dtor(object TSRMLS_CC);
+ GC_REMOVE_FROM_BUFFER(object);
efree(intern);
}
/* }}} */
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index 82f166fe6d..c6634ecf8a 100644
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -170,6 +170,7 @@ static void spl_array_object_free_storage(zend_object *object TSRMLS_DC)
efree(intern->debug_info);
}
+ GC_REMOVE_FROM_BUFFER(object);
efree(intern);
}
/* }}} */
diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index b86994c7d2..86d745463f 100644
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -127,6 +127,7 @@ static void spl_filesystem_object_free_storage(zend_object *object TSRMLS_DC) /*
//????zend_iterator_dtor(&intern->it->intern);
}
+ GC_REMOVE_FROM_BUFFER(object);
efree(intern);
} /* }}} */
diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c
index 8f444d0061..f453ba7175 100644
--- a/ext/spl/spl_dllist.c
+++ b/ext/spl/spl_dllist.c
@@ -367,6 +367,7 @@ static void spl_dllist_object_free_storage(zend_object *object TSRMLS_DC) /* {{{
efree(intern->debug_info);
}
+ GC_REMOVE_FROM_BUFFER(object);
efree(intern);
}
/* }}} */
diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c
index 0a8b8502fd..784d1db968 100644
--- a/ext/spl/spl_fixedarray.c
+++ b/ext/spl/spl_fixedarray.c
@@ -210,6 +210,7 @@ static void spl_fixedarray_object_free_storage(zend_object *object TSRMLS_DC) /*
zend_object_std_dtor(&intern->std TSRMLS_CC);
zval_ptr_dtor(&intern->retval);
+ GC_REMOVE_FROM_BUFFER(object);
efree(intern);
}
/* }}} */
diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c
index 969fdba736..5358e3da9d 100644
--- a/ext/spl/spl_heap.c
+++ b/ext/spl/spl_heap.c
@@ -378,6 +378,7 @@ static void spl_heap_object_free_storage(zend_object *object TSRMLS_DC) /* {{{ *
efree(intern->debug_info);
}
+ GC_REMOVE_FROM_BUFFER(object);
efree(intern);
}
/* }}} */
diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c
index 55587c48af..f424491966 100644
--- a/ext/spl/spl_iterators.c
+++ b/ext/spl/spl_iterators.c
@@ -889,6 +889,7 @@ static void spl_RecursiveIteratorIterator_free_storage(zend_object *_object TSRM
smart_str_free(&object->postfix[0]);
+ GC_REMOVE_FROM_BUFFER(_object);
efree(object);
}
/* }}} */
@@ -2268,6 +2269,7 @@ static void spl_dual_it_free_storage(zend_object *_object TSRMLS_DC)
//zend_object_std_dtor(&object->std TSRMLS_CC);
+ GC_REMOVE_FROM_BUFFER(_object);
efree(object);
}
/* }}} */
diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c
index 803ca4a59c..3728e45005 100644
--- a/ext/spl/spl_observer.c
+++ b/ext/spl/spl_observer.c
@@ -114,6 +114,7 @@ void spl_SplObjectStorage_free_storage(zend_object *object TSRMLS_DC) /* {{{ */
efree(intern->debug_info);
}
+ GC_REMOVE_FROM_BUFFER(object);
efree(intern);
} /* }}} */
diff --git a/ext/standard/array.c b/ext/standard/array.c
index cb3aa761bc..ab16b67ee0 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -2258,9 +2258,7 @@ PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS
if (Z_ISREF_P(dest_entry)) {
if (Z_REFCOUNT_P(dest_entry) == 1) {
- zend_reference *ref = Z_REF_P(dest_entry);
- ZVAL_COPY_VALUE(dest_entry, dest_zval);
- efree(ref);
+ ZVAL_UNREF(dest_entry);
} else {
Z_DELREF_P(dest_entry);
ZVAL_DUP(dest_entry, dest_zval);