Ruby: ext/objspace/objspace.c Source File

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
54 struct total_data {
55 size_t total;
56 VALUE klass;
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
78 typedef void (*each_obj_with_flags)(VALUE, void*);
79
80 struct obj_itr {
81 each_obj_with_flags cb;
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;
200 CASE_TYPE(T_NONE);
201 CASE_TYPE(T_OBJECT);
202 CASE_TYPE(T_CLASS);
203 CASE_TYPE(T_MODULE);
204 CASE_TYPE(T_FLOAT);
205 CASE_TYPE(T_STRING);
206 CASE_TYPE(T_REGEXP);
207 CASE_TYPE(T_ARRAY);
208 CASE_TYPE(T_HASH);
209 CASE_TYPE(T_STRUCT);
210 CASE_TYPE(T_BIGNUM);
211 CASE_TYPE(T_FILE);
212 CASE_TYPE(T_DATA);
213 CASE_TYPE(T_MATCH);
214 CASE_TYPE(T_COMPLEX);
215 CASE_TYPE(T_RATIONAL);
216 CASE_TYPE(T_NIL);
217 CASE_TYPE(T_TRUE);
218 CASE_TYPE(T_FALSE);
219 CASE_TYPE(T_SYMBOL);
220 CASE_TYPE(T_FIXNUM);
221 CASE_TYPE(T_UNDEF);
222 CASE_TYPE(T_IMEMO);
223 CASE_TYPE(T_NODE);
224 CASE_TYPE(T_ICLASS);
225 CASE_TYPE(T_MOVED);
226 CASE_TYPE(T_ZOMBIE);
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
281 struct dynamic_symbol_counts {
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
399 COUNT_NODE(NODE_SCOPE);
400 COUNT_NODE(NODE_BLOCK);
401 COUNT_NODE(NODE_IF);
402 COUNT_NODE(NODE_UNLESS);
403 COUNT_NODE(NODE_CASE);
404 COUNT_NODE(NODE_CASE2);
405 COUNT_NODE(NODE_CASE3);
406 COUNT_NODE(NODE_WHEN);
407 COUNT_NODE(NODE_IN);
408 COUNT_NODE(NODE_WHILE);
409 COUNT_NODE(NODE_UNTIL);
410 COUNT_NODE(NODE_ITER);
411 COUNT_NODE(NODE_FOR);
412 COUNT_NODE(NODE_FOR_MASGN);
413 COUNT_NODE(NODE_BREAK);
414 COUNT_NODE(NODE_NEXT);
415 COUNT_NODE(NODE_REDO);
416 COUNT_NODE(NODE_RETRY);
417 COUNT_NODE(NODE_BEGIN);
418 COUNT_NODE(NODE_RESCUE);
419 COUNT_NODE(NODE_RESBODY);
420 COUNT_NODE(NODE_ENSURE);
421 COUNT_NODE(NODE_AND);
422 COUNT_NODE(NODE_OR);
423 COUNT_NODE(NODE_MASGN);
424 COUNT_NODE(NODE_LASGN);
425 COUNT_NODE(NODE_DASGN);
426 COUNT_NODE(NODE_DASGN_CURR);
427 COUNT_NODE(NODE_GASGN);
428 COUNT_NODE(NODE_IASGN);
429 COUNT_NODE(NODE_CDECL);
430 COUNT_NODE(NODE_CVASGN);
431 COUNT_NODE(NODE_OP_ASGN1);
432 COUNT_NODE(NODE_OP_ASGN2);
433 COUNT_NODE(NODE_OP_ASGN_AND);
434 COUNT_NODE(NODE_OP_ASGN_OR);
435 COUNT_NODE(NODE_OP_CDECL);
436 COUNT_NODE(NODE_CALL);
437 COUNT_NODE(NODE_OPCALL);
438 COUNT_NODE(NODE_FCALL);
439 COUNT_NODE(NODE_VCALL);
440 COUNT_NODE(NODE_QCALL);
441 COUNT_NODE(NODE_SUPER);
442 COUNT_NODE(NODE_ZSUPER);
443 COUNT_NODE(NODE_LIST);
444 COUNT_NODE(NODE_ZLIST);
445 COUNT_NODE(NODE_VALUES);
446 COUNT_NODE(NODE_HASH);
447 COUNT_NODE(NODE_RETURN);
448 COUNT_NODE(NODE_YIELD);
449 COUNT_NODE(NODE_LVAR);
450 COUNT_NODE(NODE_DVAR);
451 COUNT_NODE(NODE_GVAR);
452 COUNT_NODE(NODE_IVAR);
453 COUNT_NODE(NODE_CONST);
454 COUNT_NODE(NODE_CVAR);
455 COUNT_NODE(NODE_NTH_REF);
456 COUNT_NODE(NODE_BACK_REF);
457 COUNT_NODE(NODE_MATCH);
458 COUNT_NODE(NODE_MATCH2);
459 COUNT_NODE(NODE_MATCH3);
460 COUNT_NODE(NODE_LIT);
461 COUNT_NODE(NODE_STR);
462 COUNT_NODE(NODE_DSTR);
463 COUNT_NODE(NODE_XSTR);
464 COUNT_NODE(NODE_DXSTR);
465 COUNT_NODE(NODE_EVSTR);
466 COUNT_NODE(NODE_DREGX);
467 COUNT_NODE(NODE_ONCE);
468 COUNT_NODE(NODE_ARGS);
469 COUNT_NODE(NODE_ARGS_AUX);
470 COUNT_NODE(NODE_OPT_ARG);
471 COUNT_NODE(NODE_KW_ARG);
472 COUNT_NODE(NODE_POSTARG);
473 COUNT_NODE(NODE_ARGSCAT);
474 COUNT_NODE(NODE_ARGSPUSH);
475 COUNT_NODE(NODE_SPLAT);
476 COUNT_NODE(NODE_BLOCK_PASS);
477 COUNT_NODE(NODE_DEFN);
478 COUNT_NODE(NODE_DEFS);
479 COUNT_NODE(NODE_ALIAS);
480 COUNT_NODE(NODE_VALIAS);
481 COUNT_NODE(NODE_UNDEF);
482 COUNT_NODE(NODE_CLASS);
483 COUNT_NODE(NODE_MODULE);
484 COUNT_NODE(NODE_SCLASS);
485 COUNT_NODE(NODE_COLON2);
486 COUNT_NODE(NODE_COLON3);
487 COUNT_NODE(NODE_DOT2);
488 COUNT_NODE(NODE_DOT3);
489 COUNT_NODE(NODE_FLIP2);
490 COUNT_NODE(NODE_FLIP3);
491 COUNT_NODE(NODE_SELF);
492 COUNT_NODE(NODE_NIL);
493 COUNT_NODE(NODE_TRUE);
494 COUNT_NODE(NODE_FALSE);
495 COUNT_NODE(NODE_ERRINFO);
496 COUNT_NODE(NODE_DEFINED);
497 COUNT_NODE(NODE_POSTEXE);
498 COUNT_NODE(NODE_DSYM);
499 COUNT_NODE(NODE_ATTRASGN);
500 COUNT_NODE(NODE_LAMBDA);
501 COUNT_NODE(NODE_ARYPTN);
502 COUNT_NODE(NODE_FNDPTN);
503 COUNT_NODE(NODE_HSHPTN);
504#undef COUNT_NODE
505 case NODE_LAST: break;
506 }
507 UNREACHABLE;
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";
527 key = ID2SYM(rb_intern(name));
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{
664 rb_gc_mark((VALUE)ptr);
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,},
677 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
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
714 struct rof_data {
715 VALUE refs;
716 VALUE internals;
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
726 if (rb_objspace_markable_object_p(obj)) {
727 if (rb_objspace_internal_object_p(obj)) {
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{
788 if (rb_objspace_markable_object_p(obj)) {
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
807 struct rofr_data {
808 VALUE categories;
809 const char *last_category;
810 VALUE last_category_str;
811 VALUE last_category_objects;
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
835 if (rb_objspace_markable_object_p(obj) &&
836 obj != data->categories &&
837 obj != data->last_category_objects) {
838 if (rb_objspace_internal_object_p(obj)) {
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
965Init_objspace(void)
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}
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1301
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:749
UNREACHABLE
#define UNREACHABLE
Definition: assume.h:30
compilers.h
Internal header absorbing C compipler differences.
OBJ_BUILTIN_TYPE
#define OBJ_BUILTIN_TYPE(obj)
Definition: compilers.h:68
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:653
rb_define_module_function
#define rb_define_module_function(klass, mid, func, arity)
Defines klass#mid and makes it a module function.
Definition: cxxanyargs.hpp:672
ptr
struct RIMemo * ptr
Definition: debug.c:88
PRIsVALUE
#define PRIsVALUE
Definition: function.c:10
rb_objspace_internal_object_p
int rb_objspace_internal_object_p(VALUE obj)
Definition: gc.c:3355
rb_obj_id
VALUE rb_obj_id(VALUE obj)
Definition: gc.c:4110
rb_obj_memsize_of
size_t rb_obj_memsize_of(VALUE obj)
Definition: gc.c:4296
rb_objspace_reachable_objects_from
void rb_objspace_reachable_objects_from(VALUE obj, void(func)(VALUE, void *), void *data)
Definition: gc.c:10169
rb_objspace_data_type_name
const char * rb_objspace_data_type_name(VALUE obj)
Definition: gc.c:2534
rb_objspace_markable_object_p
int rb_objspace_markable_object_p(VALUE obj)
Definition: gc.c:3926
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:6112
rb_objspace_each_objects
void rb_objspace_each_objects(each_obj_callback *callback, void *data)
Definition: gc.c:3285
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:10202
CLASS_OF
#define CLASS_OF
Definition: globals.h:153
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:797
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:871
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2296
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2917
rb_typeddata_is_kind_of
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:1007
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:768
rb_ident_hash_new
VALUE rb_ident_hash_new(void)
Definition: hash.c:4443
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:1057
rb_eArgError
VALUE rb_eArgError
Definition: error.c:1058
rb_cObject
VALUE rb_cObject
Object class.
Definition: object.c:49
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:724
rb_hash_foreach
void rb_hash_foreach(VALUE hash, rb_foreach_func *func, VALUE farg)
Definition: hash.c:1498
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:2046
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2901
rb_hash_lookup
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:2072
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:1538
ID_SCOPE_MASK
#define ID_SCOPE_MASK
Definition: id.h:32
imemo.h
IMEMO: Internal memo object.
IMEMO_MASK
#define IMEMO_MASK
Definition: imemo.h:23
imemo_type
imemo_type
Definition: imemo.h:34
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:1077
rb_str_new2
#define rb_str_new2
Definition: string.h:276
rb_const_get
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:2624
rb_undef_alloc_func
void rb_undef_alloc_func(VALUE)
Definition: vm_method.c:954
ID2SYM
#define ID2SYM
Definition: symbol.h:44
rb_sym2str
VALUE rb_sym2str(VALUE)
Definition: symbol.c:927
rb_intern
ID rb_intern(const char *)
Definition: symbol.c:785
io.h
re.h
FIX2INT
#define FIX2INT
Definition: int.h:41
class.h
Internal header for Class.
gc.h
Internal header for GC.
hash.h
Internal header for Hash.
RHASH_TBL_RAW
#define RHASH_TBL_RAW(h)
Definition: hash.h:118
internal.h
INT2FIX
#define INT2FIX
Definition: long.h:48
T_MASK
#define T_MASK
Definition: md5.c:131
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:56
name
const char * name
Definition: nkf.c:208
node.h
node_type
node_type
Definition: node.h:21
NODE_OR
@ NODE_OR
Definition: node.h:45
NODE_LVAR
@ NODE_LVAR
Definition: node.h:72
NODE_FOR
@ NODE_FOR
Definition: node.h:34
NODE_OP_ASGN_OR
@ NODE_OP_ASGN_OR
Definition: node.h:57
NODE_SPLAT
@ NODE_SPLAT
Definition: node.h:98
NODE_DEFS
@ NODE_DEFS
Definition: node.h:101
NODE_REDO
@ NODE_REDO
Definition: node.h:38
NODE_IN
@ NODE_IN
Definition: node.h:30
NODE_MATCH
@ NODE_MATCH
Definition: node.h:80
NODE_MATCH2
@ NODE_MATCH2
Definition: node.h:81
NODE_STR
@ NODE_STR
Definition: node.h:84
NODE_DSYM
@ NODE_DSYM
Definition: node.h:121
NODE_DASGN_CURR
@ NODE_DASGN_CURR
Definition: node.h:49
NODE_LIST
@ NODE_LIST
Definition: node.h:66
NODE_CVAR
@ NODE_CVAR
Definition: node.h:77
NODE_NEXT
@ NODE_NEXT
Definition: node.h:37
NODE_MODULE
@ NODE_MODULE
Definition: node.h:106
NODE_ARGSCAT
@ NODE_ARGSCAT
Definition: node.h:96
NODE_DASGN
@ NODE_DASGN
Definition: node.h:48
NODE_LASGN
@ NODE_LASGN
Definition: node.h:47
NODE_AND
@ NODE_AND
Definition: node.h:44
NODE_MASGN
@ NODE_MASGN
Definition: node.h:46
NODE_CLASS
@ NODE_CLASS
Definition: node.h:105
NODE_CVASGN
@ NODE_CVASGN
Definition: node.h:53
NODE_CALL
@ NODE_CALL
Definition: node.h:59
NODE_OP_ASGN2
@ NODE_OP_ASGN2
Definition: node.h:55
NODE_FALSE
@ NODE_FALSE
Definition: node.h:117
NODE_FLIP2
@ NODE_FLIP2
Definition: node.h:112
NODE_EVSTR
@ NODE_EVSTR
Definition: node.h:88
NODE_DVAR
@ NODE_DVAR
Definition: node.h:73
NODE_ATTRASGN
@ NODE_ATTRASGN
Definition: node.h:122
NODE_BEGIN
@ NODE_BEGIN
Definition: node.h:40
NODE_UNTIL
@ NODE_UNTIL
Definition: node.h:32
NODE_FCALL
@ NODE_FCALL
Definition: node.h:61
NODE_MATCH3
@ NODE_MATCH3
Definition: node.h:82
NODE_LAST
@ NODE_LAST
Definition: node.h:127
NODE_SUPER
@ NODE_SUPER
Definition: node.h:64
NODE_CASE2
@ NODE_CASE2
Definition: node.h:27
NODE_DXSTR
@ NODE_DXSTR
Definition: node.h:87
NODE_IASGN
@ NODE_IASGN
Definition: node.h:51
NODE_GASGN
@ NODE_GASGN
Definition: node.h:50
NODE_OP_CDECL
@ NODE_OP_CDECL
Definition: node.h:58
NODE_RESCUE
@ NODE_RESCUE
Definition: node.h:41
NODE_SCOPE
@ NODE_SCOPE
Definition: node.h:22
NODE_SCLASS
@ NODE_SCLASS
Definition: node.h:107
NODE_HASH
@ NODE_HASH
Definition: node.h:69
NODE_YIELD
@ NODE_YIELD
Definition: node.h:71
NODE_LAMBDA
@ NODE_LAMBDA
Definition: node.h:123
NODE_CDECL
@ NODE_CDECL
Definition: node.h:52
NODE_OP_ASGN_AND
@ NODE_OP_ASGN_AND
Definition: node.h:56
NODE_BLOCK
@ NODE_BLOCK
Definition: node.h:23
NODE_TRUE
@ NODE_TRUE
Definition: node.h:116
NODE_ARGS_AUX
@ NODE_ARGS_AUX
Definition: node.h:92
NODE_CASE
@ NODE_CASE
Definition: node.h:26
NODE_ITER
@ NODE_ITER
Definition: node.h:33
NODE_RETRY
@ NODE_RETRY
Definition: node.h:39
NODE_DOT3
@ NODE_DOT3
Definition: node.h:111
NODE_RETURN
@ NODE_RETURN
Definition: node.h:70
NODE_BACK_REF
@ NODE_BACK_REF
Definition: node.h:79
NODE_QCALL
@ NODE_QCALL
Definition: node.h:63
NODE_ENSURE
@ NODE_ENSURE
Definition: node.h:43
NODE_SELF
@ NODE_SELF
Definition: node.h:114
NODE_DOT2
@ NODE_DOT2
Definition: node.h:110
NODE_OPT_ARG
@ NODE_OPT_ARG
Definition: node.h:93
NODE_FNDPTN
@ NODE_FNDPTN
Definition: node.h:126
NODE_LIT
@ NODE_LIT
Definition: node.h:83
NODE_UNDEF
@ NODE_UNDEF
Definition: node.h:104
NODE_FLIP3
@ NODE_FLIP3
Definition: node.h:113
NODE_POSTARG
@ NODE_POSTARG
Definition: node.h:95
NODE_NTH_REF
@ NODE_NTH_REF
Definition: node.h:78
NODE_VCALL
@ NODE_VCALL
Definition: node.h:62
NODE_KW_ARG
@ NODE_KW_ARG
Definition: node.h:94
NODE_DEFN
@ NODE_DEFN
Definition: node.h:100
NODE_GVAR
@ NODE_GVAR
Definition: node.h:74
NODE_ALIAS
@ NODE_ALIAS
Definition: node.h:102
NODE_COLON2
@ NODE_COLON2
Definition: node.h:108
NODE_POSTEXE
@ NODE_POSTEXE
Definition: node.h:120
NODE_IVAR
@ NODE_IVAR
Definition: node.h:75
NODE_ERRINFO
@ NODE_ERRINFO
Definition: node.h:118
NODE_BLOCK_PASS
@ NODE_BLOCK_PASS
Definition: node.h:99
NODE_ZSUPER
@ NODE_ZSUPER
Definition: node.h:65
NODE_DREGX
@ NODE_DREGX
Definition: node.h:89
NODE_DEFINED
@ NODE_DEFINED
Definition: node.h:119
NODE_ONCE
@ NODE_ONCE
Definition: node.h:90
NODE_IF
@ NODE_IF
Definition: node.h:24
NODE_HSHPTN
@ NODE_HSHPTN
Definition: node.h:125
NODE_ZLIST
@ NODE_ZLIST
Definition: node.h:67
NODE_ARYPTN
@ NODE_ARYPTN
Definition: node.h:124
NODE_XSTR
@ NODE_XSTR
Definition: node.h:86
NODE_BREAK
@ NODE_BREAK
Definition: node.h:36
NODE_UNLESS
@ NODE_UNLESS
Definition: node.h:25
NODE_VALIAS
@ NODE_VALIAS
Definition: node.h:103
NODE_WHEN
@ NODE_WHEN
Definition: node.h:29
NODE_CASE3
@ NODE_CASE3
Definition: node.h:28
NODE_COLON3
@ NODE_COLON3
Definition: node.h:109
NODE_CONST
@ NODE_CONST
Definition: node.h:76
NODE_NIL
@ NODE_NIL
Definition: node.h:115
NODE_VALUES
@ NODE_VALUES
Definition: node.h:68
NODE_RESBODY
@ NODE_RESBODY
Definition: node.h:42
NODE_DSTR
@ NODE_DSTR
Definition: node.h:85
NODE_FOR_MASGN
@ NODE_FOR_MASGN
Definition: node.h:35
NODE_WHILE
@ NODE_WHILE
Definition: node.h:31
NODE_ARGSPUSH
@ NODE_ARGSPUSH
Definition: node.h:97
NODE_OP_ASGN1
@ NODE_OP_ASGN1
Definition: node.h:54
NODE_OPCALL
@ NODE_OPCALL
Definition: node.h:60
NODE_ARGS
@ NODE_ARGS
Definition: node.h:91
nd_type
#define nd_type(n)
Definition: node.h:188
each_obj_with_flags
void(* each_obj_with_flags)(VALUE, void *)
Definition: objspace.c:78
Init_object_tracing
void Init_object_tracing(VALUE rb_mObjSpace)
Definition: object_tracing.c:561
Init_objspace_dump
void Init_objspace_dump(VALUE rb_mObjSpace)
Definition: objspace_dump.c:622
rb_sym_immortal_count
size_t rb_sym_immortal_count(void)
Definition: symbol.c:998
COUNT_NODE
#define COUNT_NODE(n)
Init_objspace
void Init_objspace(void)
Definition: objspace.c:965
CASE_TYPE
#define CASE_TYPE(t)
key
key
Definition: openssl_missing.h:185
RBASIC
#define RBASIC(obj)
Definition: rbasic.h:34
RCLASS_SUPER
#define RCLASS_SUPER
Definition: rclass.h:33
DATA_PTR
#define DATA_PTR(obj)
Definition: rdata.h:56
RHASH_EMPTY_P
#define RHASH_EMPTY_P(h)
Definition: rhash.h:51
TypedData_Wrap_Struct
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: rtypeddata.h:101
RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_FREE_IMMEDIATELY
Definition: rtypeddata.h:62
ruby.h
argc
int argc
Definition: ruby.c:240
argv
char ** argv
Definition: ruby.c:241
sanitizers.h
Internal header for ASAN / MSAN / etc.
SIZET2NUM
#define SIZET2NUM
Definition: size_t.h:52
RTEST
#define RTEST
Definition: special_consts.h:42
Qnil
#define Qnil
Definition: special_consts.h:51
Qfalse
#define Qfalse
Definition: special_consts.h:50
NIL_P
#define NIL_P
Definition: special_consts.h:46
rb_sprintf
VALUE rb_sprintf(const char *,...)
Definition: sprintf.c:1203
st.h
ST_CONTINUE
@ ST_CONTINUE
Definition: st.h:99
st_data_t
unsigned long st_data_t
Definition: st.h:22
st_foreach
#define st_foreach
Definition: st.h:142
RNode
Definition: node.h:149
dynamic_symbol_counts
Definition: objspace.c:281
dynamic_symbol_counts::mortal
size_t mortal
Definition: objspace.c:282
dynamic_symbol_counts::immortal
size_t immortal
Definition: objspace.c:283
obj_itr
Definition: objspace.c:80
obj_itr::data
void * data
Definition: objspace.c:82
obj_itr::cb
each_obj_with_flags cb
Definition: objspace.c:81
rb_data_type_struct
Definition: rtypeddata.h:70
rof_data
Definition: objspace.c:714
rof_data::internals
VALUE internals
Definition: objspace.c:716
rof_data::refs
VALUE refs
Definition: objspace.c:715
rofr_data
Definition: objspace.c:807
rofr_data::categories
VALUE categories
Definition: objspace.c:808
rofr_data::last_category_str
VALUE last_category_str
Definition: objspace.c:810
rofr_data::last_category
const char * last_category
Definition: objspace.c:809
rofr_data::last_category_objects
VALUE last_category_objects
Definition: objspace.c:811
total_data
Definition: objspace.c:54
total_data::total
size_t total
Definition: objspace.c:55
total_data::klass
VALUE klass
Definition: objspace.c:56
symbol.h
RSYMBOL
#define RSYMBOL(obj)
Definition: symbol.h:33
VALUE
unsigned long VALUE
Definition: value.h:38
ID
unsigned long ID
Definition: value.h:39
T_COMPLEX
#define T_COMPLEX
Definition: value_type.h:58
T_FILE
#define T_FILE
Definition: value_type.h:61
T_STRING
#define T_STRING
Definition: value_type.h:77
T_NIL
#define T_NIL
Definition: value_type.h:71
T_FLOAT
#define T_FLOAT
Definition: value_type.h:63
T_IMEMO
#define T_IMEMO
Definition: value_type.h:66
T_BIGNUM
#define T_BIGNUM
Definition: value_type.h:56
T_STRUCT
#define T_STRUCT
Definition: value_type.h:78
T_FIXNUM
#define T_FIXNUM
Definition: value_type.h:62
T_DATA
#define T_DATA
Definition: value_type.h:59
T_NONE
#define T_NONE
Definition: value_type.h:73
T_NODE
#define T_NODE
Definition: value_type.h:72
T_MODULE
#define T_MODULE
Definition: value_type.h:69
T_TRUE
#define T_TRUE
Definition: value_type.h:80
T_RATIONAL
#define T_RATIONAL
Definition: value_type.h:75
T_ICLASS
#define T_ICLASS
Definition: value_type.h:65
T_HASH
#define T_HASH
Definition: value_type.h:64
T_FALSE
#define T_FALSE
Definition: value_type.h:60
T_UNDEF
#define T_UNDEF
Definition: value_type.h:81
T_ZOMBIE
#define T_ZOMBIE
Definition: value_type.h:82
T_ARRAY
#define T_ARRAY
Definition: value_type.h:55
T_OBJECT
#define T_OBJECT
Definition: value_type.h:74
T_SYMBOL
#define T_SYMBOL
Definition: value_type.h:79
T_MATCH
#define T_MATCH
Definition: value_type.h:68
T_CLASS
#define T_CLASS
Definition: value_type.h:57
BUILTIN_TYPE
#define BUILTIN_TYPE
Definition: value_type.h:84
T_MOVED
#define T_MOVED
Definition: value_type.h:70
ruby_value_type
ruby_value_type
C-level type of an object.
Definition: value_type.h:110
T_REGEXP
#define T_REGEXP
Definition: value_type.h:76