Ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
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
39static VALUE
40memsize_of_m(VALUE self, VALUE obj)
41{
43}
44
45struct total_data {
46 size_t total;
48};
49
50static int
51total_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
104static VALUE
105memsize_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
117static int
118set_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
126static VALUE
127setup_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
146static int
147cos_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
160static VALUE
161type2sym(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;
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
222static VALUE
223count_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
252static int
253cs_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
273size_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
301static VALUE
302count_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
318static int
319cn_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
357static VALUE
358count_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 }
483 set:
484 rb_hash_aset(hash, node, SIZET2NUM(nodes[i]));
485 }
486 }
487 return hash;
488}
489
490static int
491cto_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";
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
554static VALUE
555count_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
562static ID imemo_type_ids[IMEMO_MASK+1];
563
564static int
565count_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
619static VALUE
620count_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
643static void
644iow_mark(void *ptr)
645{
647}
648
649static size_t
650iow_size(const void *ptr)
651{
652 VALUE obj = (VALUE)ptr;
653 return rb_obj_memsize_of(obj);
654}
655
656static const rb_data_type_t iow_data_type = {
657 "ObjectSpace::InternalObjectWrapper",
658 {iow_mark, 0, iow_size,},
660};
661
662static VALUE rb_mInternalObjectWrapper;
663
664static VALUE
665iow_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. */
671static VALUE
672iow_type(VALUE self)
673{
674 VALUE obj = (VALUE)DATA_PTR(self);
675 return type2sym(BUILTIN_TYPE(obj));
676}
677
678/* See Object#inspect. */
679static VALUE
680iow_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. */
689static VALUE
690iow_internal_object_id(VALUE self)
691{
692 VALUE obj = (VALUE)DATA_PTR(self);
693 return rb_obj_id(obj);
694}
695
696struct rof_data {
699};
700
701static void
702reachable_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
717static int
718collect_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
767static VALUE
768reachable_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
791struct rofr_data {
793 const char *last_category;
796};
797
798static void
799reachable_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
829static int
830collect_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 */
844static VALUE
845reachable_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
857static VALUE
858wrap_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 */
880static VALUE
881objspace_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 */
902static VALUE
903objspace_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
924void Init_object_tracing(VALUE rb_mObjSpace);
925void 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
942void
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}
struct RIMemo * ptr
Definition: debug.c:65
VALUE rb_define_class_under(VALUE, const char *, VALUE)
Defines a class under the namespace of outer.
Definition: class.c:711
VALUE rb_define_module(const char *)
Definition: class.c:785
VALUE rb_cObject
Object class.
Definition: ruby.h:2012
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:874
void rb_bug(const char *fmt,...)
Definition: error.c:636
VALUE rb_eTypeError
Definition: error.c:924
VALUE rb_eArgError
Definition: error.c:925
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
const char * name
Definition: nkf.c:208
void Init_object_tracing(VALUE rb_mObjSpace)
void Init_objspace_dump(VALUE rb_mObjSpace)
size_t rb_sym_immortal_count(void)
Definition: symbol.c:848
#define COUNT_NODE(n)
void Init_objspace(void)
Definition: objspace.c:943
#define CASE_TYPE(t)
#define rb_str_new2
VALUE rb_hash_lookup(VALUE, VALUE)
Definition: hash.c:2063
void rb_hash_foreach(VALUE, int(*)(VALUE, VALUE, VALUE), VALUE)
#define T_COMPLEX
int rb_objspace_internal_object_p(VALUE obj)
Definition: gc.c:3110
#define T_FILE
void rb_objspace_each_objects(int(*callback)(void *start, void *end, size_t stride, void *data), void *data)
void rb_objspace_reachable_objects_from_root(void(func)(const char *category, VALUE, void *), void *data)
Definition: gc.c:9509
#define RTEST(v)
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:2391
#define RCLASS_SUPER(c)
unsigned long st_data_t
#define RBASIC(obj)
#define T_STRING
VALUE rb_hash_aref(VALUE, VALUE)
Definition: hash.c:2037
#define T_MASK
size_t rb_obj_memsize_of(VALUE)
Definition: gc.c:3950
const VALUE VALUE obj
#define OBJ_BUILTIN_TYPE(obj)
#define T_NIL
#define UNREACHABLE
#define T_FLOAT
#define T_IMEMO
#define T_BIGNUM
VALUE rb_ident_hash_new(void)
Definition: hash.c:4278
#define NIL_P(v)
#define T_STRUCT
#define ID2SYM(x)
#define T_FIXNUM
const char size_t n
#define T_DATA
unsigned long VALUE
VALUE rb_ary_push(VALUE, VALUE)
Definition: array.c:1195
#define T_NONE
#define T_NODE
VALUE rb_sym2str(VALUE)
Definition: symbol.c:784
VALUE rb_obj_id(VALUE)
Definition: gc.c:3786
#define T_MODULE
uint32_t i
void rb_objspace_reachable_objects_from(VALUE obj, void(func)(VALUE, void *), void *data)
Definition: gc.c:9481
#define T_TRUE
#define T_RATIONAL
const char * rb_objspace_data_type_name(VALUE obj)
Definition: gc.c:2445
void rb_define_module_function(VALUE, const char *, VALUE(*)(), int)
#define T_ICLASS
#define T_HASH
#define RUBY_TYPED_FREE_IMMEDIATELY
#define PRIsVALUE
#define FIX2INT(x)
int VALUE v
int rb_objspace_markable_object_p(VALUE obj)
Definition: gc.c:3613
VALUE rb_ary_new(void)
Definition: array.c:723
#define rb_scan_args(argc, argvp, fmt,...)
#define IMEMO_MASK
#define T_FALSE
void rb_gc_mark(VALUE)
Definition: gc.c:5228
#define rb_intern(str)
#define TypedData_Wrap_Struct(klass, data_type, sval)
#define T_UNDEF
#define T_ZOMBIE
#define Qnil
#define DATA_PTR(dta)
#define T_ARRAY
#define T_OBJECT
#define RB_TYPE_P(obj, type)
#define INT2FIX(i)
#define T_SYMBOL
const VALUE * argv
#define T_MATCH
#define T_CLASS
#define CLASS_OF(v)
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
Definition: hash.c:2852
#define T_MOVED
#define RHASH_TBL(h)
#define nd_type(n)
VALUE rb_sprintf(const char *,...) __attribute__((format(printf
unsigned long ID
#define RHASH_EMPTY_P(h)
#define ID_SCOPE_MASK
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
#define BUILTIN_TYPE(x)
VALUE rb_hash_new(void)
Definition: hash.c:1523
#define SIZET2NUM(v)
#define T_REGEXP
st_table * st_init_numtable(void)
Definition: st.c:653
int st_insert(st_table *tab, st_data_t key, st_data_t value)
Definition: st.c:1171
int st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
Definition: st.c:1717
VALUE internals
Definition: objspace.c:698
st_table * refs
Definition: objspace.c:697
VALUE categories
Definition: objspace.c:792
VALUE last_category_str
Definition: objspace.c:794
const char * last_category
Definition: objspace.c:793
VALUE last_category_objects
Definition: objspace.c:795
size_t total
Definition: objspace.c:46
VALUE klass
Definition: objspace.c:47
#define RSYMBOL(obj)
Definition: symbol.h:33