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:
parent
cfc8c8a9b8
commit
9176aa650f
2 changed files with 6 additions and 8 deletions
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue