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,20 +190,19 @@ allocation_info_tracer_memsize(const void *ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
st_table *table = (st_table *)data;
|
||||||
if (allocated_object != rb_gc_location(allocated_object)) {
|
|
||||||
return ST_REPLACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ST_CONTINUE;
|
if (key != rb_gc_location(key)) {
|
||||||
}
|
DURING_GC_COULD_MALLOC_REGION_START();
|
||||||
|
|
||||||
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);
|
st_insert(table, rb_gc_location(key), value);
|
||||||
|
}
|
||||||
|
DURING_GC_COULD_MALLOC_REGION_END();
|
||||||
|
|
||||||
|
return ST_DELETE;
|
||||||
|
}
|
||||||
|
|
||||||
return ST_CONTINUE;
|
return ST_CONTINUE;
|
||||||
}
|
}
|
||||||
@ -214,7 +213,10 @@ allocation_info_tracer_compact(void *ptr)
|
|||||||
struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
|
struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
|
||||||
|
|
||||||
if (trace_arg->object_table &&
|
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");
|
rb_raise(rb_eRuntimeError, "hash modified during iteration");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,6 +287,24 @@ class TestObjSpace < Test::Unit::TestCase
|
|||||||
assert true # success
|
assert true # success
|
||||||
end
|
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
|
def test_dump_flags
|
||||||
# Ensure that the fstring is promoted to old generation
|
# Ensure that the fstring is promoted to old generation
|
||||||
4.times { GC.start }
|
4.times { GC.start }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user