summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hawthorn <john@hawthorn.email>2026-01-20 11:55:36 -0800
committerJohn Hawthorn <john@hawthorn.email>2026-01-30 19:42:26 -0800
commite8d8f50fa82f1f05cc6fa927be7c3415f028e73c (patch)
tree01616a4395db218b1ae7f07828e37aae2e588399
parent6327f59307d8cd62438ed1fee80058b8c7cc5fab (diff)
Clear age and unprotected bits for page at once
This aims to speed up sweeping by clearing all age and wb_unprotected bits for unmarked objects. This should be faster because we can clear up to a whole plane of objects (64 slots) at once.
-rw-r--r--gc/default/default.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/gc/default/default.c b/gc/default/default.c
index 60e5d624c9..90232c7618 100644
--- a/gc/default/default.c
+++ b/gc/default/default.c
@@ -3510,7 +3510,6 @@ gc_sweep_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bit
}
gc_report(3, objspace, "page_sweep: %s is added to freelist\n", rb_obj_info(vp));
ctx->empty_slots++;
- RVALUE_AGE_SET_BITMAP(vp, 0);
heap_page_add_freeobj(objspace, sweep_page, vp);
break;
case T_ZOMBIE:
@@ -3527,7 +3526,6 @@ gc_sweep_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bit
if (RVALUE_REMEMBERED(objspace, vp)) rb_bug("page_sweep: %p - remembered.", (void *)p);
}
#endif
- if (RVALUE_WB_UNPROTECTED(objspace, vp)) CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(vp), vp);
#if RGENGC_CHECK_MODE
#define CHECK(x) if (x(objspace, vp) != FALSE) rb_bug("obj_free: " #x "(%s) != FALSE", rb_obj_info(vp))
@@ -3544,7 +3542,6 @@ gc_sweep_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bit
}
(void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, BASE_SLOT_SIZE);
- RVALUE_AGE_SET_BITMAP(vp, 0);
heap_page_add_freeobj(objspace, sweep_page, vp);
gc_report(3, objspace, "page_sweep: %s (fast path) added to freelist\n", rb_obj_info(vp));
ctx->freed_slots++;
@@ -3557,7 +3554,6 @@ gc_sweep_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bit
rb_gc_obj_free_vm_weak_references(vp);
if (rb_gc_obj_free(objspace, vp)) {
(void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, BASE_SLOT_SIZE);
- RVALUE_AGE_SET_BITMAP(vp, 0);
heap_page_add_freeobj(objspace, sweep_page, vp);
gc_report(3, objspace, "page_sweep: %s is added to freelist\n", rb_obj_info(vp));
ctx->freed_slots++;
@@ -3611,6 +3607,18 @@ gc_sweep_page(rb_objspace_t *objspace, rb_heap_t *heap, struct gc_sweep_context
bits_t slot_mask = heap->slot_bits_mask;
+ // Clear wb_unprotected and age bits for all unmarked slots
+ {
+ bits_t *wb_unprotected_bits = sweep_page->wb_unprotected_bits;
+ bits_t *age_bits = sweep_page->age_bits;
+ for (int i = 0; i < bitmap_plane_count; i++) {
+ bits_t unmarked = ~bits[i] & slot_mask;
+ wb_unprotected_bits[i] &= ~unmarked;
+ age_bits[i * 2] &= ~unmarked;
+ age_bits[i * 2 + 1] &= ~unmarked;
+ }
+ }
+
// Skip out of range slots at the head of the page
bitset = ~bits[0];
bitset >>= NUM_IN_PAGE(p);