summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gc.c101
1 files changed, 64 insertions, 37 deletions
diff --git a/gc.c b/gc.c
index 3844333a90..7f1ff7ce0f 100644
--- a/gc.c
+++ b/gc.c
@@ -683,7 +683,7 @@ typedef struct rb_heap_struct {
struct list_head pages;
struct heap_page *sweeping_page; /* iterator for .pages */
struct heap_page *compact_cursor;
- size_t compact_cursor_index;
+ RVALUE * compact_cursor_index;
#if GC_ENABLE_INCREMENTAL_MARK
struct heap_page *pooled_pages;
#endif
@@ -4895,11 +4895,48 @@ unlock_page_body(rb_objspace_t *objspace, struct heap_page_body *body)
}
}
+static inline bool
+try_move_in_plane(rb_objspace_t *objspace, rb_heap_t *heap, intptr_t p, bits_t bits, VALUE dest)
+{
+ if (bits) {
+ do {
+ if (bits & 1) {
+ /* We're trying to move "p" */
+ objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)p)]++;
+
+ if (gc_is_moveable_obj(objspace, (VALUE)p)) {
+ /* We were able to move "p" */
+ objspace->rcompactor.moved_count_table[BUILTIN_TYPE((VALUE)p)]++;
+ objspace->rcompactor.total_moved++;
+
+ bool from_freelist = false;
+
+ if (BUILTIN_TYPE(dest) == T_NONE) {
+ from_freelist = true;
+ }
+
+ gc_move(objspace, (VALUE)p, dest);
+ gc_pin(objspace, (VALUE)p);
+ heap->compact_cursor_index = (RVALUE *)p;
+ if (from_freelist) {
+ FL_SET((VALUE)p, FL_FROM_FREELIST);
+ }
+
+ return true;
+ }
+ }
+ p += sizeof(RVALUE);
+ bits >>= 1;
+ } while (bits);
+ }
+
+ return false;
+}
+
static short
try_move(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page, VALUE dest)
{
struct heap_page * cursor = heap->compact_cursor;
- char from_freelist = 0;
GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(dest), dest));
@@ -4907,49 +4944,39 @@ try_move(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page,
* T_NONE, it is an object that just got freed but hasn't been
* added to the freelist yet */
- if (BUILTIN_TYPE(dest) == T_NONE) {
- from_freelist = 1;
- }
-
while(1) {
- size_t index = heap->compact_cursor_index;
+ size_t index;
bits_t *mark_bits = cursor->mark_bits;
bits_t *pin_bits = cursor->pinned_bits;
- RVALUE * p = cursor->start;
- RVALUE * offset = p - NUM_IN_PAGE(p);
+ RVALUE * p;
+
+ if (heap->compact_cursor_index) {
+ index = BITMAP_INDEX(heap->compact_cursor_index);
+ p = heap->compact_cursor_index;
+ GC_ASSERT(cursor == GET_HEAP_PAGE(p));
+ } else {
+ index = 0;
+ p = cursor->start;
+ }
+
+ bits_t bits = mark_bits[index] & ~pin_bits[index];
+
+ bits >>= NUM_IN_PAGE(p);
+ if (try_move_in_plane(objspace, heap, (intptr_t)p, bits, dest)) return 1;
+
+ if (index == 0) {
+ p = cursor->start + (BITS_BITLENGTH - NUM_IN_PAGE(cursor->start));
+ } else {
+ p = cursor->start + (BITS_BITLENGTH - NUM_IN_PAGE(cursor->start)) + (BITS_BITLENGTH * index);
+ }
/* Find an object to move and move it. Movable objects must be
* marked, so we iterate using the marking bitmap */
- for (size_t i = index; i < HEAP_PAGE_BITMAP_LIMIT; i++) {
+ for (size_t i = index + 1; i < HEAP_PAGE_BITMAP_LIMIT; i++) {
bits_t bits = mark_bits[i] & ~pin_bits[i];
-
- if (bits) {
- p = offset + i * BITS_BITLENGTH;
-
- do {
- if (bits & 1) {
- /* We're trying to move "p" */
- objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)p)]++;
-
- if (gc_is_moveable_obj(objspace, (VALUE)p)) {
- /* We were able to move "p" */
- objspace->rcompactor.moved_count_table[BUILTIN_TYPE((VALUE)p)]++;
- objspace->rcompactor.total_moved++;
- gc_move(objspace, (VALUE)p, dest);
- gc_pin(objspace, (VALUE)p);
- heap->compact_cursor_index = i;
- if (from_freelist) {
- FL_SET((VALUE)p, FL_FROM_FREELIST);
- }
-
- return 1;
- }
- }
- p++;
- bits >>= 1;
- } while (bits);
- }
+ if (try_move_in_plane(objspace, heap, (intptr_t)p, bits, dest)) return 1;
+ p += BITS_BITLENGTH;
}
/* We couldn't find a movable object on the compact cursor, so lets