Add the size pool slot size to the output of ObjectSpace.dump/dump_all

This commit is contained in:
Matt Valentine-House 2022-02-01 21:36:29 +00:00 коммит произвёл Peter Zhu
Родитель a3caf196d9
Коммит 9fab2c1a1a
3 изменённых файлов: 39 добавлений и 0 удалений

Просмотреть файл

@ -35,6 +35,7 @@ struct dump_config {
const char *root_category; const char *root_category;
VALUE cur_obj; VALUE cur_obj;
VALUE cur_obj_klass; VALUE cur_obj_klass;
size_t cur_page_slot_size;
size_t cur_obj_references; size_t cur_obj_references;
unsigned int roots: 1; unsigned int roots: 1;
unsigned int full_heap: 1; unsigned int full_heap: 1;
@ -360,6 +361,9 @@ dump_object(VALUE obj, struct dump_config *dc)
dump_append(dc, obj_type(obj)); dump_append(dc, obj_type(obj));
dump_append(dc, "\""); dump_append(dc, "\"");
dump_append(dc, ", \"slot_size\":");
dump_append_sizet(dc, dc->cur_page_slot_size);
if (dc->cur_obj_klass) { if (dc->cur_obj_klass) {
dump_append(dc, ", \"class\":"); dump_append(dc, ", \"class\":");
dump_append_ref(dc, dc->cur_obj_klass); dump_append_ref(dc, dc->cur_obj_klass);
@ -539,6 +543,7 @@ heap_i(void *vstart, void *vend, size_t stride, void *data)
for (; v != (VALUE)vend; v += stride) { for (; v != (VALUE)vend; v += stride) {
void *ptr = asan_poisoned_object_p(v); void *ptr = asan_poisoned_object_p(v);
asan_unpoison_object(v, false); asan_unpoison_object(v, false);
dc->cur_page_slot_size = stride;
if (dc->full_heap || RBASIC(v)->flags) if (dc->full_heap || RBASIC(v)->flags)
dump_object(v, dc); dump_object(v, dc);
@ -616,6 +621,10 @@ static VALUE
objspace_dump(VALUE os, VALUE obj, VALUE output) objspace_dump(VALUE os, VALUE obj, VALUE output)
{ {
struct dump_config dc = {0,}; struct dump_config dc = {0,};
if (!RB_SPECIAL_CONST_P(obj)) {
dc.cur_page_slot_size = rb_gc_obj_slot_size(obj);
}
dump_output(&dc, output, Qnil, Qnil); dump_output(&dc, output, Qnil, Qnil);
dump_object(obj, &dc); dump_object(obj, &dc);

2
gc.h
Просмотреть файл

@ -136,6 +136,8 @@ void rb_objspace_each_objects_without_setup(
int (*callback)(void *, void *, size_t, void *), int (*callback)(void *, void *, size_t, void *),
void *data); void *data);
size_t rb_gc_obj_slot_size(VALUE obj);
RUBY_SYMBOL_EXPORT_END RUBY_SYMBOL_EXPORT_END
#endif /* RUBY_GC_H */ #endif /* RUBY_GC_H */

Просмотреть файл

@ -431,6 +431,27 @@ class TestObjSpace < Test::Unit::TestCase
end end
end end
def test_dump_objects_dumps_page_slot_sizes
assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error|
begin;
def dump_my_heap_please
ObjectSpace.dump_all(output: $stdout)
end
p $stdout == dump_my_heap_please
end;
assert_equal 'true', output.pop
assert(output.count > 1)
output.each { |l|
obj = JSON.parse(l)
next if obj["type"] == "ROOT"
assert(obj["slot_size"] != nil)
assert(obj["slot_size"] % GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] == 0)
}
end
end
def test_dump_escapes_method_name def test_dump_escapes_method_name
method_name = "foo\"bar" method_name = "foo\"bar"
klass = Class.new do klass = Class.new do
@ -449,6 +470,13 @@ class TestObjSpace < Test::Unit::TestCase
ObjectSpace.trace_object_allocations_stop ObjectSpace.trace_object_allocations_stop
end end
def test_dump_includes_slot_size
str = "TEST"
dump = ObjectSpace.dump(str)
assert_includes dump, "\"slot_size\":#{GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]}"
end
def test_dump_reference_addresses_match_dump_all_addresses def test_dump_reference_addresses_match_dump_all_addresses
assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error| assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error|
begin; begin;