diff options
author | John Hawthorn <[email protected]> | 2019-11-21 11:05:48 -0800 |
---|---|---|
committer | Aaron Patterson <[email protected]> | 2019-11-22 12:42:24 -0800 |
commit | 8e743fad4e9124bd59bb5f14473cb188db9d3c34 (patch) | |
tree | 87f0c9f44b45c746ef45b5bf0c9ce9615f0200b2 | |
parent | 26fd8d962ce42b7eb8d1c1eb43ddfa1ff24dc3aa (diff) |
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.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/2688
-rw-r--r-- | gc.c | 28 |
1 files changed, 4 insertions, 24 deletions
@@ -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; |