Skip to content

Reduce gc stack usage for strings (and resources) #17194

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 40 additions & 40 deletions Zend/zend_gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ static void gc_scan_black(zend_refcounted *ref, gc_stack *stack)
zval *entry = (zval*) Z_PTR_P(zv);
zval *weakmap = zv+1;
ZEND_ASSERT(Z_REFCOUNTED_P(weakmap));
if (Z_OPT_REFCOUNTED_P(entry)) {
if (Z_OPT_COLLECTABLE_P(entry)) {
GC_UNSET_FROM_WEAKMAP_KEY(entry);
if (GC_REF_CHECK_COLOR(Z_COUNTED_P(weakmap), GC_GREY)) {
/* Weakmap was scanned in gc_mark_roots, we must
Expand Down Expand Up @@ -855,7 +855,7 @@ static void gc_scan_black(zend_refcounted *ref, gc_stack *stack)
ZEND_ASSERT(Z_TYPE_P(zv+1) == IS_PTR);
zval *key = zv;
zval *entry = (zval*) Z_PTR_P(zv+1);
if (Z_OPT_REFCOUNTED_P(entry)) {
if (Z_OPT_COLLECTABLE_P(entry)) {
GC_UNSET_FROM_WEAKMAP(entry);
if (GC_REF_CHECK_COLOR(Z_COUNTED_P(key), GC_GREY)) {
/* Key was scanned in gc_mark_roots, we must
Expand Down Expand Up @@ -893,7 +893,7 @@ static void gc_scan_black(zend_refcounted *ref, gc_stack *stack)
if (!GC_REF_CHECK_COLOR(ht, GC_BLACK)) {
GC_REF_SET_BLACK(ht);
for (; n != 0; n--) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
GC_ADDREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_BLACK)) {
Expand All @@ -909,14 +909,14 @@ static void gc_scan_black(zend_refcounted *ref, gc_stack *stack)

handle_zvals:
for (; n != 0; n--) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
GC_ADDREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_BLACK)) {
GC_REF_SET_BLACK(ref);
zv++;
while (--n) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
zend_refcounted *ref = Z_COUNTED_P(zv);
GC_ADDREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_BLACK)) {
Expand Down Expand Up @@ -948,7 +948,7 @@ static void gc_scan_black(zend_refcounted *ref, gc_stack *stack)
if (Z_TYPE_P(zv) == IS_INDIRECT) {
zv = Z_INDIRECT_P(zv);
}
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
GC_ADDREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_BLACK)) {
Expand All @@ -959,7 +959,7 @@ static void gc_scan_black(zend_refcounted *ref, gc_stack *stack)
if (Z_TYPE_P(zv) == IS_INDIRECT) {
zv = Z_INDIRECT_P(zv);
}
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
zend_refcounted *ref = Z_COUNTED_P(zv);
GC_ADDREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_BLACK)) {
Expand All @@ -975,7 +975,7 @@ static void gc_scan_black(zend_refcounted *ref, gc_stack *stack)
p++;
}
} else if (GC_TYPE(ref) == IS_REFERENCE) {
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
if (Z_COLLECTABLE(((zend_reference*)ref)->val)) {
ref = Z_COUNTED(((zend_reference*)ref)->val);
GC_ADDREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_BLACK)) {
Expand Down Expand Up @@ -1019,7 +1019,7 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
zval *entry = (zval*) Z_PTR_P(zv);
zval *weakmap = zv+1;
ZEND_ASSERT(Z_REFCOUNTED_P(weakmap));
if (Z_REFCOUNTED_P(entry)) {
if (Z_COLLECTABLE_P(entry)) {
GC_SET_FROM_WEAKMAP_KEY(entry);
ref = Z_COUNTED_P(entry);
/* Only DELREF if the contribution from the weakmap has
Expand All @@ -1043,7 +1043,7 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
for (; n != 0; n--) {
ZEND_ASSERT(Z_TYPE_P(zv) == IS_PTR);
zval *entry = (zval*) Z_PTR_P(zv);
if (Z_REFCOUNTED_P(entry)) {
if (Z_COLLECTABLE_P(entry)) {
GC_SET_FROM_WEAKMAP(entry);
ref = Z_COUNTED_P(entry);
/* Only DELREF if the contribution from the weakmap key
Expand All @@ -1069,7 +1069,7 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
if (!GC_REF_CHECK_COLOR(ht, GC_GREY)) {
GC_REF_SET_COLOR(ht, GC_GREY);
for (; n != 0; n--) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
GC_DELREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
Expand All @@ -1084,14 +1084,14 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
}
handle_zvals:
for (; n != 0; n--) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
GC_DELREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
GC_REF_SET_COLOR(ref, GC_GREY);
zv++;
while (--n) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
zend_refcounted *ref = Z_COUNTED_P(zv);
GC_DELREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
Expand Down Expand Up @@ -1123,7 +1123,7 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
if (Z_TYPE_P(zv) == IS_INDIRECT) {
zv = Z_INDIRECT_P(zv);
}
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
GC_DELREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
Expand All @@ -1134,7 +1134,7 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
if (Z_TYPE_P(zv) == IS_INDIRECT) {
zv = Z_INDIRECT_P(zv);
}
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
zend_refcounted *ref = Z_COUNTED_P(zv);
GC_DELREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
Expand All @@ -1150,7 +1150,7 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
p++;
}
} else if (GC_TYPE(ref) == IS_REFERENCE) {
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
if (Z_COLLECTABLE(((zend_reference*)ref)->val)) {
ref = Z_COUNTED(((zend_reference*)ref)->val);
GC_DELREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
Expand Down Expand Up @@ -1263,7 +1263,7 @@ static void gc_scan(zend_refcounted *ref, gc_stack *stack)
for (; n != 0; n--) {
ZEND_ASSERT(Z_TYPE_P(zv) == IS_PTR);
zval *entry = (zval*) Z_PTR_P(zv);
if (Z_OPT_REFCOUNTED_P(entry)) {
if (Z_OPT_COLLECTABLE_P(entry)) {
ref = Z_COUNTED_P(entry);
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
GC_REF_SET_COLOR(ref, GC_WHITE);
Expand All @@ -1282,7 +1282,7 @@ static void gc_scan(zend_refcounted *ref, gc_stack *stack)
GC_REF_SET_COLOR(ht, GC_WHITE);
GC_STACK_PUSH((zend_refcounted *) ht);
for (; n != 0; n--) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
GC_REF_SET_COLOR(ref, GC_WHITE);
Expand All @@ -1297,13 +1297,13 @@ static void gc_scan(zend_refcounted *ref, gc_stack *stack)

handle_zvals:
for (; n != 0; n--) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
GC_REF_SET_COLOR(ref, GC_WHITE);
zv++;
while (--n) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
zend_refcounted *ref = Z_COUNTED_P(zv);
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
GC_REF_SET_COLOR(ref, GC_WHITE);
Expand Down Expand Up @@ -1335,7 +1335,7 @@ static void gc_scan(zend_refcounted *ref, gc_stack *stack)
if (Z_TYPE_P(zv) == IS_INDIRECT) {
zv = Z_INDIRECT_P(zv);
}
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
GC_REF_SET_COLOR(ref, GC_WHITE);
Expand All @@ -1345,7 +1345,7 @@ static void gc_scan(zend_refcounted *ref, gc_stack *stack)
if (Z_TYPE_P(zv) == IS_INDIRECT) {
zv = Z_INDIRECT_P(zv);
}
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
zend_refcounted *ref = Z_COUNTED_P(zv);
if (GC_REF_CHECK_COLOR(ref, GC_GREY)) {
GC_REF_SET_COLOR(ref, GC_WHITE);
Expand All @@ -1360,7 +1360,7 @@ static void gc_scan(zend_refcounted *ref, gc_stack *stack)
p++;
}
} else if (GC_TYPE(ref) == IS_REFERENCE) {
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
if (Z_COLLECTABLE(((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);
Expand Down Expand Up @@ -1473,7 +1473,7 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
for (; n != 0; n--) {
ZEND_ASSERT(Z_TYPE_P(zv) == IS_PTR);
zval *entry = (zval*) Z_PTR_P(zv);
if (Z_REFCOUNTED_P(entry) && GC_FROM_WEAKMAP_KEY(entry)) {
if (Z_COLLECTABLE_P(entry) && GC_FROM_WEAKMAP_KEY(entry)) {
GC_UNSET_FROM_WEAKMAP_KEY(entry);
GC_UNSET_FROM_WEAKMAP(entry);
ref = Z_COUNTED_P(entry);
Expand All @@ -1494,7 +1494,7 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
for (; n != 0; n--) {
ZEND_ASSERT(Z_TYPE_P(zv) == IS_PTR);
zval *entry = (zval*) Z_PTR_P(zv);
if (Z_REFCOUNTED_P(entry) && GC_FROM_WEAKMAP(entry)) {
if (Z_COLLECTABLE_P(entry) && GC_FROM_WEAKMAP(entry)) {
GC_UNSET_FROM_WEAKMAP_KEY(entry);
GC_UNSET_FROM_WEAKMAP(entry);
ref = Z_COUNTED_P(entry);
Expand All @@ -1517,7 +1517,7 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
if (GC_REF_CHECK_COLOR(ht, GC_WHITE)) {
GC_REF_SET_BLACK(ht);
for (; n != 0; n--) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
GC_ADDREF(ref);
if (GC_REF_CHECK_COLOR(ref, GC_WHITE)) {
Expand All @@ -1533,14 +1533,14 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta

handle_zvals:
for (; n != 0; n--) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
GC_ADDREF(ref);
if (GC_REF_CHECK_COLOR(ref, GC_WHITE)) {
GC_REF_SET_BLACK(ref);
zv++;
while (--n) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
zend_refcounted *ref = Z_COUNTED_P(zv);
GC_ADDREF(ref);
if (GC_REF_CHECK_COLOR(ref, GC_WHITE)) {
Expand Down Expand Up @@ -1576,7 +1576,7 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
if (Z_TYPE_P(zv) == IS_INDIRECT) {
zv = Z_INDIRECT_P(zv);
}
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
GC_ADDREF(ref);
if (GC_REF_CHECK_COLOR(ref, GC_WHITE)) {
Expand All @@ -1587,7 +1587,7 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
if (Z_TYPE_P(zv) == IS_INDIRECT) {
zv = Z_INDIRECT_P(zv);
}
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
zend_refcounted *ref = Z_COUNTED_P(zv);
GC_ADDREF(ref);
if (GC_REF_CHECK_COLOR(ref, GC_WHITE)) {
Expand All @@ -1603,7 +1603,7 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
p++;
}
} else if (GC_TYPE(ref) == IS_REFERENCE) {
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
if (Z_COLLECTABLE(((zend_reference*)ref)->val)) {
ref = Z_COUNTED(((zend_reference*)ref)->val);
GC_ADDREF(ref);
if (GC_REF_CHECK_COLOR(ref, GC_WHITE)) {
Expand Down Expand Up @@ -1681,7 +1681,7 @@ static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffe
GC_REMOVE_FROM_BUFFER(ref);
count++;
} else if (GC_TYPE(ref) == IS_REFERENCE) {
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
if (Z_COLLECTABLE(((zend_reference*)ref)->val)) {
ref = Z_COUNTED(((zend_reference*)ref)->val);
goto tail_call;
}
Expand All @@ -1704,7 +1704,7 @@ static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffe
for (; n != 0; n--) {
ZEND_ASSERT(Z_TYPE_P(zv) == IS_PTR);
zval *entry = (zval*) Z_PTR_P(zv);
if (Z_OPT_REFCOUNTED_P(entry)) {
if (Z_OPT_COLLECTABLE_P(entry)) {
ref = Z_COUNTED_P(entry);
GC_STACK_PUSH(ref);
}
Expand All @@ -1717,7 +1717,7 @@ static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffe
zv = table;
if (UNEXPECTED(ht)) {
for (; n != 0; n--) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
GC_STACK_PUSH(ref);
}
Expand All @@ -1732,11 +1732,11 @@ static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffe

handle_zvals:
for (; n != 0; n--) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
zv++;
while (--n) {
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
zend_refcounted *ref = Z_COUNTED_P(zv);
GC_STACK_PUSH(ref);
}
Expand All @@ -1763,15 +1763,15 @@ static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffe
if (Z_TYPE_P(zv) == IS_INDIRECT) {
zv = Z_INDIRECT_P(zv);
}
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
ref = Z_COUNTED_P(zv);
p++;
while (--n) {
zv = &p->val;
if (Z_TYPE_P(zv) == IS_INDIRECT) {
zv = Z_INDIRECT_P(zv);
}
if (Z_REFCOUNTED_P(zv)) {
if (Z_COLLECTABLE_P(zv)) {
zend_refcounted *ref = Z_COUNTED_P(zv);
GC_STACK_PUSH(ref);
}
Expand Down Expand Up @@ -2175,7 +2175,7 @@ static void zend_gc_check_root_tmpvars(void) {
if (kind == ZEND_LIVE_TMPVAR || kind == ZEND_LIVE_LOOP) {
uint32_t var_num = range->var & ~ZEND_LIVE_MASK;
zval *var = ZEND_CALL_VAR(ex, var_num);
if (Z_REFCOUNTED_P(var)) {
if (Z_COLLECTABLE_P(var)) {
gc_check_possible_root(Z_COUNTED_P(var));
}
}
Expand Down Expand Up @@ -2205,7 +2205,7 @@ static void zend_gc_remove_root_tmpvars(void) {
if (kind == ZEND_LIVE_TMPVAR || kind == ZEND_LIVE_LOOP) {
uint32_t var_num = range->var & ~ZEND_LIVE_MASK;
zval *var = ZEND_CALL_VAR(ex, var_num);
if (Z_REFCOUNTED_P(var)) {
if (Z_COLLECTABLE_P(var)) {
GC_REMOVE_FROM_BUFFER(Z_COUNTED_P(var));
}
}
Expand Down
5 changes: 4 additions & 1 deletion Zend/zend_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,7 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) {
#define IS_ARRAY_EX (IS_ARRAY | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT) | (IS_TYPE_COLLECTABLE << Z_TYPE_FLAGS_SHIFT))
#define IS_OBJECT_EX (IS_OBJECT | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT) | (IS_TYPE_COLLECTABLE << Z_TYPE_FLAGS_SHIFT))
#define IS_RESOURCE_EX (IS_RESOURCE | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT))
#define IS_REFERENCE_EX (IS_REFERENCE | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT))
#define IS_REFERENCE_EX (IS_REFERENCE | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT) | (IS_TYPE_COLLECTABLE << Z_TYPE_FLAGS_SHIFT))

#define IS_CONSTANT_AST_EX (IS_CONSTANT_AST | (IS_TYPE_REFCOUNTED << Z_TYPE_FLAGS_SHIFT))

Expand Down Expand Up @@ -943,6 +943,9 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) {
#define Z_OPT_REFCOUNTED(zval) Z_TYPE_INFO_REFCOUNTED(Z_TYPE_INFO(zval))
#define Z_OPT_REFCOUNTED_P(zval_p) Z_OPT_REFCOUNTED(*(zval_p))

#define Z_OPT_COLLECTABLE(zval) ((Z_TYPE_INFO(zval) & (IS_TYPE_COLLECTABLE << Z_TYPE_FLAGS_SHIFT)) != 0)
#define Z_OPT_COLLECTABLE_P(zval_p) Z_OPT_COLLECTABLE(*(zval_p))

/* deprecated: (COPYABLE is the same as IS_ARRAY) */
#define Z_OPT_COPYABLE(zval) (Z_OPT_TYPE(zval) == IS_ARRAY)
#define Z_OPT_COPYABLE_P(zval_p) Z_OPT_COPYABLE(*(zval_p))
Expand Down
Loading