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

commit cf129f10defd844cb4d15538890c7c180caa74a3
Author: Andy Wingo <wi...@igalia.com>
AuthorDate: Fri Aug 30 21:19:51 2024 +0200

    nofl: Block marks are bytes
    
    There was no need to use a bitvector, and the marks were only being
    partially cleared.  More straightforward (and still low overhead) as
    bytes.
---
 src/nofl-space.h | 33 +++++++++++++--------------------
 1 file changed, 13 insertions(+), 20 deletions(-)

diff --git a/src/nofl-space.h b/src/nofl-space.h
index 3df0960f0..037dff0d2 100644
--- a/src/nofl-space.h
+++ b/src/nofl-space.h
@@ -236,30 +236,24 @@ nofl_metadata_byte_for_object(struct gc_ref ref) {
   return nofl_metadata_byte_for_addr(gc_ref_value(ref));
 }
 
-static int
-nofl_block_is_marked(uintptr_t addr) {
+static uint8_t*
+nofl_block_mark_loc(uintptr_t addr) {
   uintptr_t base = align_down(addr, NOFL_SLAB_SIZE);
   struct nofl_slab *slab = (struct nofl_slab *) base;
   unsigned block_idx = (addr / NOFL_BLOCK_SIZE) % NOFL_BLOCKS_PER_SLAB;
-  uint8_t mark_byte = block_idx / 8;
-  GC_ASSERT(mark_byte < NOFL_HEADER_BYTES_PER_SLAB);
-  uint8_t mark_mask = 1U << (block_idx % 8);
-  uint8_t byte = atomic_load_explicit(&slab->header.block_marks[mark_byte],
-                                      memory_order_relaxed);
-  return byte & mark_mask;
+  return &slab->header.block_marks[block_idx];
+}
+
+static int
+nofl_block_is_marked(uintptr_t addr) {
+  return atomic_load_explicit(nofl_block_mark_loc(addr), memory_order_relaxed);
 }
 
 static void
 nofl_block_set_mark(uintptr_t addr) {
-  uintptr_t base = align_down(addr, NOFL_SLAB_SIZE);
-  struct nofl_slab *slab = (struct nofl_slab *) base;
-  unsigned block_idx = (addr / NOFL_BLOCK_SIZE) % NOFL_BLOCKS_PER_SLAB;
-  uint8_t mark_byte = block_idx / 8;
-  GC_ASSERT(mark_byte < NOFL_HEADER_BYTES_PER_SLAB);
-  uint8_t mark_mask = 1U << (block_idx % 8);
-  atomic_fetch_or_explicit(&slab->header.block_marks[mark_byte],
-                           mark_mask,
-                           memory_order_relaxed);
+  uint8_t *loc = nofl_block_mark_loc(addr);
+  if (!atomic_load_explicit(loc, memory_order_relaxed))
+    atomic_store_explicit(loc, 1, memory_order_relaxed);
 }
 
 #define NOFL_GRANULES_PER_BLOCK (NOFL_BLOCK_SIZE / NOFL_GRANULE_SIZE)
@@ -982,7 +976,7 @@ static void
 nofl_space_clear_block_marks(struct nofl_space *space) {
   for (size_t s = 0; s < space->nslabs; s++) {
     struct nofl_slab *slab = space->slabs[s];
-    memset(slab->header.block_marks, 0, NOFL_BLOCKS_PER_SLAB / 8);
+    memset(slab->header.block_marks, 0, sizeof(slab->header.block_marks));
   }
 }
 
@@ -1282,8 +1276,7 @@ static inline int
 nofl_space_set_nonempty_mark(struct nofl_space *space, uint8_t *metadata,
                              uint8_t byte, struct gc_ref ref) {
   nofl_space_set_mark(space, metadata, byte);
-  if (!nofl_block_is_marked(gc_ref_value(ref)))
-    nofl_block_set_mark(gc_ref_value(ref));
+  nofl_block_set_mark(gc_ref_value(ref));
   return 1;
 }
 

Reply via email to