1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 03:30:27 +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) {
return 0;
return GC_get_gc_no();
}
void gc_ephemeron_init(struct gc_mutator *mut, struct gc_ephemeron *ephemeron,

View file

@ -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;