|
|
|
@ -194,7 +194,7 @@ ZEND_API void gc_zobj_possible_root(zval *zv TSRMLS_DC) |
|
|
|
{ |
|
|
|
struct _store_object *obj; |
|
|
|
|
|
|
|
if (UNEXPECTED(Z_OBJ_HT_P(zv)->get_properties == NULL || |
|
|
|
if (UNEXPECTED(Z_OBJ_HT_P(zv)->get_gc == NULL || |
|
|
|
EG(objects_store).object_buckets == NULL)) { |
|
|
|
return; |
|
|
|
} |
|
|
|
@ -275,48 +275,38 @@ tail_call: |
|
|
|
GC_ZVAL_SET_BLACK(pz); |
|
|
|
|
|
|
|
if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) { |
|
|
|
zend_object_get_properties_t get_props; |
|
|
|
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_BLACK) { |
|
|
|
GC_SET_BLACK(obj->buffered); |
|
|
|
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
|
|
|
(get_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) { |
|
|
|
if (get_props == zend_std_get_properties) { |
|
|
|
zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object)); |
|
|
|
|
|
|
|
if (!zobj->properties) { |
|
|
|
int i; |
|
|
|
int n = zobj->ce->default_properties_count; |
|
|
|
|
|
|
|
while (n > 0 && !zobj->properties_table[n-1]) n--; |
|
|
|
for (i = 0; i < n; i++) { |
|
|
|
if (zobj->properties_table[i]) { |
|
|
|
pz = zobj->properties_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 (i == n - 1) { |
|
|
|
goto tail_call; |
|
|
|
} else { |
|
|
|
zval_scan_black(pz TSRMLS_CC); |
|
|
|
} |
|
|
|
} |
|
|
|
(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 (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); |
|
|
|
} |
|
|
|
} |
|
|
|
return; |
|
|
|
} else { |
|
|
|
p = zobj->properties->pListHead; |
|
|
|
} |
|
|
|
} else { |
|
|
|
HashTable *props = get_props(pz TSRMLS_CC); |
|
|
|
if(!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
} |
|
|
|
if (!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (Z_TYPE_P(pz) == IS_ARRAY) { |
|
|
|
@ -343,39 +333,30 @@ tail_call: |
|
|
|
static void zobj_scan_black(struct _store_object *obj, zval *pz TSRMLS_DC) |
|
|
|
{ |
|
|
|
Bucket *p; |
|
|
|
zend_object_get_properties_t get_props; |
|
|
|
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_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) { |
|
|
|
if (get_props == zend_std_get_properties) { |
|
|
|
zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object)); |
|
|
|
|
|
|
|
if (!zobj->properties) { |
|
|
|
int i; |
|
|
|
|
|
|
|
for (i = 0; i < zobj->ce->default_properties_count; i++) { |
|
|
|
if (zobj->properties_table[i]) { |
|
|
|
pz = zobj->properties_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); |
|
|
|
} |
|
|
|
} |
|
|
|
(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); |
|
|
|
} |
|
|
|
return; |
|
|
|
} else { |
|
|
|
p = zobj->properties->pListHead; |
|
|
|
} |
|
|
|
} else { |
|
|
|
HashTable *props = get_props(pz TSRMLS_CC); |
|
|
|
if(!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
} |
|
|
|
if (!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
while (p != NULL) { |
|
|
|
pz = *(zval**)p->pData; |
|
|
|
if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) { |
|
|
|
@ -400,7 +381,7 @@ tail_call: |
|
|
|
GC_ZVAL_SET_COLOR(pz, GC_GREY); |
|
|
|
|
|
|
|
if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) { |
|
|
|
zend_object_get_properties_t get_props; |
|
|
|
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--; |
|
|
|
@ -408,39 +389,29 @@ tail_call: |
|
|
|
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_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) { |
|
|
|
if (get_props == zend_std_get_properties) { |
|
|
|
zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object)); |
|
|
|
|
|
|
|
if (!zobj->properties) { |
|
|
|
int i; |
|
|
|
int n = zobj->ce->default_properties_count; |
|
|
|
|
|
|
|
while (n > 0 && !zobj->properties_table[n-1]) n--; |
|
|
|
for (i = 0; i < n; i++) { |
|
|
|
if (zobj->properties_table[i]) { |
|
|
|
pz = zobj->properties_table[i]; |
|
|
|
if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) { |
|
|
|
pz->refcount__gc--; |
|
|
|
} |
|
|
|
if (i == n - 1) { |
|
|
|
goto tail_call; |
|
|
|
} else { |
|
|
|
zval_mark_grey(pz TSRMLS_CC); |
|
|
|
} |
|
|
|
} |
|
|
|
(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 (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); |
|
|
|
} |
|
|
|
return; |
|
|
|
} else { |
|
|
|
p = zobj->properties->pListHead; |
|
|
|
} |
|
|
|
} else { |
|
|
|
HashTable *props = get_props(pz TSRMLS_CC); |
|
|
|
if(!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
} |
|
|
|
if (!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (Z_TYPE_P(pz) == IS_ARRAY) { |
|
|
|
@ -468,39 +439,30 @@ tail_call: |
|
|
|
static void zobj_mark_grey(struct _store_object *obj, zval *pz TSRMLS_DC) |
|
|
|
{ |
|
|
|
Bucket *p; |
|
|
|
zend_object_get_properties_t get_props; |
|
|
|
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_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) { |
|
|
|
if (get_props == zend_std_get_properties) { |
|
|
|
zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object)); |
|
|
|
|
|
|
|
if (!zobj->properties) { |
|
|
|
int i; |
|
|
|
|
|
|
|
for (i = 0; i < zobj->ce->default_properties_count; i++) { |
|
|
|
if (zobj->properties_table[i]) { |
|
|
|
pz = zobj->properties_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); |
|
|
|
} |
|
|
|
(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--; |
|
|
|
} |
|
|
|
return; |
|
|
|
} else { |
|
|
|
p = zobj->properties->pListHead; |
|
|
|
} |
|
|
|
} else { |
|
|
|
HashTable *props = get_props(pz TSRMLS_CC); |
|
|
|
if(!props) { |
|
|
|
return; |
|
|
|
zval_mark_grey(pz TSRMLS_CC); |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
} |
|
|
|
if (!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
while (p != NULL) { |
|
|
|
pz = *(zval**)p->pData; |
|
|
|
if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) { |
|
|
|
@ -558,7 +520,7 @@ tail_call: |
|
|
|
} else { |
|
|
|
GC_ZVAL_SET_COLOR(pz, GC_WHITE); |
|
|
|
if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) { |
|
|
|
zend_object_get_properties_t get_props; |
|
|
|
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) { |
|
|
|
@ -567,36 +529,26 @@ tail_call: |
|
|
|
} else { |
|
|
|
GC_SET_COLOR(obj->buffered, GC_WHITE); |
|
|
|
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
|
|
|
(get_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) { |
|
|
|
if (get_props == zend_std_get_properties) { |
|
|
|
zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object)); |
|
|
|
|
|
|
|
if (!zobj->properties) { |
|
|
|
int i; |
|
|
|
int n = zobj->ce->default_properties_count; |
|
|
|
|
|
|
|
while (n > 0 && !zobj->properties_table[n-1]) n--; |
|
|
|
for (i = 0; i < n; i++) { |
|
|
|
if (zobj->properties_table[i]) { |
|
|
|
pz = zobj->properties_table[i]; |
|
|
|
if (i == n - 1) { |
|
|
|
goto tail_call; |
|
|
|
} else { |
|
|
|
zval_scan(pz TSRMLS_CC); |
|
|
|
} |
|
|
|
} |
|
|
|
(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); |
|
|
|
} |
|
|
|
return; |
|
|
|
} else { |
|
|
|
p = zobj->properties->pListHead; |
|
|
|
} |
|
|
|
} else { |
|
|
|
HashTable *props = get_props(pz TSRMLS_CC); |
|
|
|
if(!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
} |
|
|
|
if (!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -623,7 +575,7 @@ tail_call: |
|
|
|
static void zobj_scan(zval *pz TSRMLS_DC) |
|
|
|
{ |
|
|
|
Bucket *p; |
|
|
|
zend_object_get_properties_t get_props; |
|
|
|
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; |
|
|
|
@ -634,30 +586,21 @@ static void zobj_scan(zval *pz TSRMLS_DC) |
|
|
|
} else { |
|
|
|
GC_SET_COLOR(obj->buffered, GC_WHITE); |
|
|
|
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
|
|
|
(get_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) { |
|
|
|
if (get_props == zend_std_get_properties) { |
|
|
|
zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object)); |
|
|
|
|
|
|
|
if (!zobj->properties) { |
|
|
|
int i; |
|
|
|
|
|
|
|
for (i = 0; i < zobj->ce->default_properties_count; i++) { |
|
|
|
if (zobj->properties_table[i]) { |
|
|
|
pz = zobj->properties_table[i]; |
|
|
|
zval_scan(pz TSRMLS_CC); |
|
|
|
} |
|
|
|
} |
|
|
|
return; |
|
|
|
} else { |
|
|
|
p = zobj->properties->pListHead; |
|
|
|
} |
|
|
|
} else { |
|
|
|
HashTable *props = get_props(pz TSRMLS_CC); |
|
|
|
if(!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
(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; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
while (p != NULL) { |
|
|
|
zval_scan(*(zval**)p->pData TSRMLS_CC); |
|
|
|
p = p->pListNext; |
|
|
|
@ -697,52 +640,44 @@ tail_call: |
|
|
|
GC_ZVAL_SET_BLACK(pz); |
|
|
|
|
|
|
|
if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) { |
|
|
|
zend_object_get_properties_t get_props; |
|
|
|
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) { |
|
|
|
GC_SET_BLACK(obj->buffered); |
|
|
|
|
|
|
|
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
|
|
|
(get_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) { |
|
|
|
if (get_props == zend_std_get_properties) { |
|
|
|
zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object)); |
|
|
|
(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); |
|
|
|
|
|
|
|
if (!zobj->properties) { |
|
|
|
int i; |
|
|
|
int n = zobj->ce->default_properties_count; |
|
|
|
|
|
|
|
while (n > 0 && !zobj->properties_table[n-1]) n--; |
|
|
|
|
|
|
|
/* 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 (!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; |
|
|
|
} |
|
|
|
|
|
|
|
for (i = 0; i < n; i++) { |
|
|
|
if (zobj->properties_table[i]) { |
|
|
|
pz = zobj->properties_table[i]; |
|
|
|
if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) { |
|
|
|
pz->refcount__gc++; |
|
|
|
} |
|
|
|
if (i == n - 1) { |
|
|
|
goto tail_call; |
|
|
|
} else { |
|
|
|
zval_collect_white(pz TSRMLS_CC); |
|
|
|
} |
|
|
|
} |
|
|
|
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); |
|
|
|
} |
|
|
|
return; |
|
|
|
} else { |
|
|
|
p = zobj->properties->pListHead; |
|
|
|
} |
|
|
|
} else { |
|
|
|
HashTable *props = get_props(pz TSRMLS_CC); |
|
|
|
if(!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
} |
|
|
|
if (!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
@ -776,40 +711,31 @@ static void zobj_collect_white(zval *pz TSRMLS_DC) |
|
|
|
Bucket *p; |
|
|
|
|
|
|
|
if (EG(objects_store).object_buckets) { |
|
|
|
zend_object_get_properties_t get_props; |
|
|
|
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) { |
|
|
|
GC_SET_BLACK(obj->buffered); |
|
|
|
|
|
|
|
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid && |
|
|
|
(get_props = Z_OBJ_HANDLER_P(pz, get_properties)) != NULL)) { |
|
|
|
if (get_props == zend_std_get_properties) { |
|
|
|
zend_object* zobj = ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj.object)); |
|
|
|
|
|
|
|
if (!zobj->properties) { |
|
|
|
int i; |
|
|
|
|
|
|
|
for (i = 0; i < zobj->ce->default_properties_count; i++) { |
|
|
|
if (zobj->properties_table[i]) { |
|
|
|
pz = zobj->properties_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); |
|
|
|
} |
|
|
|
(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++; |
|
|
|
} |
|
|
|
return; |
|
|
|
} else { |
|
|
|
p = zobj->properties->pListHead; |
|
|
|
zval_collect_white(pz TSRMLS_CC); |
|
|
|
} |
|
|
|
} else { |
|
|
|
HashTable *props = get_props(pz TSRMLS_CC); |
|
|
|
if(!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
} |
|
|
|
if (!props) { |
|
|
|
return; |
|
|
|
} |
|
|
|
p = props->pListHead; |
|
|
|
while (p != NULL) { |
|
|
|
pz = *(zval**)p->pData; |
|
|
|
if (Z_TYPE_P(pz) != IS_ARRAY || Z_ARRVAL_P(pz) != &EG(symbol_table)) { |
|
|
|
|