summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-05-28 19:40:04 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-05-28 19:40:04 +0000
commit6abf7938bface30fe562eb612bfb0ed66c6ff8d7 (patch)
tree2d351f51f9b89b6955e47897215593ae516f1e99
parent4d059bf9f5f10f3d3088de49fc87e5555db7770d (diff)
* ext/objspace/objspace.c: add two methods to debug internals.
* ObjectSpace.internal_class_of: return RBASIC_CLASS(obj). * ObjectSpace.internal_super_of: return RCLASS_SUPER(cls). * NEWS: add information about both methods. * test/objspace/test_objspace.rb: add tests for both methods. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50662 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog11
-rw-r--r--NEWS2
-rw-r--r--ext/objspace/objspace.c70
-rw-r--r--test/objspace/test_objspace.rb51
4 files changed, 134 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 6b5aa5d3fc..c642a3328c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Fri May 29 04:37:38 2015 Koichi Sasada <ko1@atdot.net>
+
+ * ext/objspace/objspace.c: add two methods to debug internals.
+
+ * ObjectSpace.internal_class_of: return RBASIC_CLASS(obj).
+ * ObjectSpace.internal_super_of: return RCLASS_SUPER(cls).
+
+ * NEWS: add information about both methods.
+
+ * test/objspace/test_objspace.rb: add tests for both methods.
+
Thu May 28 06:55:53 2015 Anton Davydov <antondavydov.o@gmail.com>
* ext/tk/sample/figmemo_sample.rb (open_file),
diff --git a/NEWS b/NEWS
index 03c9432e02..2ba73b4a26 100644
--- a/NEWS
+++ b/NEWS
@@ -51,6 +51,8 @@ with all sufficient information, see the ChangeLog file.
* ObjectSpace (objspace)
* ObjectSpace.count_imemo_objects is added.
+ * ObjectSpace.internal_class_of is added.
+ * ObjectSpace.internal_super_of is added.
* OpenSSL
* OpenSSL::SSL::SSLSocket#accept_nonblock and
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c
index 844beef381..bc53b8462b 100644
--- a/ext/objspace/objspace.c
+++ b/ext/objspace/objspace.c
@@ -792,6 +792,73 @@ reachable_objects_from_root(VALUE self)
return hash;
}
+static VALUE
+wrap_klass_iow(VALUE klass)
+{
+ if (!RTEST(klass)) {
+ return Qnil;
+ }
+ else if (RB_TYPE_P(klass, T_ICLASS)) {
+ return iow_newobj(klass);
+ }
+ else {
+ return klass;
+ }
+}
+
+/*
+ * call-seq:
+ * ObjectSpace.internal_class_of(obj) -> Class or Module
+ *
+ * [MRI specific feature] Return internal class of obj.
+ * obj can be an instance of InternalObjectWrapper.
+ *
+ * Note that you should not use this method in your application.
+ */
+static VALUE
+objspace_internal_class_of(VALUE self, VALUE obj)
+{
+ VALUE klass;
+
+ if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
+ obj = (VALUE)DATA_PTR(obj);
+ }
+
+ klass = CLASS_OF(obj);
+ return wrap_klass_iow(klass);
+}
+
+/*
+ * call-seq:
+ * ObjectSpace.internal_super_of(cls) -> Class or Module
+ *
+ * [MRI specific feature] Return internal super class of cls (Class or Module).
+ * obj can be an instance of InternalObjectWrapper.
+ *
+ * Note that you should not use this method in your application.
+ */
+static VALUE
+objspace_internal_super_of(VALUE self, VALUE obj)
+{
+ VALUE super;
+
+ if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
+ obj = (VALUE)DATA_PTR(obj);
+ }
+
+ switch (TYPE(obj)) {
+ case T_MODULE:
+ case T_CLASS:
+ case T_ICLASS:
+ super = RCLASS_SUPER(obj);
+ break;
+ default:
+ rb_raise(rb_eArgError, "class or module is expected");
+ }
+
+ return wrap_klass_iow(super);
+}
+
void Init_object_tracing(VALUE rb_mObjSpace);
void Init_objspace_dump(VALUE rb_mObjSpace);
@@ -830,6 +897,9 @@ Init_objspace(void)
rb_define_module_function(rb_mObjSpace, "reachable_objects_from", reachable_objects_from, 1);
rb_define_module_function(rb_mObjSpace, "reachable_objects_from_root", reachable_objects_from_root, 0);
+ rb_define_module_function(rb_mObjSpace, "internal_class_of", objspace_internal_class_of, 1);
+ rb_define_module_function(rb_mObjSpace, "internal_super_of", objspace_internal_super_of, 1);
+
/*
* This class is used as a return value from
* ObjectSpace::reachable_objects_from.
diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb
index 329e418008..8845b83c4e 100644
--- a/test/objspace/test_objspace.rb
+++ b/test/objspace/test_objspace.rb
@@ -285,4 +285,55 @@ class TestObjSpace < Test::Unit::TestCase
assert_not_match /"fd":/, output
end
end
+
+ def traverse_classes klass
+ h = {}
+ while klass && !h.has_key?(klass)
+ h[klass] = true
+ klass = ObjectSpace.internal_class_of(klass)
+ end
+ end
+
+ def test_internal_class_of
+ i = 0
+ ObjectSpace.each_object{|o|
+ traverse_classes ObjectSpace.internal_class_of(o)
+ i += 1
+ }
+ assert_operator i, :>, 0
+ end
+
+ def traverse_super_classes klass
+ while klass
+ klass = ObjectSpace.internal_super_of(klass)
+ end
+ end
+
+ def all_super_classes klass
+ klasses = []
+ while klass
+ klasses << klass
+ klass = ObjectSpace.internal_super_of(klass)
+ end
+ klasses
+ end
+
+ def test_internal_super_of
+ klasses = all_super_classes(String)
+ String.ancestors.each{|k|
+ case k
+ when Class
+ assert_equal(true, klasses.include?(k), k.inspect)
+ when Module
+ assert_equal(false, klasses.include?(k), k.inspect) # Internal object (T_ICLASS)
+ end
+ }
+
+ i = 0
+ ObjectSpace.each_object(Module){|o|
+ traverse_super_classes ObjectSpace.internal_super_of(o)
+ i += 1
+ }
+ assert_operator i, :>, 0
+ end
end