ruby-prof 0.18.0-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +500 -0
  3. data/LICENSE +25 -0
  4. data/README.rdoc +487 -0
  5. data/Rakefile +113 -0
  6. data/bin/ruby-prof +345 -0
  7. data/bin/ruby-prof-check-trace +45 -0
  8. data/examples/flat.txt +50 -0
  9. data/examples/graph.dot +84 -0
  10. data/examples/graph.html +823 -0
  11. data/examples/graph.txt +139 -0
  12. data/examples/multi.flat.txt +23 -0
  13. data/examples/multi.graph.html +760 -0
  14. data/examples/multi.grind.dat +114 -0
  15. data/examples/multi.stack.html +547 -0
  16. data/examples/stack.html +547 -0
  17. data/ext/ruby_prof/extconf.rb +68 -0
  18. data/ext/ruby_prof/rp_call_info.c +425 -0
  19. data/ext/ruby_prof/rp_call_info.h +53 -0
  20. data/ext/ruby_prof/rp_measure.c +40 -0
  21. data/ext/ruby_prof/rp_measure.h +45 -0
  22. data/ext/ruby_prof/rp_measure_allocations.c +76 -0
  23. data/ext/ruby_prof/rp_measure_cpu_time.c +136 -0
  24. data/ext/ruby_prof/rp_measure_gc_runs.c +73 -0
  25. data/ext/ruby_prof/rp_measure_gc_time.c +60 -0
  26. data/ext/ruby_prof/rp_measure_memory.c +77 -0
  27. data/ext/ruby_prof/rp_measure_process_time.c +71 -0
  28. data/ext/ruby_prof/rp_measure_wall_time.c +45 -0
  29. data/ext/ruby_prof/rp_method.c +630 -0
  30. data/ext/ruby_prof/rp_method.h +75 -0
  31. data/ext/ruby_prof/rp_stack.c +173 -0
  32. data/ext/ruby_prof/rp_stack.h +63 -0
  33. data/ext/ruby_prof/rp_thread.c +277 -0
  34. data/ext/ruby_prof/rp_thread.h +27 -0
  35. data/ext/ruby_prof/ruby_prof.c +794 -0
  36. data/ext/ruby_prof/ruby_prof.h +60 -0
  37. data/ext/ruby_prof/vc/ruby_prof.sln +31 -0
  38. data/ext/ruby_prof/vc/ruby_prof.vcxproj +141 -0
  39. data/lib/2.6.3/ruby_prof.so +0 -0
  40. data/lib/ruby-prof.rb +68 -0
  41. data/lib/ruby-prof/aggregate_call_info.rb +76 -0
  42. data/lib/ruby-prof/assets/call_stack_printer.css.html +117 -0
  43. data/lib/ruby-prof/assets/call_stack_printer.js.html +385 -0
  44. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  45. data/lib/ruby-prof/call_info.rb +115 -0
  46. data/lib/ruby-prof/call_info_visitor.rb +40 -0
  47. data/lib/ruby-prof/compatibility.rb +179 -0
  48. data/lib/ruby-prof/method_info.rb +121 -0
  49. data/lib/ruby-prof/printers/abstract_printer.rb +104 -0
  50. data/lib/ruby-prof/printers/call_info_printer.rb +41 -0
  51. data/lib/ruby-prof/printers/call_stack_printer.rb +265 -0
  52. data/lib/ruby-prof/printers/call_tree_printer.rb +143 -0
  53. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  54. data/lib/ruby-prof/printers/flat_printer.rb +70 -0
  55. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +83 -0
  56. data/lib/ruby-prof/printers/graph_html_printer.rb +249 -0
  57. data/lib/ruby-prof/printers/graph_printer.rb +116 -0
  58. data/lib/ruby-prof/printers/multi_printer.rb +84 -0
  59. data/lib/ruby-prof/profile.rb +26 -0
  60. data/lib/ruby-prof/profile/exclude_common_methods.rb +207 -0
  61. data/lib/ruby-prof/profile/legacy_method_elimination.rb +50 -0
  62. data/lib/ruby-prof/rack.rb +174 -0
  63. data/lib/ruby-prof/task.rb +147 -0
  64. data/lib/ruby-prof/thread.rb +35 -0
  65. data/lib/ruby-prof/version.rb +3 -0
  66. data/lib/unprof.rb +10 -0
  67. data/ruby-prof.gemspec +58 -0
  68. data/test/abstract_printer_test.rb +53 -0
  69. data/test/aggregate_test.rb +136 -0
  70. data/test/basic_test.rb +128 -0
  71. data/test/block_test.rb +74 -0
  72. data/test/call_info_test.rb +78 -0
  73. data/test/call_info_visitor_test.rb +31 -0
  74. data/test/duplicate_names_test.rb +32 -0
  75. data/test/dynamic_method_test.rb +55 -0
  76. data/test/enumerable_test.rb +21 -0
  77. data/test/exceptions_test.rb +24 -0
  78. data/test/exclude_methods_test.rb +146 -0
  79. data/test/exclude_threads_test.rb +53 -0
  80. data/test/fiber_test.rb +79 -0
  81. data/test/issue137_test.rb +63 -0
  82. data/test/line_number_test.rb +80 -0
  83. data/test/measure_allocations_test.rb +26 -0
  84. data/test/measure_cpu_time_test.rb +212 -0
  85. data/test/measure_gc_runs_test.rb +32 -0
  86. data/test/measure_gc_time_test.rb +36 -0
  87. data/test/measure_memory_test.rb +33 -0
  88. data/test/measure_process_time_test.rb +61 -0
  89. data/test/measure_wall_time_test.rb +255 -0
  90. data/test/method_elimination_test.rb +84 -0
  91. data/test/module_test.rb +45 -0
  92. data/test/multi_printer_test.rb +104 -0
  93. data/test/no_method_class_test.rb +15 -0
  94. data/test/pause_resume_test.rb +166 -0
  95. data/test/prime.rb +54 -0
  96. data/test/printers_test.rb +275 -0
  97. data/test/printing_recursive_graph_test.rb +127 -0
  98. data/test/rack_test.rb +157 -0
  99. data/test/recursive_test.rb +215 -0
  100. data/test/singleton_test.rb +38 -0
  101. data/test/stack_printer_test.rb +77 -0
  102. data/test/stack_test.rb +138 -0
  103. data/test/start_stop_test.rb +112 -0
  104. data/test/test_helper.rb +267 -0
  105. data/test/thread_test.rb +187 -0
  106. data/test/unique_call_path_test.rb +202 -0
  107. data/test/yarv_test.rb +55 -0
  108. metadata +199 -0
@@ -0,0 +1,68 @@
1
+ require "mkmf"
2
+
3
+ if RUBY_ENGINE != "ruby"
4
+ STDERR.puts("\n\n***** This gem is MRI-specific. It does not support #{RUBY_ENGINE}. *****\n\n")
5
+ exit(1)
6
+ end
7
+
8
+ if RUBY_VERSION < "1.9.3"
9
+ STDERR.puts("\n\n***** Ruby version #{RUBY_VERSION} is no longer supported. Please upgrade to 1.9.3 or higher. *****\n\n")
10
+ exit(1)
11
+ end
12
+
13
+ # For the love of bitfields...
14
+ $CFLAGS += ' -std=c99'
15
+
16
+ # standard ruby methods
17
+ have_func("rb_gc_stat")
18
+ have_func("rb_gc_count")
19
+ have_func("rb_remove_event_hook_with_data")
20
+
21
+ # Alexander Dymo GC patch
22
+ have_func("rb_os_allocated_objects")
23
+ have_func("rb_gc_allocated_size")
24
+
25
+ # Stefan Kaes GC patches
26
+ have_func("rb_gc_collections")
27
+ have_func("rb_gc_time")
28
+ # for ruby 2.1
29
+ have_func("rb_gc_total_time")
30
+ have_func("rb_gc_total_mallocs")
31
+ have_func("rb_gc_total_malloced_bytes")
32
+
33
+ # Lloyd Hilaiel's heap info patch
34
+ have_func("rb_heap_total_mem")
35
+ have_func("rb_gc_heap_info")
36
+
37
+ def add_define(name, value = nil)
38
+ if value
39
+ $defs.push("-D#{name}=#{value}")
40
+ else
41
+ $defs.push("-D#{name}")
42
+ end
43
+ end
44
+
45
+ def windows?
46
+ RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
47
+ end
48
+
49
+ if !windows? && RUBY_PLATFORM !~ /(darwin|openbsd)/
50
+ $LDFLAGS += " -lrt" # for clock_gettime
51
+ end
52
+ add_define("RUBY_PROF_RUBY_VERSION", RUBY_VERSION.split('.')[0..2].inject(0){|v,d| v*100+d.to_i})
53
+
54
+ # for ruby 1.9, determine whether threads inherit trace flags (latest 1.9.2 and later should work correctly)
55
+ if RUBY_VERSION > "1.9"
56
+ require 'set'
57
+ threads = Set.new
58
+ set_trace_func lambda { |*args| threads << Thread.current.object_id }
59
+ Thread.new{1}.join
60
+ set_trace_func nil
61
+ if threads.size < 2
62
+ # if we end up here, ruby does not automatically activate tracing in spawned threads
63
+ STDERR.puts("Ruby #{RUBY_VERSION} does not activate tracing in spawned threads. Consider upgrading.")
64
+ exit(1)
65
+ end
66
+ end
67
+
68
+ create_makefile("ruby_prof")
@@ -0,0 +1,425 @@
1
+ /* Copyright (C) 2005-2019 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
2
+ Please see the LICENSE file for copyright and distribution information */
3
+
4
+ #include "ruby_prof.h"
5
+
6
+ #define INITIAL_CALL_INFOS_SIZE 2
7
+
8
+ VALUE cCallInfo;
9
+
10
+
11
+ // Forward declarations
12
+ st_table * call_info_table_create();
13
+
14
+
15
+ /* ======= prof_call_info_t ========*/
16
+ prof_call_info_t *
17
+ prof_call_info_create(prof_method_t* method, prof_call_info_t* parent)
18
+ {
19
+ prof_call_info_t *result = ALLOC(prof_call_info_t);
20
+ result->object = Qnil;
21
+ result->target = method;
22
+ result->parent = parent;
23
+ result->call_infos = call_info_table_create();
24
+ result->children = Qnil;
25
+
26
+ result->total_time = 0;
27
+ result->self_time = 0;
28
+ result->wait_time = 0;
29
+
30
+ result->called = 0;
31
+
32
+ result->recursive = 0;
33
+ result->depth = 0;
34
+ result->line = 0;
35
+
36
+ return result;
37
+ }
38
+ static void
39
+ prof_call_info_ruby_gc_free(prof_call_info_t *call_info)
40
+ {
41
+ /* Has this thread object been accessed by Ruby? If
42
+ yes clean it up so to avoid a segmentation fault. */
43
+ if (call_info->object != Qnil)
44
+ {
45
+ RDATA(call_info->object)->data = NULL;
46
+ RDATA(call_info->object)->dfree = NULL;
47
+ RDATA(call_info->object)->dmark = NULL;
48
+ }
49
+ call_info->object = Qnil;
50
+ }
51
+
52
+ static void
53
+ prof_call_info_free(prof_call_info_t *call_info)
54
+ {
55
+ prof_call_info_ruby_gc_free(call_info);
56
+ st_free_table(call_info->call_infos);
57
+ xfree(call_info);
58
+ }
59
+
60
+ static void
61
+ prof_call_info_mark(prof_call_info_t *call_info)
62
+ {
63
+ if (call_info->object)
64
+ rb_gc_mark(call_info->object);
65
+
66
+ if (call_info->children)
67
+ rb_gc_mark(call_info->children);
68
+
69
+ /* We don't mark the call info child table since that will be done
70
+ via the appropriate method */
71
+ }
72
+
73
+ VALUE
74
+ prof_call_info_wrap(prof_call_info_t *call_info)
75
+ {
76
+ if (call_info->object == Qnil)
77
+ {
78
+ call_info->object = Data_Wrap_Struct(cCallInfo, prof_call_info_mark, prof_call_info_ruby_gc_free, call_info);
79
+ }
80
+ return call_info->object;
81
+ }
82
+
83
+ static prof_call_info_t *
84
+ prof_get_call_info(VALUE self)
85
+ {
86
+ /* Can't use Data_Get_Struct because that triggers the event hook
87
+ ending up in endless recursion. */
88
+ prof_call_info_t* result = DATA_PTR(self);
89
+
90
+ if (!result)
91
+ rb_raise(rb_eRuntimeError, "This RubyProf::CallInfo instance has already been freed, likely because its profile has been freed.");
92
+
93
+ return result;
94
+ }
95
+
96
+ /* ======= Call Info Table ========*/
97
+ st_table *
98
+ call_info_table_create()
99
+ {
100
+ return st_init_table(&type_method_hash);
101
+ }
102
+
103
+ size_t
104
+ call_info_table_insert(st_table *table, const prof_method_key_t *key, prof_call_info_t *val)
105
+ {
106
+ return st_insert(table, (st_data_t) key, (st_data_t) val);
107
+ }
108
+
109
+ prof_call_info_t *
110
+ call_info_table_lookup(st_table *table, const prof_method_key_t *key)
111
+ {
112
+ st_data_t val;
113
+ if (st_lookup(table, (st_data_t) key, &val))
114
+ {
115
+ return (prof_call_info_t *) val;
116
+ }
117
+ else
118
+ {
119
+ return NULL;
120
+ }
121
+ }
122
+
123
+
124
+ /* ======= RubyProf::CallInfo ========*/
125
+
126
+ /* Document-class: RubyProf::CallInfo
127
+ RubyProf::CallInfo is a helper class used by RubyProf::MethodInfo
128
+ to keep track of which child methods were called and how long
129
+ they took to execute. */
130
+
131
+
132
+ /* call-seq:
133
+ called -> MethodInfo
134
+
135
+ Returns the target method. */
136
+ static VALUE
137
+ prof_call_info_target(VALUE self)
138
+ {
139
+ /* Target is a pointer to a method_info - so we have to be careful
140
+ about the GC. We will wrap the method_info but provide no
141
+ free method so the underlying object is not freed twice! */
142
+
143
+ prof_call_info_t *result = prof_get_call_info(self);
144
+ return prof_method_wrap(result->target);
145
+ }
146
+
147
+ /* call-seq:
148
+ called -> int
149
+
150
+ Returns the total amount of times this method was called. */
151
+ static VALUE
152
+ prof_call_info_called(VALUE self)
153
+ {
154
+ prof_call_info_t *result = prof_get_call_info(self);
155
+ return INT2NUM(result->called);
156
+ }
157
+
158
+ /* call-seq:
159
+ called=n -> n
160
+
161
+ Sets the call count to n. */
162
+ static VALUE
163
+ prof_call_info_set_called(VALUE self, VALUE called)
164
+ {
165
+ prof_call_info_t *result = prof_get_call_info(self);
166
+ result->called = NUM2INT(called);
167
+ return called;
168
+ }
169
+
170
+ /* call-seq:
171
+ recursive? -> boolean
172
+
173
+ Returns the true if this call info is a recursive invocation */
174
+ static VALUE
175
+ prof_call_info_recursive(VALUE self)
176
+ {
177
+ prof_call_info_t *result = prof_get_call_info(self);
178
+ return result->recursive ? Qtrue : Qfalse;
179
+ }
180
+
181
+ /* call-seq:
182
+ depth -> int
183
+
184
+ returns the depth of this call info in the call graph */
185
+ static VALUE
186
+ prof_call_info_depth(VALUE self)
187
+ {
188
+ prof_call_info_t *result = prof_get_call_info(self);
189
+ return rb_int_new(result->depth);
190
+ }
191
+
192
+ /* call-seq:
193
+ line_no -> int
194
+
195
+ returns the line number of the method */
196
+ static VALUE
197
+ prof_call_info_line(VALUE self)
198
+ {
199
+ prof_call_info_t *result = prof_get_call_info(self);
200
+ return rb_int_new(result->line);
201
+ }
202
+
203
+ /* call-seq:
204
+ total_time -> float
205
+
206
+ Returns the total amount of time spent in this method and its children. */
207
+ static VALUE
208
+ prof_call_info_total_time(VALUE self)
209
+ {
210
+ prof_call_info_t *result = prof_get_call_info(self);
211
+ return rb_float_new(result->total_time);
212
+ }
213
+
214
+ /* call-seq:
215
+ add_total_time(call_info) -> nil
216
+
217
+ adds total time time from call_info to self. */
218
+ static VALUE
219
+ prof_call_info_add_total_time(VALUE self, VALUE other)
220
+ {
221
+ prof_call_info_t *result = prof_get_call_info(self);
222
+ prof_call_info_t *other_info = prof_get_call_info(other);
223
+
224
+ result->total_time += other_info->total_time;
225
+ return Qnil;
226
+ }
227
+
228
+ /* call-seq:
229
+ self_time -> float
230
+
231
+ Returns the total amount of time spent in this method. */
232
+ static VALUE
233
+ prof_call_info_self_time(VALUE self)
234
+ {
235
+ prof_call_info_t *result = prof_get_call_info(self);
236
+
237
+ return rb_float_new(result->self_time);
238
+ }
239
+
240
+ /* call-seq:
241
+ add_self_time(call_info) -> nil
242
+
243
+ adds self time from call_info to self. */
244
+ static VALUE
245
+ prof_call_info_add_self_time(VALUE self, VALUE other)
246
+ {
247
+ prof_call_info_t *result = prof_get_call_info(self);
248
+ prof_call_info_t *other_info = prof_get_call_info(other);
249
+
250
+ result->self_time += other_info->self_time;
251
+ return Qnil;
252
+ }
253
+
254
+ /* call-seq:
255
+ wait_time -> float
256
+
257
+ Returns the total amount of time this method waited for other threads. */
258
+ static VALUE
259
+ prof_call_info_wait_time(VALUE self)
260
+ {
261
+ prof_call_info_t *result = prof_get_call_info(self);
262
+
263
+ return rb_float_new(result->wait_time);
264
+ }
265
+
266
+ /* call-seq:
267
+ add_wait_time(call_info) -> nil
268
+
269
+ adds wait time from call_info to self. */
270
+
271
+ static VALUE
272
+ prof_call_info_add_wait_time(VALUE self, VALUE other)
273
+ {
274
+ prof_call_info_t *result = prof_get_call_info(self);
275
+ prof_call_info_t *other_info = prof_get_call_info(other);
276
+
277
+ result->wait_time += other_info->wait_time;
278
+ return Qnil;
279
+ }
280
+
281
+ /* call-seq:
282
+ parent -> call_info
283
+
284
+ Returns the call_infos parent call_info object (the method that called this method).*/
285
+ static VALUE
286
+ prof_call_info_parent(VALUE self)
287
+ {
288
+ prof_call_info_t *result = prof_get_call_info(self);
289
+ if (result->parent)
290
+ return prof_call_info_wrap(result->parent);
291
+ else
292
+ return Qnil;
293
+ }
294
+
295
+ /* call-seq:
296
+ parent=new_parent -> new_parent
297
+
298
+ Changes the parent of self to new_parent and returns it.*/
299
+ static VALUE
300
+ prof_call_info_set_parent(VALUE self, VALUE new_parent)
301
+ {
302
+ prof_call_info_t *result = prof_get_call_info(self);
303
+ if (new_parent == Qnil)
304
+ result->parent = NULL;
305
+ else
306
+ result->parent = prof_get_call_info(new_parent);
307
+ return prof_call_info_parent(self);
308
+ }
309
+
310
+ static int
311
+ prof_call_info_collect_children(st_data_t key, st_data_t value, st_data_t result)
312
+ {
313
+ prof_call_info_t *call_info = (prof_call_info_t *) value;
314
+ VALUE arr = (VALUE) result;
315
+ rb_ary_push(arr, prof_call_info_wrap(call_info));
316
+ return ST_CONTINUE;
317
+ }
318
+
319
+ /* call-seq:
320
+ children -> hash
321
+
322
+ Returns an array of call info objects of methods that this method
323
+ called (ie, children).*/
324
+ static VALUE
325
+ prof_call_info_children(VALUE self)
326
+ {
327
+ prof_call_info_t *call_info = prof_get_call_info(self);
328
+ if (call_info->children == Qnil)
329
+ {
330
+ call_info->children = rb_ary_new();
331
+ st_foreach(call_info->call_infos, prof_call_info_collect_children, call_info->children);
332
+ }
333
+ return call_info->children;
334
+ }
335
+
336
+ /* ======= Call Infos ========*/
337
+ prof_call_infos_t*
338
+ prof_call_infos_create()
339
+ {
340
+ prof_call_infos_t *result = ALLOC(prof_call_infos_t);
341
+ result->start = ALLOC_N(prof_call_info_t*, INITIAL_CALL_INFOS_SIZE);
342
+ result->end = result->start + INITIAL_CALL_INFOS_SIZE;
343
+ result->ptr = result->start;
344
+ result->object = Qnil;
345
+ return result;
346
+ }
347
+
348
+ void
349
+ prof_call_infos_mark(prof_call_infos_t *call_infos)
350
+ {
351
+ prof_call_info_t **call_info;
352
+
353
+ if (call_infos->object)
354
+ rb_gc_mark(call_infos->object);
355
+
356
+ for(call_info=call_infos->start; call_info<call_infos->ptr; call_info++)
357
+ {
358
+ prof_call_info_mark(*call_info);
359
+ }
360
+ }
361
+
362
+ void
363
+ prof_call_infos_free(prof_call_infos_t *call_infos)
364
+ {
365
+ prof_call_info_t **call_info;
366
+
367
+ for(call_info=call_infos->start; call_info<call_infos->ptr; call_info++)
368
+ {
369
+ prof_call_info_free(*call_info);
370
+ }
371
+ }
372
+
373
+ void
374
+ prof_add_call_info(prof_call_infos_t *call_infos, prof_call_info_t *call_info)
375
+ {
376
+ if (call_infos->ptr == call_infos->end)
377
+ {
378
+ size_t len = call_infos->ptr - call_infos->start;
379
+ size_t new_capacity = (call_infos->end - call_infos->start) * 2;
380
+ REALLOC_N(call_infos->start, prof_call_info_t*, new_capacity);
381
+ call_infos->ptr = call_infos->start + len;
382
+ call_infos->end = call_infos->start + new_capacity;
383
+ }
384
+ *call_infos->ptr = call_info;
385
+ call_infos->ptr++;
386
+ }
387
+
388
+ VALUE
389
+ prof_call_infos_wrap(prof_call_infos_t *call_infos)
390
+ {
391
+ if (call_infos->object == Qnil)
392
+ {
393
+ prof_call_info_t **i;
394
+ call_infos->object = rb_ary_new();
395
+ for(i=call_infos->start; i<call_infos->ptr; i++)
396
+ {
397
+ VALUE call_info = prof_call_info_wrap(*i);
398
+ rb_ary_push(call_infos->object, call_info);
399
+ }
400
+ }
401
+ return call_infos->object;
402
+ }
403
+
404
+ void rp_init_call_info()
405
+ {
406
+ /* CallInfo */
407
+ cCallInfo = rb_define_class_under(mProf, "CallInfo", rb_cObject);
408
+ rb_undef_method(CLASS_OF(cCallInfo), "new");
409
+ rb_define_method(cCallInfo, "parent", prof_call_info_parent, 0);
410
+ rb_define_method(cCallInfo, "parent=", prof_call_info_set_parent, 1);
411
+ rb_define_method(cCallInfo, "children", prof_call_info_children, 0);
412
+ rb_define_method(cCallInfo, "target", prof_call_info_target, 0);
413
+ rb_define_method(cCallInfo, "called", prof_call_info_called, 0);
414
+ rb_define_method(cCallInfo, "called=", prof_call_info_set_called, 1);
415
+ rb_define_method(cCallInfo, "total_time", prof_call_info_total_time, 0);
416
+ rb_define_method(cCallInfo, "add_total_time", prof_call_info_add_total_time, 1);
417
+ rb_define_method(cCallInfo, "self_time", prof_call_info_self_time, 0);
418
+ rb_define_method(cCallInfo, "add_self_time", prof_call_info_add_self_time, 1);
419
+ rb_define_method(cCallInfo, "wait_time", prof_call_info_wait_time, 0);
420
+ rb_define_method(cCallInfo, "add_wait_time", prof_call_info_add_wait_time, 1);
421
+
422
+ rb_define_method(cCallInfo, "recursive?", prof_call_info_recursive, 0);
423
+ rb_define_method(cCallInfo, "depth", prof_call_info_depth, 0);
424
+ rb_define_method(cCallInfo, "line", prof_call_info_line, 0);
425
+ }