Ruby  2.5.0dev(2017-10-22revision60238)
objspace.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  objspace.c - ObjectSpace extender for MRI.
4 
5  $Author$
6  created at: Wed Jun 17 07:39:17 2009
7 
8  NOTE: This extension library is only expected to exist with C Ruby.
9 
10  All the files in this distribution are covered under the Ruby's
11  license (see the file COPYING).
12 
13 **********************************************************************/
14 
15 #include "internal.h"
16 #include <ruby/st.h>
17 #include <ruby/io.h>
18 #include <ruby/re.h>
19 #include "node.h"
20 #include "gc.h"
21 #include "symbol.h"
22 
23 /*
24  * call-seq:
25  * ObjectSpace.memsize_of(obj) -> Integer
26  *
27  * Return consuming memory size of obj.
28  *
29  * Note that the return size is incomplete. You need to deal with this
30  * information as only a *HINT*. Especially, the size of +T_DATA+ may not be
31  * correct.
32  *
33  * This method is only expected to work with C Ruby.
34  *
35  * From Ruby 2.2, memsize_of(obj) returns a memory size includes
36  * sizeof(RVALUE).
37  */
38 
39 static VALUE
40 memsize_of_m(VALUE self, VALUE obj)
41 {
42  return SIZET2NUM(rb_obj_memsize_of(obj));
43 }
44 
45 struct total_data {
46  size_t total;
48 };
49 
50 static int
51 total_i(void *vstart, void *vend, size_t stride, void *ptr)
52 {
53  VALUE v;
54  struct total_data *data = (struct total_data *)ptr;
55 
56  for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
57  if (RBASIC(v)->flags) {
58  switch (BUILTIN_TYPE(v)) {
59  case T_NONE:
60  case T_IMEMO:
61  case T_ICLASS:
62  case T_NODE:
63  case T_ZOMBIE:
64  continue;
65  default:
66  if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
67  data->total += rb_obj_memsize_of(v);
68  }
69  }
70  }
71  }
72 
73  return 0;
74 }
75 
76 /*
77  * call-seq:
78  * ObjectSpace.memsize_of_all([klass]) -> Integer
79  *
80  * Return consuming memory size of all living objects.
81  *
82  * If +klass+ (should be Class object) is given, return the total memory size
83  * of instances of the given class.
84  *
85  * Note that the returned size is incomplete. You need to deal with this
86  * information as only a *HINT*. Especially, the size of +T_DATA+ may not be
87  * correct.
88  *
89  * Note that this method does *NOT* return total malloc'ed memory size.
90  *
91  * This method can be defined by the following Ruby code:
92  *
93  * def memsize_of_all klass = false
94  * total = 0
95  * ObjectSpace.each_object{|e|
96  * total += ObjectSpace.memsize_of(e) if klass == false || e.kind_of?(klass)
97  * }
98  * total
99  * end
100  *
101  * This method is only expected to work with C Ruby.
102  */
103 
104 static VALUE
105 memsize_of_all_m(int argc, VALUE *argv, VALUE self)
106 {
107  struct total_data data = {0, 0};
108 
109  if (argc > 0) {
110  rb_scan_args(argc, argv, "01", &data.klass);
111  }
112 
113  rb_objspace_each_objects(total_i, &data);
114  return SIZET2NUM(data.total);
115 }
116 
117 static int
118 set_zero_i(st_data_t key, st_data_t val, st_data_t arg)
119 {
120  VALUE k = (VALUE)key;
121  VALUE hash = (VALUE)arg;
122  rb_hash_aset(hash, k, INT2FIX(0));
123  return ST_CONTINUE;
124 }
125 
126 static VALUE
127 setup_hash(int argc, VALUE *argv)
128 {
129  VALUE hash;
130 
131  if (rb_scan_args(argc, argv, "01", &hash) == 1) {
132  if (!RB_TYPE_P(hash, T_HASH))
133  rb_raise(rb_eTypeError, "non-hash given");
134  }
135 
136  if (hash == Qnil) {
137  hash = rb_hash_new();
138  }
139  else if (!RHASH_EMPTY_P(hash)) {
140  st_foreach(RHASH_TBL(hash), set_zero_i, hash);
141  }
142 
143  return hash;
144 }
145 
146 static int
147 cos_i(void *vstart, void *vend, size_t stride, void *data)
148 {
149  size_t *counts = (size_t *)data;
150  VALUE v = (VALUE)vstart;
151 
152  for (;v != (VALUE)vend; v += stride) {
153  if (RBASIC(v)->flags) {
154  counts[BUILTIN_TYPE(v)] += rb_obj_memsize_of(v);
155  }
156  }
157  return 0;
158 }
159 
160 static VALUE
161 type2sym(enum ruby_value_type i)
162 {
163  VALUE type;
164  switch (i) {
165 #define CASE_TYPE(t) case t: type = ID2SYM(rb_intern(#t)); break;
166  CASE_TYPE(T_NONE);
174  CASE_TYPE(T_HASH);
177  CASE_TYPE(T_FILE);
178  CASE_TYPE(T_DATA);
182  CASE_TYPE(T_NIL);
183  CASE_TYPE(T_TRUE);
189  CASE_TYPE(T_NODE);
192 #undef CASE_TYPE
193  default: rb_bug("type2sym: unknown type (%d)", i);
194  }
195  return type;
196 }
197 
198 /*
199  * call-seq:
200  * ObjectSpace.count_objects_size([result_hash]) -> hash
201  *
202  * Counts objects size (in bytes) for each type.
203  *
204  * Note that this information is incomplete. You need to deal with
205  * this information as only a *HINT*. Especially, total size of
206  * T_DATA may be wrong.
207  *
208  * It returns a hash as:
209  * {:TOTAL=>1461154, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249, ...}
210  *
211  * If the optional argument, result_hash, is given,
212  * it is overwritten and returned.
213  * This is intended to avoid probe effect.
214  *
215  * The contents of the returned hash is implementation defined.
216  * It may be changed in future.
217  *
218  * This method is only expected to work with C Ruby.
219  */
220 
221 static VALUE
222 count_objects_size(int argc, VALUE *argv, VALUE os)
223 {
224  size_t counts[T_MASK+1];
225  size_t total = 0;
226  enum ruby_value_type i;
227  VALUE hash = setup_hash(argc, argv);
228 
229  for (i = 0; i <= T_MASK; i++) {
230  counts[i] = 0;
231  }
232 
233  rb_objspace_each_objects(cos_i, &counts[0]);
234 
235  for (i = 0; i <= T_MASK; i++) {
236  if (counts[i]) {
237  VALUE type = type2sym(i);
238  total += counts[i];
239  rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
240  }
241  }
242  rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
243  return hash;
244 }
245 
247  size_t mortal;
248  size_t immortal;
249 };
250 
251 static int
252 cs_i(void *vstart, void *vend, size_t stride, void *n)
253 {
254  struct dynamic_symbol_counts *counts = (struct dynamic_symbol_counts *)n;
255  VALUE v = (VALUE)vstart;
256 
257  for (; v != (VALUE)vend; v += stride) {
258  if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_SYMBOL) {
259  ID id = RSYMBOL(v)->id;
260  if ((id & ~ID_SCOPE_MASK) == 0) {
261  counts->mortal++;
262  }
263  else {
264  counts->immortal++;
265  }
266  }
267  }
268 
269  return 0;
270 }
271 
272 size_t rb_sym_immortal_count(void);
273 
274 /*
275  * call-seq:
276  * ObjectSpace.count_symbols([result_hash]) -> hash
277  *
278  * Counts symbols for each Symbol type.
279  *
280  * This method is only for MRI developers interested in performance and memory
281  * usage of Ruby programs.
282  *
283  * If the optional argument, result_hash, is given, it is overwritten and
284  * returned. This is intended to avoid probe effect.
285  *
286  * Note:
287  * The contents of the returned hash is implementation defined.
288  * It may be changed in future.
289  *
290  * This method is only expected to work with C Ruby.
291  *
292  * On this version of MRI, they have 3 types of Symbols (and 1 total counts).
293  *
294  * * mortal_dynamic_symbol: GC target symbols (collected by GC)
295  * * immortal_dynamic_symbol: Immortal symbols promoted from dynamic symbols (do not collected by GC)
296  * * immortal_static_symbol: Immortal symbols (do not collected by GC)
297  * * immortal_symbol: total immortal symbols (immortal_dynamic_symbol+immortal_static_symbol)
298  */
299 
300 static VALUE
301 count_symbols(int argc, VALUE *argv, VALUE os)
302 {
303  struct dynamic_symbol_counts dynamic_counts = {0, 0};
304  VALUE hash = setup_hash(argc, argv);
305 
306  size_t immortal_symbols = rb_sym_immortal_count();
307  rb_objspace_each_objects(cs_i, &dynamic_counts);
308 
309  rb_hash_aset(hash, ID2SYM(rb_intern("mortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.mortal));
310  rb_hash_aset(hash, ID2SYM(rb_intern("immortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.immortal));
311  rb_hash_aset(hash, ID2SYM(rb_intern("immortal_static_symbol")), SIZET2NUM(immortal_symbols - dynamic_counts.immortal));
312  rb_hash_aset(hash, ID2SYM(rb_intern("immortal_symbol")), SIZET2NUM(immortal_symbols));
313 
314  return hash;
315 }
316 
317 static int
318 cn_i(void *vstart, void *vend, size_t stride, void *n)
319 {
320  size_t *nodes = (size_t *)n;
321  VALUE v = (VALUE)vstart;
322 
323  for (; v != (VALUE)vend; v += stride) {
324  if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_NODE) {
325  size_t s = nd_type((NODE *)v);
326  nodes[s]++;
327  }
328  }
329 
330  return 0;
331 }
332 
333 /*
334  * call-seq:
335  * ObjectSpace.count_nodes([result_hash]) -> hash
336  *
337  * Counts nodes for each node type.
338  *
339  * This method is only for MRI developers interested in performance and memory
340  * usage of Ruby programs.
341  *
342  * It returns a hash as:
343  *
344  * {:NODE_METHOD=>2027, :NODE_FBODY=>1927, :NODE_CFUNC=>1798, ...}
345  *
346  * If the optional argument, result_hash, is given, it is overwritten and
347  * returned. This is intended to avoid probe effect.
348  *
349  * Note:
350  * The contents of the returned hash is implementation defined.
351  * It may be changed in future.
352  *
353  * This method is only expected to work with C Ruby.
354  */
355 
356 static VALUE
357 count_nodes(int argc, VALUE *argv, VALUE os)
358 {
359  size_t nodes[NODE_LAST+1];
360  size_t i;
361  VALUE hash = setup_hash(argc, argv);
362 
363  for (i = 0; i <= NODE_LAST; i++) {
364  nodes[i] = 0;
365  }
366 
367  rb_objspace_each_objects(cn_i, &nodes[0]);
368 
369  for (i=0; i<NODE_LAST; i++) {
370  if (nodes[i] != 0) {
371  VALUE node;
372  switch (i) {
373 #define COUNT_NODE(n) case n: node = ID2SYM(rb_intern(#n)); break;
474 #undef COUNT_NODE
475  default: node = INT2FIX(i);
476  }
477  rb_hash_aset(hash, node, SIZET2NUM(nodes[i]));
478  }
479  }
480  return hash;
481 }
482 
483 static int
484 cto_i(void *vstart, void *vend, size_t stride, void *data)
485 {
486  VALUE hash = (VALUE)data;
487  VALUE v = (VALUE)vstart;
488 
489  for (; v != (VALUE)vend; v += stride) {
490  if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_DATA) {
491  VALUE counter;
492  VALUE key = RBASIC(v)->klass;
493 
494  if (key == 0) {
495  const char *name = rb_objspace_data_type_name(v);
496  if (name == 0) name = "unknown";
497  key = ID2SYM(rb_intern(name));
498  }
499 
500  counter = rb_hash_aref(hash, key);
501  if (NIL_P(counter)) {
502  counter = INT2FIX(1);
503  }
504  else {
505  counter = INT2FIX(FIX2INT(counter) + 1);
506  }
507 
508  rb_hash_aset(hash, key, counter);
509  }
510  }
511 
512  return 0;
513 }
514 
515 /*
516  * call-seq:
517  * ObjectSpace.count_tdata_objects([result_hash]) -> hash
518  *
519  * Counts objects for each +T_DATA+ type.
520  *
521  * This method is only for MRI developers interested in performance and memory
522  * usage of Ruby programs.
523  *
524  * It returns a hash as:
525  *
526  * {RubyVM::InstructionSequence=>504, :parser=>5, :barrier=>6,
527  * :mutex=>6, Proc=>60, RubyVM::Env=>57, Mutex=>1, Encoding=>99,
528  * ThreadGroup=>1, Binding=>1, Thread=>1, RubyVM=>1, :iseq=>1,
529  * Random=>1, ARGF.class=>1, Data=>1, :autoload=>3, Time=>2}
530  * # T_DATA objects existing at startup on r32276.
531  *
532  * If the optional argument, result_hash, is given, it is overwritten and
533  * returned. This is intended to avoid probe effect.
534  *
535  * The contents of the returned hash is implementation specific and may change
536  * in the future.
537  *
538  * In this version, keys are Class object or Symbol object.
539  *
540  * If object is kind of normal (accessible) object, the key is Class object.
541  * If object is not a kind of normal (internal) object, the key is symbol
542  * name, registered by rb_data_type_struct.
543  *
544  * This method is only expected to work with C Ruby.
545  */
546 
547 static VALUE
548 count_tdata_objects(int argc, VALUE *argv, VALUE self)
549 {
550  VALUE hash = setup_hash(argc, argv);
551  rb_objspace_each_objects(cto_i, (void *)hash);
552  return hash;
553 }
554 
555 static ID imemo_type_ids[IMEMO_MASK+1];
556 
557 static int
558 count_imemo_objects_i(void *vstart, void *vend, size_t stride, void *data)
559 {
560  VALUE hash = (VALUE)data;
561  VALUE v = (VALUE)vstart;
562 
563  for (; v != (VALUE)vend; v += stride) {
564  if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_IMEMO) {
565  VALUE counter;
566  VALUE key = ID2SYM(imemo_type_ids[imemo_type(v)]);
567 
568  counter = rb_hash_aref(hash, key);
569 
570  if (NIL_P(counter)) {
571  counter = INT2FIX(1);
572  }
573  else {
574  counter = INT2FIX(FIX2INT(counter) + 1);
575  }
576 
577  rb_hash_aset(hash, key, counter);
578  }
579  }
580 
581  return 0;
582 }
583 
584 /*
585  * call-seq:
586  * ObjectSpace.count_imemo_objects([result_hash]) -> hash
587  *
588  * Counts objects for each +T_IMEMO+ type.
589  *
590  * This method is only for MRI developers interested in performance and memory
591  * usage of Ruby programs.
592  *
593  * It returns a hash as:
594  *
595  * {:imemo_ifunc=>8,
596  * :imemo_svar=>7,
597  * :imemo_cref=>509,
598  * :imemo_memo=>1,
599  * :imemo_throw_data=>1}
600  *
601  * If the optional argument, result_hash, is given, it is overwritten and
602  * returned. This is intended to avoid probe effect.
603  *
604  * The contents of the returned hash is implementation specific and may change
605  * in the future.
606  *
607  * In this version, keys are symbol objects.
608  *
609  * This method is only expected to work with C Ruby.
610  */
611 
612 static VALUE
613 count_imemo_objects(int argc, VALUE *argv, VALUE self)
614 {
615  VALUE hash = setup_hash(argc, argv);
616 
617  if (imemo_type_ids[0] == 0) {
618  imemo_type_ids[0] = rb_intern("imemo_none");
619  imemo_type_ids[1] = rb_intern("imemo_cref");
620  imemo_type_ids[2] = rb_intern("imemo_svar");
621  imemo_type_ids[3] = rb_intern("imemo_throw_data");
622  imemo_type_ids[4] = rb_intern("imemo_ifunc");
623  imemo_type_ids[5] = rb_intern("imemo_memo");
624  imemo_type_ids[6] = rb_intern("imemo_ment");
625  imemo_type_ids[7] = rb_intern("imemo_iseq");
626  imemo_type_ids[8] = rb_intern("imemo_alloc");
627  }
628 
629  rb_objspace_each_objects(count_imemo_objects_i, (void *)hash);
630 
631  return hash;
632 }
633 
634 static void
635 iow_mark(void *ptr)
636 {
637  rb_gc_mark((VALUE)ptr);
638 }
639 
640 static size_t
641 iow_size(const void *ptr)
642 {
643  VALUE obj = (VALUE)ptr;
644  return rb_obj_memsize_of(obj);
645 }
646 
647 static const rb_data_type_t iow_data_type = {
648  "ObjectSpace::InternalObjectWrapper",
649  {iow_mark, 0, iow_size,},
651 };
652 
653 static VALUE rb_mInternalObjectWrapper;
654 
655 static VALUE
656 iow_newobj(VALUE obj)
657 {
658  return TypedData_Wrap_Struct(rb_mInternalObjectWrapper, &iow_data_type, (void *)obj);
659 }
660 
661 /* Returns the type of the internal object. */
662 static VALUE
663 iow_type(VALUE self)
664 {
665  VALUE obj = (VALUE)DATA_PTR(self);
666  return type2sym(BUILTIN_TYPE(obj));
667 }
668 
669 /* See Object#inspect. */
670 static VALUE
671 iow_inspect(VALUE self)
672 {
673  VALUE obj = (VALUE)DATA_PTR(self);
674  VALUE type = type2sym(BUILTIN_TYPE(obj));
675 
676  return rb_sprintf("#<InternalObject:%p %"PRIsVALUE">", (void *)obj, rb_sym2str(type));
677 }
678 
679 /* Returns the Object#object_id of the internal object. */
680 static VALUE
681 iow_internal_object_id(VALUE self)
682 {
683  VALUE obj = (VALUE)DATA_PTR(self);
684  return rb_obj_id(obj);
685 }
686 
687 struct rof_data {
690 };
691 
692 static void
693 reachable_object_from_i(VALUE obj, void *data_ptr)
694 {
695  struct rof_data *data = (struct rof_data *)data_ptr;
696  VALUE key = obj;
697  VALUE val = obj;
698 
701  val = iow_newobj(obj);
702  rb_ary_push(data->internals, val);
703  }
704  st_insert(data->refs, key, val);
705  }
706 }
707 
708 static int
709 collect_values(st_data_t key, st_data_t value, st_data_t data)
710 {
711  VALUE ary = (VALUE)data;
712  rb_ary_push(ary, (VALUE)value);
713  return ST_CONTINUE;
714 }
715 
716 /*
717  * call-seq:
718  * ObjectSpace.reachable_objects_from(obj) -> array or nil
719  *
720  * [MRI specific feature] Return all reachable objects from `obj'.
721  *
722  * This method returns all reachable objects from `obj'.
723  *
724  * If `obj' has two or more references to the same object `x', then returned
725  * array only includes one `x' object.
726  *
727  * If `obj' is a non-markable (non-heap management) object such as true,
728  * false, nil, symbols and Fixnums (and Flonum) then it simply returns nil.
729  *
730  * If `obj' has references to an internal object, then it returns instances of
731  * ObjectSpace::InternalObjectWrapper class. This object contains a reference
732  * to an internal object and you can check the type of internal object with
733  * `type' method.
734  *
735  * If `obj' is instance of ObjectSpace::InternalObjectWrapper class, then this
736  * method returns all reachable object from an internal object, which is
737  * pointed by `obj'.
738  *
739  * With this method, you can find memory leaks.
740  *
741  * This method is only expected to work except with C Ruby.
742  *
743  * Example:
744  * ObjectSpace.reachable_objects_from(['a', 'b', 'c'])
745  * #=> [Array, 'a', 'b', 'c']
746  *
747  * ObjectSpace.reachable_objects_from(['a', 'a', 'a'])
748  * #=> [Array, 'a', 'a', 'a'] # all 'a' strings have different object id
749  *
750  * ObjectSpace.reachable_objects_from([v = 'a', v, v])
751  * #=> [Array, 'a']
752  *
753  * ObjectSpace.reachable_objects_from(1)
754  * #=> nil # 1 is not markable (heap managed) object
755  *
756  */
757 
758 static VALUE
759 reachable_objects_from(VALUE self, VALUE obj)
760 {
762  VALUE ret = rb_ary_new();
763  struct rof_data data;
764 
765  if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
766  obj = (VALUE)DATA_PTR(obj);
767  }
768 
769  data.refs = st_init_numtable();
770  data.internals = rb_ary_new();
771 
772  rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data);
773 
774  st_foreach(data.refs, collect_values, (st_data_t)ret);
775  return ret;
776  }
777  else {
778  return Qnil;
779  }
780 }
781 
782 struct rofr_data {
784  const char *last_category;
787 };
788 
789 static void
790 reachable_object_from_root_i(const char *category, VALUE obj, void *ptr)
791 {
792  struct rofr_data *data = (struct rofr_data *)ptr;
793  VALUE category_str;
794  VALUE category_objects;
795 
796  if (category == data->last_category) {
797  category_str = data->last_category_str;
798  category_objects = data->last_category_objects;
799  }
800  else {
801  data->last_category = category;
802  category_str = data->last_category_str = rb_str_new2(category);
803  category_objects = data->last_category_objects = rb_ident_hash_new();
804  if (!NIL_P(rb_hash_lookup(data->categories, category_str))) {
805  rb_bug("reachable_object_from_root_i: category should insert at once");
806  }
807  rb_hash_aset(data->categories, category_str, category_objects);
808  }
809 
811  obj != data->categories &&
812  obj != data->last_category_objects) {
814  obj = iow_newobj(obj);
815  }
816  rb_hash_aset(category_objects, obj, obj);
817  }
818 }
819 
820 static int
821 collect_values_of_values(VALUE category, VALUE category_objects, VALUE categories)
822 {
823  VALUE ary = rb_ary_new();
824  st_foreach(rb_hash_tbl(category_objects), collect_values, ary);
825  rb_hash_aset(categories, category, ary);
826  return ST_CONTINUE;
827 }
828 
829 /*
830  * call-seq:
831  * ObjectSpace.reachable_objects_from_root -> hash
832  *
833  * [MRI specific feature] Return all reachable objects from root.
834  */
835 static VALUE
836 reachable_objects_from_root(VALUE self)
837 {
838  struct rofr_data data;
839  VALUE hash = data.categories = rb_ident_hash_new();
840  data.last_category = 0;
841 
842  rb_objspace_reachable_objects_from_root(reachable_object_from_root_i, &data);
843  rb_hash_foreach(hash, collect_values_of_values, hash);
844 
845  return hash;
846 }
847 
848 static VALUE
849 wrap_klass_iow(VALUE klass)
850 {
851  if (!RTEST(klass)) {
852  return Qnil;
853  }
854  else if (RB_TYPE_P(klass, T_ICLASS)) {
855  return iow_newobj(klass);
856  }
857  else {
858  return klass;
859  }
860 }
861 
862 /*
863  * call-seq:
864  * ObjectSpace.internal_class_of(obj) -> Class or Module
865  *
866  * [MRI specific feature] Return internal class of obj.
867  * obj can be an instance of InternalObjectWrapper.
868  *
869  * Note that you should not use this method in your application.
870  */
871 static VALUE
872 objspace_internal_class_of(VALUE self, VALUE obj)
873 {
874  VALUE klass;
875 
876  if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
877  obj = (VALUE)DATA_PTR(obj);
878  }
879 
880  klass = CLASS_OF(obj);
881  return wrap_klass_iow(klass);
882 }
883 
884 /*
885  * call-seq:
886  * ObjectSpace.internal_super_of(cls) -> Class or Module
887  *
888  * [MRI specific feature] Return internal super class of cls (Class or Module).
889  * obj can be an instance of InternalObjectWrapper.
890  *
891  * Note that you should not use this method in your application.
892  */
893 static VALUE
894 objspace_internal_super_of(VALUE self, VALUE obj)
895 {
896  VALUE super;
897 
898  if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
899  obj = (VALUE)DATA_PTR(obj);
900  }
901 
902  switch (OBJ_BUILTIN_TYPE(obj)) {
903  case T_MODULE:
904  case T_CLASS:
905  case T_ICLASS:
906  super = RCLASS_SUPER(obj);
907  break;
908  default:
909  rb_raise(rb_eArgError, "class or module is expected");
910  }
911 
912  return wrap_klass_iow(super);
913 }
914 
915 void Init_object_tracing(VALUE rb_mObjSpace);
916 void Init_objspace_dump(VALUE rb_mObjSpace);
917 
918 /*
919  * Document-module: ObjectSpace
920  *
921  * The objspace library extends the ObjectSpace module and adds several
922  * methods to get internal statistic information about
923  * object/memory management.
924  *
925  * You need to <code>require 'objspace'</code> to use this extension module.
926  *
927  * Generally, you *SHOULD NOT* use this library if you do not know
928  * about the MRI implementation. Mainly, this library is for (memory)
929  * profiler developers and MRI developers who need to know about MRI
930  * memory usage.
931  */
932 
933 void
935 {
936  VALUE rb_mObjSpace;
937 #if 0
938  rb_mObjSpace = rb_define_module("ObjectSpace"); /* let rdoc know */
939 #endif
940  rb_mObjSpace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
941 
942  rb_define_module_function(rb_mObjSpace, "memsize_of", memsize_of_m, 1);
943  rb_define_module_function(rb_mObjSpace, "memsize_of_all", memsize_of_all_m, -1);
944 
945  rb_define_module_function(rb_mObjSpace, "count_objects_size", count_objects_size, -1);
946  rb_define_module_function(rb_mObjSpace, "count_symbols", count_symbols, -1);
947  rb_define_module_function(rb_mObjSpace, "count_nodes", count_nodes, -1);
948  rb_define_module_function(rb_mObjSpace, "count_tdata_objects", count_tdata_objects, -1);
949  rb_define_module_function(rb_mObjSpace, "count_imemo_objects", count_imemo_objects, -1);
950 
951  rb_define_module_function(rb_mObjSpace, "reachable_objects_from", reachable_objects_from, 1);
952  rb_define_module_function(rb_mObjSpace, "reachable_objects_from_root", reachable_objects_from_root, 0);
953 
954  rb_define_module_function(rb_mObjSpace, "internal_class_of", objspace_internal_class_of, 1);
955  rb_define_module_function(rb_mObjSpace, "internal_super_of", objspace_internal_super_of, 1);
956 
957  /*
958  * This class is used as a return value from
959  * ObjectSpace::reachable_objects_from.
960  *
961  * When ObjectSpace::reachable_objects_from returns an object with
962  * references to an internal object, an instance of this class is returned.
963  *
964  * You can use the #type method to check the type of the internal object.
965  */
966  rb_mInternalObjectWrapper = rb_define_class_under(rb_mObjSpace, "InternalObjectWrapper", rb_cObject);
967  rb_define_method(rb_mInternalObjectWrapper, "type", iow_type, 0);
968  rb_define_method(rb_mInternalObjectWrapper, "inspect", iow_inspect, 0);
969  rb_define_method(rb_mInternalObjectWrapper, "internal_object_id", iow_internal_object_id, 0);
970 
971  Init_object_tracing(rb_mObjSpace);
972  Init_objspace_dump(rb_mObjSpace);
973 }
#define T_SYMBOL
Definition: ruby.h:508
#define T_OBJECT
Definition: ruby.h:491
Definition: node.h:91
Definition: node.h:31
void rb_bug(const char *fmt,...)
Definition: error.c:521
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
VALUE rb_obj_id(VALUE obj)
Definition: gc.c:3158
#define T_FIXNUM
Definition: ruby.h:503
Definition: st.h:79
#define T_MATCH
Definition: ruby.h:507
Definition: node.h:49
void Init_objspace(void)
Definition: objspace.c:934
#define CLASS_OF(v)
Definition: ruby.h:453
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
#define T_MODULE
Definition: ruby.h:494
const char * last_category
Definition: objspace.c:784
#define st_foreach
Definition: regint.h:186
VALUE last_category_str
Definition: objspace.c:785
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:1162
Definition: st.h:99
#define T_RATIONAL
Definition: ruby.h:509
Definition: node.h:41
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:924
#define NODE_LAST
Definition: node.h:230
void rb_objspace_reachable_objects_from_root(void(func)(const char *category, VALUE, void *), void *passing_data)
Definition: gc.c:7627
struct st_table * rb_hash_tbl(VALUE hash)
Definition: hash.c:475
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
#define IMEMO_MASK
Definition: internal.h:849
#define T_HASH
Definition: ruby.h:499
#define DATA_PTR(dta)
Definition: ruby.h:1106
void rb_objspace_each_objects(each_obj_callback *callback, void *data)
Definition: gc.c:2489
void rb_gc_mark(VALUE ptr)
Definition: gc.c:4464
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:853
int rb_objspace_markable_object_p(VALUE obj)
Definition: gc.c:3065
#define T_ARRAY
Definition: ruby.h:498
#define T_UNDEF
Definition: ruby.h:512
#define nd_type(n)
Definition: node.h:272
VALUE internals
Definition: objspace.c:689
#define RHASH_TBL(h)
Definition: ruby.h:1056
Definition: node.h:27
VALUE rb_eArgError
Definition: error.c:802
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:759
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:22
Definition: node.h:233
VALUE klass
Definition: objspace.c:47
void rb_hash_foreach(VALUE hash, int(*func)(ANYARGS), VALUE farg)
Definition: hash.c:385
size_t rb_obj_memsize_of(VALUE obj)
Definition: gc.c:3327
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
VALUE rb_obj_is_kind_of(VALUE, VALUE)
call-seq: obj.is_a?(class) -> true or false obj.kind_of?(class) -> true or false
Definition: object.c:842
#define ID_SCOPE_MASK
Definition: id.h:32
#define CASE_TYPE(t)
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1616
#define val
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
#define T_NIL
Definition: ruby.h:490
VALUE rb_ary_new(void)
Definition: array.c:499
#define T_TRUE
Definition: ruby.h:504
#define RSYMBOL(obj)
Definition: symbol.h:33
#define NIL_P(v)
Definition: ruby.h:451
VALUE categories
Definition: objspace.c:783
#define OBJ_BUILTIN_TYPE(obj)
Definition: internal.h:1945
#define T_FLOAT
Definition: ruby.h:495
int argc
Definition: ruby.c:187
Definition: node.h:61
#define T_BIGNUM
Definition: ruby.h:501
#define T_NODE
Definition: ruby.h:513
#define rb_str_new2
Definition: intern.h:835
#define T_COMPLEX
Definition: ruby.h:510
st_table * refs
Definition: objspace.c:688
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:2292
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
Definition: class.c:1731
#define T_DATA
Definition: ruby.h:506
int rb_objspace_internal_object_p(VALUE obj)
Definition: gc.c:2552
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1452
VALUE rb_hash_new(void)
Definition: hash.c:424
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1908
#define T_IMEMO
Definition: ruby.h:511
#define PRIsVALUE
Definition: ruby.h:135
unsigned long ID
Definition: ruby.h:86
#define T_STRUCT
Definition: ruby.h:500
#define Qnil
Definition: ruby.h:438
#define BUILTIN_TYPE(x)
Definition: ruby.h:518
unsigned long VALUE
Definition: ruby.h:85
#define RBASIC(obj)
Definition: ruby.h:1197
const char * rb_objspace_data_type_name(VALUE obj)
Definition: gc.c:2091
VALUE rb_eTypeError
Definition: error.c:801
#define FIX2INT(x)
Definition: ruby.h:686
void Init_object_tracing(VALUE rb_mObjSpace)
size_t total
Definition: objspace.c:46
ruby_value_type
Definition: ruby.h:455
VALUE rb_ident_hash_new(void)
Definition: hash.c:2924
#define INT2FIX(i)
Definition: ruby.h:232
#define RCLASS_SUPER(c)
Definition: classext.h:16
Definition: node.h:47
void rb_objspace_reachable_objects_from(VALUE obj, void(func)(VALUE, void *), void *data)
Definition: gc.c:7599
#define st_init_numtable
Definition: regint.h:178
Definition: node.h:207
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:831
#define RTEST(v)
Definition: ruby.h:450
Definition: node.h:141
#define T_STRING
Definition: ruby.h:496
#define T_FALSE
Definition: ruby.h:505
#define T_FILE
Definition: ruby.h:502
#define st_insert
Definition: regint.h:184
#define T_CLASS
Definition: ruby.h:492
const char * name
Definition: nkf.c:208
#define ID2SYM(x)
Definition: ruby.h:383
Definition: node.h:63
imemo_type
Definition: internal.h:838
Definition: node.h:33
Definition: node.h:43
#define RHASH_EMPTY_P(h)
Definition: ruby.h:1060
VALUE rb_define_module(const char *name)
Definition: class.c:768
#define rb_intern(str)
#define T_ZOMBIE
Definition: ruby.h:514
#define T_NONE
Definition: ruby.h:489
size_t rb_sym_immortal_count(void)
Definition: symbol.c:814
#define T_ICLASS
Definition: ruby.h:493
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
void Init_objspace_dump(VALUE rb_mObjSpace)
#define SIZET2NUM(v)
Definition: ruby.h:264
VALUE last_category_objects
Definition: objspace.c:786
#define T_REGEXP
Definition: ruby.h:497
Definition: node.h:139
#define T_MASK
Definition: md5.c:131
#define COUNT_NODE(n)
char ** argv
Definition: ruby.c:188
#define rb_sym2str(sym)
Definition: console.c:107