mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Clean up gc_scan() implementation
The HT handling no longer needs to be shared, so move it into the right branch. Also use a couple of early gotos to reduce nesting.
This commit is contained in:
parent
5f8ed7765a
commit
5bde82a442
1 changed files with 77 additions and 83 deletions
160
Zend/zend_gc.c
160
Zend/zend_gc.c
|
@ -991,98 +991,48 @@ static void gc_mark_roots(gc_stack *stack)
|
||||||
|
|
||||||
static void gc_scan(zend_refcounted *ref, gc_stack *stack)
|
static void gc_scan(zend_refcounted *ref, gc_stack *stack)
|
||||||
{
|
{
|
||||||
HashTable *ht = NULL;
|
|
||||||
Bucket *p, *end;
|
Bucket *p, *end;
|
||||||
zval *zv;
|
zval *zv;
|
||||||
GC_STACK_DCL(stack);
|
GC_STACK_DCL(stack);
|
||||||
|
|
||||||
tail_call:
|
tail_call:
|
||||||
if (GC_REF_CHECK_COLOR(ref, GC_WHITE)) {
|
if (!GC_REF_CHECK_COLOR(ref, GC_WHITE)) {
|
||||||
if (GC_REFCOUNT(ref) > 0) {
|
goto next;
|
||||||
if (!GC_REF_CHECK_COLOR(ref, GC_BLACK)) {
|
}
|
||||||
GC_REF_SET_BLACK(ref);
|
|
||||||
if (UNEXPECTED(!_stack->next)) {
|
if (GC_REFCOUNT(ref) > 0) {
|
||||||
gc_stack_next(_stack);
|
if (!GC_REF_CHECK_COLOR(ref, GC_BLACK)) {
|
||||||
}
|
GC_REF_SET_BLACK(ref);
|
||||||
/* Split stack and reuse the tail */
|
if (UNEXPECTED(!_stack->next)) {
|
||||||
_stack->next->prev = NULL;
|
gc_stack_next(_stack);
|
||||||
gc_scan_black(ref, _stack->next);
|
|
||||||
_stack->next->prev = _stack;
|
|
||||||
}
|
}
|
||||||
} else {
|
/* Split stack and reuse the tail */
|
||||||
if (GC_TYPE(ref) == IS_OBJECT) {
|
_stack->next->prev = NULL;
|
||||||
zend_object *obj = (zend_object*)ref;
|
gc_scan_black(ref, _stack->next);
|
||||||
|
_stack->next->prev = _stack;
|
||||||
|
}
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) {
|
if (GC_TYPE(ref) == IS_OBJECT) {
|
||||||
int n;
|
zend_object *obj = (zend_object*)ref;
|
||||||
zval *zv, *end;
|
if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) {
|
||||||
|
int n;
|
||||||
ht = obj->handlers->get_gc(obj, &zv, &n);
|
zval *zv, *end;
|
||||||
if (UNEXPECTED(ht)) {
|
HashTable *ht = obj->handlers->get_gc(obj, &zv, &n);
|
||||||
if (GC_REF_CHECK_COLOR(ht, GC_GREY)) {
|
if (UNEXPECTED(ht)) {
|
||||||
GC_REF_SET_COLOR(ht, GC_WHITE);
|
if (GC_REF_CHECK_COLOR(ht, GC_GREY)) {
|
||||||
GC_STACK_PUSH((zend_refcounted *) ht);
|
GC_REF_SET_COLOR(ht, GC_WHITE);
|
||||||
}
|
GC_STACK_PUSH((zend_refcounted *) ht);
|
||||||
ht = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!n) goto next;
|
|
||||||
end = zv + n;
|
|
||||||
while (!Z_REFCOUNTED_P(--end)) {
|
|
||||||
if (zv == end) goto next;
|
|
||||||
}
|
|
||||||
while (zv != end) {
|
|
||||||
if (Z_REFCOUNTED_P(zv)) {
|
|
||||||
ref = Z_COUNTED_P(zv);
|
|
||||||
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
|
|
||||||
GC_REF_SET_COLOR(ref, GC_WHITE);
|
|
||||||
GC_STACK_PUSH(ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
zv++;
|
|
||||||
}
|
|
||||||
ref = Z_COUNTED_P(zv);
|
|
||||||
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
|
|
||||||
GC_REF_SET_COLOR(ref, GC_WHITE);
|
|
||||||
goto tail_call;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
goto next;
|
|
||||||
} else if (GC_TYPE(ref) == IS_ARRAY) {
|
|
||||||
ZEND_ASSERT((zend_array*)ref != &EG(symbol_table));
|
|
||||||
ht = (zend_array*)ref;
|
|
||||||
} else if (GC_TYPE(ref) == IS_REFERENCE) {
|
|
||||||
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
|
|
||||||
ref = Z_COUNTED(((zend_reference*)ref)->val);
|
|
||||||
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
|
|
||||||
GC_REF_SET_COLOR(ref, GC_WHITE);
|
|
||||||
goto tail_call;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goto next;
|
|
||||||
} else {
|
|
||||||
goto next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ht->nNumUsed) goto next;
|
if (!n) goto next;
|
||||||
p = ht->arData;
|
end = zv + n;
|
||||||
end = p + ht->nNumUsed;
|
while (!Z_REFCOUNTED_P(--end)) {
|
||||||
while (1) {
|
if (zv == end) goto next;
|
||||||
end--;
|
|
||||||
zv = &end->val;
|
|
||||||
if (Z_TYPE_P(zv) == IS_INDIRECT) {
|
|
||||||
zv = Z_INDIRECT_P(zv);
|
|
||||||
}
|
|
||||||
if (Z_REFCOUNTED_P(zv)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (p == end) goto next;
|
|
||||||
}
|
}
|
||||||
while (p != end) {
|
while (zv != end) {
|
||||||
zv = &p->val;
|
|
||||||
if (Z_TYPE_P(zv) == IS_INDIRECT) {
|
|
||||||
zv = Z_INDIRECT_P(zv);
|
|
||||||
}
|
|
||||||
if (Z_REFCOUNTED_P(zv)) {
|
if (Z_REFCOUNTED_P(zv)) {
|
||||||
ref = Z_COUNTED_P(zv);
|
ref = Z_COUNTED_P(zv);
|
||||||
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
|
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
|
||||||
|
@ -1090,13 +1040,57 @@ tail_call:
|
||||||
GC_STACK_PUSH(ref);
|
GC_STACK_PUSH(ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p++;
|
zv++;
|
||||||
}
|
}
|
||||||
|
ref = Z_COUNTED_P(zv);
|
||||||
|
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
|
||||||
|
GC_REF_SET_COLOR(ref, GC_WHITE);
|
||||||
|
goto tail_call;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (GC_TYPE(ref) == IS_ARRAY) {
|
||||||
|
HashTable *ht = (HashTable *)ref;
|
||||||
|
ZEND_ASSERT(ht != &EG(symbol_table));
|
||||||
|
if (!ht->nNumUsed) goto next;
|
||||||
|
p = ht->arData;
|
||||||
|
end = p + ht->nNumUsed;
|
||||||
|
while (1) {
|
||||||
|
end--;
|
||||||
|
zv = &end->val;
|
||||||
|
if (Z_TYPE_P(zv) == IS_INDIRECT) {
|
||||||
|
zv = Z_INDIRECT_P(zv);
|
||||||
|
}
|
||||||
|
if (Z_REFCOUNTED_P(zv)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (p == end) goto next;
|
||||||
|
}
|
||||||
|
while (p != end) {
|
||||||
zv = &p->val;
|
zv = &p->val;
|
||||||
if (Z_TYPE_P(zv) == IS_INDIRECT) {
|
if (Z_TYPE_P(zv) == IS_INDIRECT) {
|
||||||
zv = Z_INDIRECT_P(zv);
|
zv = Z_INDIRECT_P(zv);
|
||||||
}
|
}
|
||||||
ref = Z_COUNTED_P(zv);
|
if (Z_REFCOUNTED_P(zv)) {
|
||||||
|
ref = Z_COUNTED_P(zv);
|
||||||
|
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
|
||||||
|
GC_REF_SET_COLOR(ref, GC_WHITE);
|
||||||
|
GC_STACK_PUSH(ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
zv = &p->val;
|
||||||
|
if (Z_TYPE_P(zv) == IS_INDIRECT) {
|
||||||
|
zv = Z_INDIRECT_P(zv);
|
||||||
|
}
|
||||||
|
ref = Z_COUNTED_P(zv);
|
||||||
|
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
|
||||||
|
GC_REF_SET_COLOR(ref, GC_WHITE);
|
||||||
|
goto tail_call;
|
||||||
|
}
|
||||||
|
} else if (GC_TYPE(ref) == IS_REFERENCE) {
|
||||||
|
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
|
||||||
|
ref = Z_COUNTED(((zend_reference*)ref)->val);
|
||||||
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
|
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
|
||||||
GC_REF_SET_COLOR(ref, GC_WHITE);
|
GC_REF_SET_COLOR(ref, GC_WHITE);
|
||||||
goto tail_call;
|
goto tail_call;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue