summaryrefslogtreecommitdiffhomepage
path: root/types.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2021-07-10 19:27:52 +0200
committerJo-Philipp Wich <jo@mein.io>2021-07-10 19:29:28 +0200
commitdad8f3aed4ca5f2f93e2be6f1243632439dec541 (patch)
treec7ccb3813ad791cf3f912f61916b776cd022d6a9 /types.c
parent62dbd6470e2e1b049ba18669d21f91d60063e347 (diff)
types: properly deal with circular data in GC mark phase
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'types.c')
-rw-r--r--types.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/types.c b/types.c
index 54bc50e..d0f23f9 100644
--- a/types.c
+++ b/types.c
@@ -126,30 +126,34 @@ ucv_gc_mark(uc_value_t *uv)
struct lh_entry *entry;
size_t i;
+ if (ucv_is_marked(uv))
+ return;
+
switch (ucv_type(uv)) {
case UC_ARRAY:
array = (uc_array_t *)uv;
+ if (array->ref.next)
+ ucv_set_mark(uv);
+
ucv_gc_mark(array->proto);
for (i = 0; i < array->count; i++)
ucv_gc_mark(array->entries[i]);
- if (array->ref.next)
- ucv_set_mark(uv);
-
break;
case UC_OBJECT:
object = (uc_object_t *)uv;
+ if (object->ref.next)
+ ucv_set_mark(uv);
+
ucv_gc_mark(object->proto);
lh_foreach(object->table, entry)
ucv_gc_mark((uc_value_t *)lh_entry_v(entry));
- if (object->ref.next)
- ucv_set_mark(uv);
break;
@@ -157,14 +161,14 @@ ucv_gc_mark(uc_value_t *uv)
closure = (uc_closure_t *)uv;
function = closure->function;
+ if (closure->ref.next)
+ ucv_set_mark(uv);
+
for (i = 0; i < function->nupvals; i++)
ucv_gc_mark((uc_value_t *)closure->upvals[i]);
ucv_gc_mark((uc_value_t *)function);
- if (closure->ref.next)
- ucv_set_mark(uv);
-
break;
case UC_UPVALUE: