Ruby: ext/objspace/object_tracing.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

object_tracing.c
Go to the documentation of this file.
1/**********************************************************************
2
3 object_tracing.c - Object Tracing mechanism/ObjectSpace extender for MRI.
4
5 $Author$
6 created at: Mon May 27 16:27:44 2013
7
8 NOTE: This extension library is not expected to exist except C Ruby.
9 NOTE: This feature is an example usage of internal event tracing APIs.
10
11 All the files in this distribution are covered under the Ruby's
12 license (see the file COPYING).
13
14**********************************************************************/
15
16#include "internal.h"
17#include "ruby/debug.h"
18#include "objspace.h"
19
20 struct traceobj_arg {
21 int running;
22 int keep_remains;
23 VALUE newobj_trace;
24 VALUE freeobj_trace;
25 st_table *object_table; /* obj (VALUE) -> allocation_info */
26 st_table *str_table; /* cstr -> refcount */
27 struct traceobj_arg *prev_traceobj_arg;
28};
29
30static const char *
31make_unique_str(st_table *tbl, const char *str, long len)
32{
33 if (!str) {
34 return NULL;
35 }
36 else {
37 st_data_t n;
38 char *result;
39
40 if (st_lookup(tbl, (st_data_t)str, &n)) {
41 st_insert(tbl, (st_data_t)str, n+1);
42 st_get_key(tbl, (st_data_t)str, &n);
43 result = (char *)n;
44 }
45 else {
46 result = (char *)ruby_xmalloc(len+1);
47 strncpy(result, str, len);
48 result[len] = 0;
49 st_add_direct(tbl, (st_data_t)result, 1);
50 }
51 return result;
52 }
53}
54
55static void
56delete_unique_str(st_table *tbl, const char *str)
57{
58 if (str) {
59 st_data_t n;
60
61 st_lookup(tbl, (st_data_t)str, &n);
62 if (n == 1) {
63 n = (st_data_t)str;
64 st_delete(tbl, &n, 0);
65 ruby_xfree((char *)n);
66 }
67 else {
68 st_insert(tbl, (st_data_t)str, n-1);
69 }
70 }
71}
72
73static void
74newobj_i(VALUE tpval, void *data)
75{
76 struct traceobj_arg *arg = (struct traceobj_arg *)data;
77 rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval);
78 VALUE obj = rb_tracearg_object(tparg);
79 VALUE path = rb_tracearg_path(tparg);
80 VALUE line = rb_tracearg_lineno(tparg);
81 VALUE mid = rb_tracearg_method_id(tparg);
82 VALUE klass = rb_tracearg_defined_class(tparg);
83 struct allocation_info *info;
84 const char *path_cstr = RTEST(path) ? make_unique_str(arg->str_table, RSTRING_PTR(path), RSTRING_LEN(path)) : 0;
85 VALUE class_path = (RTEST(klass) && !OBJ_FROZEN(klass)) ? rb_class_path_cached(klass) : Qnil;
86 const char *class_path_cstr = RTEST(class_path) ? make_unique_str(arg->str_table, RSTRING_PTR(class_path), RSTRING_LEN(class_path)) : 0;
87 st_data_t v;
88
89 if (st_lookup(arg->object_table, (st_data_t)obj, &v)) {
90 info = (struct allocation_info *)v;
91 if (arg->keep_remains) {
92 if (info->living) {
93 /* do nothing. there is possibility to keep living if FREEOBJ events while suppressing tracing */
94 }
95 }
96 /* reuse info */
97 delete_unique_str(arg->str_table, info->path);
98 delete_unique_str(arg->str_table, info->class_path);
99 }
100 else {
101 info = (struct allocation_info *)ruby_xmalloc(sizeof(struct allocation_info));
102 }
103 info->living = 1;
104 info->flags = RBASIC(obj)->flags;
105 info->klass = RBASIC_CLASS(obj);
106
107 info->path = path_cstr;
108 info->line = NUM2INT(line);
109 info->mid = mid;
110 info->class_path = class_path_cstr;
111 info->generation = rb_gc_count();
112 st_insert(arg->object_table, (st_data_t)obj, (st_data_t)info);
113}
114
115static void
116freeobj_i(VALUE tpval, void *data)
117{
118 struct traceobj_arg *arg = (struct traceobj_arg *)data;
119 rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval);
120 st_data_t obj = (st_data_t)rb_tracearg_object(tparg);
121 st_data_t v;
122 struct allocation_info *info;
123
124 if (arg->keep_remains) {
125 if (st_lookup(arg->object_table, obj, &v)) {
126 info = (struct allocation_info *)v;
127 info->living = 0;
128 }
129 }
130 else {
131 if (st_delete(arg->object_table, &obj, &v)) {
132 info = (struct allocation_info *)v;
133 delete_unique_str(arg->str_table, info->path);
134 delete_unique_str(arg->str_table, info->class_path);
135 ruby_xfree(info);
136 }
137 }
138}
139
140static int
141free_keys_i(st_data_t key, st_data_t value, st_data_t data)
142{
143 ruby_xfree((void *)key);
144 return ST_CONTINUE;
145}
146
147static int
148free_values_i(st_data_t key, st_data_t value, st_data_t data)
149{
150 ruby_xfree((void *)value);
151 return ST_CONTINUE;
152}
153
154static void
155allocation_info_tracer_mark(void *ptr)
156{
157 struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
158 rb_gc_mark(trace_arg->newobj_trace);
159 rb_gc_mark(trace_arg->freeobj_trace);
160}
161
162static void
163allocation_info_tracer_free(void *ptr)
164{
165 struct traceobj_arg *arg = (struct traceobj_arg *)ptr;
166 /* clear tables */
167 st_foreach(arg->object_table, free_values_i, 0);
168 st_free_table(arg->object_table);
169 st_foreach(arg->str_table, free_keys_i, 0);
170 st_free_table(arg->str_table);
171 xfree(arg);
172}
173
174static size_t
175allocation_info_tracer_memsize(const void *ptr)
176{
177 size_t size;
178 struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
179 size = sizeof(*trace_arg);
180 size += st_memsize(trace_arg->object_table);
181 size += st_memsize(trace_arg->str_table);
182 return size;
183}
184
185static int
186hash_foreach_should_replace_key(st_data_t key, st_data_t value, st_data_t argp, int error)
187{
188 VALUE allocated_object;
189
190 allocated_object = (VALUE)value;
191 if (allocated_object != rb_gc_location(allocated_object)) {
192 return ST_REPLACE;
193 }
194
195 return ST_CONTINUE;
196}
197
198static int
199hash_replace_key(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
200{
201 *key = rb_gc_location((VALUE)*key);
202
203 return ST_CONTINUE;
204}
205
206static void
207allocation_info_tracer_compact(void *ptr)
208{
209 struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
210
211 if (trace_arg->object_table &&
212 st_foreach_with_replace(trace_arg->object_table, hash_foreach_should_replace_key, hash_replace_key, 0)) {
213 rb_raise(rb_eRuntimeError, "hash modified during iteration");
214 }
215}
216
217static const rb_data_type_t allocation_info_tracer_type = {
218 "ObjectTracing/allocation_info_tracer",
219 {
220 allocation_info_tracer_mark,
221 allocation_info_tracer_free, /* Never called because global */
222 allocation_info_tracer_memsize,
223 allocation_info_tracer_compact,
224 },
225 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
226};
227
228static VALUE traceobj_arg;
229static struct traceobj_arg *tmp_trace_arg; /* TODO: Do not use global variables */
230static int tmp_keep_remains; /* TODO: Do not use global variables */
231
232static struct traceobj_arg *
233get_traceobj_arg(void)
234{
235 if (tmp_trace_arg == 0) {
236 VALUE obj = TypedData_Make_Struct(rb_cObject, struct traceobj_arg, &allocation_info_tracer_type, tmp_trace_arg);
237 traceobj_arg = obj;
238 rb_gc_register_mark_object(traceobj_arg);
239 tmp_trace_arg->running = 0;
240 tmp_trace_arg->keep_remains = tmp_keep_remains;
241 tmp_trace_arg->newobj_trace = 0;
242 tmp_trace_arg->freeobj_trace = 0;
243 tmp_trace_arg->object_table = st_init_numtable();
244 tmp_trace_arg->str_table = st_init_strtable();
245 }
246 return tmp_trace_arg;
247}
248
249/*
250 * call-seq: trace_object_allocations_start
251 *
252 * Starts tracing object allocations.
253 *
254 */
255static VALUE
256trace_object_allocations_start(VALUE self)
257{
258 struct traceobj_arg *arg = get_traceobj_arg();
259
260 if (arg->running++ > 0) {
261 /* do nothing */
262 }
263 else {
264 if (arg->newobj_trace == 0) {
265 arg->newobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, newobj_i, arg);
266 arg->freeobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_FREEOBJ, freeobj_i, arg);
267 }
268 rb_tracepoint_enable(arg->newobj_trace);
269 rb_tracepoint_enable(arg->freeobj_trace);
270 }
271
272 return Qnil;
273}
274
275/*
276 * call-seq: trace_object_allocations_stop
277 *
278 * Stop tracing object allocations.
279 *
280 * Note that if ::trace_object_allocations_start is called n-times, then
281 * tracing will stop after calling ::trace_object_allocations_stop n-times.
282 *
283 */
284static VALUE
285trace_object_allocations_stop(VALUE self)
286{
287 struct traceobj_arg *arg = get_traceobj_arg();
288
289 if (arg->running > 0) {
290 arg->running--;
291 }
292
293 if (arg->running == 0) {
294 if (arg->newobj_trace != 0) {
295 rb_tracepoint_disable(arg->newobj_trace);
296 }
297 if (arg->freeobj_trace != 0) {
298 rb_tracepoint_disable(arg->freeobj_trace);
299 }
300 }
301
302 return Qnil;
303}
304
305/*
306 * call-seq: trace_object_allocations_clear
307 *
308 * Clear recorded tracing information.
309 *
310 */
311static VALUE
312trace_object_allocations_clear(VALUE self)
313{
314 struct traceobj_arg *arg = get_traceobj_arg();
315
316 /* clear tables */
317 st_foreach(arg->object_table, free_values_i, 0);
318 st_clear(arg->object_table);
319 st_foreach(arg->str_table, free_keys_i, 0);
320 st_clear(arg->str_table);
321
322 /* do not touch TracePoints */
323
324 return Qnil;
325}
326
327/*
328 * call-seq: trace_object_allocations { block }
329 *
330 * Starts tracing object allocations from the ObjectSpace extension module.
331 *
332 * For example:
333 *
334 * require 'objspace'
335 *
336 * class C
337 * include ObjectSpace
338 *
339 * def foo
340 * trace_object_allocations do
341 * obj = Object.new
342 * p "#{allocation_sourcefile(obj)}:#{allocation_sourceline(obj)}"
343 * end
344 * end
345 * end
346 *
347 * C.new.foo #=> "objtrace.rb:8"
348 *
349 * This example has included the ObjectSpace module to make it easier to read,
350 * but you can also use the ::trace_object_allocations notation (recommended).
351 *
352 * Note that this feature introduces a huge performance decrease and huge
353 * memory consumption.
354 */
355static VALUE
356trace_object_allocations(VALUE self)
357{
358 trace_object_allocations_start(self);
359 return rb_ensure(rb_yield, Qnil, trace_object_allocations_stop, self);
360}
361
362int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data);
363static int object_allocations_reporter_registered = 0;
364
365static int
366object_allocations_reporter_i(st_data_t key, st_data_t val, st_data_t ptr)
367{
368 FILE *out = (FILE *)ptr;
369 VALUE obj = (VALUE)key;
370 struct allocation_info *info = (struct allocation_info *)val;
371
372 fprintf(out, "-- %p (%s F: %p, ", (void *)obj, info->living ? "live" : "dead", (void *)info->flags);
373 if (info->class_path) fprintf(out, "C: %s", info->class_path);
374 else fprintf(out, "C: %p", (void *)info->klass);
375 fprintf(out, "@%s:%lu", info->path ? info->path : "", info->line);
376 if (!NIL_P(info->mid)) {
377 VALUE m = rb_sym2str(info->mid);
378 fprintf(out, " (%s)", RSTRING_PTR(m));
379 }
380 fprintf(out, ")\n");
381
382 return ST_CONTINUE;
383}
384
385static void
386object_allocations_reporter(FILE *out, void *ptr)
387{
388 fprintf(out, "== object_allocations_reporter: START\n");
389 if (tmp_trace_arg) {
390 st_foreach(tmp_trace_arg->object_table, object_allocations_reporter_i, (st_data_t)out);
391 }
392 fprintf(out, "== object_allocations_reporter: END\n");
393}
394
395static VALUE
396trace_object_allocations_debug_start(VALUE self)
397{
398 tmp_keep_remains = 1;
399 if (object_allocations_reporter_registered == 0) {
400 object_allocations_reporter_registered = 1;
401 rb_bug_reporter_add(object_allocations_reporter, 0);
402 }
403
404 return trace_object_allocations_start(self);
405}
406
407static struct allocation_info *
408lookup_allocation_info(VALUE obj)
409{
410 if (tmp_trace_arg) {
411 st_data_t info;
412 if (st_lookup(tmp_trace_arg->object_table, obj, &info)) {
413 return (struct allocation_info *)info;
414 }
415 }
416 return NULL;
417}
418
419struct allocation_info *
420objspace_lookup_allocation_info(VALUE obj)
421{
422 return lookup_allocation_info(obj);
423}
424
425/*
426 * call-seq: allocation_sourcefile(object) -> string
427 *
428 * Returns the source file origin from the given +object+.
429 *
430 * See ::trace_object_allocations for more information and examples.
431 */
432static VALUE
433allocation_sourcefile(VALUE self, VALUE obj)
434{
435 struct allocation_info *info = lookup_allocation_info(obj);
436
437 if (info && info->path) {
438 return rb_str_new2(info->path);
439 }
440 else {
441 return Qnil;
442 }
443}
444
445/*
446 * call-seq: allocation_sourceline(object) -> integer
447 *
448 * Returns the original line from source for from the given +object+.
449 *
450 * See ::trace_object_allocations for more information and examples.
451 */
452static VALUE
453allocation_sourceline(VALUE self, VALUE obj)
454{
455 struct allocation_info *info = lookup_allocation_info(obj);
456
457 if (info) {
458 return INT2FIX(info->line);
459 }
460 else {
461 return Qnil;
462 }
463}
464
465/*
466 * call-seq: allocation_class_path(object) -> string
467 *
468 * Returns the class for the given +object+.
469 *
470 * class A
471 * def foo
472 * ObjectSpace::trace_object_allocations do
473 * obj = Object.new
474 * p "#{ObjectSpace::allocation_class_path(obj)}"
475 * end
476 * end
477 * end
478 *
479 * A.new.foo #=> "Class"
480 *
481 * See ::trace_object_allocations for more information and examples.
482 */
483static VALUE
484allocation_class_path(VALUE self, VALUE obj)
485{
486 struct allocation_info *info = lookup_allocation_info(obj);
487
488 if (info && info->class_path) {
489 return rb_str_new2(info->class_path);
490 }
491 else {
492 return Qnil;
493 }
494}
495
496/*
497 * call-seq: allocation_method_id(object) -> string
498 *
499 * Returns the method identifier for the given +object+.
500 *
501 * class A
502 * include ObjectSpace
503 *
504 * def foo
505 * trace_object_allocations do
506 * obj = Object.new
507 * p "#{allocation_class_path(obj)}##{allocation_method_id(obj)}"
508 * end
509 * end
510 * end
511 *
512 * A.new.foo #=> "Class#new"
513 *
514 * See ::trace_object_allocations for more information and examples.
515 */
516static VALUE
517allocation_method_id(VALUE self, VALUE obj)
518{
519 struct allocation_info *info = lookup_allocation_info(obj);
520 if (info) {
521 return info->mid;
522 }
523 else {
524 return Qnil;
525 }
526}
527
528/*
529 * call-seq: allocation_generation(object) -> integer or nil
530 *
531 * Returns garbage collector generation for the given +object+.
532 *
533 * class B
534 * include ObjectSpace
535 *
536 * def foo
537 * trace_object_allocations do
538 * obj = Object.new
539 * p "Generation is #{allocation_generation(obj)}"
540 * end
541 * end
542 * end
543 *
544 * B.new.foo #=> "Generation is 3"
545 *
546 * See ::trace_object_allocations for more information and examples.
547 */
548static VALUE
549allocation_generation(VALUE self, VALUE obj)
550{
551 struct allocation_info *info = lookup_allocation_info(obj);
552 if (info) {
553 return SIZET2NUM(info->generation);
554 }
555 else {
556 return Qnil;
557 }
558}
559
560void
561Init_object_tracing(VALUE rb_mObjSpace)
562{
563#if 0
564 rb_mObjSpace = rb_define_module("ObjectSpace"); /* let rdoc know */
565#endif
566
567 rb_define_module_function(rb_mObjSpace, "trace_object_allocations", trace_object_allocations, 0);
568 rb_define_module_function(rb_mObjSpace, "trace_object_allocations_start", trace_object_allocations_start, 0);
569 rb_define_module_function(rb_mObjSpace, "trace_object_allocations_stop", trace_object_allocations_stop, 0);
570 rb_define_module_function(rb_mObjSpace, "trace_object_allocations_clear", trace_object_allocations_clear, 0);
571
572 rb_define_module_function(rb_mObjSpace, "trace_object_allocations_debug_start", trace_object_allocations_debug_start, 0);
573
574 rb_define_module_function(rb_mObjSpace, "allocation_sourcefile", allocation_sourcefile, 1);
575 rb_define_module_function(rb_mObjSpace, "allocation_sourceline", allocation_sourceline, 1);
576 rb_define_module_function(rb_mObjSpace, "allocation_class_path", allocation_class_path, 1);
577 rb_define_module_function(rb_mObjSpace, "allocation_method_id", allocation_method_id, 1);
578 rb_define_module_function(rb_mObjSpace, "allocation_generation", allocation_generation, 1);
579}
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
debug.h
rb_tracearg_object
VALUE rb_tracearg_object(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:1018
rb_tracearg_defined_class
VALUE rb_tracearg_defined_class(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:910
rb_tracepoint_new
VALUE rb_tracepoint_new(VALUE target_thread_not_supported_yet, rb_event_flag_t events, void(*func)(VALUE, void *), void *data)
Definition: vm_trace.c:1407
rb_tracepoint_disable
VALUE rb_tracepoint_disable(VALUE tpval)
Definition: vm_trace.c:1233
rb_tracearg_path
VALUE rb_tracearg_path(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:828
rb_tracepoint_enable
VALUE rb_tracepoint_enable(VALUE tpval)
Definition: vm_trace.c:1125
rb_tracearg_method_id
VALUE rb_tracearg_method_id(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:896
rb_tracearg_from_tracepoint
rb_trace_arg_t * rb_tracearg_from_tracepoint(VALUE tpval)
Definition: vm_trace.c:796
rb_tracearg_lineno
VALUE rb_tracearg_lineno(rb_trace_arg_t *trace_arg)
Definition: vm_trace.c:822
out
string_t out
Definition: enough.c:230
len
uint8_t len
Definition: escape.c:17
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
RUBY_INTERNAL_EVENT_FREEOBJ
#define RUBY_INTERNAL_EVENT_FREEOBJ
Definition: event.h:57
RUBY_INTERNAL_EVENT_NEWOBJ
#define RUBY_INTERNAL_EVENT_NEWOBJ
Definition: event.h:56
RSTRING_LEN
#define RSTRING_LEN(string)
Definition: fbuffer.h:22
RSTRING_PTR
#define RSTRING_PTR(string)
Definition: fbuffer.h:19
ruby_xfree
void ruby_xfree(void *x)
Deallocates a storage instance.
Definition: gc.c:10914
rb_gc_location
VALUE rb_gc_location(VALUE value)
Definition: gc.c:9003
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:6112
ruby_xmalloc
void * ruby_xmalloc(size_t size)
Allocates a storage instance.
Definition: gc.c:12795
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Inform the garbage collector that object is a live Ruby object that should not be moved.
Definition: gc.c:8022
rb_gc_count
size_t rb_gc_count(void)
Definition: gc.c:9529
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:871
OBJ_FROZEN
#define OBJ_FROZEN
Definition: fl_type.h:136
rb_bug_reporter_add
int rb_bug_reporter_add(void(*func)(FILE *, void *), void *data)
Definition: error.c:587
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2917
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:1055
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1148
rb_cObject
VALUE rb_cObject
Object class.
Definition: object.c:49
rb_str_new2
#define rb_str_new2
Definition: string.h:276
rb_class_path_cached
VALUE rb_class_path_cached(VALUE)
Definition: variable.c:178
rb_sym2str
VALUE rb_sym2str(VALUE)
Definition: symbol.c:927
NUM2INT
#define NUM2INT
Definition: int.h:44
internal.h
size
voidpf void uLong size
Definition: ioapi.h:138
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1341
INT2FIX
#define INT2FIX
Definition: long.h:48
Init_object_tracing
void Init_object_tracing(VALUE rb_mObjSpace)
Definition: object_tracing.c:561
objspace_lookup_allocation_info
struct allocation_info * objspace_lookup_allocation_info(VALUE obj)
Definition: object_tracing.c:420
objspace.h
key
key
Definition: openssl_missing.h:185
RBASIC
#define RBASIC(obj)
Definition: rbasic.h:34
RBASIC_CLASS
#define RBASIC_CLASS
Definition: rbasic.h:35
NULL
#define NULL
Definition: regenc.h:69
RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_FREE_IMMEDIATELY
Definition: rtypeddata.h:62
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: rtypeddata.h:122
SIZET2NUM
#define SIZET2NUM
Definition: size_t.h:52
RTEST
#define RTEST
Definition: special_consts.h:42
Qnil
#define Qnil
Definition: special_consts.h:51
NIL_P
#define NIL_P
Definition: special_consts.h:46
ST_REPLACE
@ ST_REPLACE
Definition: st.h:99
ST_CONTINUE
@ ST_CONTINUE
Definition: st.h:99
st_data_t
unsigned long st_data_t
Definition: st.h:22
st_get_key
#define st_get_key
Definition: st.h:130
st_foreach
#define st_foreach
Definition: st.h:142
st_init_numtable
#define st_init_numtable
Definition: st.h:106
st_lookup
#define st_lookup
Definition: st.h:128
st_clear
#define st_clear
Definition: st.h:160
st_add_direct
#define st_add_direct
Definition: st.h:154
st_delete
#define st_delete
Definition: st.h:118
st_memsize
#define st_memsize
Definition: st.h:174
st_insert
#define st_insert
Definition: st.h:124
st_foreach_with_replace
#define st_foreach_with_replace
Definition: st.h:140
st_free_table
#define st_free_table
Definition: st.h:156
st_init_strtable
#define st_init_strtable
Definition: st.h:110
__sFILE
Definition: vsnprintf.c:169
allocation_info
Definition: objspace.h:5
allocation_info::class_path
const char * class_path
Definition: objspace.h:14
allocation_info::flags
VALUE flags
Definition: objspace.h:8
allocation_info::klass
VALUE klass
Definition: objspace.h:9
allocation_info::line
unsigned long line
Definition: objspace.h:13
allocation_info::path
const char * path
Definition: objspace.h:12
allocation_info::generation
size_t generation
Definition: objspace.h:16
allocation_info::mid
VALUE mid
Definition: objspace.h:15
allocation_info::living
int living
Definition: objspace.h:7
rb_data_type_struct
Definition: rtypeddata.h:70
rb_trace_arg_struct
Definition: vm_core.h:1933
st_table
Definition: st.h:79
traceobj_arg
Definition: object_tracing.c:20
traceobj_arg::str_table
st_table * str_table
Definition: object_tracing.c:26
traceobj_arg::prev_traceobj_arg
struct traceobj_arg * prev_traceobj_arg
Definition: object_tracing.c:27
traceobj_arg::keep_remains
int keep_remains
Definition: object_tracing.c:22
traceobj_arg::object_table
st_table * object_table
Definition: object_tracing.c:25
traceobj_arg::running
int running
Definition: object_tracing.c:21
traceobj_arg::freeobj_trace
VALUE freeobj_trace
Definition: object_tracing.c:24
traceobj_arg::newobj_trace
VALUE newobj_trace
Definition: object_tracing.c:23
error
void error(const char *msg)
Definition: untgz.c:593
VALUE
unsigned long VALUE
Definition: value.h:38
xfree
#define xfree
Definition: xmalloc.h:49