diff options
author | Dmitry Stogov <dmitry@zend.com> | 2014-03-19 17:00:28 +0400 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2014-03-19 17:00:28 +0400 |
commit | b7938ab1bd765897bd6f08a48a8aea494a961ea9 (patch) | |
tree | 22f8034d42dfac8f03b4bb6d6573e5a7f6361ac8 | |
parent | 2e3e96b24bb1c547362af53b952f823f451e6bce (diff) | |
download | php-git-b7938ab1bd765897bd6f08a48a8aea494a961ea9.tar.gz |
Refactored GC (incomplete)
-rw-r--r-- | Zend/zend.h | 14 | ||||
-rw-r--r-- | Zend/zend_closures.c | 1 | ||||
-rw-r--r-- | Zend/zend_execute.c | 26 | ||||
-rw-r--r-- | Zend/zend_execute.h | 6 | ||||
-rw-r--r-- | Zend/zend_gc.c | 894 | ||||
-rw-r--r-- | Zend/zend_gc.h | 48 | ||||
-rw-r--r-- | Zend/zend_generators.c | 2 | ||||
-rw-r--r-- | Zend/zend_objects.c | 3 | ||||
-rw-r--r-- | Zend/zend_objects_API.c | 19 | ||||
-rw-r--r-- | Zend/zend_objects_API.h | 1 | ||||
-rw-r--r-- | Zend/zend_operators.c | 5 | ||||
-rw-r--r-- | Zend/zend_string.h | 2 | ||||
-rw-r--r-- | Zend/zend_types.h | 22 | ||||
-rw-r--r-- | Zend/zend_variables.c | 155 | ||||
-rw-r--r-- | Zend/zend_variables.h | 6 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 12 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 75 | ||||
-rw-r--r-- | ext/date/php_date.c | 4 | ||||
-rw-r--r-- | ext/reflection/php_reflection.c | 1 | ||||
-rw-r--r-- | ext/spl/spl_array.c | 1 | ||||
-rw-r--r-- | ext/spl/spl_directory.c | 1 | ||||
-rw-r--r-- | ext/spl/spl_dllist.c | 1 | ||||
-rw-r--r-- | ext/spl/spl_fixedarray.c | 1 | ||||
-rw-r--r-- | ext/spl/spl_heap.c | 1 | ||||
-rw-r--r-- | ext/spl/spl_iterators.c | 2 | ||||
-rw-r--r-- | ext/spl/spl_observer.c | 1 | ||||
-rw-r--r-- | ext/standard/array.c | 4 |
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); |