From 9176aa650f7c4c7906887d9e7db62dcaa3c89e07 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Fri, 20 Oct 2023 11:43:40 +0200 Subject: [PATCH] Fix BDW ephemeron implementation * src/gc-ephemeron.c: Use key null-ness as dead ephemeron indicator; works better with BDW-GC's disappearing link. * src/bdw.c (gc_heap_ephemeron_trace_epoch): Fix to actually define the epoch. Whoops! --- src/bdw.c | 2 +- src/gc-ephemeron.c | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/bdw.c b/src/bdw.c index 186b50a8c..f429b43c2 100644 --- a/src/bdw.c +++ b/src/bdw.c @@ -181,7 +181,7 @@ struct gc_ephemeron* gc_allocate_ephemeron(struct gc_mutator *mut) { } unsigned gc_heap_ephemeron_trace_epoch(struct gc_heap *heap) { - return 0; + return GC_get_gc_no(); } void gc_ephemeron_init(struct gc_mutator *mut, struct gc_ephemeron *ephemeron, diff --git a/src/gc-ephemeron.c b/src/gc-ephemeron.c index a13c4bb98..8a42c1a84 100644 --- a/src/gc-ephemeron.c +++ b/src/gc-ephemeron.c @@ -238,7 +238,6 @@ enum { struct gc_ephemeron { GC_EMBEDDER_EPHEMERON_HEADER uint8_t state; - uint8_t is_dead; unsigned epoch; struct gc_ephemeron *chain; struct gc_ephemeron *pending; @@ -264,7 +263,7 @@ static struct gc_ephemeron** ephemeron_chain(struct gc_ephemeron *e) { return &e->chain; } static int ephemeron_is_dead(struct gc_ephemeron *e) { - return atomic_load_explicit(&e->is_dead, memory_order_acquire); + return !atomic_load_explicit(&e->key.value, memory_order_acquire); } static int ephemeron_is_not_dead(struct gc_ephemeron *e) { return !ephemeron_is_dead(e); @@ -284,7 +283,7 @@ struct gc_ephemeron* gc_ephemeron_chain_next(struct gc_ephemeron *e) { return follow_chain(ephemeron_chain(e)); } void gc_ephemeron_mark_dead(struct gc_ephemeron *e) { - atomic_store_explicit(&e->is_dead, 1, memory_order_release); + atomic_store_explicit(&e->key.value, 0, memory_order_release); } //////////////////////////////////////////////////////////////////////// @@ -327,7 +326,7 @@ static struct gc_ephemeron* pop_resolved(struct gc_ephemeron **loc) { //////////////////////////////////////////////////////////////////////// struct gc_ref gc_ephemeron_key(struct gc_ephemeron *e) { - return ephemeron_is_dead(e) ? gc_ref_null() : e->key; + return gc_ref(atomic_load_explicit(&e->key.value, memory_order_acquire)); } struct gc_ref gc_ephemeron_value(struct gc_ephemeron *e) { @@ -471,7 +470,7 @@ void gc_trace_ephemeron(struct gc_ephemeron *e, // as dead and here; the consequence would be that we treat an // ephemeron as live when it's not, but only for this cycle. No big // deal. - if (atomic_load_explicit(&e->is_dead, memory_order_acquire)) { + if (ephemeron_is_dead(e)) { // CLAIMED[epoch] -> TRACED[epoch]. atomic_store_explicit(&e->state, EPHEMERON_STATE_TRACED, memory_order_release); @@ -553,7 +552,7 @@ gc_sweep_pending_ephemerons(struct gc_pending_ephemerons *state, e; e = follow_pending(&e->pending)) { // PENDING -> TRACED, but dead. - atomic_store_explicit(&e->is_dead, 1, memory_order_release); + atomic_store_explicit(&e->key.value, 0, memory_order_release); atomic_store_explicit(&e->state, EPHEMERON_STATE_TRACED, memory_order_release); } @@ -572,7 +571,6 @@ void gc_ephemeron_init_internal(struct gc_heap *heap, // assumption is that the ephemeron is younger than the key and the // value. ephemeron->state = EPHEMERON_STATE_TRACED; - ephemeron->is_dead = 0; ephemeron->epoch = gc_heap_ephemeron_trace_epoch(heap) - 1; ephemeron->chain = NULL; ephemeron->pending = NULL;