aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gc.c29
-rw-r--r--internal.h1
2 files changed, 25 insertions, 5 deletions
diff --git a/gc.c b/gc.c
index 55af43720e..bd00824882 100644
--- a/gc.c
+++ b/gc.c
@@ -7312,8 +7312,8 @@ update_id_to_obj(st_data_t *key, st_data_t *value, st_data_t arg, int exists)
}
}
-static void
-gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free)
+static VALUE
+gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, VALUE moved_list)
{
int marked;
int wb_unprotected;
@@ -7392,7 +7392,10 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free)
/* Assign forwarding address */
src->as.moved.flags = T_MOVED;
src->as.moved.destination = (VALUE)dest;
+ src->as.moved.next = moved_list;
GC_ASSERT(BUILTIN_TYPE((VALUE)dest) != T_NONE);
+
+ return (VALUE)src;
}
struct heap_cursor {
@@ -7489,13 +7492,15 @@ int compare_pinned(const void *left, const void *right, void *dummy)
return right_count - left_count;
}
-static void
+static VALUE
gc_compact_heap(rb_objspace_t *objspace)
{
struct heap_cursor free_cursor;
struct heap_cursor scan_cursor;
struct heap_page **page_list;
+ VALUE moved_list;
+ moved_list = Qfalse;
memset(objspace->rcompactor.considered_count_table, 0, T_MASK * sizeof(size_t));
memset(objspace->rcompactor.moved_count_table, 0, T_MASK * sizeof(size_t));
@@ -7558,7 +7563,7 @@ gc_compact_heap(rb_objspace_t *objspace)
GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) != T_NONE);
GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) != T_MOVED);
- gc_move(objspace, (VALUE)scan_cursor.slot, (VALUE)free_cursor.slot);
+ moved_list = gc_move(objspace, (VALUE)scan_cursor.slot, (VALUE)free_cursor.slot, moved_list);
GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) != T_MOVED);
GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) != T_NONE);
@@ -7569,6 +7574,8 @@ gc_compact_heap(rb_objspace_t *objspace)
}
}
free(page_list);
+
+ return moved_list;
}
static void
@@ -8195,13 +8202,17 @@ static VALUE
gc_verify_compaction_references(VALUE mod)
{
rb_objspace_t *objspace = &rb_objspace;
+ VALUE moved_list;
if (dont_gc) return Qnil;
/* Ensure objects are pinned */
rb_gc();
- gc_compact_heap(objspace);
+ /* Double heap size */
+ heap_add_pages(objspace, heap_eden, heap_allocated_pages);
+
+ moved_list = gc_compact_heap(objspace);
heap_eden->freelist = NULL;
gc_update_references(objspace);
@@ -8214,6 +8225,14 @@ gc_verify_compaction_references(VALUE mod)
gc_verify_internal_consistency(mod);
+#if __has_feature(address_sanitizer)
+ while (moved_list) {
+ VALUE current = moved_list;
+ moved_list = RANY(moved_list)->as.moved.next;
+ poison_object(current);
+ }
+#endif
+
/* GC after compaction to eliminate T_MOVED */
rb_gc();
diff --git a/internal.h b/internal.h
index 0ce1dcd495..4d3a5061d2 100644
--- a/internal.h
+++ b/internal.h
@@ -838,6 +838,7 @@ struct RHash {
struct RMoved {
VALUE flags;
VALUE destination;
+ VALUE next;
};
/* missing/setproctitle.c */