Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)
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 "gc.h"
16#include "internal.h"
17#include "internal/class.h"
18#include "internal/compilers.h"
19#include "internal/hash.h"
20#include "internal/imemo.h"
21#include "internal/sanitizers.h"
22#include "node.h"
23#include "ruby/io.h"
24#include "ruby/re.h"
25#include "ruby/st.h"
26#include "symbol.h"
27
28#undef rb_funcall
29
30#include "ruby/ruby.h"
31
32/*
33 * call-seq:
34 * ObjectSpace.memsize_of(obj) -> Integer
35 *
36 * Return consuming memory size of obj in bytes.
37 *
38 * Note that the return size is incomplete. You need to deal with this
39 * information as only a *HINT*. Especially, the size of +T_DATA+ may not be
40 * correct.
41 *
42 * This method is only expected to work with C Ruby.
43 *
44 * From Ruby 2.2, memsize_of(obj) returns a memory size includes
45 * sizeof(RVALUE).
46 */
47
48static VALUE
49memsize_of_m(VALUE self, VALUE obj)
50{
51 return SIZET2NUM(rb_obj_memsize_of(obj));
52}
53
54struct total_data {
55 size_t total;
57};
58
59static void
60total_i(VALUE v, void *ptr)
61{
62 struct total_data *data = (struct total_data *)ptr;
63
64 switch (BUILTIN_TYPE(v)) {
65 case T_NONE:
66 case T_IMEMO:
67 case T_ICLASS:
68 case T_NODE:
69 case T_ZOMBIE:
70 return;
71 default:
72 if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
73 data->total += rb_obj_memsize_of(v);
74 }
75 }
76}
77
78typedef void (*each_obj_with_flags)(VALUE, void*);
79
80struct obj_itr {
82 void *data;
83};
84
85static int
86heap_iter(void *vstart, void *vend, size_t stride, void *ptr)
87{
88 struct obj_itr * ctx = (struct obj_itr *)ptr;
89 VALUE v;
90
91 for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
92 void *poisoned = asan_poisoned_object_p(v);
93 asan_unpoison_object(v, false);
94
95 if (RBASIC(v)->flags) {
96 (*ctx->cb)(v, ctx->data);
97 }
98
99 if (poisoned) {
100 asan_poison_object(v);
101 }
102 }
103
104 return 0;
105}
106
107static void
108each_object_with_flags(each_obj_with_flags cb, void *ctx)
109{
110 struct obj_itr data;
111 data.cb = cb;
112 data.data = ctx;
113 rb_objspace_each_objects(heap_iter, &data);
114}
115
116/*
117 * call-seq:
118 * ObjectSpace.memsize_of_all([klass]) -> Integer
119 *
120 * Return consuming memory size of all living objects in bytes.
121 *
122 * If +klass+ (should be Class object) is given, return the total memory size
123 * of instances of the given class.
124 *
125 * Note that the returned size is incomplete. You need to deal with this
126 * information as only a *HINT*. Especially, the size of +T_DATA+ may not be
127 * correct.
128 *
129 * Note that this method does *NOT* return total malloc'ed memory size.
130 *
131 * This method can be defined by the following Ruby code:
132 *
133 * def memsize_of_all klass = false
134 * total = 0
135 * ObjectSpace.each_object{|e|
136 * total += ObjectSpace.memsize_of(e) if klass == false || e.kind_of?(klass)
137 * }
138 * total
139 * end
140 *
141 * This method is only expected to work with C Ruby.
142 */
143
144static VALUE
145memsize_of_all_m(int argc, VALUE *argv, VALUE self)
146{
147 struct total_data data = {0, 0};
148
149 if (argc > 0) {
150 rb_scan_args(argc, argv, "01", &data.klass);
151 }
152
153 each_object_with_flags(total_i, &data);
154 return SIZET2NUM(data.total);
155}
156
157static int
158set_zero_i(st_data_t key, st_data_t val, st_data_t arg)
159{
160 VALUE k = (VALUE)key;
161 VALUE hash = (VALUE)arg;
162 rb_hash_aset(hash, k, INT2FIX(0));
163 return ST_CONTINUE;
164}
165
166static VALUE
167setup_hash(int argc, VALUE *argv)
168{
169 VALUE hash;
170
171 if (rb_scan_args(argc, argv, "01", &hash) == 1) {
172 if (!RB_TYPE_P(hash, T_HASH))
173 rb_raise(rb_eTypeError, "non-hash given");
174 }
175
176 if (hash == Qnil) {
177 hash = rb_hash_new();
178 }
179 else if (!RHASH_EMPTY_P(hash)) {
180 /* WB: no new reference */
181 st_foreach(RHASH_TBL_RAW(hash), set_zero_i, hash);
182 }
183
184 return hash;
185}
186
187static void
188cos_i(VALUE v, void *data)
189{
190 size_t *counts = (size_t *)data;
191 counts[BUILTIN_TYPE(v)] += rb_obj_memsize_of(v);
192}
193
194static VALUE
195type2sym(enum ruby_value_type i)
196{
197 VALUE type;
198 switch (i) {
199#define CASE_TYPE(t) case t: type = ID2SYM(rb_intern(#t)); break;
227#undef CASE_TYPE
228 default: rb_bug("type2sym: unknown type (%d)", i);
229 }
230 return type;
231}
232
233/*
234 * call-seq:
235 * ObjectSpace.count_objects_size([result_hash]) -> hash
236 *
237 * Counts objects size (in bytes) for each type.
238 *
239 * Note that this information is incomplete. You need to deal with
240 * this information as only a *HINT*. Especially, total size of
241 * T_DATA may be wrong.
242 *
243 * It returns a hash as:
244 * {:TOTAL=>1461154, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249, ...}
245 *
246 * If the optional argument, result_hash, is given,
247 * it is overwritten and returned.
248 * This is intended to avoid probe effect.
249 *
250 * The contents of the returned hash is implementation defined.
251 * It may be changed in future.
252 *
253 * This method is only expected to work with C Ruby.
254 */
255
256static VALUE
257count_objects_size(int argc, VALUE *argv, VALUE os)
258{
259 size_t counts[T_MASK+1];
260 size_t total = 0;
261 enum ruby_value_type i;
262 VALUE hash = setup_hash(argc, argv);
263
264 for (i = 0; i <= T_MASK; i++) {
265 counts[i] = 0;
266 }
267
268 each_object_with_flags(cos_i, &counts[0]);
269
270 for (i = 0; i <= T_MASK; i++) {
271 if (counts[i]) {
272 VALUE type = type2sym(i);
273 total += counts[i];
274 rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
275 }
276 }
277 rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
278 return hash;
279}
280
282 size_t mortal;
283 size_t immortal;
284};
285
286static void
287cs_i(VALUE v, void *n)
288{
289 struct dynamic_symbol_counts *counts = (struct dynamic_symbol_counts *)n;
290
291 if (BUILTIN_TYPE(v) == T_SYMBOL) {
292 ID id = RSYMBOL(v)->id;
293 if ((id & ~ID_SCOPE_MASK) == 0) {
294 counts->mortal++;
295 }
296 else {
297 counts->immortal++;
298 }
299 }
300}
301
302size_t rb_sym_immortal_count(void);
303
304/*
305 * call-seq:
306 * ObjectSpace.count_symbols([result_hash]) -> hash
307 *
308 * Counts symbols for each Symbol type.
309 *
310 * This method is only for MRI developers interested in performance and memory
311 * usage of Ruby programs.
312 *
313 * If the optional argument, result_hash, is given, it is overwritten and
314 * returned. This is intended to avoid probe effect.
315 *
316 * Note:
317 * The contents of the returned hash is implementation defined.
318 * It may be changed in future.
319 *
320 * This method is only expected to work with C Ruby.
321 *
322 * On this version of MRI, they have 3 types of Symbols (and 1 total counts).
323 *
324 * * mortal_dynamic_symbol: GC target symbols (collected by GC)
325 * * immortal_dynamic_symbol: Immortal symbols promoted from dynamic symbols (do not collected by GC)
326 * * immortal_static_symbol: Immortal symbols (do not collected by GC)
327 * * immortal_symbol: total immortal symbols (immortal_dynamic_symbol+immortal_static_symbol)
328 */
329
330static VALUE
331count_symbols(int argc, VALUE *argv, VALUE os)
332{
333 struct dynamic_symbol_counts dynamic_counts = {0, 0};
334 VALUE hash = setup_hash(argc, argv);
335
336 size_t immortal_symbols = rb_sym_immortal_count();
337 each_object_with_flags(cs_i, &dynamic_counts);
338
339 rb_hash_aset(hash, ID2SYM(rb_intern("mortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.mortal));
340 rb_hash_aset(hash, ID2SYM(rb_intern("immortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.immortal));
341 rb_hash_aset(hash, ID2SYM(rb_intern("immortal_static_symbol")), SIZET2NUM(immortal_symbols - dynamic_counts.immortal));
342 rb_hash_aset(hash, ID2SYM(rb_intern("immortal_symbol")), SIZET2NUM(immortal_symbols));
343
344 return hash;
345}
346
347static void
348cn_i(VALUE v, void *n)
349{
350 size_t *nodes = (size_t *)n;
351
352 if (BUILTIN_TYPE(v) == T_NODE) {
353 size_t s = nd_type((NODE *)v);
354 nodes[s]++;
355 }
356}
357
358/*
359 * call-seq:
360 * ObjectSpace.count_nodes([result_hash]) -> hash
361 *
362 * Counts nodes for each node type.
363 *
364 * This method is only for MRI developers interested in performance and memory
365 * usage of Ruby programs.
366 *
367 * It returns a hash as:
368 *
369 * {:NODE_METHOD=>2027, :NODE_FBODY=>1927, :NODE_CFUNC=>1798, ...}
370 *
371 * If the optional argument, result_hash, is given, it is overwritten and
372 * returned. This is intended to avoid probe effect.
373 *
374 * Note:
375 * The contents of the returned hash is implementation defined.
376 * It may be changed in future.
377 *
378 * This method is only expected to work with C Ruby.
379 */
380
381static VALUE
382count_nodes(int argc, VALUE *argv, VALUE os)
383{
384 size_t nodes[NODE_LAST+1];
385 enum node_type i;
386 VALUE hash = setup_hash(argc, argv);
387
388 for (i = 0; i <= NODE_LAST; i++) {
389 nodes[i] = 0;
390 }
391
392 each_object_with_flags(cn_i, &nodes[0]);
393
394 for (i=0; i<NODE_LAST; i++) {
395 if (nodes[i] != 0) {
396 VALUE node;
397 switch (i) {
398#define COUNT_NODE(n) case n: node = ID2SYM(rb_intern(#n)); goto set
504#undef COUNT_NODE
505 case NODE_LAST: break;
506 }
508 set:
509 rb_hash_aset(hash, node, SIZET2NUM(nodes[i]));
510 }
511 }
512 return hash;
513}
514
515static void
516cto_i(VALUE v, void *data)
517{
518 VALUE hash = (VALUE)data;
519
520 if (BUILTIN_TYPE(v) == T_DATA) {
521 VALUE counter;
522 VALUE key = RBASIC(v)->klass;
523
524 if (key == 0) {
525 const char *name = rb_objspace_data_type_name(v);
526 if (name == 0) name = "unknown";
528 }
529
530 counter = rb_hash_aref(hash, key);
531 if (NIL_P(counter)) {
532 counter = INT2FIX(1);
533 }
534 else {
535 counter = INT2FIX(FIX2INT(counter) + 1);
536 }
537
538 rb_hash_aset(hash, key, counter);
539 }
540}
541
542/*
543 * call-seq:
544 * ObjectSpace.count_tdata_objects([result_hash]) -> hash
545 *
546 * Counts objects for each +T_DATA+ type.
547 *
548 * This method is only for MRI developers interested in performance and memory
549 * usage of Ruby programs.
550 *
551 * It returns a hash as:
552 *
553 * {RubyVM::InstructionSequence=>504, :parser=>5, :barrier=>6,
554 * :mutex=>6, Proc=>60, RubyVM::Env=>57, Mutex=>1, Encoding=>99,
555 * ThreadGroup=>1, Binding=>1, Thread=>1, RubyVM=>1, :iseq=>1,
556 * Random=>1, ARGF.class=>1, Data=>1, :autoload=>3, Time=>2}
557 * # T_DATA objects existing at startup on r32276.
558 *
559 * If the optional argument, result_hash, is given, it is overwritten and
560 * returned. This is intended to avoid probe effect.
561 *
562 * The contents of the returned hash is implementation specific and may change
563 * in the future.
564 *
565 * In this version, keys are Class object or Symbol object.
566 *
567 * If object is kind of normal (accessible) object, the key is Class object.
568 * If object is not a kind of normal (internal) object, the key is symbol
569 * name, registered by rb_data_type_struct.
570 *
571 * This method is only expected to work with C Ruby.
572 */
573
574static VALUE
575count_tdata_objects(int argc, VALUE *argv, VALUE self)
576{
577 VALUE hash = setup_hash(argc, argv);
578 each_object_with_flags(cto_i, (void *)hash);
579 return hash;
580}
581
582static ID imemo_type_ids[IMEMO_MASK+1];
583
584static void
585count_imemo_objects_i(VALUE v, void *data)
586{
587 VALUE hash = (VALUE)data;
588
589 if (BUILTIN_TYPE(v) == T_IMEMO) {
590 VALUE counter;
591 VALUE key = ID2SYM(imemo_type_ids[imemo_type(v)]);
592
593 counter = rb_hash_aref(hash, key);
594
595 if (NIL_P(counter)) {
596 counter = INT2FIX(1);
597 }
598 else {
599 counter = INT2FIX(FIX2INT(counter) + 1);
600 }
601
602 rb_hash_aset(hash, key, counter);
603 }
604}
605
606/*
607 * call-seq:
608 * ObjectSpace.count_imemo_objects([result_hash]) -> hash
609 *
610 * Counts objects for each +T_IMEMO+ type.
611 *
612 * This method is only for MRI developers interested in performance and memory
613 * usage of Ruby programs.
614 *
615 * It returns a hash as:
616 *
617 * {:imemo_ifunc=>8,
618 * :imemo_svar=>7,
619 * :imemo_cref=>509,
620 * :imemo_memo=>1,
621 * :imemo_throw_data=>1}
622 *
623 * If the optional argument, result_hash, is given, it is overwritten and
624 * returned. This is intended to avoid probe effect.
625 *
626 * The contents of the returned hash is implementation specific and may change
627 * in the future.
628 *
629 * In this version, keys are symbol objects.
630 *
631 * This method is only expected to work with C Ruby.
632 */
633
634static VALUE
635count_imemo_objects(int argc, VALUE *argv, VALUE self)
636{
637 VALUE hash = setup_hash(argc, argv);
638
639 if (imemo_type_ids[0] == 0) {
640 imemo_type_ids[0] = rb_intern("imemo_env");
641 imemo_type_ids[1] = rb_intern("imemo_cref");
642 imemo_type_ids[2] = rb_intern("imemo_svar");
643 imemo_type_ids[3] = rb_intern("imemo_throw_data");
644 imemo_type_ids[4] = rb_intern("imemo_ifunc");
645 imemo_type_ids[5] = rb_intern("imemo_memo");
646 imemo_type_ids[6] = rb_intern("imemo_ment");
647 imemo_type_ids[7] = rb_intern("imemo_iseq");
648 imemo_type_ids[8] = rb_intern("imemo_tmpbuf");
649 imemo_type_ids[9] = rb_intern("imemo_ast");
650 imemo_type_ids[10] = rb_intern("imemo_parser_strterm");
651 imemo_type_ids[11] = rb_intern("imemo_callinfo");
652 imemo_type_ids[12] = rb_intern("imemo_callcache");
653 imemo_type_ids[13] = rb_intern("imemo_constcache");
654 }
655
656 each_object_with_flags(count_imemo_objects_i, (void *)hash);
657
658 return hash;
659}
660
661static void
662iow_mark(void *ptr)
663{
665}
666
667static size_t
668iow_size(const void *ptr)
669{
670 VALUE obj = (VALUE)ptr;
671 return rb_obj_memsize_of(obj);
672}
673
674static const rb_data_type_t iow_data_type = {
675 "ObjectSpace::InternalObjectWrapper",
676 {iow_mark, 0, iow_size,},
678};
679
680static VALUE rb_cInternalObjectWrapper;
681
682static VALUE
683iow_newobj(VALUE obj)
684{
685 return TypedData_Wrap_Struct(rb_cInternalObjectWrapper, &iow_data_type, (void *)obj);
686}
687
688/* Returns the type of the internal object. */
689static VALUE
690iow_type(VALUE self)
691{
692 VALUE obj = (VALUE)DATA_PTR(self);
693 return type2sym(BUILTIN_TYPE(obj));
694}
695
696/* See Object#inspect. */
697static VALUE
698iow_inspect(VALUE self)
699{
700 VALUE obj = (VALUE)DATA_PTR(self);
701 VALUE type = type2sym(BUILTIN_TYPE(obj));
702
703 return rb_sprintf("#<InternalObject:%p %"PRIsVALUE">", (void *)obj, rb_sym2str(type));
704}
705
706/* Returns the Object#object_id of the internal object. */
707static VALUE
708iow_internal_object_id(VALUE self)
709{
710 VALUE obj = (VALUE)DATA_PTR(self);
711 return rb_obj_id(obj);
712}
713
714struct rof_data {
717};
718
719static void
720reachable_object_from_i(VALUE obj, void *data_ptr)
721{
722 struct rof_data *data = (struct rof_data *)data_ptr;
723 VALUE key = obj;
724 VALUE val = obj;
725
728 val = iow_newobj(obj);
729 rb_ary_push(data->internals, val);
730 }
731 rb_hash_aset(data->refs, key, val);
732 }
733}
734
735static int
736collect_values(st_data_t key, st_data_t value, st_data_t data)
737{
738 VALUE ary = (VALUE)data;
739 rb_ary_push(ary, (VALUE)value);
740 return ST_CONTINUE;
741}
742
743/*
744 * call-seq:
745 * ObjectSpace.reachable_objects_from(obj) -> array or nil
746 *
747 * [MRI specific feature] Return all reachable objects from `obj'.
748 *
749 * This method returns all reachable objects from `obj'.
750 *
751 * If `obj' has two or more references to the same object `x', then returned
752 * array only includes one `x' object.
753 *
754 * If `obj' is a non-markable (non-heap management) object such as true,
755 * false, nil, symbols and Fixnums (and Flonum) then it simply returns nil.
756 *
757 * If `obj' has references to an internal object, then it returns instances of
758 * ObjectSpace::InternalObjectWrapper class. This object contains a reference
759 * to an internal object and you can check the type of internal object with
760 * `type' method.
761 *
762 * If `obj' is instance of ObjectSpace::InternalObjectWrapper class, then this
763 * method returns all reachable object from an internal object, which is
764 * pointed by `obj'.
765 *
766 * With this method, you can find memory leaks.
767 *
768 * This method is only expected to work except with C Ruby.
769 *
770 * Example:
771 * ObjectSpace.reachable_objects_from(['a', 'b', 'c'])
772 * #=> [Array, 'a', 'b', 'c']
773 *
774 * ObjectSpace.reachable_objects_from(['a', 'a', 'a'])
775 * #=> [Array, 'a', 'a', 'a'] # all 'a' strings have different object id
776 *
777 * ObjectSpace.reachable_objects_from([v = 'a', v, v])
778 * #=> [Array, 'a']
779 *
780 * ObjectSpace.reachable_objects_from(1)
781 * #=> nil # 1 is not markable (heap managed) object
782 *
783 */
784
785static VALUE
786reachable_objects_from(VALUE self, VALUE obj)
787{
789 struct rof_data data;
790
791 if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
792 obj = (VALUE)DATA_PTR(obj);
793 }
794
795 data.refs = rb_ident_hash_new();
796 data.internals = rb_ary_new();
797
798 rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data);
799
800 return rb_funcall(data.refs, rb_intern("values"), 0);
801 }
802 else {
803 return Qnil;
804 }
805}
806
807struct rofr_data {
809 const char *last_category;
812};
813
814static void
815reachable_object_from_root_i(const char *category, VALUE obj, void *ptr)
816{
817 struct rofr_data *data = (struct rofr_data *)ptr;
818 VALUE category_str;
819 VALUE category_objects;
820
821 if (category == data->last_category) {
822 category_str = data->last_category_str;
823 category_objects = data->last_category_objects;
824 }
825 else {
826 data->last_category = category;
827 category_str = data->last_category_str = rb_str_new2(category);
828 category_objects = data->last_category_objects = rb_ident_hash_new();
829 if (!NIL_P(rb_hash_lookup(data->categories, category_str))) {
830 rb_bug("reachable_object_from_root_i: category should insert at once");
831 }
832 rb_hash_aset(data->categories, category_str, category_objects);
833 }
834
836 obj != data->categories &&
837 obj != data->last_category_objects) {
839 obj = iow_newobj(obj);
840 }
841 rb_hash_aset(category_objects, obj, obj);
842 }
843}
844
845static int
846collect_values_of_values(VALUE category, VALUE category_objects, VALUE categories)
847{
848 VALUE ary = rb_ary_new();
849 rb_hash_foreach(category_objects, collect_values, ary);
850 rb_hash_aset(categories, category, ary);
851 return ST_CONTINUE;
852}
853
854/*
855 * call-seq:
856 * ObjectSpace.reachable_objects_from_root -> hash
857 *
858 * [MRI specific feature] Return all reachable objects from root.
859 */
860static VALUE
861reachable_objects_from_root(VALUE self)
862{
863 struct rofr_data data;
864 VALUE hash = data.categories = rb_ident_hash_new();
865 data.last_category = 0;
866
867 rb_objspace_reachable_objects_from_root(reachable_object_from_root_i, &data);
868 rb_hash_foreach(hash, collect_values_of_values, hash);
869
870 return hash;
871}
872
873static VALUE
874wrap_klass_iow(VALUE klass)
875{
876 if (!RTEST(klass)) {
877 return Qnil;
878 }
879 else if (RB_TYPE_P(klass, T_ICLASS) ||
880 CLASS_OF(klass) == Qfalse /* hidden object */) {
881 return iow_newobj(klass);
882 }
883 else {
884 return klass;
885 }
886}
887
888/*
889 * call-seq:
890 * ObjectSpace.internal_class_of(obj) -> Class or Module
891 *
892 * [MRI specific feature] Return internal class of obj.
893 * obj can be an instance of InternalObjectWrapper.
894 *
895 * Note that you should not use this method in your application.
896 */
897static VALUE
898objspace_internal_class_of(VALUE self, VALUE obj)
899{
900 VALUE klass;
901
902 if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
903 obj = (VALUE)DATA_PTR(obj);
904 }
905
906 if (RB_TYPE_P(obj, T_IMEMO)) {
907 return Qnil;
908 }
909 else {
910 klass = CLASS_OF(obj);
911 return wrap_klass_iow(klass);
912 }
913}
914
915/*
916 * call-seq:
917 * ObjectSpace.internal_super_of(cls) -> Class or Module
918 *
919 * [MRI specific feature] Return internal super class of cls (Class or Module).
920 * obj can be an instance of InternalObjectWrapper.
921 *
922 * Note that you should not use this method in your application.
923 */
924static VALUE
925objspace_internal_super_of(VALUE self, VALUE obj)
926{
927 VALUE super;
928
929 if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
930 obj = (VALUE)DATA_PTR(obj);
931 }
932
933 switch (OBJ_BUILTIN_TYPE(obj)) {
934 case T_MODULE:
935 case T_CLASS:
936 case T_ICLASS:
937 super = RCLASS_SUPER(obj);
938 break;
939 default:
940 rb_raise(rb_eArgError, "class or module is expected");
941 }
942
943 return wrap_klass_iow(super);
944}
945
946void Init_object_tracing(VALUE rb_mObjSpace);
947void Init_objspace_dump(VALUE rb_mObjSpace);
948
949/*
950 * Document-module: ObjectSpace
951 *
952 * The objspace library extends the ObjectSpace module and adds several
953 * methods to get internal statistic information about
954 * object/memory management.
955 *
956 * You need to <code>require 'objspace'</code> to use this extension module.
957 *
958 * Generally, you *SHOULD NOT* use this library if you do not know
959 * about the MRI implementation. Mainly, this library is for (memory)
960 * profiler developers and MRI developers who need to know about MRI
961 * memory usage.
962 */
963
964void
966{
967#undef rb_intern
968 VALUE rb_mObjSpace;
969#if 0
970 rb_mObjSpace = rb_define_module("ObjectSpace"); /* let rdoc know */
971#endif
972 rb_mObjSpace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
973
974 rb_define_module_function(rb_mObjSpace, "memsize_of", memsize_of_m, 1);
975 rb_define_module_function(rb_mObjSpace, "memsize_of_all", memsize_of_all_m, -1);
976
977 rb_define_module_function(rb_mObjSpace, "count_objects_size", count_objects_size, -1);
978 rb_define_module_function(rb_mObjSpace, "count_symbols", count_symbols, -1);
979 rb_define_module_function(rb_mObjSpace, "count_nodes", count_nodes, -1);
980 rb_define_module_function(rb_mObjSpace, "count_tdata_objects", count_tdata_objects, -1);
981 rb_define_module_function(rb_mObjSpace, "count_imemo_objects", count_imemo_objects, -1);
982
983 rb_define_module_function(rb_mObjSpace, "reachable_objects_from", reachable_objects_from, 1);
984 rb_define_module_function(rb_mObjSpace, "reachable_objects_from_root", reachable_objects_from_root, 0);
985
986 rb_define_module_function(rb_mObjSpace, "internal_class_of", objspace_internal_class_of, 1);
987 rb_define_module_function(rb_mObjSpace, "internal_super_of", objspace_internal_super_of, 1);
988
989 /*
990 * This class is used as a return value from
991 * ObjectSpace::reachable_objects_from.
992 *
993 * When ObjectSpace::reachable_objects_from returns an object with
994 * references to an internal object, an instance of this class is returned.
995 *
996 * You can use the #type method to check the type of the internal object.
997 */
998 rb_cInternalObjectWrapper = rb_define_class_under(rb_mObjSpace, "InternalObjectWrapper", rb_cObject);
999 rb_undef_alloc_func(rb_cInternalObjectWrapper);
1000 rb_define_method(rb_cInternalObjectWrapper, "type", iow_type, 0);
1001 rb_define_method(rb_cInternalObjectWrapper, "inspect", iow_inspect, 0);
1002 rb_define_method(rb_cInternalObjectWrapper, "internal_object_id", iow_internal_object_id, 0);
1003
1004 Init_object_tracing(rb_mObjSpace);
1005 Init_objspace_dump(rb_mObjSpace);
1006}
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1301
VALUE rb_ary_new(void)
Definition: array.c:749
#define UNREACHABLE
Definition: assume.h:30
Internal header absorbing C compipler differences.
#define OBJ_BUILTIN_TYPE(obj)
Definition: compilers.h:68
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:653
#define rb_define_module_function(klass, mid, func, arity)
Defines klass#mid and makes it a module function.
Definition: cxxanyargs.hpp:672
struct RIMemo * ptr
Definition: debug.c:88
#define PRIsVALUE
Definition: function.c:10
int rb_objspace_internal_object_p(VALUE obj)
Definition: gc.c:3355
VALUE rb_obj_id(VALUE obj)
Definition: gc.c:4110
size_t rb_obj_memsize_of(VALUE obj)
Definition: gc.c:4296
void rb_objspace_reachable_objects_from(VALUE obj, void(func)(VALUE, void *), void *data)
Definition: gc.c:10169
const char * rb_objspace_data_type_name(VALUE obj)
Definition: gc.c:2534
int rb_objspace_markable_object_p(VALUE obj)
Definition: gc.c:3926
void rb_gc_mark(VALUE ptr)
Definition: gc.c:6112
void rb_objspace_each_objects(each_obj_callback *callback, void *data)
Definition: gc.c:3285
void rb_objspace_reachable_objects_from_root(void(func)(const char *category, VALUE, void *), void *passing_data)
Definition: gc.c:10202
#define CLASS_OF
Definition: globals.h:153
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:797
VALUE rb_define_module(const char *name)
Definition: class.c:871
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2296
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2917
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:1007
void rb_bug(const char *fmt,...)
Definition: error.c:768
VALUE rb_ident_hash_new(void)
Definition: hash.c:4443
VALUE rb_eTypeError
Definition: error.c:1057
VALUE rb_eArgError
Definition: error.c:1058
VALUE rb_cObject
Object class.
Definition: object.c:49
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:724
void rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
Definition: hash.c:1498
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:2046
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2901
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:2072
VALUE rb_hash_new(void)
Definition: hash.c:1538
#define ID_SCOPE_MASK
Definition: id.h:32
IMEMO: Internal memo object.
#define IMEMO_MASK
Definition: imemo.h:23
imemo_type
Definition: imemo.h:34
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:1077
#define rb_str_new2
Definition: string.h:276
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:2624
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:954
#define ID2SYM
Definition: symbol.h:44
VALUE rb_sym2str(VALUE)
Definition: symbol.c:927
ID rb_intern(const char *)
Definition: symbol.c:785
#define FIX2INT
Definition: int.h:41
Internal header for Class.
Internal header for GC.
Internal header for Hash.
#define RHASH_TBL_RAW(h)
Definition: hash.h:118
#define INT2FIX
Definition: long.h:48
#define T_MASK
Definition: md5.c:131
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:56
const char * name
Definition: nkf.c:208
node_type
Definition: node.h:21
@ NODE_OR
Definition: node.h:45
@ NODE_LVAR
Definition: node.h:72
@ NODE_FOR
Definition: node.h:34
@ NODE_OP_ASGN_OR
Definition: node.h:57
@ NODE_SPLAT
Definition: node.h:98
@ NODE_DEFS
Definition: node.h:101
@ NODE_REDO
Definition: node.h:38
@ NODE_IN
Definition: node.h:30
@ NODE_MATCH
Definition: node.h:80
@ NODE_MATCH2
Definition: node.h:81
@ NODE_STR
Definition: node.h:84
@ NODE_DSYM
Definition: node.h:121
@ NODE_DASGN_CURR
Definition: node.h:49
@ NODE_LIST
Definition: node.h:66
@ NODE_CVAR
Definition: node.h:77
@ NODE_NEXT
Definition: node.h:37
@ NODE_MODULE
Definition: node.h:106
@ NODE_ARGSCAT
Definition: node.h:96
@ NODE_DASGN
Definition: node.h:48
@ NODE_LASGN
Definition: node.h:47
@ NODE_AND
Definition: node.h:44
@ NODE_MASGN
Definition: node.h:46
@ NODE_CLASS
Definition: node.h:105
@ NODE_CVASGN
Definition: node.h:53
@ NODE_CALL
Definition: node.h:59
@ NODE_OP_ASGN2
Definition: node.h:55
@ NODE_FALSE
Definition: node.h:117
@ NODE_FLIP2
Definition: node.h:112
@ NODE_EVSTR
Definition: node.h:88
@ NODE_DVAR
Definition: node.h:73
@ NODE_ATTRASGN
Definition: node.h:122
@ NODE_BEGIN
Definition: node.h:40
@ NODE_UNTIL
Definition: node.h:32
@ NODE_FCALL
Definition: node.h:61
@ NODE_MATCH3
Definition: node.h:82
@ NODE_LAST
Definition: node.h:127
@ NODE_SUPER
Definition: node.h:64
@ NODE_CASE2
Definition: node.h:27
@ NODE_DXSTR
Definition: node.h:87
@ NODE_IASGN
Definition: node.h:51
@ NODE_GASGN
Definition: node.h:50
@ NODE_OP_CDECL
Definition: node.h:58
@ NODE_RESCUE
Definition: node.h:41
@ NODE_SCOPE
Definition: node.h:22
@ NODE_SCLASS
Definition: node.h:107
@ NODE_HASH
Definition: node.h:69
@ NODE_YIELD
Definition: node.h:71
@ NODE_LAMBDA
Definition: node.h:123
@ NODE_CDECL
Definition: node.h:52
@ NODE_OP_ASGN_AND
Definition: node.h:56
@ NODE_BLOCK
Definition: node.h:23
@ NODE_TRUE
Definition: node.h:116
@ NODE_ARGS_AUX
Definition: node.h:92
@ NODE_CASE
Definition: node.h:26
@ NODE_ITER
Definition: node.h:33
@ NODE_RETRY
Definition: node.h:39
@ NODE_DOT3
Definition: node.h:111
@ NODE_RETURN
Definition: node.h:70
@ NODE_BACK_REF
Definition: node.h:79
@ NODE_QCALL
Definition: node.h:63
@ NODE_ENSURE
Definition: node.h:43
@ NODE_SELF
Definition: node.h:114
@ NODE_DOT2
Definition: node.h:110
@ NODE_OPT_ARG
Definition: node.h:93
@ NODE_FNDPTN
Definition: node.h:126
@ NODE_LIT
Definition: node.h:83
@ NODE_UNDEF
Definition: node.h:104
@ NODE_FLIP3
Definition: node.h:113
@ NODE_POSTARG
Definition: node.h:95
@ NODE_NTH_REF
Definition: node.h:78
@ NODE_VCALL
Definition: node.h:62
@ NODE_KW_ARG
Definition: node.h:94
@ NODE_DEFN
Definition: node.h:100
@ NODE_GVAR
Definition: node.h:74
@ NODE_ALIAS
Definition: node.h:102
@ NODE_COLON2
Definition: node.h:108
@ NODE_POSTEXE
Definition: node.h:120
@ NODE_IVAR
Definition: node.h:75
@ NODE_ERRINFO
Definition: node.h:118
@ NODE_BLOCK_PASS
Definition: node.h:99
@ NODE_ZSUPER
Definition: node.h:65
@ NODE_DREGX
Definition: node.h:89
@ NODE_DEFINED
Definition: node.h:119
@ NODE_ONCE
Definition: node.h:90
@ NODE_IF
Definition: node.h:24
@ NODE_HSHPTN
Definition: node.h:125
@ NODE_ZLIST
Definition: node.h:67
@ NODE_ARYPTN
Definition: node.h:124
@ NODE_XSTR
Definition: node.h:86
@ NODE_BREAK
Definition: node.h:36
@ NODE_UNLESS
Definition: node.h:25
@ NODE_VALIAS
Definition: node.h:103
@ NODE_WHEN
Definition: node.h:29
@ NODE_CASE3
Definition: node.h:28
@ NODE_COLON3
Definition: node.h:109
@ NODE_CONST
Definition: node.h:76
@ NODE_NIL
Definition: node.h:115
@ NODE_VALUES
Definition: node.h:68
@ NODE_RESBODY
Definition: node.h:42
@ NODE_DSTR
Definition: node.h:85
@ NODE_FOR_MASGN
Definition: node.h:35
@ NODE_WHILE
Definition: node.h:31
@ NODE_ARGSPUSH
Definition: node.h:97
@ NODE_OP_ASGN1
Definition: node.h:54
@ NODE_OPCALL
Definition: node.h:60
@ NODE_ARGS
Definition: node.h:91
#define nd_type(n)
Definition: node.h:188
void(* each_obj_with_flags)(VALUE, void *)
Definition: objspace.c:78
void Init_object_tracing(VALUE rb_mObjSpace)
void Init_objspace_dump(VALUE rb_mObjSpace)
size_t rb_sym_immortal_count(void)
Definition: symbol.c:998
#define COUNT_NODE(n)
void Init_objspace(void)
Definition: objspace.c:965
#define CASE_TYPE(t)
#define RBASIC(obj)
Definition: rbasic.h:34
#define RCLASS_SUPER
Definition: rclass.h:33
#define DATA_PTR(obj)
Definition: rdata.h:56
#define RHASH_EMPTY_P(h)
Definition: rhash.h:51
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: rtypeddata.h:101
@ RUBY_TYPED_FREE_IMMEDIATELY
Definition: rtypeddata.h:62
int argc
Definition: ruby.c:240
char ** argv
Definition: ruby.c:241
Internal header for ASAN / MSAN / etc.
#define SIZET2NUM
Definition: size_t.h:52
#define RTEST
#define Qnil
#define Qfalse
#define NIL_P
VALUE rb_sprintf(const char *,...)
Definition: sprintf.c:1203
@ ST_CONTINUE
Definition: st.h:99
unsigned long st_data_t
Definition: st.h:22
#define st_foreach
Definition: st.h:142
Definition: node.h:149
void * data
Definition: objspace.c:82
each_obj_with_flags cb
Definition: objspace.c:81
VALUE internals
Definition: objspace.c:716
VALUE refs
Definition: objspace.c:715
VALUE categories
Definition: objspace.c:808
VALUE last_category_str
Definition: objspace.c:810
const char * last_category
Definition: objspace.c:809
VALUE last_category_objects
Definition: objspace.c:811
size_t total
Definition: objspace.c:55
VALUE klass
Definition: objspace.c:56
#define RSYMBOL(obj)
Definition: symbol.h:33
unsigned long VALUE
Definition: value.h:38
unsigned long ID
Definition: value.h:39
#define T_COMPLEX
Definition: value_type.h:58
#define T_FILE
Definition: value_type.h:61
#define T_STRING
Definition: value_type.h:77
#define T_NIL
Definition: value_type.h:71
#define T_FLOAT
Definition: value_type.h:63
#define T_IMEMO
Definition: value_type.h:66
#define T_BIGNUM
Definition: value_type.h:56
#define T_STRUCT
Definition: value_type.h:78
#define T_FIXNUM
Definition: value_type.h:62
#define T_DATA
Definition: value_type.h:59
#define T_NONE
Definition: value_type.h:73
#define T_NODE
Definition: value_type.h:72
#define T_MODULE
Definition: value_type.h:69
#define T_TRUE
Definition: value_type.h:80
#define T_RATIONAL
Definition: value_type.h:75
#define T_ICLASS
Definition: value_type.h:65
#define T_HASH
Definition: value_type.h:64
#define T_FALSE
Definition: value_type.h:60
#define T_UNDEF
Definition: value_type.h:81
#define T_ZOMBIE
Definition: value_type.h:82
#define T_ARRAY
Definition: value_type.h:55
#define T_OBJECT
Definition: value_type.h:74
#define T_SYMBOL
Definition: value_type.h:79
#define T_MATCH
Definition: value_type.h:68
#define T_CLASS
Definition: value_type.h:57
#define BUILTIN_TYPE
Definition: value_type.h:84
#define T_MOVED
Definition: value_type.h:70
ruby_value_type
C-level type of an object.
Definition: value_type.h:110
#define T_REGEXP
Definition: value_type.h:76