1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 11:40:18 +02:00

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!
This commit is contained in:
Andy Wingo 2023-10-20 11:43:40 +02:00
parent cfc8c8a9b8
commit 9176aa650f
2 changed files with 6 additions and 8 deletions

View file

@ -181,7 +181,7 @@ struct gc_ephemeron* gc_allocate_ephemeron(struct gc_mutator *mut) {
} }
unsigned gc_heap_ephemeron_trace_epoch(struct gc_heap *heap) { 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, void gc_ephemeron_init(struct gc_mutator *mut, struct gc_ephemeron *ephemeron,

View file

@ -238,7 +238,6 @@ enum {
struct gc_ephemeron { struct gc_ephemeron {
GC_EMBEDDER_EPHEMERON_HEADER GC_EMBEDDER_EPHEMERON_HEADER
uint8_t state; uint8_t state;
uint8_t is_dead;
unsigned epoch; unsigned epoch;
struct gc_ephemeron *chain; struct gc_ephemeron *chain;
struct gc_ephemeron *pending; struct gc_ephemeron *pending;
@ -264,7 +263,7 @@ static struct gc_ephemeron** ephemeron_chain(struct gc_ephemeron *e) {
return &e->chain; return &e->chain;
} }
static int ephemeron_is_dead(struct gc_ephemeron *e) { 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) { static int ephemeron_is_not_dead(struct gc_ephemeron *e) {
return !ephemeron_is_dead(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)); return follow_chain(ephemeron_chain(e));
} }
void gc_ephemeron_mark_dead(struct gc_ephemeron *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) { 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) { 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 // 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 // ephemeron as live when it's not, but only for this cycle. No big
// deal. // deal.
if (atomic_load_explicit(&e->is_dead, memory_order_acquire)) { if (ephemeron_is_dead(e)) {
// CLAIMED[epoch] -> TRACED[epoch]. // CLAIMED[epoch] -> TRACED[epoch].
atomic_store_explicit(&e->state, EPHEMERON_STATE_TRACED, atomic_store_explicit(&e->state, EPHEMERON_STATE_TRACED,
memory_order_release); memory_order_release);
@ -553,7 +552,7 @@ gc_sweep_pending_ephemerons(struct gc_pending_ephemerons *state,
e; e;
e = follow_pending(&e->pending)) { e = follow_pending(&e->pending)) {
// PENDING -> TRACED, but dead. // 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, atomic_store_explicit(&e->state, EPHEMERON_STATE_TRACED,
memory_order_release); 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 // assumption is that the ephemeron is younger than the key and the
// value. // value.
ephemeron->state = EPHEMERON_STATE_TRACED; ephemeron->state = EPHEMERON_STATE_TRACED;
ephemeron->is_dead = 0;
ephemeron->epoch = gc_heap_ephemeron_trace_epoch(heap) - 1; ephemeron->epoch = gc_heap_ephemeron_trace_epoch(heap) - 1;
ephemeron->chain = NULL; ephemeron->chain = NULL;
ephemeron->pending = NULL; ephemeron->pending = NULL;