wingo pushed a commit to branch wip-whippet
in repository guile.

commit 9176aa650f7c4c7906887d9e7db62dcaa3c89e07
Author: Andy Wingo <wi...@igalia.com>
AuthorDate: Fri Oct 20 11:43:40 2023 +0200

    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;

Reply via email to