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:
Nikita Popov 2021-07-12 11:49:12 +02:00
parent 5f8ed7765a
commit 5bde82a442

View file

@ -991,13 +991,15 @@ 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)) {
goto next;
}
if (GC_REFCOUNT(ref) > 0) { if (GC_REFCOUNT(ref) > 0) {
if (!GC_REF_CHECK_COLOR(ref, GC_BLACK)) { if (!GC_REF_CHECK_COLOR(ref, GC_BLACK)) {
GC_REF_SET_BLACK(ref); GC_REF_SET_BLACK(ref);
@ -1009,21 +1011,20 @@ tail_call:
gc_scan_black(ref, _stack->next); gc_scan_black(ref, _stack->next);
_stack->next->prev = _stack; _stack->next->prev = _stack;
} }
} else { goto next;
}
if (GC_TYPE(ref) == IS_OBJECT) { if (GC_TYPE(ref) == IS_OBJECT) {
zend_object *obj = (zend_object*)ref; zend_object *obj = (zend_object*)ref;
if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) { if (EXPECTED(!(OBJ_FLAGS(ref) & IS_OBJ_FREE_CALLED))) {
int n; int n;
zval *zv, *end; zval *zv, *end;
HashTable *ht = obj->handlers->get_gc(obj, &zv, &n);
ht = obj->handlers->get_gc(obj, &zv, &n);
if (UNEXPECTED(ht)) { if (UNEXPECTED(ht)) {
if (GC_REF_CHECK_COLOR(ht, GC_GREY)) { if (GC_REF_CHECK_COLOR(ht, GC_GREY)) {
GC_REF_SET_COLOR(ht, GC_WHITE); GC_REF_SET_COLOR(ht, GC_WHITE);
GC_STACK_PUSH((zend_refcounted *) ht); GC_STACK_PUSH((zend_refcounted *) ht);
} }
ht = NULL;
} }
if (!n) goto next; if (!n) goto next;
@ -1047,23 +1048,9 @@ tail_call:
goto tail_call; goto tail_call;
} }
} }
goto next;
} else if (GC_TYPE(ref) == IS_ARRAY) { } else if (GC_TYPE(ref) == IS_ARRAY) {
ZEND_ASSERT((zend_array*)ref != &EG(symbol_table)); HashTable *ht = (HashTable *)ref;
ht = (zend_array*)ref; ZEND_ASSERT(ht != &EG(symbol_table));
} 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 (!ht->nNumUsed) goto next;
p = ht->arData; p = ht->arData;
end = p + ht->nNumUsed; end = p + ht->nNumUsed;
@ -1101,6 +1088,13 @@ tail_call:
GC_REF_SET_COLOR(ref, GC_WHITE); GC_REF_SET_COLOR(ref, GC_WHITE);
goto tail_call; 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)) {
GC_REF_SET_COLOR(ref, GC_WHITE);
goto tail_call;
}
} }
} }