Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
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 <ruby/io.h>
16 #include "internal.h"
17 #include <ruby/st.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 {
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);
193 #undef CASE_TYPE
194  default: rb_bug("type2sym: unknown type (%d)", i);
195  }
196  return type;
197 }
198 
199 /*
200  * call-seq:
201  * ObjectSpace.count_objects_size([result_hash]) -> hash
202  *
203  * Counts objects size (in bytes) for each type.
204  *
205  * Note that this information is incomplete. You need to deal with
206  * this information as only a *HINT*. Especially, total size of
207  * T_DATA may be wrong.
208  *
209  * It returns a hash as:
210  * {:TOTAL=>1461154, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249, ...}
211  *
212  * If the optional argument, result_hash, is given,
213  * it is overwritten and returned.
214  * This is intended to avoid probe effect.
215  *
216  * The contents of the returned hash is implementation defined.
217  * It may be changed in future.
218  *
219  * This method is only expected to work with C Ruby.
220  */
221 
222 static VALUE
223 count_objects_size(int argc, VALUE *argv, VALUE os)
224 {
225  size_t counts[T_MASK+1];
226  size_t total = 0;
227  enum ruby_value_type i;
228  VALUE hash = setup_hash(argc, argv);
229 
230  for (i = 0; i <= T_MASK; i++) {
231  counts[i] = 0;
232  }
233 
234  rb_objspace_each_objects(cos_i, &counts[0]);
235 
236  for (i = 0; i <= T_MASK; i++) {
237  if (counts[i]) {
238  VALUE type = type2sym(i);
239  total += counts[i];
240  rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
241  }
242  }
243  rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
244  return hash;
245 }
246 
248  size_t mortal;
249  size_t immortal;
250 };
251 
252 static int
253 cs_i(void *vstart, void *vend, size_t stride, void *n)
254 {
255  struct dynamic_symbol_counts *counts = (struct dynamic_symbol_counts *)n;
256  VALUE v = (VALUE)vstart;
257 
258  for (; v != (VALUE)vend; v += stride) {
259  if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_SYMBOL) {
260  ID id = RSYMBOL(v)->id;
261  if ((id & ~ID_SCOPE_MASK) == 0) {
262  counts->mortal++;
263  }
264  else {
265  counts->immortal++;
266  }
267  }
268  }
269 
270  return 0;
271 }
272 
273 size_t rb_sym_immortal_count(void);
274 
275 /*
276  * call-seq:
277  * ObjectSpace.count_symbols([result_hash]) -> hash
278  *
279  * Counts symbols for each Symbol type.
280  *
281  * This method is only for MRI developers interested in performance and memory
282  * usage of Ruby programs.
283  *
284  * If the optional argument, result_hash, is given, it is overwritten and
285  * returned. This is intended to avoid probe effect.
286  *
287  * Note:
288  * The contents of the returned hash is implementation defined.
289  * It may be changed in future.
290  *
291  * This method is only expected to work with C Ruby.
292  *
293  * On this version of MRI, they have 3 types of Symbols (and 1 total counts).
294  *
295  * * mortal_dynamic_symbol: GC target symbols (collected by GC)
296  * * immortal_dynamic_symbol: Immortal symbols promoted from dynamic symbols (do not collected by GC)
297  * * immortal_static_symbol: Immortal symbols (do not collected by GC)
298  * * immortal_symbol: total immortal symbols (immortal_dynamic_symbol+immortal_static_symbol)
299  */
300 
301 static VALUE
302 count_symbols(int argc, VALUE *argv, VALUE os)
303 {
304  struct dynamic_symbol_counts dynamic_counts = {0, 0};
305  VALUE hash = setup_hash(argc, argv);
306 
307  size_t immortal_symbols = rb_sym_immortal_count();
308  rb_objspace_each_objects(cs_i, &dynamic_counts);
309 
310  rb_hash_aset(hash, ID2SYM(rb_intern("mortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.mortal));
311  rb_hash_aset(hash, ID2SYM(rb_intern("immortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.immortal));
312  rb_hash_aset(hash, ID2SYM(rb_intern("immortal_static_symbol")), SIZET2NUM(immortal_symbols - dynamic_counts.immortal));
313  rb_hash_aset(hash, ID2SYM(rb_intern("immortal_symbol")), SIZET2NUM(immortal_symbols));
314 
315  return hash;
316 }
317 
318 static int
319 cn_i(void *vstart, void *vend, size_t stride, void *n)
320 {
321  size_t *nodes = (size_t *)n;
322  VALUE v = (VALUE)vstart;
323 
324  for (; v != (VALUE)vend; v += stride) {
325  if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_NODE) {
326  size_t s = nd_type((NODE *)v);
327  nodes[s]++;
328  }
329  }
330 
331  return 0;
332 }
333 
334 /*
335  * call-seq:
336  * ObjectSpace.count_nodes([result_hash]) -> hash
337  *
338  * Counts nodes for each node type.
339  *
340  * This method is only for MRI developers interested in performance and memory
341  * usage of Ruby programs.
342  *
343  * It returns a hash as:
344  *
345  * {:NODE_METHOD=>2027, :NODE_FBODY=>1927, :NODE_CFUNC=>1798, ...}
346  *
347  * If the optional argument, result_hash, is given, it is overwritten and
348  * returned. This is intended to avoid probe effect.
349  *
350  * Note:
351  * The contents of the returned hash is implementation defined.
352  * It may be changed in future.
353  *
354  * This method is only expected to work with C Ruby.
355  */
356 
357 static VALUE
358 count_nodes(int argc, VALUE *argv, VALUE os)
359 {
360  size_t nodes[NODE_LAST+1];
361  enum node_type i;
362  VALUE hash = setup_hash(argc, argv);
363 
364  for (i = 0; i <= NODE_LAST; i++) {
365  nodes[i] = 0;
366  }
367 
368  rb_objspace_each_objects(cn_i, &nodes[0]);
369 
370  for (i=0; i<NODE_LAST; i++) {
371  if (nodes[i] != 0) {
372  VALUE node;
373  switch (i) {
374 #define COUNT_NODE(n) case n: node = ID2SYM(rb_intern(#n)); goto set
479 #undef COUNT_NODE
480  case NODE_LAST: break;
481  }
482  UNREACHABLE;
483  set:
484  rb_hash_aset(hash, node, SIZET2NUM(nodes[i]));
485  }
486  }
487  return hash;
488 }
489 
490 static int
491 cto_i(void *vstart, void *vend, size_t stride, void *data)
492 {
493  VALUE hash = (VALUE)data;
494  VALUE v = (VALUE)vstart;
495 
496  for (; v != (VALUE)vend; v += stride) {
497  if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_DATA) {
498  VALUE counter;
499  VALUE key = RBASIC(v)->klass;
500 
501  if (key == 0) {
502  const char *name = rb_objspace_data_type_name(v);
503  if (name == 0) name = "unknown";
504  key = ID2SYM(rb_intern(name));
505  }
506 
507  counter = rb_hash_aref(hash, key);
508  if (NIL_P(counter)) {
509  counter = INT2FIX(1);
510  }
511  else {
512  counter = INT2FIX(FIX2INT(counter) + 1);
513  }
514 
515  rb_hash_aset(hash, key, counter);
516  }
517  }
518 
519  return 0;
520 }
521 
522 /*
523  * call-seq:
524  * ObjectSpace.count_tdata_objects([result_hash]) -> hash
525  *
526  * Counts objects for each +T_DATA+ type.
527  *
528  * This method is only for MRI developers interested in performance and memory
529  * usage of Ruby programs.
530  *
531  * It returns a hash as:
532  *
533  * {RubyVM::InstructionSequence=>504, :parser=>5, :barrier=>6,
534  * :mutex=>6, Proc=>60, RubyVM::Env=>57, Mutex=>1, Encoding=>99,
535  * ThreadGroup=>1, Binding=>1, Thread=>1, RubyVM=>1, :iseq=>1,
536  * Random=>1, ARGF.class=>1, Data=>1, :autoload=>3, Time=>2}
537  * # T_DATA objects existing at startup on r32276.
538  *
539  * If the optional argument, result_hash, is given, it is overwritten and
540  * returned. This is intended to avoid probe effect.
541  *
542  * The contents of the returned hash is implementation specific and may change
543  * in the future.
544  *
545  * In this version, keys are Class object or Symbol object.
546  *
547  * If object is kind of normal (accessible) object, the key is Class object.
548  * If object is not a kind of normal (internal) object, the key is symbol
549  * name, registered by rb_data_type_struct.
550  *
551  * This method is only expected to work with C Ruby.
552  */
553 
554 static VALUE
555 count_tdata_objects(int argc, VALUE *argv, VALUE self)
556 {
557  VALUE hash = setup_hash(argc, argv);
558  rb_objspace_each_objects(cto_i, (void *)hash);
559  return hash;
560 }
561 
562 static ID imemo_type_ids[IMEMO_MASK+1];
563 
564 static int
565 count_imemo_objects_i(void *vstart, void *vend, size_t stride, void *data)
566 {
567  VALUE hash = (VALUE)data;
568  VALUE v = (VALUE)vstart;
569 
570  for (; v != (VALUE)vend; v += stride) {
571  if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_IMEMO) {
572  VALUE counter;
573  VALUE key = ID2SYM(imemo_type_ids[imemo_type(v)]);
574 
575  counter = rb_hash_aref(hash, key);
576 
577  if (NIL_P(counter)) {
578  counter = INT2FIX(1);
579  }
580  else {
581  counter = INT2FIX(FIX2INT(counter) + 1);
582  }
583 
584  rb_hash_aset(hash, key, counter);
585  }
586  }
587 
588  return 0;
589 }
590 
591 /*
592  * call-seq:
593  * ObjectSpace.count_imemo_objects([result_hash]) -> hash
594  *
595  * Counts objects for each +T_IMEMO+ type.
596  *
597  * This method is only for MRI developers interested in performance and memory
598  * usage of Ruby programs.
599  *
600  * It returns a hash as:
601  *
602  * {:imemo_ifunc=>8,
603  * :imemo_svar=>7,
604  * :imemo_cref=>509,
605  * :imemo_memo=>1,
606  * :imemo_throw_data=>1}
607  *
608  * If the optional argument, result_hash, is given, it is overwritten and
609  * returned. This is intended to avoid probe effect.
610  *
611  * The contents of the returned hash is implementation specific and may change
612  * in the future.
613  *
614  * In this version, keys are symbol objects.
615  *
616  * This method is only expected to work with C Ruby.
617  */
618 
619 static VALUE
620 count_imemo_objects(int argc, VALUE *argv, VALUE self)
621 {
622  VALUE hash = setup_hash(argc, argv);
623 
624  if (imemo_type_ids[0] == 0) {
625  imemo_type_ids[0] = rb_intern("imemo_env");
626  imemo_type_ids[1] = rb_intern("imemo_cref");
627  imemo_type_ids[2] = rb_intern("imemo_svar");
628  imemo_type_ids[3] = rb_intern("imemo_throw_data");
629  imemo_type_ids[4] = rb_intern("imemo_ifunc");
630  imemo_type_ids[5] = rb_intern("imemo_memo");
631  imemo_type_ids[6] = rb_intern("imemo_ment");
632  imemo_type_ids[7] = rb_intern("imemo_iseq");
633  imemo_type_ids[8] = rb_intern("imemo_tmpbuf");
634  imemo_type_ids[9] = rb_intern("imemo_ast");
635  imemo_type_ids[10] = rb_intern("imemo_parser_strterm");
636  }
637 
638  rb_objspace_each_objects(count_imemo_objects_i, (void *)hash);
639 
640  return hash;
641 }
642 
643 static void
644 iow_mark(void *ptr)
645 {
646  rb_gc_mark((VALUE)ptr);
647 }
648 
649 static size_t
650 iow_size(const void *ptr)
651 {
652  VALUE obj = (VALUE)ptr;
653  return rb_obj_memsize_of(obj);
654 }
655 
656 static const rb_data_type_t iow_data_type = {
657  "ObjectSpace::InternalObjectWrapper",
658  {iow_mark, 0, iow_size,},
660 };
661 
662 static VALUE rb_mInternalObjectWrapper;
663 
664 static VALUE
665 iow_newobj(VALUE obj)
666 {
667  return TypedData_Wrap_Struct(rb_mInternalObjectWrapper, &iow_data_type, (void *)obj);
668 }
669 
670 /* Returns the type of the internal object. */
671 static VALUE
672 iow_type(VALUE self)
673 {
674  VALUE obj = (VALUE)DATA_PTR(self);
675  return type2sym(BUILTIN_TYPE(obj));
676 }
677 
678 /* See Object#inspect. */
679 static VALUE
680 iow_inspect(VALUE self)
681 {
682  VALUE obj = (VALUE)DATA_PTR(self);
683  VALUE type = type2sym(BUILTIN_TYPE(obj));
684 
685  return rb_sprintf("#<InternalObject:%p %"PRIsVALUE">", (void *)obj, rb_sym2str(type));
686 }
687 
688 /* Returns the Object#object_id of the internal object. */
689 static VALUE
690 iow_internal_object_id(VALUE self)
691 {
692  VALUE obj = (VALUE)DATA_PTR(self);
693  return rb_obj_id(obj);
694 }
695 
696 struct rof_data {
699 };
700 
701 static void
702 reachable_object_from_i(VALUE obj, void *data_ptr)
703 {
704  struct rof_data *data = (struct rof_data *)data_ptr;
705  VALUE key = obj;
706  VALUE val = obj;
707 
710  val = iow_newobj(obj);
711  rb_ary_push(data->internals, val);
712  }
713  st_insert(data->refs, key, val);
714  }
715 }
716 
717 static int
718 collect_values(st_data_t key, st_data_t value, st_data_t data)
719 {
720  VALUE ary = (VALUE)data;
721  rb_ary_push(ary, (VALUE)value);
722  return ST_CONTINUE;
723 }
724 
725 /*
726  * call-seq:
727  * ObjectSpace.reachable_objects_from(obj) -> array or nil
728  *
729  * [MRI specific feature] Return all reachable objects from `obj'.
730  *
731  * This method returns all reachable objects from `obj'.
732  *
733  * If `obj' has two or more references to the same object `x', then returned
734  * array only includes one `x' object.
735  *
736  * If `obj' is a non-markable (non-heap management) object such as true,
737  * false, nil, symbols and Fixnums (and Flonum) then it simply returns nil.
738  *
739  * If `obj' has references to an internal object, then it returns instances of
740  * ObjectSpace::InternalObjectWrapper class. This object contains a reference
741  * to an internal object and you can check the type of internal object with
742  * `type' method.
743  *
744  * If `obj' is instance of ObjectSpace::InternalObjectWrapper class, then this
745  * method returns all reachable object from an internal object, which is
746  * pointed by `obj'.
747  *
748  * With this method, you can find memory leaks.
749  *
750  * This method is only expected to work except with C Ruby.
751  *
752  * Example:
753  * ObjectSpace.reachable_objects_from(['a', 'b', 'c'])
754  * #=> [Array, 'a', 'b', 'c']
755  *
756  * ObjectSpace.reachable_objects_from(['a', 'a', 'a'])
757  * #=> [Array, 'a', 'a', 'a'] # all 'a' strings have different object id
758  *
759  * ObjectSpace.reachable_objects_from([v = 'a', v, v])
760  * #=> [Array, 'a']
761  *
762  * ObjectSpace.reachable_objects_from(1)
763  * #=> nil # 1 is not markable (heap managed) object
764  *
765  */
766 
767 static VALUE
768 reachable_objects_from(VALUE self, VALUE obj)
769 {
771  VALUE ret = rb_ary_new();
772  struct rof_data data;
773 
774  if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
775  obj = (VALUE)DATA_PTR(obj);
776  }
777 
778  data.refs = st_init_numtable();
779  data.internals = rb_ary_new();
780 
781  rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data);
782 
783  st_foreach(data.refs, collect_values, (st_data_t)ret);
784  return ret;
785  }
786  else {
787  return Qnil;
788  }
789 }
790 
791 struct rofr_data {
793  const char *last_category;
796 };
797 
798 static void
799 reachable_object_from_root_i(const char *category, VALUE obj, void *ptr)
800 {
801  struct rofr_data *data = (struct rofr_data *)ptr;
802  VALUE category_str;
803  VALUE category_objects;
804 
805  if (category == data->last_category) {
806  category_str = data->last_category_str;
807  category_objects = data->last_category_objects;
808  }
809  else {
810  data->last_category = category;
811  category_str = data->last_category_str = rb_str_new2(category);
812  category_objects = data->last_category_objects = rb_ident_hash_new();
813  if (!NIL_P(rb_hash_lookup(data->categories, category_str))) {
814  rb_bug("reachable_object_from_root_i: category should insert at once");
815  }
816  rb_hash_aset(data->categories, category_str, category_objects);
817  }
818 
820  obj != data->categories &&
821  obj != data->last_category_objects) {
823  obj = iow_newobj(obj);
824  }
825  rb_hash_aset(category_objects, obj, obj);
826  }
827 }
828 
829 static int
830 collect_values_of_values(VALUE category, VALUE category_objects, VALUE categories)
831 {
832  VALUE ary = rb_ary_new();
833  rb_hash_foreach(category_objects, collect_values, ary);
834  rb_hash_aset(categories, category, ary);
835  return ST_CONTINUE;
836 }
837 
838 /*
839  * call-seq:
840  * ObjectSpace.reachable_objects_from_root -> hash
841  *
842  * [MRI specific feature] Return all reachable objects from root.
843  */
844 static VALUE
845 reachable_objects_from_root(VALUE self)
846 {
847  struct rofr_data data;
848  VALUE hash = data.categories = rb_ident_hash_new();
849  data.last_category = 0;
850 
851  rb_objspace_reachable_objects_from_root(reachable_object_from_root_i, &data);
852  rb_hash_foreach(hash, collect_values_of_values, hash);
853 
854  return hash;
855 }
856 
857 static VALUE
858 wrap_klass_iow(VALUE klass)
859 {
860  if (!RTEST(klass)) {
861  return Qnil;
862  }
863  else if (RB_TYPE_P(klass, T_ICLASS)) {
864  return iow_newobj(klass);
865  }
866  else {
867  return klass;
868  }
869 }
870 
871 /*
872  * call-seq:
873  * ObjectSpace.internal_class_of(obj) -> Class or Module
874  *
875  * [MRI specific feature] Return internal class of obj.
876  * obj can be an instance of InternalObjectWrapper.
877  *
878  * Note that you should not use this method in your application.
879  */
880 static VALUE
881 objspace_internal_class_of(VALUE self, VALUE obj)
882 {
883  VALUE klass;
884 
885  if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
886  obj = (VALUE)DATA_PTR(obj);
887  }
888 
889  klass = CLASS_OF(obj);
890  return wrap_klass_iow(klass);
891 }
892 
893 /*
894  * call-seq:
895  * ObjectSpace.internal_super_of(cls) -> Class or Module
896  *
897  * [MRI specific feature] Return internal super class of cls (Class or Module).
898  * obj can be an instance of InternalObjectWrapper.
899  *
900  * Note that you should not use this method in your application.
901  */
902 static VALUE
903 objspace_internal_super_of(VALUE self, VALUE obj)
904 {
905  VALUE super;
906 
907  if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
908  obj = (VALUE)DATA_PTR(obj);
909  }
910 
911  switch (OBJ_BUILTIN_TYPE(obj)) {
912  case T_MODULE:
913  case T_CLASS:
914  case T_ICLASS:
915  super = RCLASS_SUPER(obj);
916  break;
917  default:
918  rb_raise(rb_eArgError, "class or module is expected");
919  }
920 
921  return wrap_klass_iow(super);
922 }
923 
924 void Init_object_tracing(VALUE rb_mObjSpace);
925 void Init_objspace_dump(VALUE rb_mObjSpace);
926 
927 /*
928  * Document-module: ObjectSpace
929  *
930  * The objspace library extends the ObjectSpace module and adds several
931  * methods to get internal statistic information about
932  * object/memory management.
933  *
934  * You need to <code>require 'objspace'</code> to use this extension module.
935  *
936  * Generally, you *SHOULD NOT* use this library if you do not know
937  * about the MRI implementation. Mainly, this library is for (memory)
938  * profiler developers and MRI developers who need to know about MRI
939  * memory usage.
940  */
941 
942 void
944 {
945 #undef rb_intern
946  VALUE rb_mObjSpace;
947 #if 0
948  rb_mObjSpace = rb_define_module("ObjectSpace"); /* let rdoc know */
949 #endif
950  rb_mObjSpace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
951 
952  rb_define_module_function(rb_mObjSpace, "memsize_of", memsize_of_m, 1);
953  rb_define_module_function(rb_mObjSpace, "memsize_of_all", memsize_of_all_m, -1);
954 
955  rb_define_module_function(rb_mObjSpace, "count_objects_size", count_objects_size, -1);
956  rb_define_module_function(rb_mObjSpace, "count_symbols", count_symbols, -1);
957  rb_define_module_function(rb_mObjSpace, "count_nodes", count_nodes, -1);
958  rb_define_module_function(rb_mObjSpace, "count_tdata_objects", count_tdata_objects, -1);
959  rb_define_module_function(rb_mObjSpace, "count_imemo_objects", count_imemo_objects, -1);
960 
961  rb_define_module_function(rb_mObjSpace, "reachable_objects_from", reachable_objects_from, 1);
962  rb_define_module_function(rb_mObjSpace, "reachable_objects_from_root", reachable_objects_from_root, 0);
963 
964  rb_define_module_function(rb_mObjSpace, "internal_class_of", objspace_internal_class_of, 1);
965  rb_define_module_function(rb_mObjSpace, "internal_super_of", objspace_internal_super_of, 1);
966 
967  /*
968  * This class is used as a return value from
969  * ObjectSpace::reachable_objects_from.
970  *
971  * When ObjectSpace::reachable_objects_from returns an object with
972  * references to an internal object, an instance of this class is returned.
973  *
974  * You can use the #type method to check the type of the internal object.
975  */
976  rb_mInternalObjectWrapper = rb_define_class_under(rb_mObjSpace, "InternalObjectWrapper", rb_cObject);
977  rb_define_method(rb_mInternalObjectWrapper, "type", iow_type, 0);
978  rb_define_method(rb_mInternalObjectWrapper, "inspect", iow_inspect, 0);
979  rb_define_method(rb_mInternalObjectWrapper, "internal_object_id", iow_internal_object_id, 0);
980 
981  Init_object_tracing(rb_mObjSpace);
982  Init_objspace_dump(rb_mObjSpace);
983 }
NODE_NEXT
@ NODE_NEXT
Definition: node.h:47
dynamic_symbol_counts::immortal
size_t immortal
Definition: objspace.c:249
NODE_COLON3
@ NODE_COLON3
Definition: node.h:119
i
uint32_t i
Definition: rb_mjit_min_header-2.7.1.h:5425
NODE_NIL
@ NODE_NIL
Definition: node.h:125
ID
unsigned long ID
Definition: ruby.h:103
T_FALSE
#define T_FALSE
Definition: ruby.h:537
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.1.h:5703
NODE_ATTRASGN
@ NODE_ATTRASGN
Definition: node.h:132
T_FLOAT
#define T_FLOAT
Definition: ruby.h:527
dynamic_symbol_counts
Definition: objspace.c:247
NODE_DSYM
@ NODE_DSYM
Definition: node.h:131
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
NODE_HSHPTN
@ NODE_HSHPTN
Definition: node.h:135
NODE_RESCUE
@ NODE_RESCUE
Definition: node.h:51
rb_objspace_data_type_name
const char * rb_objspace_data_type_name(VALUE obj)
Definition: gc.c:2432
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.1.h:13179
st_data_t
unsigned long st_data_t
Definition: rb_mjit_min_header-2.7.1.h:5324
NODE_OP_ASGN1
@ NODE_OP_ASGN1
Definition: node.h:64
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:717
ruby_value_type
ruby_value_type
Definition: ruby.h:486
rofr_data::last_category_str
VALUE last_category_str
Definition: objspace.c:794
rb_ident_hash_new
VALUE rb_ident_hash_new(void)
Definition: hash.c:4272
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:1523
NODE_TRUE
@ NODE_TRUE
Definition: node.h:126
NODE_MATCH3
@ NODE_MATCH3
Definition: node.h:92
NODE_NTH_REF
@ NODE_NTH_REF
Definition: node.h:88
NODE_ZLIST
@ NODE_ZLIST
Definition: node.h:77
NODE_DREGX
@ NODE_DREGX
Definition: node.h:99
IMEMO_MASK
#define IMEMO_MASK
Definition: internal.h:1145
gc.h
NODE_OR
@ NODE_OR
Definition: node.h:55
NODE_ARYPTN
@ NODE_ARYPTN
Definition: node.h:134
NODE_OP_ASGN_OR
@ NODE_OP_ASGN_OR
Definition: node.h:67
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
n
const char size_t n
Definition: rb_mjit_min_header-2.7.1.h:5417
T_MASK
#define T_MASK
Definition: md5.c:131
NODE_HASH
@ NODE_HASH
Definition: node.h:79
OBJ_BUILTIN_TYPE
#define OBJ_BUILTIN_TYPE(obj)
Definition: internal.h:2602
NODE_CONST
@ NODE_CONST
Definition: node.h:86
re.h
NODE_LASGN
@ NODE_LASGN
Definition: node.h:57
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:2032
st_init_numtable
st_table * st_init_numtable(void)
Definition: st.c:653
NODE_FLIP2
@ NODE_FLIP2
Definition: node.h:122
NODE_ARGSPUSH
@ NODE_ARGSPUSH
Definition: node.h:107
NODE_FOR
@ NODE_FOR
Definition: node.h:44
VALUE
unsigned long VALUE
Definition: ruby.h:102
NODE_CASE
@ NODE_CASE
Definition: node.h:36
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
rb_intern
#define rb_intern(str)
NODE_OP_ASGN2
@ NODE_OP_ASGN2
Definition: node.h:65
NODE_ARGSCAT
@ NODE_ARGSCAT
Definition: node.h:106
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
NODE_DOT2
@ NODE_DOT2
Definition: node.h:120
NODE_EVSTR
@ NODE_EVSTR
Definition: node.h:98
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:772
ID_SCOPE_MASK
#define ID_SCOPE_MASK
Definition: id.h:32
NODE_UNTIL
@ NODE_UNTIL
Definition: node.h:42
RSYMBOL
#define RSYMBOL(obj)
Definition: symbol.h:33
NODE_CVASGN
@ NODE_CVASGN
Definition: node.h:63
NODE_AND
@ NODE_AND
Definition: node.h:54
NODE_LIT
@ NODE_LIT
Definition: node.h:93
rof_data::internals
VALUE internals
Definition: objspace.c:698
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.1.h:5562
NODE_MASGN
@ NODE_MASGN
Definition: node.h:56
T_RATIONAL
#define T_RATIONAL
Definition: ruby.h:541
NODE_DXSTR
@ NODE_DXSTR
Definition: node.h:97
NODE_OPCALL
@ NODE_OPCALL
Definition: node.h:70
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
ptr
struct RIMemo * ptr
Definition: debug.c:74
rb_obj_id
VALUE rb_obj_id(VALUE obj)
Definition: gc.c:3772
T_DATA
#define T_DATA
Definition: ruby.h:538
rb_objspace_reachable_objects_from
void rb_objspace_reachable_objects_from(VALUE obj, void(func)(VALUE, void *), void *data)
Definition: gc.c:9467
rofr_data::last_category
const char * last_category
Definition: objspace.c:793
NODE_OP_ASGN_AND
@ NODE_OP_ASGN_AND
Definition: node.h:66
T_NODE
#define T_NODE
Definition: ruby.h:545
NODE_DASGN
@ NODE_DASGN
Definition: node.h:58
rofr_data::categories
VALUE categories
Definition: objspace.c:792
NODE_BLOCK
@ NODE_BLOCK
Definition: node.h:33
st.h
T_COMPLEX
#define T_COMPLEX
Definition: ruby.h:542
NODE_ERRINFO
@ NODE_ERRINFO
Definition: node.h:128
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
NODE_KW_ARG
@ NODE_KW_ARG
Definition: node.h:104
NODE_DSTR
@ NODE_DSTR
Definition: node.h:95
st_insert
int st_insert(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1171
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
T_SYMBOL
#define T_SYMBOL
Definition: ruby.h:540
T_OBJECT
#define T_OBJECT
Definition: ruby.h:523
NODE_SPLAT
@ NODE_SPLAT
Definition: node.h:108
NODE_ITER
@ NODE_ITER
Definition: node.h:43
NODE_CDECL
@ NODE_CDECL
Definition: node.h:62
NODE_CVAR
@ NODE_CVAR
Definition: node.h:87
NODE_IN
@ NODE_IN
Definition: node.h:40
NODE_ZSUPER
@ NODE_ZSUPER
Definition: node.h:75
rb_sym_immortal_count
size_t rb_sym_immortal_count(void)
Definition: symbol.c:848
NODE_LAMBDA
@ NODE_LAMBDA
Definition: node.h:133
NODE_SUPER
@ NODE_SUPER
Definition: node.h:74
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
NODE_VCALL
@ NODE_VCALL
Definition: node.h:72
NODE_VALIAS
@ NODE_VALIAS
Definition: node.h:113
T_FILE
#define T_FILE
Definition: ruby.h:534
NODE_DEFS
@ NODE_DEFS
Definition: node.h:111
NODE_UNLESS
@ NODE_UNLESS
Definition: node.h:35
T_ICLASS
#define T_ICLASS
Definition: ruby.h:525
imemo_type
imemo_type
Definition: internal.h:1132
rb_objspace_markable_object_p
int rb_objspace_markable_object_p(VALUE obj)
Definition: gc.c:3600
NODE_DEFN
@ NODE_DEFN
Definition: node.h:110
rb_objspace_internal_object_p
int rb_objspace_internal_object_p(VALUE obj)
Definition: gc.c:3097
DATA_PTR
#define DATA_PTR(dta)
Definition: ruby.h:1175
rof_data::refs
st_table * refs
Definition: objspace.c:697
node.h
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:535
COUNT_NODE
#define COUNT_NODE(n)
rofr_data
Definition: objspace.c:791
NODE_CLASS
@ NODE_CLASS
Definition: node.h:115
RHASH_EMPTY_P
#define RHASH_EMPTY_P(h)
Definition: ruby.h:1131
NODE_IF
@ NODE_IF
Definition: node.h:34
NODE_ENSURE
@ NODE_ENSURE
Definition: node.h:53
NODE_MATCH2
@ NODE_MATCH2
Definition: node.h:91
T_REGEXP
#define T_REGEXP
Definition: ruby.h:529
Init_object_tracing
void Init_object_tracing(VALUE rb_mObjSpace)
Definition: object_tracing.c:482
rb_hash_lookup
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:2058
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
NODE_CASE3
@ NODE_CASE3
Definition: node.h:38
TypedData_Wrap_Struct
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:1231
NODE_DASGN_CURR
@ NODE_DASGN_CURR
Definition: node.h:59
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
NODE_COLON2
@ NODE_COLON2
Definition: node.h:118
NODE_DOT3
@ NODE_DOT3
Definition: node.h:121
total_data::klass
VALUE klass
Definition: objspace.c:47
node_type
node_type
Definition: node.h:22
T_CLASS
#define T_CLASS
Definition: ruby.h:524
T_MATCH
#define T_MATCH
Definition: ruby.h:539
NODE_BREAK
@ NODE_BREAK
Definition: node.h:46
NODE_GVAR
@ NODE_GVAR
Definition: node.h:84
NODE_XSTR
@ NODE_XSTR
Definition: node.h:96
symbol.h
dynamic_symbol_counts::mortal
size_t mortal
Definition: objspace.c:248
RCLASS_SUPER
#define RCLASS_SUPER(c)
Definition: classext.h:16
NODE_ARGS
@ NODE_ARGS
Definition: node.h:101
NODE_DVAR
@ NODE_DVAR
Definition: node.h:83
rb_hash_foreach
void rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
Definition: hash.c:1483
NODE_ALIAS
@ NODE_ALIAS
Definition: node.h:112
T_NONE
#define T_NONE
Definition: ruby.h:521
NODE_OP_CDECL
@ NODE_OP_CDECL
Definition: node.h:68
key
key
Definition: openssl_missing.h:181
T_HASH
#define T_HASH
Definition: ruby.h:531
NODE_POSTARG
@ NODE_POSTARG
Definition: node.h:105
NODE_SELF
@ NODE_SELF
Definition: node.h:124
NODE_LVAR
@ NODE_LVAR
Definition: node.h:82
rb_typeddata_is_kind_of
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:872
NODE_STR
@ NODE_STR
Definition: node.h:94
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
T_MODULE
#define T_MODULE
Definition: ruby.h:526
st_foreach
int st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
Definition: st.c:1718
rb_define_module_function
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
Definition: class.c:1771
Init_objspace
void Init_objspace(void)
Definition: objspace.c:943
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.1.h:6333
NODE_IVAR
@ NODE_IVAR
Definition: node.h:85
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
NODE_BEGIN
@ NODE_BEGIN
Definition: node.h:50
rb_objspace_each_objects
void rb_objspace_each_objects(each_obj_callback *callback, void *data)
Definition: gc.c:3027
NODE_POSTEXE
@ NODE_POSTEXE
Definition: node.h:130
NODE_RESBODY
@ NODE_RESBODY
Definition: node.h:52
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:634
rb_objspace_reachable_objects_from_root
void rb_objspace_reachable_objects_from_root(void(func)(const char *category, VALUE, void *), void *passing_data)
Definition: gc.c:9495
NODE_RETURN
@ NODE_RETURN
Definition: node.h:80
internal.h
NODE_FALSE
@ NODE_FALSE
Definition: node.h:127
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
argv
char ** argv
Definition: ruby.c:223
NODE_ONCE
@ NODE_ONCE
Definition: node.h:100
ST_CONTINUE
@ ST_CONTINUE
Definition: st.h:99
NODE_IASGN
@ NODE_IASGN
Definition: node.h:61
UNREACHABLE
#define UNREACHABLE
Definition: ruby.h:63
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1197
NODE_ARGS_AUX
@ NODE_ARGS_AUX
Definition: node.h:102
T_NIL
#define T_NIL
Definition: ruby.h:522
T_MOVED
#define T_MOVED
Definition: ruby.h:547
NODE_WHEN
@ NODE_WHEN
Definition: node.h:39
NODE_BLOCK_PASS
@ NODE_BLOCK_PASS
Definition: node.h:109
NODE_MATCH
@ NODE_MATCH
Definition: node.h:90
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
T_ZOMBIE
#define T_ZOMBIE
Definition: ruby.h:546
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2847
NODE_OPT_ARG
@ NODE_OPT_ARG
Definition: node.h:103
NODE_CALL
@ NODE_CALL
Definition: node.h:69
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
NODE_CASE2
@ NODE_CASE2
Definition: node.h:37
io.h
argc
int argc
Definition: ruby.c:222
T_IMEMO
#define T_IMEMO
Definition: ruby.h:543
rb_obj_memsize_of
size_t rb_obj_memsize_of(VALUE obj)
Definition: gc.c:3936
Init_objspace_dump
void Init_objspace_dump(VALUE rb_mObjSpace)
Definition: objspace_dump.c:499
rb_data_type_struct
Definition: ruby.h:1148
BUILTIN_TYPE
#define BUILTIN_TYPE(x)
Definition: ruby.h:551
v
int VALUE v
Definition: rb_mjit_min_header-2.7.1.h:12257
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1267
NODE_FCALL
@ NODE_FCALL
Definition: node.h:71
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:5214
total_data::total
size_t total
Definition: objspace.c:46
NODE_YIELD
@ NODE_YIELD
Definition: node.h:81
CASE_TYPE
#define CASE_TYPE(t)
NODE_UNDEF
@ NODE_UNDEF
Definition: node.h:114
rof_data
Definition: objspace.c:696
NODE_BACK_REF
@ NODE_BACK_REF
Definition: node.h:89
T_STRING
#define T_STRING
Definition: ruby.h:528
NODE_DEFINED
@ NODE_DEFINED
Definition: node.h:129
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:698
rb_sym2str
VALUE rb_sym2str(VALUE)
Definition: symbol.c:784
SIZET2NUM
#define SIZET2NUM(v)
Definition: ruby.h:295
RHASH_TBL
#define RHASH_TBL(h)
Definition: ruby.h:1127
NODE_LAST
@ NODE_LAST
Definition: node.h:136
NODE_VALUES
@ NODE_VALUES
Definition: node.h:78
NODE_FLIP3
@ NODE_FLIP3
Definition: node.h:123
nd_type
#define nd_type(n)
Definition: node.h:188
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
total_data
Definition: objspace.c:45
T_STRUCT
#define T_STRUCT
Definition: ruby.h:532
Qnil
#define Qnil
Definition: ruby.h:469
NODE_REDO
@ NODE_REDO
Definition: node.h:48
rofr_data::last_category_objects
VALUE last_category_objects
Definition: objspace.c:795
NODE_MODULE
@ NODE_MODULE
Definition: node.h:116
st_table
Definition: st.h:79
NODE_QCALL
@ NODE_QCALL
Definition: node.h:73
NODE_SCOPE
@ NODE_SCOPE
Definition: node.h:32
NODE_RETRY
@ NODE_RETRY
Definition: node.h:49
NODE_LIST
@ NODE_LIST
Definition: node.h:76
T_TRUE
#define T_TRUE
Definition: ruby.h:536
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
RTEST
#define RTEST(v)
Definition: ruby.h:481
NODE_FOR_MASGN
@ NODE_FOR_MASGN
Definition: node.h:45
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
RNode
Definition: node.h:149
T_UNDEF
#define T_UNDEF
Definition: ruby.h:544
NODE_WHILE
@ NODE_WHILE
Definition: node.h:41
NODE_SCLASS
@ NODE_SCLASS
Definition: node.h:117
name
const char * name
Definition: nkf.c:208
NODE_GASGN
@ NODE_GASGN
Definition: node.h:60
rb_const_get
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:2387