Fix ObjectSpace.trace_object_allocations for compaction
We need to reinsert into the ST table when an object moves because it is a numtable that hashes on the object address, so when an object moves we need to reinsert it rather than just updating the key.
This commit is contained in:
parent
b038530506
commit
15765eac0a
Notes:
git
2024-12-16 15:13:13 +00:00
@ -190,31 +190,33 @@ allocation_info_tracer_memsize(const void *ptr)
|
||||
}
|
||||
|
||||
static int
|
||||
hash_foreach_should_replace_key(st_data_t key, st_data_t value, st_data_t argp, int error)
|
||||
allocation_info_tracer_compact_update_object_table_i(st_data_t key, st_data_t value, st_data_t data)
|
||||
{
|
||||
VALUE allocated_object = (VALUE)key;
|
||||
if (allocated_object != rb_gc_location(allocated_object)) {
|
||||
return ST_REPLACE;
|
||||
st_table *table = (st_table *)data;
|
||||
|
||||
if (key != rb_gc_location(key)) {
|
||||
DURING_GC_COULD_MALLOC_REGION_START();
|
||||
{
|
||||
st_insert(table, rb_gc_location(key), value);
|
||||
}
|
||||
DURING_GC_COULD_MALLOC_REGION_END();
|
||||
|
||||
return ST_DELETE;
|
||||
}
|
||||
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
static int
|
||||
hash_replace_key(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
|
||||
{
|
||||
*key = rb_gc_location((VALUE)*key);
|
||||
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
allocation_info_tracer_compact(void *ptr)
|
||||
{
|
||||
struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
|
||||
|
||||
if (trace_arg->object_table &&
|
||||
st_foreach_with_replace(trace_arg->object_table, hash_foreach_should_replace_key, hash_replace_key, 0)) {
|
||||
st_foreach(
|
||||
trace_arg->object_table,
|
||||
allocation_info_tracer_compact_update_object_table_i,
|
||||
(st_data_t)trace_arg->object_table)) {
|
||||
rb_raise(rb_eRuntimeError, "hash modified during iteration");
|
||||
}
|
||||
}
|
||||
|
@ -287,6 +287,24 @@ class TestObjSpace < Test::Unit::TestCase
|
||||
assert true # success
|
||||
end
|
||||
|
||||
def test_trace_object_allocations_compaction
|
||||
omit "compaction is not supported on this platform" unless GC.respond_to?(:compact)
|
||||
|
||||
assert_separately(%w(-robjspace), <<~RUBY)
|
||||
ObjectSpace.trace_object_allocations do
|
||||
objs = 100.times.map do
|
||||
Object.new
|
||||
end
|
||||
|
||||
assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(objs[0]))
|
||||
|
||||
GC.verify_compaction_references(expand_heap: true, toward: :empty)
|
||||
|
||||
assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(objs[0]))
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
def test_dump_flags
|
||||
# Ensure that the fstring is promoted to old generation
|
||||
4.times { GC.start }
|
||||
|
Loading…
x
Reference in New Issue
Block a user