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;
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;
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
}
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;
}
}
-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;
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) {
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++;
if (!newRoot) {
return;
}
- GC_SET_PURPLE(ref->u.v.buffer);
+ GC_SET_PURPLE(ref->u.v.gc_info);
GC_G(unused) = newRoot->prev;
}
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;
}
}
-//???
-#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;
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);
}
}
}
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);
}
}
}
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
}
/*
//??? 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);
}
}
}
//??? 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);
}
}
}
//??? 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);
}
}
}
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
//??? 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);
}
}
}
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;