From 8e743fad4e9124bd59bb5f14473cb188db9d3c34 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Thu, 21 Nov 2019 11:05:48 -0800 Subject: Count pinned slots using only bitmap This is significantly faster than checking BUILTIN_TYPEs because we access significantly less memory. We also use popcount to count entire words at a time. The only functional difference from the previous implementation is that T_ZOMBIE objects will no longer be counted. However those are temporary objects which should be small in number, and this method has always been an estimate. --- gc.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) (limited to 'gc.c') diff --git a/gc.c b/gc.c index d2b4330889..9cc230bd3d 100644 --- a/gc.c +++ b/gc.c @@ -620,6 +620,7 @@ enum { BITS_SIZE = sizeof(bits_t), BITS_BITLENGTH = ( BITS_SIZE * CHAR_BIT ) }; +#define popcount_bits rb_popcount_intptr struct heap_page_header { struct heap_page *page; @@ -7698,32 +7699,11 @@ init_cursors(rb_objspace_t *objspace, struct heap_cursor *free, struct heap_curs static int count_pinned(struct heap_page *page) { - RVALUE *pstart = page->start; - RVALUE *pend = pstart + page->total_slots; int pinned = 0; + int i; - VALUE v = (VALUE)pstart; - for (; v != (VALUE)pend; v += sizeof(RVALUE)) { - void *poisoned = asan_poisoned_object_p(v); - asan_unpoison_object(v, false); - - switch (BUILTIN_TYPE(v)) { - case T_NONE: - break; - case T_ZOMBIE: - pinned++; - break; - default: - if (RVALUE_PINNED(v)) { - pinned++; - } - break; - } - - if (poisoned) { - GC_ASSERT(BUILTIN_TYPE(v) == T_NONE); - asan_poison_object(v); - } + for (i = 0; i < HEAP_PAGE_BITMAP_LIMIT; i++) { + pinned += popcount_bits(page->pinned_bits[i]); } return pinned; -- cgit v1.2.3