Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

objspace.c
Go to the documentation of this file.
1 /**********************************************************************
2
3 objspace.c - ObjectSpace extender for MRI.
4
5 $Author: ko1 $
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/ruby.h>
16 #include <ruby/st.h>
17 #include <ruby/io.h>
18 #include <ruby/re.h>
19 #include "node.h"
20 #include "gc.h"
21 #include "internal.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
36 static VALUE
37 memsize_of_m(VALUE self, VALUE obj)
38 {
39 return SIZET2NUM(rb_obj_memsize_of(obj));
40 }
41
42 struct total_data {
43 size_t total;
44 VALUE klass;
45 };
46
47 static int
48 total_i(void *vstart, void *vend, size_t stride, void *ptr)
49 {
50 VALUE v;
51 struct total_data *data = (struct total_data *)ptr;
52
53 for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
54 if (RBASIC(v)->flags) {
55 switch (BUILTIN_TYPE(v)) {
56 case T_NONE:
57 case T_ICLASS:
58 case T_NODE:
59 case T_ZOMBIE:
60 continue;
61 case T_CLASS:
62 if (FL_TEST(v, FL_SINGLETON))
63 continue;
64 default:
65 if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
66 data->total += rb_obj_memsize_of(v);
67 }
68 }
69 }
70 }
71
72 return 0;
73 }
74
75 /*
76 * call-seq:
77 * ObjectSpace.memsize_of_all([klass]) -> Integer
78 *
79 * Return consuming memory size of all living objects.
80 *
81 * If +klass+ (should be Class object) is given, return the total memory size
82 * of instances of the given class.
83 *
84 * Note that the returned size is incomplete. You need to deal with this
85 * information as only a *HINT*. Especially, the size of +T_DATA+ may not be
86 * correct.
87 *
88 * Note that this method does *NOT* return total malloc'ed memory size.
89 *
90 * This method can be defined by the following Ruby code:
91 *
92 * def memsize_of_all klass = false
93 * total = 0
94 * ObjectSpace.each_object{|e|
95 * total += ObjectSpace.memsize_of(e) if klass == false || e.kind_of?(klass)
96 * }
97 * total
98 * end
99 *
100 * This method is only expected to work with C Ruby.
101 */
102
103 static VALUE
104 memsize_of_all_m(int argc, VALUE *argv, VALUE self)
105 {
106 struct total_data data = {0, 0};
107
108 if (argc > 0) {
109 rb_scan_args(argc, argv, "01", &data.klass);
110 }
111
112 rb_objspace_each_objects(total_i, &data);
113 return SIZET2NUM(data.total);
114 }
115
116 static int
117 set_zero_i(st_data_t key, st_data_t val, st_data_t arg)
118 {
119 VALUE k = (VALUE)key;
120 VALUE hash = (VALUE)arg;
121 rb_hash_aset(hash, k, INT2FIX(0));
122 return ST_CONTINUE;
123 }
124
125 static int
126 cos_i(void *vstart, void *vend, size_t stride, void *data)
127 {
128 size_t *counts = (size_t *)data;
129 VALUE v = (VALUE)vstart;
130
131 for (;v != (VALUE)vend; v += stride) {
132 if (RBASIC(v)->flags) {
133 counts[BUILTIN_TYPE(v)] += rb_obj_memsize_of(v);
134 }
135 }
136 return 0;
137 }
138
139 static VALUE
140 type2sym(enum ruby_value_type i)
141 {
142 VALUE type;
143 switch (i) {
144 #define CASE_TYPE(t) case t: type = ID2SYM(rb_intern(#t)); break;
145 CASE_TYPE(T_NONE);
146 CASE_TYPE(T_OBJECT);
147 CASE_TYPE(T_CLASS);
148 CASE_TYPE(T_MODULE);
149 CASE_TYPE(T_FLOAT);
150 CASE_TYPE(T_STRING);
151 CASE_TYPE(T_REGEXP);
152 CASE_TYPE(T_ARRAY);
153 CASE_TYPE(T_HASH);
154 CASE_TYPE(T_STRUCT);
155 CASE_TYPE(T_BIGNUM);
156 CASE_TYPE(T_FILE);
157 CASE_TYPE(T_DATA);
158 CASE_TYPE(T_MATCH);
159 CASE_TYPE(T_COMPLEX);
160 CASE_TYPE(T_RATIONAL);
161 CASE_TYPE(T_NIL);
162 CASE_TYPE(T_TRUE);
163 CASE_TYPE(T_FALSE);
164 CASE_TYPE(T_SYMBOL);
165 CASE_TYPE(T_FIXNUM);
166 CASE_TYPE(T_UNDEF);
167 CASE_TYPE(T_NODE);
168 CASE_TYPE(T_ICLASS);
169 CASE_TYPE(T_ZOMBIE);
170 #undef CASE_TYPE
171 default: rb_bug("type2sym: unknown type (%d)", i);
172 }
173 return type;
174 }
175
176 /*
177 * call-seq:
178 * ObjectSpace.count_objects_size([result_hash]) -> hash
179 *
180 * Counts objects size (in bytes) for each type.
181 *
182 * Note that this information is incomplete. You need to deal with
183 * this information as only a *HINT*. Especially, total size of
184 * T_DATA may not right size.
185 *
186 * It returns a hash as:
187 * {:TOTAL=>1461154, :T_CLASS=>158280, :T_MODULE=>20672, :T_STRING=>527249, ...}
188 *
189 * If the optional argument, result_hash, is given,
190 * it is overwritten and returned.
191 * This is intended to avoid probe effect.
192 *
193 * The contents of the returned hash is implementation defined.
194 * It may be changed in future.
195 *
196 * This method is only expected to work with C Ruby.
197 */
198
199 static VALUE
200 count_objects_size(int argc, VALUE *argv, VALUE os)
201 {
202 size_t counts[T_MASK+1];
203 size_t total = 0;
204 enum ruby_value_type i;
205 VALUE hash;
206
207 if (rb_scan_args(argc, argv, "01", &hash) == 1) {
208 if (!RB_TYPE_P(hash, T_HASH))
209 rb_raise(rb_eTypeError, "non-hash given");
210 }
211
212 for (i = 0; i <= T_MASK; i++) {
213 counts[i] = 0;
214 }
215
216 rb_objspace_each_objects(cos_i, &counts[0]);
217
218 if (hash == Qnil) {
219 hash = rb_hash_new();
220 }
221 else if (!RHASH_EMPTY_P(hash)) {
222 st_foreach(RHASH_TBL(hash), set_zero_i, hash);
223 }
224
225 for (i = 0; i <= T_MASK; i++) {
226 if (counts[i]) {
227 VALUE type = type2sym(i);
228 total += counts[i];
229 rb_hash_aset(hash, type, SIZET2NUM(counts[i]));
230 }
231 }
232 rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(total));
233 return hash;
234 }
235
236 static int
237 cn_i(void *vstart, void *vend, size_t stride, void *n)
238 {
239 size_t *nodes = (size_t *)n;
240 VALUE v = (VALUE)vstart;
241
242 for (; v != (VALUE)vend; v += stride) {
243 if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_NODE) {
244 size_t s = nd_type((NODE *)v);
245 nodes[s]++;
246 }
247 }
248
249 return 0;
250 }
251
252 /*
253 * call-seq:
254 * ObjectSpace.count_nodes([result_hash]) -> hash
255 *
256 * Counts nodes for each node type.
257 *
258 * This method is only for MRI developers interested in performance and memory
259 * usage of Ruby programs.
260 *
261 * It returns a hash as:
262 *
263 * {:NODE_METHOD=>2027, :NODE_FBODY=>1927, :NODE_CFUNC=>1798, ...}
264 *
265 * If the optional argument, result_hash, is given, it is overwritten and
266 * returned. This is intended to avoid probe effect.
267 *
268 * Note:
269 * The contents of the returned hash is implementation defined.
270 * It may be changed in future.
271 *
272 * This method is only expected to work with C Ruby.
273 */
274
275 static VALUE
276 count_nodes(int argc, VALUE *argv, VALUE os)
277 {
278 size_t nodes[NODE_LAST+1];
279 size_t i;
280 VALUE hash;
281
282 if (rb_scan_args(argc, argv, "01", &hash) == 1) {
283 if (!RB_TYPE_P(hash, T_HASH))
284 rb_raise(rb_eTypeError, "non-hash given");
285 }
286
287 for (i = 0; i <= NODE_LAST; i++) {
288 nodes[i] = 0;
289 }
290
291 rb_objspace_each_objects(cn_i, &nodes[0]);
292
293 if (hash == Qnil) {
294 hash = rb_hash_new();
295 }
296 else if (!RHASH_EMPTY_P(hash)) {
297 st_foreach(RHASH_TBL(hash), set_zero_i, hash);
298 }
299
300 for (i=0; i<NODE_LAST; i++) {
301 if (nodes[i] != 0) {
302 VALUE node;
303 switch (i) {
304 #define COUNT_NODE(n) case n: node = ID2SYM(rb_intern(#n)); break;
305 COUNT_NODE(NODE_SCOPE);
306 COUNT_NODE(NODE_BLOCK);
307 COUNT_NODE(NODE_IF);
308 COUNT_NODE(NODE_CASE);
309 COUNT_NODE(NODE_WHEN);
310 COUNT_NODE(NODE_OPT_N);
311 COUNT_NODE(NODE_WHILE);
312 COUNT_NODE(NODE_UNTIL);
313 COUNT_NODE(NODE_ITER);
314 COUNT_NODE(NODE_FOR);
315 COUNT_NODE(NODE_BREAK);
316 COUNT_NODE(NODE_NEXT);
317 COUNT_NODE(NODE_REDO);
318 COUNT_NODE(NODE_RETRY);
319 COUNT_NODE(NODE_BEGIN);
320 COUNT_NODE(NODE_RESCUE);
321 COUNT_NODE(NODE_RESBODY);
322 COUNT_NODE(NODE_ENSURE);
323 COUNT_NODE(NODE_AND);
324 COUNT_NODE(NODE_OR);
325 COUNT_NODE(NODE_MASGN);
326 COUNT_NODE(NODE_LASGN);
327 COUNT_NODE(NODE_DASGN);
328 COUNT_NODE(NODE_DASGN_CURR);
329 COUNT_NODE(NODE_GASGN);
330 COUNT_NODE(NODE_IASGN);
331 COUNT_NODE(NODE_IASGN2);
332 COUNT_NODE(NODE_CDECL);
333 COUNT_NODE(NODE_CVASGN);
334 COUNT_NODE(NODE_CVDECL);
335 COUNT_NODE(NODE_OP_ASGN1);
336 COUNT_NODE(NODE_OP_ASGN2);
337 COUNT_NODE(NODE_OP_ASGN_AND);
338 COUNT_NODE(NODE_OP_ASGN_OR);
339 COUNT_NODE(NODE_OP_CDECL);
340 COUNT_NODE(NODE_CALL);
341 COUNT_NODE(NODE_FCALL);
342 COUNT_NODE(NODE_VCALL);
343 COUNT_NODE(NODE_SUPER);
344 COUNT_NODE(NODE_ZSUPER);
345 COUNT_NODE(NODE_ARRAY);
346 COUNT_NODE(NODE_ZARRAY);
347 COUNT_NODE(NODE_VALUES);
348 COUNT_NODE(NODE_HASH);
349 COUNT_NODE(NODE_RETURN);
350 COUNT_NODE(NODE_YIELD);
351 COUNT_NODE(NODE_LVAR);
352 COUNT_NODE(NODE_DVAR);
353 COUNT_NODE(NODE_GVAR);
354 COUNT_NODE(NODE_IVAR);
355 COUNT_NODE(NODE_CONST);
356 COUNT_NODE(NODE_CVAR);
357 COUNT_NODE(NODE_NTH_REF);
358 COUNT_NODE(NODE_BACK_REF);
359 COUNT_NODE(NODE_MATCH);
360 COUNT_NODE(NODE_MATCH2);
361 COUNT_NODE(NODE_MATCH3);
362 COUNT_NODE(NODE_LIT);
363 COUNT_NODE(NODE_STR);
364 COUNT_NODE(NODE_DSTR);
365 COUNT_NODE(NODE_XSTR);
366 COUNT_NODE(NODE_DXSTR);
367 COUNT_NODE(NODE_EVSTR);
368 COUNT_NODE(NODE_DREGX);
369 COUNT_NODE(NODE_DREGX_ONCE);
370 COUNT_NODE(NODE_ARGS);
371 COUNT_NODE(NODE_ARGS_AUX);
372 COUNT_NODE(NODE_OPT_ARG);
373 COUNT_NODE(NODE_KW_ARG);
374 COUNT_NODE(NODE_POSTARG);
375 COUNT_NODE(NODE_ARGSCAT);
376 COUNT_NODE(NODE_ARGSPUSH);
377 COUNT_NODE(NODE_SPLAT);
378 COUNT_NODE(NODE_TO_ARY);
379 COUNT_NODE(NODE_BLOCK_ARG);
380 COUNT_NODE(NODE_BLOCK_PASS);
381 COUNT_NODE(NODE_DEFN);
382 COUNT_NODE(NODE_DEFS);
383 COUNT_NODE(NODE_ALIAS);
384 COUNT_NODE(NODE_VALIAS);
385 COUNT_NODE(NODE_UNDEF);
386 COUNT_NODE(NODE_CLASS);
387 COUNT_NODE(NODE_MODULE);
388 COUNT_NODE(NODE_SCLASS);
389 COUNT_NODE(NODE_COLON2);
390 COUNT_NODE(NODE_COLON3);
391 COUNT_NODE(NODE_CREF);
392 COUNT_NODE(NODE_DOT2);
393 COUNT_NODE(NODE_DOT3);
394 COUNT_NODE(NODE_FLIP2);
395 COUNT_NODE(NODE_FLIP3);
396 COUNT_NODE(NODE_SELF);
397 COUNT_NODE(NODE_NIL);
398 COUNT_NODE(NODE_TRUE);
399 COUNT_NODE(NODE_FALSE);
400 COUNT_NODE(NODE_ERRINFO);
401 COUNT_NODE(NODE_DEFINED);
402 COUNT_NODE(NODE_POSTEXE);
403 COUNT_NODE(NODE_ALLOCA);
404 COUNT_NODE(NODE_BMETHOD);
405 COUNT_NODE(NODE_MEMO);
406 COUNT_NODE(NODE_IFUNC);
407 COUNT_NODE(NODE_DSYM);
408 COUNT_NODE(NODE_ATTRASGN);
409 COUNT_NODE(NODE_PRELUDE);
410 COUNT_NODE(NODE_LAMBDA);
411 #undef COUNT_NODE
412 default: node = INT2FIX(i);
413 }
414 rb_hash_aset(hash, node, SIZET2NUM(nodes[i]));
415 }
416 }
417 return hash;
418 }
419
420 static int
421 cto_i(void *vstart, void *vend, size_t stride, void *data)
422 {
423 VALUE hash = (VALUE)data;
424 VALUE v = (VALUE)vstart;
425
426 for (; v != (VALUE)vend; v += stride) {
427 if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_DATA) {
428 VALUE counter;
429 VALUE key = RBASIC(v)->klass;
430
431 if (key == 0) {
432 const char *name = rb_objspace_data_type_name(v);
433 if (name == 0) name = "unknown";
434 key = ID2SYM(rb_intern(name));
435 }
436
437 counter = rb_hash_aref(hash, key);
438 if (NIL_P(counter)) {
439 counter = INT2FIX(1);
440 }
441 else {
442 counter = INT2FIX(FIX2INT(counter) + 1);
443 }
444
445 rb_hash_aset(hash, key, counter);
446 }
447 }
448
449 return 0;
450 }
451
452 /*
453 * call-seq:
454 * ObjectSpace.count_tdata_objects([result_hash]) -> hash
455 *
456 * Counts objects for each +T_DATA+ type.
457 *
458 * This method is only for MRI developers interested in performance and memory
459 * usage of Ruby programs.
460 *
461 * It returns a hash as:
462 *
463 * {RubyVM::InstructionSequence=>504, :parser=>5, :barrier=>6,
464 * :mutex=>6, Proc=>60, RubyVM::Env=>57, Mutex=>1, Encoding=>99,
465 * ThreadGroup=>1, Binding=>1, Thread=>1, RubyVM=>1, :iseq=>1,
466 * Random=>1, ARGF.class=>1, Data=>1, :autoload=>3, Time=>2}
467 * # T_DATA objects existing at startup on r32276.
468 *
469 * If the optional argument, result_hash, is given, it is overwritten and
470 * returned. This is intended to avoid probe effect.
471 *
472 * The contents of the returned hash is implementation specific and may change
473 * in the future.
474 *
475 * In this version, keys are Class object or Symbol object.
476 *
477 * If object is kind of normal (accessible) object, the key is Class object.
478 * If object is not a kind of normal (internal) object, the key is symbol
479 * name, registered by rb_data_type_struct.
480 *
481 * This method is only expected to work with C Ruby.
482 */
483
484 static VALUE
485 count_tdata_objects(int argc, VALUE *argv, VALUE self)
486 {
487 VALUE hash;
488
489 if (rb_scan_args(argc, argv, "01", &hash) == 1) {
490 if (!RB_TYPE_P(hash, T_HASH))
491 rb_raise(rb_eTypeError, "non-hash given");
492 }
493
494 if (hash == Qnil) {
495 hash = rb_hash_new();
496 }
497 else if (!RHASH_EMPTY_P(hash)) {
498 st_foreach(RHASH_TBL(hash), set_zero_i, hash);
499 }
500
501 rb_objspace_each_objects(cto_i, (void *)hash);
502
503 return hash;
504 }
505
506 static void
507 iow_mark(void *ptr)
508 {
509 rb_gc_mark((VALUE)ptr);
510 }
511
512 static size_t
513 iow_size(const void *ptr)
514 {
515 VALUE obj = (VALUE)ptr;
516 return rb_obj_memsize_of(obj);
517 }
518
519 static const rb_data_type_t iow_data_type = {
520 "ObjectSpace::InternalObjectWrapper",
521 {iow_mark, 0, iow_size,},
522 NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
523 };
524
525 static VALUE rb_mInternalObjectWrapper;
526
527 static VALUE
528 iow_newobj(VALUE obj)
529 {
530 return rb_data_typed_object_alloc(rb_mInternalObjectWrapper, (void *)obj, &iow_data_type);
531 }
532
533 /* Returns the type of the internal object. */
534 static VALUE
535 iow_type(VALUE self)
536 {
537 VALUE obj = (VALUE)DATA_PTR(self);
538 return type2sym(BUILTIN_TYPE(obj));
539 }
540
541 /* See Object#inspect. */
542 static VALUE
543 iow_inspect(VALUE self)
544 {
545 VALUE obj = (VALUE)DATA_PTR(self);
546 VALUE type = type2sym(BUILTIN_TYPE(obj));
547
548 return rb_sprintf("#<InternalObject:%p %s>", (void *)obj, rb_id2name(SYM2ID(type)));
549 }
550
551 /* Returns the Object#object_id of the internal object. */
552 static VALUE
553 iow_internal_object_id(VALUE self)
554 {
555 VALUE obj = (VALUE)DATA_PTR(self);
556 return rb_obj_id(obj);
557 }
558
559 struct rof_data {
560 st_table *refs;
561 VALUE internals;
562 };
563
564 static void
565 reachable_object_from_i(VALUE obj, void *data_ptr)
566 {
567 struct rof_data *data = (struct rof_data *)data_ptr;
568 VALUE key = obj;
569 VALUE val = obj;
570
571 if (rb_objspace_markable_object_p(obj)) {
572 if (rb_objspace_internal_object_p(obj)) {
573 val = iow_newobj(obj);
574 rb_ary_push(data->internals, val);
575 }
576 st_insert(data->refs, key, val);
577 }
578 }
579
580 static int
581 collect_values(st_data_t key, st_data_t value, st_data_t data)
582 {
583 VALUE ary = (VALUE)data;
584 rb_ary_push(ary, (VALUE)value);
585 return ST_CONTINUE;
586 }
587
588 /*
589 * call-seq:
590 * ObjectSpace.reachable_objects_from(obj) -> array or nil
591 *
592 * [MRI specific feature] Return all reachable objects from `obj'.
593 *
594 * This method returns all reachable objects from `obj'.
595 *
596 * If `obj' has two or more references to the same object `x', then returned
597 * array only includes one `x' object.
598 *
599 * If `obj' is a non-markable (non-heap management) object such as true,
600 * false, nil, symbols and Fixnums (and Flonum) then it simply returns nil.
601 *
602 * If `obj' has references to an internal object, then it returns instances of
603 * ObjectSpace::InternalObjectWrapper class. This object contains a reference
604 * to an internal object and you can check the type of internal object with
605 * `type' method.
606 *
607 * If `obj' is instance of ObjectSpace::InternalObjectWrapper class, then this
608 * method returns all reachable object from an internal object, which is
609 * pointed by `obj'.
610 *
611 * With this method, you can find memory leaks.
612 *
613 * This method is only expected to work except with C Ruby.
614 *
615 * Example:
616 * ObjectSpace.reachable_objects_from(['a', 'b', 'c'])
617 * #=> [Array, 'a', 'b', 'c']
618 *
619 * ObjectSpace.reachable_objects_from(['a', 'a', 'a'])
620 * #=> [Array, 'a', 'a', 'a'] # all 'a' strings have different object id
621 *
622 * ObjectSpace.reachable_objects_from([v = 'a', v, v])
623 * #=> [Array, 'a']
624 *
625 * ObjectSpace.reachable_objects_from(1)
626 * #=> nil # 1 is not markable (heap managed) object
627 *
628 */
629
630 static VALUE
631 reachable_objects_from(VALUE self, VALUE obj)
632 {
633 if (rb_objspace_markable_object_p(obj)) {
634 VALUE ret = rb_ary_new();
635 struct rof_data data;
636
637 if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
638 obj = (VALUE)DATA_PTR(obj);
639 }
640
641 data.refs = st_init_numtable();
642 data.internals = rb_ary_new();
643
644 rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data);
645
646 st_foreach(data.refs, collect_values, (st_data_t)ret);
647 return ret;
648 }
649 else {
650 return Qnil;
651 }
652 }
653
654 struct rofr_data {
655 VALUE categories;
656 const char *last_category;
657 VALUE last_category_str;
658 VALUE last_category_objects;
659 };
660
661 static void
662 reachable_object_from_root_i(const char *category, VALUE obj, void *ptr)
663 {
664 struct rofr_data *data = (struct rofr_data *)ptr;
665 VALUE category_str;
666 VALUE category_objects;
667
668 if (category == data->last_category) {
669 category_str = data->last_category_str;
670 category_objects = data->last_category_objects;
671 }
672 else {
673 data->last_category = category;
674 category_str = data->last_category_str = rb_str_new2(category);
675 category_objects = data->last_category_objects = rb_hash_new();
676 rb_funcall(category_objects, rb_intern("compare_by_identity"), 0);
677 if (!NIL_P(rb_hash_lookup(data->categories, category_str))) {
678 rb_bug("reachable_object_from_root_i: category should insert at once");
679 }
680 rb_hash_aset(data->categories, category_str, category_objects);
681 }
682
683 if (rb_objspace_markable_object_p(obj) &&
684 obj != data->categories &&
685 obj != data->last_category_objects) {
686 if (rb_objspace_internal_object_p(obj)) {
687 obj = iow_newobj(obj);
688 }
689 rb_hash_aset(category_objects, obj, obj);
690 }
691 }
692
693 static int
694 collect_values_of_values(VALUE category, VALUE category_objects, VALUE categories)
695 {
696 VALUE ary = rb_ary_new();
697 st_foreach(rb_hash_tbl(category_objects), collect_values, ary);
698 rb_hash_aset(categories, category, ary);
699 return ST_CONTINUE;
700 }
701
702 /*
703 * call-seq:
704 * ObjectSpace.reachable_objects_from_root -> hash
705 *
706 * [MRI specific feature] Return all reachable objects from root.
707 */
708 static VALUE
709 reachable_objects_from_root(VALUE self)
710 {
711 struct rofr_data data;
712 VALUE hash = data.categories = rb_hash_new();
713 data.last_category = 0;
714
715 rb_funcall(hash, rb_intern("compare_by_identity"), 0);
716 rb_objspace_reachable_objects_from_root(reachable_object_from_root_i, &data);
717 rb_hash_foreach(hash, collect_values_of_values, hash);
718
719 return hash;
720 }
721
722 void Init_object_tracing(VALUE rb_mObjSpace);
723 void Init_objspace_dump(VALUE rb_mObjSpace);
724
725 /*
726 * Document-module: ObjectSpace
727 *
728 * The objspace library extends the ObjectSpace module and adds several
729 * methods to get internal statistic information about
730 * object/memory management.
731 *
732 * You need to <code>require 'objspace'</code> to use this extension module.
733 *
734 * Generally, you *SHOULD NOT* use this library if you do not know
735 * about the MRI implementation. Mainly, this library is for (memory)
736 * profiler developers and MRI developers who need to know about MRI
737 * memory usage.
738 */
739
740 void
741 Init_objspace(void)
742 {
743 VALUE rb_mObjSpace;
744 #if 0
745 rb_mObjSpace = rb_define_module("ObjectSpace"); /* let rdoc know */
746 #endif
747 rb_mObjSpace = rb_const_get(rb_cObject, rb_intern("ObjectSpace"));
748
749 rb_define_module_function(rb_mObjSpace, "memsize_of", memsize_of_m, 1);
750 rb_define_module_function(rb_mObjSpace, "memsize_of_all", memsize_of_all_m, -1);
751
752 rb_define_module_function(rb_mObjSpace, "count_objects_size", count_objects_size, -1);
753 rb_define_module_function(rb_mObjSpace, "count_nodes", count_nodes, -1);
754 rb_define_module_function(rb_mObjSpace, "count_tdata_objects", count_tdata_objects, -1);
755
756 rb_define_module_function(rb_mObjSpace, "reachable_objects_from", reachable_objects_from, 1);
757 rb_define_module_function(rb_mObjSpace, "reachable_objects_from_root", reachable_objects_from_root, 0);
758
759 /*
760 * This class is used as a return value from
761 * ObjectSpace::reachable_objects_from.
762 *
763 * When ObjectSpace::reachable_objects_from returns an object with
764 * references to an internal object, an instance of this class is returned.
765 *
766 * You can use the #type method to check the type of the internal object.
767 */
768 rb_mInternalObjectWrapper = rb_define_class_under(rb_mObjSpace, "InternalObjectWrapper", rb_cObject);
769 rb_define_method(rb_mInternalObjectWrapper, "type", iow_type, 0);
770 rb_define_method(rb_mInternalObjectWrapper, "inspect", iow_inspect, 0);
771 rb_define_method(rb_mInternalObjectWrapper, "internal_object_id", iow_internal_object_id, 0);
772
773 Init_object_tracing(rb_mObjSpace);
774 Init_objspace_dump(rb_mObjSpace);
775 }
T_SYMBOL
#define T_SYMBOL
Definition: ruby.h:494
T_OBJECT
#define T_OBJECT
Definition: ruby.h:477
NODE_CALL
Definition: node.h:93
NODE_CASE
Definition: node.h:29
NODE_BLOCK_ARG
Definition: node.h:171
NODE_ARGSCAT
Definition: node.h:163
count_objects_size
static VALUE count_objects_size(int argc, VALUE *argv, VALUE os)
Definition: objspace.c:200
iow_data_type
static const rb_data_type_t iow_data_type
Definition: objspace.c:519
NODE_DASGN
Definition: node.h:67
NODE_DOT2
Definition: node.h:197
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:327
NODE_VALUES
Definition: node.h:107
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1015
rb_hash_lookup
#define rb_hash_lookup
Definition: tcltklib.c:269
rb_mInternalObjectWrapper
static VALUE rb_mInternalObjectWrapper
Definition: objspace.c:525
rb_obj_id
VALUE rb_obj_id(VALUE obj)
Definition: gc.c:2373
NODE_UNTIL
Definition: node.h:37
NODE_FCALL
Definition: node.h:95
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:489
st_table
Definition: st.h:69
NODE_CVDECL
Definition: node.h:81
NODE_CVASGN
Definition: node.h:79
NODE_IASGN2
Definition: node.h:75
T_MATCH
#define T_MATCH
Definition: ruby.h:493
NODE_REDO
Definition: node.h:47
NODE_MASGN
Definition: node.h:63
NODE_MODULE
Definition: node.h:187
node.h
Init_objspace
void Init_objspace(void)
Definition: objspace.c:741
NODE_DXSTR
Definition: node.h:145
ruby.h
NODE_TO_ARY
Definition: node.h:169
NODE_ZSUPER
Definition: node.h:101
T_MODULE
#define T_MODULE
Definition: ruby.h:480
NODE_VALIAS
Definition: node.h:181
rofr_data::last_category
const char * last_category
Definition: objspace.c:656
NODE_BACK_REF
Definition: node.h:129
st_insert
int st_insert(st_table *, st_data_t, st_data_t)
NODE_DEFINED
Definition: node.h:215
rofr_data::last_category_str
VALUE last_category_str
Definition: objspace.c:657
NODE_BLOCK
Definition: node.h:25
rofr_data
Definition: objspace.c:654
ST_CONTINUE
Definition: st.h:100
NODE_FLIP3
Definition: node.h:203
NODE_DSTR
Definition: node.h:141
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:548
NODE_ZARRAY
Definition: node.h:105
NODE_ARRAY
Definition: node.h:103
T_RATIONAL
#define T_RATIONAL
Definition: ruby.h:495
NODE_IFUNC
Definition: node.h:225
NODE_ITER
Definition: node.h:39
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:896
NODE_CDECL
Definition: node.h:77
NODE_LAST
#define NODE_LAST
Definition: node.h:236
SYM2ID
#define SYM2ID(x)
Definition: ruby.h:356
NODE_CVAR
Definition: node.h:125
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:5807
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:775
rb_hash_tbl
struct st_table * rb_hash_tbl(VALUE hash)
Definition: hash.c:344
cto_i
static int cto_i(void *vstart, void *vend, size_t stride, void *data)
Definition: objspace.c:421
NODE_DSYM
Definition: node.h:227
NODE_SCOPE
Definition: node.h:23
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:676
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
NODE_LAMBDA
Definition: node.h:233
memsize_of_all_m
static VALUE memsize_of_all_m(int argc, VALUE *argv, VALUE self)
Definition: objspace.c:104
gc.h
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:652
T_HASH
#define T_HASH
Definition: ruby.h:485
reachable_object_from_i
static void reachable_object_from_i(VALUE obj, void *data_ptr)
Definition: objspace.c:565
NODE_DEFS
Definition: node.h:177
NODE_TRUE
Definition: node.h:209
NODE_CREF
Definition: node.h:195
DATA_PTR
#define DATA_PTR(dta)
Definition: ruby.h:992
rb_objspace_each_objects
void rb_objspace_each_objects(each_obj_callback *callback, void *data)
Definition: gc.c:1761
NODE_DREGX
Definition: node.h:149
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:3604
rb_objspace_markable_object_p
int rb_objspace_markable_object_p(VALUE obj)
Definition: gc.c:2281
NODE_DEFN
Definition: node.h:175
T_ARRAY
#define T_ARRAY
Definition: ruby.h:484
NODE_OP_ASGN_OR
Definition: node.h:89
T_UNDEF
#define T_UNDEF
Definition: ruby.h:497
nd_type
#define nd_type(n)
Definition: node.h:282
io.h
rof_data::internals
VALUE internals
Definition: objspace.c:561
NODE_MEMO
Definition: node.h:223
RHASH_TBL
#define RHASH_TBL(h)
Definition: ruby.h:927
NODE_RESCUE
Definition: node.h:53
NODE_CLASS
Definition: node.h:185
NODE_IF
Definition: node.h:27
NODE_ENSURE
Definition: node.h:57
st_data_t
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
Definition: st.h:20
RNode
Definition: node.h:239
total_data::klass
VALUE klass
Definition: objspace.c:44
rb_hash_foreach
void rb_hash_foreach(VALUE hash, int(*func)(ANYARGS), VALUE farg)
Definition: hash.c:264
FL_SINGLETON
#define FL_SINGLETON
Definition: ruby.h:1133
NODE_NTH_REF
Definition: node.h:127
rb_obj_memsize_of
size_t rb_obj_memsize_of(VALUE obj)
Definition: gc.c:2548
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
iow_type
static VALUE iow_type(VALUE self)
Definition: objspace.c:535
iow_size
static size_t iow_size(const void *ptr)
Definition: objspace.c:513
CASE_TYPE
#define CASE_TYPE(t)
FL_TEST
#define FL_TEST(x, f)
Definition: ruby.h:1169
NODE_COLON2
Definition: node.h:191
NODE_CONST
Definition: node.h:123
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1393
NODE_GVAR
Definition: node.h:119
val
#define val
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1553
NODE_ARGSPUSH
Definition: node.h:165
NODE_FLIP2
Definition: node.h:201
NODE_RESBODY
Definition: node.h:55
T_NIL
#define T_NIL
Definition: ruby.h:476
NODE_POSTEXE
Definition: node.h:217
NODE_ARGS
Definition: node.h:153
NODE_RETURN
Definition: node.h:111
rb_typeddata_is_kind_of
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:510
NODE_OP_ASGN2
Definition: node.h:85
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:495
T_TRUE
#define T_TRUE
Definition: ruby.h:490
NODE_OP_ASGN_AND
Definition: node.h:87
NIL_P
#define NIL_P(v)
Definition: ruby.h:438
rofr_data::categories
VALUE categories
Definition: objspace.c:655
NODE_EVSTR
Definition: node.h:147
NODE_PRELUDE
Definition: node.h:231
reachable_objects_from
static VALUE reachable_objects_from(VALUE self, VALUE obj)
Definition: objspace.c:631
NODE_ALIAS
Definition: node.h:179
NODE_OP_CDECL
Definition: node.h:91
NODE_POSTARG
Definition: node.h:161
NODE_SELF
Definition: node.h:205
T_FLOAT
#define T_FLOAT
Definition: ruby.h:481
NODE_BLOCK_PASS
Definition: node.h:173
argc
int argc
Definition: ruby.c:131
NODE_AND
Definition: node.h:59
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:487
T_NODE
#define T_NODE
Definition: ruby.h:498
NODE_OPT_ARG
Definition: node.h:157
NODE_IVAR
Definition: node.h:121
rb_str_new2
#define rb_str_new2
Definition: intern.h:840
T_COMPLEX
#define T_COMPLEX
Definition: ruby.h:496
NODE_BEGIN
Definition: node.h:51
rof_data::refs
st_table * refs
Definition: objspace.c:560
total_i
static int total_i(void *vstart, void *vend, size_t stride, void *ptr)
Definition: objspace.c:48
memsize_of_m
static VALUE memsize_of_m(VALUE self, VALUE obj)
Definition: objspace.c:37
count_nodes
static VALUE count_nodes(int argc, VALUE *argv, VALUE os)
Definition: objspace.c:276
rb_const_get
VALUE rb_const_get(VALUE, ID)
Definition: variable.c:1880
iow_inspect
static VALUE iow_inspect(VALUE self)
Definition: objspace.c:543
rb_define_module_function
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
Definition: class.c:1670
iow_internal_object_id
static VALUE iow_internal_object_id(VALUE self)
Definition: objspace.c:553
NODE_ERRINFO
Definition: node.h:213
T_DATA
#define T_DATA
Definition: ruby.h:492
reachable_objects_from_root
static VALUE reachable_objects_from_root(VALUE self)
Definition: objspace.c:709
rb_objspace_internal_object_p
int rb_objspace_internal_object_p(VALUE obj)
Definition: gc.c:1810
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1250
NODE_KW_ARG
Definition: node.h:159
count_tdata_objects
static VALUE count_tdata_objects(int argc, VALUE *argv, VALUE self)
Definition: objspace.c:485
NODE_SPLAT
Definition: node.h:167
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:298
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
NODE_UNDEF
Definition: node.h:183
NODE_BMETHOD
Definition: node.h:221
internal.h
Qnil
#define Qnil
Definition: ruby.h:427
T_STRUCT
#define T_STRUCT
Definition: ruby.h:486
type
int type
Definition: tcltklib.c:112
NODE_SUPER
Definition: node.h:99
BUILTIN_TYPE
#define BUILTIN_TYPE(x)
Definition: ruby.h:502
VALUE
unsigned long VALUE
Definition: ruby.h:88
NODE_VCALL
Definition: node.h:97
RBASIC
#define RBASIC(obj)
Definition: ruby.h:1116
rb_objspace_data_type_name
const char * rb_objspace_data_type_name(VALUE obj)
Definition: gc.c:1394
rof_data
Definition: objspace.c:559
FIX2INT
#define FIX2INT(x)
Definition: ruby.h:632
set_zero_i
static int set_zero_i(st_data_t key, st_data_t val, st_data_t arg)
Definition: objspace.c:117
NODE_MATCH2
Definition: node.h:133
Init_object_tracing
void Init_object_tracing(VALUE rb_mObjSpace)
Definition: object_tracing.c:472
re.h
total_data::total
size_t total
Definition: objspace.c:43
st_init_numtable
st_table * st_init_numtable(void)
Definition: st.c:272
NODE_YIELD
Definition: node.h:113
NODE_ALLOCA
Definition: node.h:219
ruby_value_type
ruby_value_type
Definition: ruby.h:442
NODE_DASGN_CURR
Definition: node.h:69
collect_values
static int collect_values(st_data_t key, st_data_t value, st_data_t data)
Definition: objspace.c:581
NODE_DOT3
Definition: node.h:199
NODE_BREAK
Definition: node.h:43
NODE_RETRY
Definition: node.h:49
rb_data_typed_object_alloc
VALUE rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type)
Definition: gc.c:1376
NODE_XSTR
Definition: node.h:143
collect_values_of_values
static int collect_values_of_values(VALUE category, VALUE category_objects, VALUE categories)
Definition: objspace.c:694
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:231
NODE_WHILE
Definition: node.h:35
NODE_SCLASS
Definition: node.h:189
cos_i
static int cos_i(void *vstart, void *vend, size_t stride, void *data)
Definition: objspace.c:126
NODE_DVAR
Definition: node.h:117
reachable_object_from_root_i
static void reachable_object_from_root_i(const char *category, VALUE obj, void *ptr)
Definition: objspace.c:662
NODE_NEXT
Definition: node.h:45
rb_objspace_reachable_objects_from
void rb_objspace_reachable_objects_from(VALUE obj, void(func)(VALUE, void *), void *data)
Definition: gc.c:5779
rb_data_type_struct
Definition: ruby.h:966
NODE_NIL
Definition: node.h:207
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:697
key
uint8_t key[16]
Definition: random.c:1250
NODE_STR
Definition: node.h:139
T_STRING
#define T_STRING
Definition: ruby.h:482
T_FALSE
#define T_FALSE
Definition: ruby.h:491
T_FILE
#define T_FILE
Definition: ruby.h:488
iow_newobj
static VALUE iow_newobj(VALUE obj)
Definition: objspace.c:528
type2sym
static VALUE type2sym(enum ruby_value_type i)
Definition: objspace.c:140
st.h
hash
static unsigned int hash(const char *str, unsigned int len)
Definition: lex.c:56
NODE_FALSE
Definition: node.h:211
T_CLASS
#define T_CLASS
Definition: ruby.h:478
NODE_GASGN
Definition: node.h:71
name
const char * name
Definition: nkf.c:208
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:355
NODE_OR
Definition: node.h:61
cn_i
static int cn_i(void *vstart, void *vend, size_t stride, void *n)
Definition: objspace.c:237
rb_id2name
const char * rb_id2name(ID id)
Definition: ripper.c:17230
NODE_COLON3
Definition: node.h:193
NODE_HASH
Definition: node.h:109
NODE_OPT_N
Definition: node.h:33
NODE_WHEN
Definition: node.h:31
NODE_ATTRASGN
Definition: node.h:229
NODE_LASGN
Definition: node.h:65
NODE_LVAR
Definition: node.h:115
NODE_MATCH
Definition: node.h:131
NODE_FOR
Definition: node.h:41
RHASH_EMPTY_P
#define RHASH_EMPTY_P(h)
Definition: ruby.h:931
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:746
rb_intern
#define rb_intern(str)
NODE_OP_ASGN1
Definition: node.h:83
T_ZOMBIE
#define T_ZOMBIE
Definition: ruby.h:499
T_NONE
#define T_NONE
Definition: ruby.h:475
total_data
Definition: objspace.c:42
NULL
#define NULL
Definition: _sdbm.c:103
T_ICLASS
#define T_ICLASS
Definition: ruby.h:479
NODE_MATCH3
Definition: node.h:135
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
Init_objspace_dump
void Init_objspace_dump(VALUE rb_mObjSpace)
Definition: objspace_dump.c:416
st_foreach
int st_foreach(st_table *, int(*)(ANYARGS), st_data_t)
Definition: st.c:1034
NODE_IASGN
Definition: node.h:73
SIZET2NUM
#define SIZET2NUM(v)
Definition: ruby.h:262
rofr_data::last_category_objects
VALUE last_category_objects
Definition: objspace.c:658
T_REGEXP
#define T_REGEXP
Definition: ruby.h:483
NODE_ARGS_AUX
Definition: node.h:155
NODE_LIT
Definition: node.h:137
T_MASK
#define T_MASK
Definition: md5.c:131
NODE_DREGX_ONCE
Definition: node.h:151
COUNT_NODE
#define COUNT_NODE(n)
iow_mark
static void iow_mark(void *ptr)
Definition: objspace.c:507
argv
char ** argv
Definition: ruby.c:132