Skip to content

Instantly share code, notes, and snippets.

@dstogov
Last active August 8, 2019 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dstogov/43a992d481f65ac16c454e1a292be38e to your computer and use it in GitHub Desktop.
Save dstogov/43a992d481f65ac16c454e1a292be38e to your computer and use it in GitHub Desktop.
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c
index 47236a934e..d5fc550a77 100644
--- a/Zend/zend_gc.c
+++ b/Zend/zend_gc.c
@@ -388,11 +388,14 @@ tail_call:
ZVAL_OBJ(&tmp, obj);
ht = get_gc(&tmp, &zv, &n);
end = zv + n;
- if (EXPECTED(!ht)) {
+ if (EXPECTED(!ht) || UNEXPECTED(GC_REF_GET_COLOR(ht) != GC_GREY)) {
if (!n) return;
while (!Z_REFCOUNTED_P(--end)) {
if (zv == end) return;
}
+ ht = NULL;
+ } else {
+ GC_REF_SET_COLOR(ht, GC_BLACK);
}
while (zv != end) {
if (Z_REFCOUNTED_P(zv)) {
@@ -498,15 +501,19 @@ tail_call:
ZVAL_OBJ(&tmp, obj);
ht = get_gc(&tmp, &zv, &n);
end = zv + n;
- if (EXPECTED(!ht)) {
+ if (EXPECTED(!ht) || UNEXPECTED(GC_REF_GET_COLOR(ht) == GC_GREY)) {
if (!n) return;
while (!Z_REFCOUNTED_P(--end)) {
if (zv == end) return;
}
+ ht = NULL;
+ } else {
+ GC_REF_SET_COLOR(ht, GC_GREY);
}
while (zv != end) {
if (Z_REFCOUNTED_P(zv)) {
ref = Z_COUNTED_P(zv);
+ ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
GC_REFCOUNT(ref)--;
gc_mark_grey(ref);
}
@@ -514,6 +521,7 @@ tail_call:
}
if (EXPECTED(!ht)) {
ref = Z_COUNTED_P(zv);
+ ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
GC_REFCOUNT(ref)--;
goto tail_call;
}
@@ -530,6 +538,7 @@ tail_call:
} else if (GC_TYPE(ref) == IS_REFERENCE) {
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
ref = Z_COUNTED(((zend_reference*)ref)->val);
+ ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
GC_REFCOUNT(ref)--;
goto tail_call;
}
@@ -559,6 +568,7 @@ tail_call:
}
if (Z_REFCOUNTED_P(zv)) {
ref = Z_COUNTED_P(zv);
+ ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
GC_REFCOUNT(ref)--;
gc_mark_grey(ref);
}
@@ -569,6 +579,7 @@ tail_call:
zv = Z_INDIRECT_P(zv);
}
ref = Z_COUNTED_P(zv);
+ ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
GC_REFCOUNT(ref)--;
goto tail_call;
}
@@ -611,11 +622,14 @@ tail_call:
ZVAL_OBJ(&tmp, obj);
ht = get_gc(&tmp, &zv, &n);
end = zv + n;
- if (EXPECTED(!ht)) {
+ if (EXPECTED(!ht) || UNEXPECTED(GC_REF_GET_COLOR(ht) != GC_GREY)) {
if (!n) return;
while (!Z_REFCOUNTED_P(--end)) {
if (zv == end) return;
}
+ ht = NULL;
+ } else {
+ GC_REF_SET_COLOR(ht, GC_BLACK);
}
while (zv != end) {
if (Z_REFCOUNTED_P(zv)) {
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c
index 8b9ee17632..a121b842d6 100644
--- a/Zend/zend_gc.c
+++ b/Zend/zend_gc.c
@@ -701,11 +701,14 @@ tail_call:
ZVAL_OBJ(&tmp, obj);
ht = get_gc(&tmp, &zv, &n);
end = zv + n;
- if (EXPECTED(!ht)) {
+ if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_BLACK))) {
+ ht = NULL;
if (!n) goto next;
while (!Z_REFCOUNTED_P(--end)) {
if (zv == end) goto next;
}
+ } else {
+ GC_REF_SET_COLOR(ht, GC_BLACK);
}
while (zv != end) {
if (Z_REFCOUNTED_P(zv)) {
@@ -820,15 +823,19 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
ZVAL_OBJ(&tmp, obj);
ht = get_gc(&tmp, &zv, &n);
end = zv + n;
- if (EXPECTED(!ht)) {
+ if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_GREY))) {
+ ht = NULL;
if (!n) goto next;
while (!Z_REFCOUNTED_P(--end)) {
if (zv == end) goto next;
}
+ } else {
+ GC_REF_SET_COLOR(ht, GC_GREY);
}
while (zv != end) {
if (Z_REFCOUNTED_P(zv)) {
ref = Z_COUNTED_P(zv);
+ ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
GC_DELREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
GC_REF_SET_COLOR(ref, GC_GREY);
@@ -839,6 +846,7 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
}
if (EXPECTED(!ht)) {
ref = Z_COUNTED_P(zv);
+ ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
GC_DELREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
GC_REF_SET_COLOR(ref, GC_GREY);
@@ -859,6 +867,7 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
} else if (GC_TYPE(ref) == IS_REFERENCE) {
if (Z_REFCOUNTED(((zend_reference*)ref)->val)) {
ref = Z_COUNTED(((zend_reference*)ref)->val);
+ ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
GC_DELREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
GC_REF_SET_COLOR(ref, GC_GREY);
@@ -891,6 +900,7 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
}
if (Z_REFCOUNTED_P(zv)) {
ref = Z_COUNTED_P(zv);
+ ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
GC_DELREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
GC_REF_SET_COLOR(ref, GC_GREY);
@@ -904,6 +914,7 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
zv = Z_INDIRECT_P(zv);
}
ref = Z_COUNTED_P(zv);
+ ZEND_ASSERT(GC_REFCOUNT(ref) > 0);
GC_DELREF(ref);
if (!GC_REF_CHECK_COLOR(ref, GC_GREY)) {
GC_REF_SET_COLOR(ref, GC_GREY);
@@ -1005,11 +1016,14 @@ tail_call:
ZVAL_OBJ(&tmp, obj);
ht = get_gc(&tmp, &zv, &n);
end = zv + n;
- if (EXPECTED(!ht)) {
+ if (EXPECTED(!ht) || UNEXPECTED(!GC_REF_CHECK_COLOR(ht, GC_GREY))) {
+ ht = NULL;
if (!n) goto next;
while (!Z_REFCOUNTED_P(--end)) {
if (zv == end) goto next;
}
+ } else {
+ GC_REF_SET_COLOR(ht, GC_WHITE);
}
while (zv != end) {
if (Z_REFCOUNTED_P(zv)) {
@@ -1176,7 +1190,8 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
ZVAL_OBJ(&tmp, obj);
ht = get_gc(&tmp, &zv, &n);
end = zv + n;
- if (EXPECTED(!ht)) {
+ if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_BLACK))) {
+ ht = NULL;
if (!n) goto next;
while (!Z_REFCOUNTED_P(--end)) {
/* count non-refcounted for compatibility ??? */
@@ -1185,6 +1200,8 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
}
if (zv == end) goto next;
}
+ } else {
+ GC_REF_SET_BLACK(ht);
}
while (zv != end) {
if (Z_REFCOUNTED_P(zv)) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment