mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
ObjectSpace.dump_all: valid JSON
* ext/objspace/objspace_dump.c: generate valid JSON for dump_all. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55377 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
0f11cda48c
commit
cfb2b14ddc
3 changed files with 42 additions and 11 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
Sat Jun 11 14:04:19 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* ext/objspace/objspace_dump.c: generate valid JSON for dump_all.
|
||||||
|
|
||||||
Sat Jun 11 13:52:33 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Sat Jun 11 13:52:33 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* lib/forwardable.rb (_delegator_method): remove __send__ call if
|
* lib/forwardable.rb (_delegator_method): remove __send__ call if
|
||||||
|
|
|
@ -191,7 +191,7 @@ dump_append_string_content(struct dump_config *dc, VALUE obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dump_object(VALUE obj, struct dump_config *dc)
|
dump_object(VALUE obj, struct dump_config *dc, int part)
|
||||||
{
|
{
|
||||||
size_t memsize;
|
size_t memsize;
|
||||||
struct allocation_info *ainfo;
|
struct allocation_info *ainfo;
|
||||||
|
@ -211,7 +211,11 @@ dump_object(VALUE obj, struct dump_config *dc)
|
||||||
if (dc->cur_obj == dc->string)
|
if (dc->cur_obj == dc->string)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dump_append(dc, "{\"address\":\"%p\", \"type\":\"%s\"", (void *)obj, obj_type(obj));
|
if (part)
|
||||||
|
dump_append(dc, "\"%p\":{", (void *)obj);
|
||||||
|
else
|
||||||
|
dump_append(dc, "{\"address\":\"%p\", ", (void *)obj);
|
||||||
|
dump_append(dc, "\"type\":\"%s\"", obj_type(obj));
|
||||||
|
|
||||||
if (dc->cur_obj_klass)
|
if (dc->cur_obj_klass)
|
||||||
dump_append(dc, ", \"class\":\"%p\"", (void *)dc->cur_obj_klass);
|
dump_append(dc, ", \"class\":\"%p\"", (void *)dc->cur_obj_klass);
|
||||||
|
@ -283,7 +287,8 @@ dump_object(VALUE obj, struct dump_config *dc)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_ZOMBIE:
|
case T_ZOMBIE:
|
||||||
dump_append(dc, "}\n");
|
dump_append(dc, "}");
|
||||||
|
dc->roots++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,16 +317,20 @@ dump_object(VALUE obj, struct dump_config *dc)
|
||||||
dump_append(dc, "}");
|
dump_append(dc, "}");
|
||||||
}
|
}
|
||||||
|
|
||||||
dump_append(dc, "}\n");
|
dump_append(dc, "}");
|
||||||
|
dc->roots++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
heap_i(void *vstart, void *vend, size_t stride, void *data)
|
heap_i(void *vstart, void *vend, size_t stride, void *data)
|
||||||
{
|
{
|
||||||
|
struct dump_config *dc = (struct dump_config *)data;
|
||||||
VALUE v = (VALUE)vstart;
|
VALUE v = (VALUE)vstart;
|
||||||
for (; v != (VALUE)vend; v += stride) {
|
for (; v != (VALUE)vend; v += stride) {
|
||||||
if (RBASIC(v)->flags)
|
if (RBASIC(v)->flags && v != dc->string) {
|
||||||
dump_object(v, data);
|
if (dc->roots++) dump_append(dc, ",\n");
|
||||||
|
dump_object(v, dc, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -332,9 +341,11 @@ root_obj_i(const char *category, VALUE obj, void *data)
|
||||||
struct dump_config *dc = (struct dump_config *)data;
|
struct dump_config *dc = (struct dump_config *)data;
|
||||||
|
|
||||||
if (dc->root_category != NULL && category != dc->root_category)
|
if (dc->root_category != NULL && category != dc->root_category)
|
||||||
dump_append(dc, "]}\n");
|
dump_append(dc, "]},\n");
|
||||||
if (dc->root_category == NULL || category != dc->root_category)
|
if (dc->root_category == NULL || category != dc->root_category) {
|
||||||
|
dump_append(dc, "\"%p\":", (void *)obj);
|
||||||
dump_append(dc, "{\"type\":\"ROOT\", \"root\":\"%s\", \"references\":[\"%p\"", category, (void *)obj);
|
dump_append(dc, "{\"type\":\"ROOT\", \"root\":\"%s\", \"references\":[\"%p\"", category, (void *)obj);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
dump_append(dc, ", \"%p\"", (void *)obj);
|
dump_append(dc, ", \"%p\"", (void *)obj);
|
||||||
|
|
||||||
|
@ -382,7 +393,7 @@ static VALUE
|
||||||
dump_result(struct dump_config *dc, VALUE output)
|
dump_result(struct dump_config *dc, VALUE output)
|
||||||
{
|
{
|
||||||
if (output == sym_string) {
|
if (output == sym_string) {
|
||||||
return dc->string;
|
return rb_str_resurrect(dc->string);
|
||||||
}
|
}
|
||||||
else if (output == sym_file) {
|
else if (output == sym_file) {
|
||||||
rb_io_flush(dc->string);
|
rb_io_flush(dc->string);
|
||||||
|
@ -418,7 +429,8 @@ objspace_dump(int argc, VALUE *argv, VALUE os)
|
||||||
|
|
||||||
output = dump_output(&dc, opts, sym_string, filename);
|
output = dump_output(&dc, opts, sym_string, filename);
|
||||||
|
|
||||||
dump_object(obj, &dc);
|
dump_object(obj, &dc, 0);
|
||||||
|
if (dc.roots) dump_append(&dc, "\n");
|
||||||
|
|
||||||
return dump_result(&dc, output);
|
return dump_result(&dc, output);
|
||||||
}
|
}
|
||||||
|
@ -450,12 +462,14 @@ objspace_dump_all(int argc, VALUE *argv, VALUE os)
|
||||||
|
|
||||||
output = dump_output(&dc, opts, sym_file, filename);
|
output = dump_output(&dc, opts, sym_file, filename);
|
||||||
|
|
||||||
|
dump_append(&dc, "{\n");
|
||||||
/* dump roots */
|
/* dump roots */
|
||||||
rb_objspace_reachable_objects_from_root(root_obj_i, &dc);
|
rb_objspace_reachable_objects_from_root(root_obj_i, &dc);
|
||||||
if (dc.roots) dump_append(&dc, "]}\n");
|
if (dc.roots) dump_append(&dc, "]}");
|
||||||
|
|
||||||
/* dump all objects */
|
/* dump all objects */
|
||||||
rb_objspace_each_objects(heap_i, &dc);
|
rb_objspace_each_objects(heap_i, &dc);
|
||||||
|
dump_append(&dc, "\n}");
|
||||||
|
|
||||||
return dump_result(&dc, output);
|
return dump_result(&dc, output);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
# frozen_string_literal: false
|
# frozen_string_literal: false
|
||||||
require "test/unit"
|
require "test/unit"
|
||||||
require "objspace"
|
require "objspace"
|
||||||
|
begin
|
||||||
|
require "json"
|
||||||
|
rescue LoadError
|
||||||
|
end
|
||||||
|
|
||||||
class TestObjSpace < Test::Unit::TestCase
|
class TestObjSpace < Test::Unit::TestCase
|
||||||
def test_memsize_of
|
def test_memsize_of
|
||||||
|
@ -218,6 +222,7 @@ class TestObjSpace < Test::Unit::TestCase
|
||||||
info = ObjectSpace.dump("foo".freeze)
|
info = ObjectSpace.dump("foo".freeze)
|
||||||
assert_match /"wb_protected":true, "old":true/, info
|
assert_match /"wb_protected":true, "old":true/, info
|
||||||
assert_match /"fstring":true/, info
|
assert_match /"fstring":true/, info
|
||||||
|
JSON.parse(info) if defined?(JSON)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_dump_to_default
|
def test_dump_to_default
|
||||||
|
@ -252,6 +257,7 @@ class TestObjSpace < Test::Unit::TestCase
|
||||||
assert_match /"embedded":true, "bytesize":11, "value":"hello world", "encoding":"UTF-8"/, info
|
assert_match /"embedded":true, "bytesize":11, "value":"hello world", "encoding":"UTF-8"/, info
|
||||||
assert_match /"file":"#{Regexp.escape __FILE__}", "line":#{line}/, info
|
assert_match /"file":"#{Regexp.escape __FILE__}", "line":#{line}/, info
|
||||||
assert_match /"method":"#{loc.base_label}"/, info
|
assert_match /"method":"#{loc.base_label}"/, info
|
||||||
|
JSON.parse(info) if defined?(JSON)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_dump_special_consts
|
def test_dump_special_consts
|
||||||
|
@ -300,6 +306,13 @@ class TestObjSpace < Test::Unit::TestCase
|
||||||
assert_match(entry, File.readlines(output).grep(/TEST STRING/).join("\n"))
|
assert_match(entry, File.readlines(output).grep(/TEST STRING/).join("\n"))
|
||||||
File.unlink(output)
|
File.unlink(output)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if defined?(JSON)
|
||||||
|
assert_ruby_status(%w[-rjson -robjspace], "#{<<-"begin;"}\n#{<<-"end;"}")
|
||||||
|
begin;
|
||||||
|
JSON.parse(ObjectSpace.dump_all(output: :string))
|
||||||
|
end;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_dump_uninitialized_file
|
def test_dump_uninitialized_file
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue