ruby-prof 1.1.0-x64-mingw32 → 1.3.0-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +19 -1
  3. data/bin/ruby-prof +100 -152
  4. data/ext/ruby_prof/rp_aggregate_call_tree.c +59 -0
  5. data/ext/ruby_prof/rp_aggregate_call_tree.h +13 -0
  6. data/ext/ruby_prof/rp_allocation.c +67 -59
  7. data/ext/ruby_prof/rp_allocation.h +3 -3
  8. data/ext/ruby_prof/rp_call_tree.c +369 -0
  9. data/ext/ruby_prof/rp_call_tree.h +43 -0
  10. data/ext/ruby_prof/rp_call_trees.c +288 -0
  11. data/ext/ruby_prof/rp_call_trees.h +28 -0
  12. data/ext/ruby_prof/rp_measure_allocations.c +11 -13
  13. data/ext/ruby_prof/rp_measure_process_time.c +11 -13
  14. data/ext/ruby_prof/rp_measure_wall_time.c +17 -15
  15. data/ext/ruby_prof/rp_measurement.c +47 -40
  16. data/ext/ruby_prof/rp_measurement.h +7 -7
  17. data/ext/ruby_prof/rp_method.c +116 -255
  18. data/ext/ruby_prof/rp_method.h +31 -39
  19. data/ext/ruby_prof/rp_profile.c +311 -281
  20. data/ext/ruby_prof/rp_profile.h +1 -2
  21. data/ext/ruby_prof/rp_stack.c +113 -105
  22. data/ext/ruby_prof/rp_stack.h +17 -20
  23. data/ext/ruby_prof/rp_thread.c +136 -111
  24. data/ext/ruby_prof/rp_thread.h +12 -9
  25. data/ext/ruby_prof/ruby_prof.c +27 -23
  26. data/ext/ruby_prof/ruby_prof.h +9 -0
  27. data/ext/ruby_prof/vc/ruby_prof.vcxproj +11 -7
  28. data/lib/ruby-prof.rb +2 -3
  29. data/lib/ruby-prof/assets/call_stack_printer.html.erb +4 -7
  30. data/lib/ruby-prof/assets/graph_printer.html.erb +5 -6
  31. data/lib/ruby-prof/{call_info.rb → call_tree.rb} +6 -6
  32. data/lib/ruby-prof/call_tree_visitor.rb +36 -0
  33. data/lib/ruby-prof/measurement.rb +5 -2
  34. data/lib/ruby-prof/method_info.rb +3 -15
  35. data/lib/ruby-prof/printers/call_info_printer.rb +12 -10
  36. data/lib/ruby-prof/printers/call_stack_printer.rb +19 -22
  37. data/lib/ruby-prof/printers/call_tree_printer.rb +1 -1
  38. data/lib/ruby-prof/printers/dot_printer.rb +3 -3
  39. data/lib/ruby-prof/printers/graph_printer.rb +3 -4
  40. data/lib/ruby-prof/printers/multi_printer.rb +2 -2
  41. data/lib/ruby-prof/rack.rb +3 -0
  42. data/lib/ruby-prof/thread.rb +3 -18
  43. data/lib/ruby-prof/version.rb +1 -1
  44. data/ruby-prof.gemspec +7 -0
  45. data/test/alias_test.rb +42 -45
  46. data/test/basic_test.rb +0 -86
  47. data/test/{call_info_visitor_test.rb → call_tree_visitor_test.rb} +6 -5
  48. data/test/call_trees_test.rb +66 -0
  49. data/test/exclude_methods_test.rb +17 -12
  50. data/test/fiber_test.rb +197 -9
  51. data/test/gc_test.rb +36 -42
  52. data/test/inverse_call_tree_test.rb +175 -0
  53. data/test/line_number_test.rb +67 -70
  54. data/test/marshal_test.rb +7 -11
  55. data/test/measure_allocations_test.rb +224 -234
  56. data/test/measure_allocations_trace_test.rb +224 -234
  57. data/test/measure_memory_trace_test.rb +814 -469
  58. data/test/measure_process_time_test.rb +0 -64
  59. data/test/measure_times.rb +2 -0
  60. data/test/measure_wall_time_test.rb +34 -58
  61. data/test/pause_resume_test.rb +19 -10
  62. data/test/prime.rb +1 -3
  63. data/test/prime_script.rb +6 -0
  64. data/test/printers_test.rb +1 -1
  65. data/test/recursive_test.rb +50 -54
  66. data/test/start_stop_test.rb +19 -19
  67. data/test/test_helper.rb +3 -15
  68. data/test/thread_test.rb +11 -11
  69. data/test/unique_call_path_test.rb +25 -95
  70. metadata +19 -10
  71. data/ext/ruby_prof/rp_call_info.c +0 -271
  72. data/ext/ruby_prof/rp_call_info.h +0 -35
  73. data/lib/2.6.5/ruby_prof.so +0 -0
  74. data/lib/ruby-prof/call_info_visitor.rb +0 -38
  75. data/test/parser_timings.rb +0 -24
@@ -0,0 +1,28 @@
1
+ /* Copyright (C) 2005-2013 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
+ #ifndef __RP_CALL_TREES_H__
5
+ #define __RP_CALL_TREES_H__
6
+
7
+ #include "ruby_prof.h"
8
+ #include "rp_call_tree.h"
9
+
10
+ /* Array of call_tree objects */
11
+ typedef struct prof_call_trees_t
12
+ {
13
+ prof_call_tree_t** start;
14
+ prof_call_tree_t** end;
15
+ prof_call_tree_t** ptr;
16
+
17
+ VALUE object;
18
+ } prof_call_trees_t;
19
+
20
+
21
+ void rp_init_call_trees();
22
+ prof_call_trees_t* prof_call_trees_create();
23
+ void prof_call_trees_free(prof_call_trees_t* call_trees);
24
+ prof_call_trees_t* prof_get_call_trees(VALUE self);
25
+ void prof_add_call_tree(prof_call_trees_t* call_trees, prof_call_tree_t* call_tree);
26
+ VALUE prof_call_trees_wrap(prof_call_trees_t* call_trees);
27
+
28
+ #endif //__RP_CALL_TREES_H__
@@ -8,14 +8,12 @@
8
8
  static VALUE cMeasureAllocations;
9
9
  VALUE total_allocated_objects_key;
10
10
 
11
- static double
12
- measure_allocations_via_gc_stats(rb_trace_arg_t* trace_arg)
11
+ static double measure_allocations_via_gc_stats(rb_trace_arg_t* trace_arg)
13
12
  {
14
13
  return rb_gc_stat(total_allocated_objects_key);
15
14
  }
16
15
 
17
- static double
18
- measure_allocations_via_tracing(rb_trace_arg_t* trace_arg)
16
+ static double measure_allocations_via_tracing(rb_trace_arg_t* trace_arg)
19
17
  {
20
18
  static double result = 0;
21
19
 
@@ -30,17 +28,17 @@ measure_allocations_via_tracing(rb_trace_arg_t* trace_arg)
30
28
 
31
29
  prof_measurer_t* prof_measurer_allocations(bool track_allocations)
32
30
  {
33
- prof_measurer_t* measure = ALLOC(prof_measurer_t);
34
- measure->mode = MEASURE_ALLOCATIONS;
35
- measure->multiplier = 1;
36
- measure->track_allocations = track_allocations;
31
+ prof_measurer_t* measure = ALLOC(prof_measurer_t);
32
+ measure->mode = MEASURE_ALLOCATIONS;
33
+ measure->multiplier = 1;
34
+ measure->track_allocations = track_allocations;
37
35
 
38
- if (track_allocations)
39
- measure->measure = measure_allocations_via_tracing;
40
- else
41
- measure->measure = measure_allocations_via_gc_stats;
36
+ if (track_allocations)
37
+ measure->measure = measure_allocations_via_tracing;
38
+ else
39
+ measure->measure = measure_allocations_via_gc_stats;
42
40
 
43
- return measure;
41
+ return measure;
44
42
  }
45
43
 
46
44
  void rp_init_measure_allocations()
@@ -6,8 +6,7 @@
6
6
 
7
7
  static VALUE cMeasureProcessTime;
8
8
 
9
- static double
10
- measure_process_time(rb_trace_arg_t* trace_arg)
9
+ static double measure_process_time(rb_trace_arg_t* trace_arg)
11
10
  {
12
11
  #if defined(_WIN32)
13
12
  FILETIME createTime;
@@ -29,16 +28,15 @@ measure_process_time(rb_trace_arg_t* trace_arg)
29
28
  #elif !defined(CLOCK_PROCESS_CPUTIME_ID)
30
29
  struct rusage usage;
31
30
  getrusage(RUSAGE_SELF, &usage);
32
- return usage.ru_stime.tv_sec + usage.ru_utime.tv_sec + ((usage.ru_stime.tv_usec + usage.ru_utime.tv_usec)/1000000.0);
31
+ return usage.ru_stime.tv_sec + usage.ru_utime.tv_sec + ((usage.ru_stime.tv_usec + usage.ru_utime.tv_usec) / 1000000.0);
33
32
  #else
34
33
  struct timespec clock;
35
- clock_gettime(CLOCK_PROCESS_CPUTIME_ID , &clock);
36
- return clock.tv_sec + (clock.tv_nsec/1000000000.0);
34
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &clock);
35
+ return clock.tv_sec + (clock.tv_nsec / 1000000000.0);
37
36
  #endif
38
37
  }
39
38
 
40
- static double
41
- multiplier_process_time(void)
39
+ static double multiplier_process_time(void)
42
40
  {
43
41
  #if defined(_WIN32)
44
42
  // Times are in 100-nanosecond time units. So instead of 10-9 use 10-7
@@ -50,12 +48,12 @@ multiplier_process_time(void)
50
48
 
51
49
  prof_measurer_t* prof_measurer_process_time(bool track_allocations)
52
50
  {
53
- prof_measurer_t* measure = ALLOC(prof_measurer_t);
54
- measure->mode = MEASURE_PROCESS_TIME;
55
- measure->measure = measure_process_time;
56
- measure->multiplier = multiplier_process_time();
57
- measure->track_allocations = track_allocations;
58
- return measure;
51
+ prof_measurer_t* measure = ALLOC(prof_measurer_t);
52
+ measure->mode = MEASURE_PROCESS_TIME;
53
+ measure->measure = measure_process_time;
54
+ measure->multiplier = multiplier_process_time();
55
+ measure->track_allocations = track_allocations;
56
+ return measure;
59
57
  }
60
58
 
61
59
  void rp_init_measure_process_time()
@@ -1,7 +1,7 @@
1
1
  /* Copyright (C) 2005-2019 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
2
2
  Please see the LICENSE file for copyright and distribution information */
3
3
 
4
- /* :nodoc: */
4
+ /* :nodoc: */
5
5
  #include "rp_measurement.h"
6
6
 
7
7
  #if defined(__APPLE__)
@@ -12,11 +12,12 @@
12
12
 
13
13
  static VALUE cMeasureWallTime;
14
14
 
15
- static double
16
- measure_wall_time(rb_trace_arg_t* trace_arg)
15
+ static double measure_wall_time(rb_trace_arg_t* trace_arg)
17
16
  {
18
17
  #if defined(_WIN32)
19
- return GetTickCount();
18
+ LARGE_INTEGER time;
19
+ QueryPerformanceCounter(&time);
20
+ return time.QuadPart;
20
21
  #elif defined(__APPLE__)
21
22
  return mach_absolute_time();// * (uint64_t)mach_timebase.numer / (uint64_t)mach_timebase.denom;
22
23
  #elif defined(__linux__)
@@ -26,18 +27,19 @@ measure_wall_time(rb_trace_arg_t* trace_arg)
26
27
  #else
27
28
  struct timeval tv;
28
29
  gettimeofday(&tv, NULL);
29
- return tv.tv_sec + (tv.tv_usec / 1000000.0);
30
+ return tv.tv_sec + (tv.tv_usec / 1000000.0);
30
31
  #endif
31
32
  }
32
33
 
33
- static double
34
- multiplier_wall_time(void)
34
+ static double multiplier_wall_time(void)
35
35
  {
36
36
  #if defined(_WIN32)
37
- return 1.0/1000.0;
37
+ LARGE_INTEGER frequency;
38
+ QueryPerformanceFrequency(&frequency);
39
+ return 1.0 / frequency.QuadPart;
38
40
  #elif defined(__APPLE__)
39
41
  mach_timebase_info_data_t mach_timebase;
40
- mach_timebase_info (&mach_timebase);
42
+ mach_timebase_info(&mach_timebase);
41
43
  return (uint64_t)mach_timebase.numer / (uint64_t)mach_timebase.denom / 1000000000.0;
42
44
  #else
43
45
  return 1.0;
@@ -46,12 +48,12 @@ multiplier_wall_time(void)
46
48
 
47
49
  prof_measurer_t* prof_measurer_wall_time(bool track_allocations)
48
50
  {
49
- prof_measurer_t* measure = ALLOC(prof_measurer_t);
50
- measure->mode = MEASURE_WALL_TIME;
51
- measure->measure = measure_wall_time;
52
- measure->multiplier = multiplier_wall_time();
53
- measure->track_allocations = track_allocations;
54
- return measure;
51
+ prof_measurer_t* measure = ALLOC(prof_measurer_t);
52
+ measure->mode = MEASURE_WALL_TIME;
53
+ measure->measure = measure_wall_time;
54
+ measure->multiplier = multiplier_wall_time();
55
+ measure->track_allocations = track_allocations;
56
+ return measure;
55
57
  }
56
58
 
57
59
  void rp_init_measure_wall_time()
@@ -40,7 +40,7 @@ double prof_measure(prof_measurer_t* measurer, rb_trace_arg_t* trace_arg)
40
40
  }
41
41
 
42
42
  /* ======= prof_measurement_t ========*/
43
- prof_measurement_t *prof_measurement_create(void)
43
+ prof_measurement_t* prof_measurement_create(void)
44
44
  {
45
45
  prof_measurement_t* result = ALLOC(prof_measurement_t);
46
46
  result->total_time = 0;
@@ -51,67 +51,78 @@ prof_measurement_t *prof_measurement_create(void)
51
51
  return result;
52
52
  }
53
53
 
54
- static void
55
- prof_measurement_ruby_gc_free(void *data)
54
+ void prof_measurement_mark(void* data)
56
55
  {
57
- prof_measurement_t* measurement = (prof_measurement_t*)data;
56
+ if (!data) return;
58
57
 
58
+ prof_measurement_t* measurement_data = (prof_measurement_t*)data;
59
+
60
+ if (measurement_data->object != Qnil)
61
+ rb_gc_mark(measurement_data->object);
62
+ }
63
+
64
+ static void prof_measurement_ruby_gc_free(void* data)
65
+ {
66
+ if (data)
67
+ {
68
+ // Measurements are freed by their owning object (call info or method)
69
+ prof_measurement_t* measurement = (prof_measurement_t*)data;
70
+ measurement->object = Qnil;
71
+ }
72
+ }
73
+
74
+ void prof_measurement_free(prof_measurement_t* measurement)
75
+ {
59
76
  /* Has this measurement object been accessed by Ruby? If
60
77
  yes clean it up so to avoid a segmentation fault. */
61
78
  if (measurement->object != Qnil)
62
79
  {
63
- RDATA(measurement->object)->dmark = NULL;
64
- RDATA(measurement->object)->dfree = NULL;
65
- RDATA(measurement->object)->data = NULL;
80
+ RTYPEDDATA(measurement->object)->data = NULL;
66
81
  measurement->object = Qnil;
67
82
  }
68
- }
69
83
 
70
- void
71
- prof_measurement_free(prof_measurement_t* measurement)
72
- {
73
- prof_measurement_ruby_gc_free(measurement);
74
84
  xfree(measurement);
75
85
  }
76
86
 
77
- size_t
78
- prof_measurement_size(const void *data)
87
+ size_t prof_measurement_size(const void* data)
79
88
  {
80
89
  return sizeof(prof_measurement_t);
81
90
  }
82
91
 
83
- void
84
- prof_measurement_mark(void *data)
92
+ static const rb_data_type_t measurement_type =
85
93
  {
86
- prof_measurement_t* measurement = (prof_measurement_t*)data;
87
- if (measurement->object != Qnil)
88
- rb_gc_mark(measurement->object);
89
- }
94
+ .wrap_struct_name = "Measurement",
95
+ .function =
96
+ {
97
+ .dmark = prof_measurement_mark,
98
+ .dfree = prof_measurement_ruby_gc_free,
99
+ .dsize = prof_measurement_size,
100
+ },
101
+ .data = NULL,
102
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
103
+ };
90
104
 
91
- VALUE
92
- prof_measurement_wrap(prof_measurement_t* measurement)
105
+ VALUE prof_measurement_wrap(prof_measurement_t* measurement)
93
106
  {
94
107
  if (measurement->object == Qnil)
95
108
  {
96
- measurement->object = Data_Wrap_Struct(cRpMeasurement, prof_measurement_mark, prof_measurement_ruby_gc_free, measurement);
109
+ measurement->object = TypedData_Wrap_Struct(cRpMeasurement, &measurement_type, measurement);
97
110
  }
98
111
  return measurement->object;
99
112
  }
100
113
 
101
- static VALUE
102
- prof_measurement_allocate(VALUE klass)
114
+ static VALUE prof_measurement_allocate(VALUE klass)
103
115
  {
104
- prof_measurement_t *measurement = prof_measurement_create();
116
+ prof_measurement_t* measurement = prof_measurement_create();
105
117
  measurement->object = prof_measurement_wrap(measurement);
106
118
  return measurement->object;
107
119
  }
108
120
 
109
- prof_measurement_t*
110
- prof_get_measurement(VALUE self)
121
+ prof_measurement_t* prof_get_measurement(VALUE self)
111
122
  {
112
123
  /* Can't use Data_Get_Struct because that triggers the event hook
113
124
  ending up in endless recursion. */
114
- prof_measurement_t* result = DATA_PTR(self);
125
+ prof_measurement_t* result = RTYPEDDATA_DATA(self);
115
126
 
116
127
  if (!result)
117
128
  rb_raise(rb_eRuntimeError, "This RubyProf::Measurement instance has already been freed, likely because its profile has been freed.");
@@ -123,8 +134,7 @@ prof_get_measurement(VALUE self)
123
134
  total_time -> float
124
135
 
125
136
  Returns the total amount of time spent in this method and its children. */
126
- static VALUE
127
- prof_measurement_total_time(VALUE self)
137
+ static VALUE prof_measurement_total_time(VALUE self)
128
138
  {
129
139
  prof_measurement_t* result = prof_get_measurement(self);
130
140
  return rb_float_new(result->total_time);
@@ -146,8 +156,7 @@ prof_measurement_self_time(VALUE self)
146
156
  wait_time -> float
147
157
 
148
158
  Returns the total amount of time this method waited for other threads. */
149
- static VALUE
150
- prof_measurement_wait_time(VALUE self)
159
+ static VALUE prof_measurement_wait_time(VALUE self)
151
160
  {
152
161
  prof_measurement_t* result = prof_get_measurement(self);
153
162
 
@@ -158,10 +167,9 @@ prof_measurement_wait_time(VALUE self)
158
167
  called -> int
159
168
 
160
169
  Returns the total amount of times this method was called. */
161
- static VALUE
162
- prof_measurement_called(VALUE self)
170
+ static VALUE prof_measurement_called(VALUE self)
163
171
  {
164
- prof_measurement_t *result = prof_get_measurement(self);
172
+ prof_measurement_t* result = prof_get_measurement(self);
165
173
  return INT2NUM(result->called);
166
174
  }
167
175
 
@@ -169,10 +177,9 @@ prof_measurement_called(VALUE self)
169
177
  called=n -> n
170
178
 
171
179
  Sets the call count to n. */
172
- static VALUE
173
- prof_measurement_set_called(VALUE self, VALUE called)
180
+ static VALUE prof_measurement_set_called(VALUE self, VALUE called)
174
181
  {
175
- prof_measurement_t *result = prof_get_measurement(self);
182
+ prof_measurement_t* result = prof_get_measurement(self);
176
183
  result->called = NUM2INT(called);
177
184
  return called;
178
185
  }
@@ -215,7 +222,7 @@ void rp_init_measure()
215
222
  rp_init_measure_allocations();
216
223
  rp_init_measure_memory();
217
224
 
218
- cRpMeasurement = rb_define_class_under(mProf, "Measurement", rb_cData);
225
+ cRpMeasurement = rb_define_class_under(mProf, "Measurement", rb_cObject);
219
226
  rb_undef_method(CLASS_OF(cRpMeasurement), "new");
220
227
  rb_define_alloc_func(cRpMeasurement, prof_measurement_allocate);
221
228
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  extern VALUE mMeasure;
10
10
 
11
- typedef double (*get_measurement)(rb_trace_arg_t *trace_arg);
11
+ typedef double (*get_measurement)(rb_trace_arg_t* trace_arg);
12
12
 
13
13
  typedef enum
14
14
  {
@@ -18,7 +18,7 @@ typedef enum
18
18
  MEASURE_MEMORY
19
19
  } prof_measure_mode_t;
20
20
 
21
- typedef struct
21
+ typedef struct prof_measurer_t
22
22
  {
23
23
  get_measurement measure;
24
24
  prof_measure_mode_t mode;
@@ -36,14 +36,14 @@ typedef struct prof_measurement_t
36
36
  VALUE object;
37
37
  } prof_measurement_t;
38
38
 
39
- prof_measurer_t *prof_get_measurer(prof_measure_mode_t measure, bool track_allocations);
40
- double prof_measure(prof_measurer_t *measurer, rb_trace_arg_t* trace_arg);
39
+ prof_measurer_t* prof_get_measurer(prof_measure_mode_t measure, bool track_allocations);
40
+ double prof_measure(prof_measurer_t* measurer, rb_trace_arg_t* trace_arg);
41
41
 
42
- prof_measurement_t *prof_measurement_create(void);
42
+ prof_measurement_t* prof_measurement_create(void);
43
43
  void prof_measurement_free(prof_measurement_t* measurement);
44
- VALUE prof_measurement_wrap(prof_measurement_t *measurement);
44
+ VALUE prof_measurement_wrap(prof_measurement_t* measurement);
45
45
  prof_measurement_t* prof_get_measurement(VALUE self);
46
- void prof_measurement_mark(void *data);
46
+ void prof_measurement_mark(void* data);
47
47
 
48
48
  void rp_init_measure(void);
49
49
 
@@ -2,14 +2,13 @@
2
2
  Please see the LICENSE file for copyright and distribution information */
3
3
 
4
4
  #include "rp_allocation.h"
5
- #include "rp_call_info.h"
5
+ #include "rp_call_trees.h"
6
6
  #include "rp_method.h"
7
7
 
8
8
  VALUE cRpMethodInfo;
9
9
 
10
10
  /* ================ Helper Functions =================*/
11
- VALUE
12
- resolve_klass(VALUE klass, unsigned int *klass_flags)
11
+ VALUE resolve_klass(VALUE klass, unsigned int* klass_flags)
13
12
  {
14
13
  VALUE result = klass;
15
14
 
@@ -62,8 +61,7 @@ resolve_klass(VALUE klass, unsigned int *klass_flags)
62
61
  return result;
63
62
  }
64
63
 
65
- VALUE
66
- resolve_klass_name(VALUE klass, unsigned int* klass_flags)
64
+ VALUE resolve_klass_name(VALUE klass, unsigned int* klass_flags)
67
65
  {
68
66
  VALUE result = Qnil;
69
67
 
@@ -83,8 +81,7 @@ resolve_klass_name(VALUE klass, unsigned int* klass_flags)
83
81
  return result;
84
82
  }
85
83
 
86
- st_data_t
87
- method_key(VALUE klass, VALUE msym)
84
+ st_data_t method_key(VALUE klass, VALUE msym)
88
85
  {
89
86
  VALUE resolved_klass = klass;
90
87
 
@@ -104,21 +101,18 @@ method_key(VALUE klass, VALUE msym)
104
101
  }
105
102
 
106
103
  /* ====== Allocation Table ====== */
107
- st_table*
108
- allocations_table_create()
104
+ st_table* allocations_table_create()
109
105
  {
110
- return st_init_numtable();
106
+ return rb_st_init_numtable();
111
107
  }
112
108
 
113
- static int
114
- allocations_table_free_iterator(st_data_t key, st_data_t value, st_data_t dummy)
115
- {
109
+ static int allocations_table_free_iterator(st_data_t key, st_data_t value, st_data_t dummy)
110
+ {
116
111
  prof_allocation_free((prof_allocation_t*)value);
117
112
  return ST_CONTINUE;
118
113
  }
119
114
 
120
- static int
121
- prof_method_collect_allocations(st_data_t key, st_data_t value, st_data_t result)
115
+ static int prof_method_collect_allocations(st_data_t key, st_data_t value, st_data_t result)
122
116
  {
123
117
  prof_allocation_t* allocation = (prof_allocation_t*)value;
124
118
  VALUE arr = (VALUE)result;
@@ -126,28 +120,25 @@ prof_method_collect_allocations(st_data_t key, st_data_t value, st_data_t result
126
120
  return ST_CONTINUE;
127
121
  }
128
122
 
129
- static int
130
- prof_method_mark_allocations(st_data_t key, st_data_t value, st_data_t data)
123
+ static int prof_method_mark_allocations(st_data_t key, st_data_t value, st_data_t data)
131
124
  {
132
125
  prof_allocation_t* allocation = (prof_allocation_t*)value;
133
126
  prof_allocation_mark(allocation);
134
127
  return ST_CONTINUE;
135
128
  }
136
129
 
137
- void
138
- allocations_table_free(st_table* table)
130
+ void allocations_table_free(st_table* table)
139
131
  {
140
- st_foreach(table, allocations_table_free_iterator, 0);
141
- st_free_table(table);
132
+ rb_st_foreach(table, allocations_table_free_iterator, 0);
133
+ rb_st_free_table(table);
142
134
  }
143
135
 
144
136
  /* ================ prof_method_t =================*/
145
- static prof_method_t*
146
- prof_get_method(VALUE self)
137
+ prof_method_t* prof_get_method(VALUE self)
147
138
  {
148
139
  /* Can't use Data_Get_Struct because that triggers the event hook
149
140
  ending up in endless recursion. */
150
- prof_method_t* result = DATA_PTR(self);
141
+ prof_method_t* result = RTYPEDDATA_DATA(self);
151
142
 
152
143
  if (!result)
153
144
  rb_raise(rb_eRuntimeError, "This RubyProf::MethodInfo instance has already been freed, likely because its profile has been freed.");
@@ -155,27 +146,24 @@ prof_get_method(VALUE self)
155
146
  return result;
156
147
  }
157
148
 
158
- prof_method_t*
159
- prof_method_create(VALUE klass, VALUE msym, VALUE source_file, int source_line)
149
+ prof_method_t* prof_method_create(VALUE profile, VALUE klass, VALUE msym, VALUE source_file, int source_line)
160
150
  {
161
- prof_method_t *result = ALLOC(prof_method_t);
151
+ prof_method_t* result = ALLOC(prof_method_t);
152
+ result->profile = profile;
153
+
162
154
  result->key = method_key(klass, msym);
163
155
  result->klass_flags = 0;
164
156
 
165
- /* Note we do not call resolve_klass_name now because that causes an object allocation that shows up
157
+ /* Note we do not call resolve_klass_name now because that causes an object allocation that shows up
166
158
  in the allocation results so we want to avoid it until after the profile run is complete. */
167
159
  result->klass = resolve_klass(klass, &result->klass_flags);
168
160
  result->klass_name = Qnil;
169
161
  result->method_name = msym;
170
162
  result->measurement = prof_measurement_create();
171
163
 
172
- result->root = false;
173
- result->excluded = false;
174
-
175
- result->parent_call_infos = method_table_create();
176
- result->child_call_infos = method_table_create();
164
+ result->call_trees = prof_call_trees_create();
177
165
  result->allocations_table = allocations_table_create();
178
-
166
+
179
167
  result->visits = 0;
180
168
  result->recursive = false;
181
169
 
@@ -187,180 +175,127 @@ prof_method_create(VALUE klass, VALUE msym, VALUE source_file, int source_line)
187
175
  return result;
188
176
  }
189
177
 
190
- prof_method_t*
191
- prof_method_create_excluded(VALUE klass, VALUE msym)
192
- {
193
- prof_method_t* result = prof_method_create(klass, msym, Qnil, 0);
194
- result->excluded = 1;
195
- return result;
196
- }
197
-
198
- static int
199
- prof_method_collect_call_infos(st_data_t key, st_data_t value, st_data_t result)
200
- {
201
- prof_call_info_t* call_info = (prof_call_info_t*)value;
202
- VALUE arr = (VALUE)result;
203
- rb_ary_push(arr, prof_call_info_wrap(call_info));
204
- return ST_CONTINUE;
205
- }
206
-
207
- static int
208
- prof_method_mark_call_infos(st_data_t key, st_data_t value, st_data_t data)
209
- {
210
- prof_call_info_t* call_info = (prof_call_info_t*)value;
211
- prof_call_info_mark(call_info);
212
- return ST_CONTINUE;
213
- }
214
-
215
- static int
216
- call_infos_free_iterator(st_data_t key, st_data_t value, st_data_t dummy)
217
- {
218
- prof_call_info_free((prof_call_info_t*)value);
219
- return ST_CONTINUE;
220
- }
221
-
222
- void
223
- call_info_table_free(st_table* table)
224
- {
225
- st_foreach(table, call_infos_free_iterator, 0);
226
- st_free_table(table);
227
- }
228
-
229
178
  /* The underlying c structures are freed when the parent profile is freed.
230
179
  However, on shutdown the Ruby GC frees objects in any will-nilly order.
231
180
  That means the ruby thread object wrapping the c thread struct may
232
181
  be freed before the parent profile. Thus we add in a free function
233
182
  for the garbage collector so that if it does get called will nil
234
183
  out our Ruby object reference.*/
235
- static void
236
- prof_method_ruby_gc_free(void *data)
184
+ static void prof_method_ruby_gc_free(void* data)
237
185
  {
238
- prof_method_t* method = (prof_method_t*)data;
239
-
240
- /* Has this method object been accessed by Ruby? If
241
- yes clean it up so to avoid a segmentation fault. */
242
- if (method->object != Qnil)
243
- {
244
- RDATA(method->object)->dmark = NULL;
245
- RDATA(method->object)->dfree = NULL;
246
- RDATA(method->object)->data = NULL;
186
+ if (data)
187
+ {
188
+ prof_method_t* method = (prof_method_t*)data;
247
189
  method->object = Qnil;
248
190
  }
249
- method->klass_name = Qnil;
250
- method->method_name = Qnil;
251
191
  }
252
192
 
253
- static void
254
- prof_method_free(prof_method_t* method)
193
+ static void prof_method_free(prof_method_t* method)
255
194
  {
256
- prof_method_ruby_gc_free(method);
257
- allocations_table_free(method->allocations_table);
258
-
259
- /* Remember call infos are referenced by their parent method and child method, so we only want
260
- to iterate over one of them to avoid a double freeing */
261
- call_info_table_free(method->parent_call_infos);
262
- xfree(method->child_call_infos);
195
+ /* Has this method object been accessed by Ruby? If
196
+ yes clean it up so to avoid a segmentation fault. */
197
+ if (method->object != Qnil)
198
+ {
199
+ RTYPEDDATA(method->object)->data = NULL;
200
+ method->object = Qnil;
201
+ }
263
202
 
203
+ allocations_table_free(method->allocations_table);
204
+ prof_call_trees_free(method->call_trees);
264
205
  prof_measurement_free(method->measurement);
265
206
  xfree(method);
266
207
  }
267
208
 
268
- size_t
269
- prof_method_size(const void *data)
209
+ size_t prof_method_size(const void* data)
270
210
  {
271
211
  return sizeof(prof_method_t);
272
212
  }
273
213
 
274
- void
275
- prof_method_mark(void *data)
214
+ void prof_method_mark(void* data)
276
215
  {
216
+ if (!data) return;
217
+
277
218
  prof_method_t* method = (prof_method_t*)data;
219
+
220
+ if (method->profile != Qnil)
221
+ rb_gc_mark(method->profile);
222
+
223
+ if (method->object != Qnil)
224
+ rb_gc_mark(method->object);
225
+
278
226
  rb_gc_mark(method->klass_name);
279
227
  rb_gc_mark(method->method_name);
280
-
228
+ rb_gc_mark(method->source_file);
229
+
281
230
  if (method->klass != Qnil)
282
231
  rb_gc_mark(method->klass);
283
232
 
284
- if (method->object != Qnil)
285
- rb_gc_mark(method->object);
286
-
287
233
  prof_measurement_mark(method->measurement);
288
-
289
- st_foreach(method->parent_call_infos, prof_method_mark_call_infos, 0);
290
- st_foreach(method->child_call_infos, prof_method_mark_call_infos, 0);
291
- st_foreach(method->allocations_table, prof_method_mark_allocations, 0);
234
+
235
+ rb_st_foreach(method->allocations_table, prof_method_mark_allocations, 0);
292
236
  }
293
237
 
294
- static VALUE
295
- prof_method_allocate(VALUE klass)
238
+ static VALUE prof_method_allocate(VALUE klass)
296
239
  {
297
- prof_method_t* method_data = prof_method_create(Qnil, Qnil, Qnil, 0);
240
+ prof_method_t* method_data = prof_method_create(Qnil, Qnil, Qnil, Qnil, 0);
298
241
  method_data->object = prof_method_wrap(method_data);
299
242
  return method_data->object;
300
243
  }
301
244
 
302
- VALUE
303
- prof_method_wrap(prof_method_t *method)
245
+ static const rb_data_type_t method_info_type =
304
246
  {
305
- if (method->object == Qnil)
306
- {
307
- method->object = Data_Wrap_Struct(cRpMethodInfo, prof_method_mark, prof_method_ruby_gc_free, method);
308
- }
309
- return method->object;
310
- }
247
+ .wrap_struct_name = "MethodInfo",
248
+ .function =
249
+ {
250
+ .dmark = prof_method_mark,
251
+ .dfree = prof_method_ruby_gc_free,
252
+ .dsize = prof_method_size,
253
+ },
254
+ .data = NULL,
255
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
256
+ };
311
257
 
312
- prof_method_t *
313
- prof_method_get(VALUE self)
258
+ VALUE prof_method_wrap(prof_method_t* method)
314
259
  {
315
- /* Can't use Data_Get_Struct because that triggers the event hook
316
- ending up in endless recursion. */
317
- prof_method_t* result = DATA_PTR(self);
318
-
319
- if (!result)
260
+ if (method->object == Qnil)
320
261
  {
321
- rb_raise(rb_eRuntimeError, "This RubyProf::MethodInfo instance has already been freed, likely because its profile has been freed.");
322
- }
323
-
324
- return result;
262
+ method->object = TypedData_Wrap_Struct(cRpMethodInfo, &method_info_type, method);
263
+ }
264
+ return method->object;
325
265
  }
326
266
 
327
- st_table *
328
- method_table_create()
267
+ st_table* method_table_create()
329
268
  {
330
- return st_init_numtable();
269
+ return rb_st_init_numtable();
331
270
  }
332
271
 
333
- static int
334
- method_table_free_iterator(st_data_t key, st_data_t value, st_data_t dummy)
272
+ static int method_table_free_iterator(st_data_t key, st_data_t value, st_data_t dummy)
335
273
  {
336
- prof_method_free((prof_method_t *)value);
274
+ prof_method_free((prof_method_t*)value);
337
275
  return ST_CONTINUE;
338
276
  }
339
277
 
340
- void
341
- method_table_free(st_table *table)
278
+ void method_table_free(st_table* table)
342
279
  {
343
- st_foreach(table, method_table_free_iterator, 0);
344
- st_free_table(table);
280
+ rb_st_foreach(table, method_table_free_iterator, 0);
281
+ rb_st_free_table(table);
345
282
  }
346
283
 
347
- size_t
348
- method_table_insert(st_table *table, st_data_t key, prof_method_t *val)
284
+ size_t method_table_insert(st_table* table, st_data_t key, prof_method_t* val)
349
285
  {
350
- return st_insert(table, (st_data_t) key, (st_data_t) val);
286
+ return rb_st_insert(table, (st_data_t)key, (st_data_t)val);
351
287
  }
352
288
 
353
- prof_method_t *
354
- method_table_lookup(st_table *table, st_data_t key)
289
+ prof_method_t* method_table_lookup(st_table* table, st_data_t key)
355
290
  {
356
291
  st_data_t val;
357
- if (st_lookup(table, (st_data_t)key, &val))
292
+ if (rb_st_lookup(table, (st_data_t)key, &val))
358
293
  {
359
- return (prof_method_t *) val;
294
+ return (prof_method_t*)val;
360
295
  }
361
296
  else
362
297
  {
363
- return NULL;
298
+ return NULL;
364
299
  }
365
300
  }
366
301
 
@@ -374,42 +309,15 @@ created. RubyProf::MethodInfo objects can be accessed via
374
309
  the RubyProf::Profile object.
375
310
  */
376
311
 
377
- /* call-seq:
378
- callers -> array
379
-
380
- Returns an array of call info objects that called this method (ie, parents).*/
381
- static VALUE
382
- prof_method_callers(VALUE self)
383
- {
384
- prof_method_t* method = prof_get_method(self);
385
- VALUE result = rb_ary_new();
386
- st_foreach(method->parent_call_infos, prof_method_collect_call_infos, result);
387
- return result;
388
- }
389
-
390
- /* call-seq:
391
- callees -> array
392
-
393
- Returns an array of call info objects that this method called (ie, children).*/
394
- static VALUE
395
- prof_method_callees(VALUE self)
396
- {
397
- prof_method_t* method = prof_get_method(self);
398
- VALUE result = rb_ary_new();
399
- st_foreach(method->child_call_infos, prof_method_collect_call_infos, result);
400
- return result;
401
- }
402
-
403
312
  /* call-seq:
404
313
  allocations -> array
405
314
 
406
315
  Returns an array of allocation information.*/
407
- static VALUE
408
- prof_method_allocations(VALUE self)
316
+ static VALUE prof_method_allocations(VALUE self)
409
317
  {
410
318
  prof_method_t* method = prof_get_method(self);
411
319
  VALUE result = rb_ary_new();
412
- st_foreach(method->allocations_table, prof_method_collect_allocations, result);
320
+ rb_st_foreach(method->allocations_table, prof_method_collect_allocations, result);
413
321
  return result;
414
322
  }
415
323
 
@@ -417,8 +325,7 @@ prof_method_allocations(VALUE self)
417
325
  called -> Measurement
418
326
 
419
327
  Returns the measurement associated with this method. */
420
- static VALUE
421
- prof_method_measurement(VALUE self)
328
+ static VALUE prof_method_measurement(VALUE self)
422
329
  {
423
330
  prof_method_t* method = prof_get_method(self);
424
331
  return prof_measurement_wrap(method->measurement);
@@ -431,7 +338,7 @@ return the source file of the method
431
338
  */
432
339
  static VALUE prof_method_source_file(VALUE self)
433
340
  {
434
- prof_method_t* method = prof_method_get(self);
341
+ prof_method_t* method = prof_get_method(self);
435
342
  return method->source_file;
436
343
  }
437
344
 
@@ -439,10 +346,9 @@ static VALUE prof_method_source_file(VALUE self)
439
346
  line_no -> int
440
347
 
441
348
  returns the line number of the method */
442
- static VALUE
443
- prof_method_line(VALUE self)
349
+ static VALUE prof_method_line(VALUE self)
444
350
  {
445
- prof_method_t* method = prof_method_get(self);
351
+ prof_method_t* method = prof_get_method(self);
446
352
  return INT2FIX(method->source_line);
447
353
  }
448
354
 
@@ -452,10 +358,9 @@ prof_method_line(VALUE self)
452
358
  Returns the name of this method's class. Singleton classes
453
359
  will have the form <Object::Object>. */
454
360
 
455
- static VALUE
456
- prof_method_klass_name(VALUE self)
361
+ static VALUE prof_method_klass_name(VALUE self)
457
362
  {
458
- prof_method_t *method = prof_method_get(self);
363
+ prof_method_t* method = prof_get_method(self);
459
364
  if (method->klass_name == Qnil)
460
365
  method->klass_name = resolve_klass_name(method->klass, &method->klass_flags);
461
366
 
@@ -467,10 +372,9 @@ prof_method_klass_name(VALUE self)
467
372
 
468
373
  Returns the klass flags */
469
374
 
470
- static VALUE
471
- prof_method_klass_flags(VALUE self)
375
+ static VALUE prof_method_klass_flags(VALUE self)
472
376
  {
473
- prof_method_t* method = prof_method_get(self);
377
+ prof_method_t* method = prof_get_method(self);
474
378
  return INT2FIX(method->klass_flags);
475
379
  }
476
380
 
@@ -480,51 +384,36 @@ prof_method_klass_flags(VALUE self)
480
384
  Returns the name of this method in the format Object#method. Singletons
481
385
  methods will be returned in the format <Object::Object>#method.*/
482
386
 
483
- static VALUE
484
- prof_method_name(VALUE self)
387
+ static VALUE prof_method_name(VALUE self)
485
388
  {
486
- prof_method_t *method = prof_method_get(self);
389
+ prof_method_t* method = prof_get_method(self);
487
390
  return method->method_name;
488
391
  }
489
392
 
490
- /* call-seq:
491
- root? -> boolean
492
-
493
- Returns the true if this method is at the top of the call stack */
494
- static VALUE
495
- prof_method_root(VALUE self)
496
- {
497
- prof_method_t *method = prof_method_get(self);
498
- return method->root ? Qtrue : Qfalse;
499
- }
500
-
501
393
  /* call-seq:
502
394
  recursive? -> boolean
503
395
 
504
396
  Returns the true if this method is recursively invoked */
505
- static VALUE
506
- prof_method_recursive(VALUE self)
397
+ static VALUE prof_method_recursive(VALUE self)
507
398
  {
508
- prof_method_t* method = prof_method_get(self);
399
+ prof_method_t* method = prof_get_method(self);
509
400
  return method->recursive ? Qtrue : Qfalse;
510
401
  }
511
402
 
512
403
  /* call-seq:
513
- excluded? -> boolean
404
+ call_trees -> CallTrees
514
405
 
515
- Returns the true if this method was excluded */
516
- static VALUE
517
- prof_method_excluded(VALUE self)
406
+ Returns the CallTrees associated with this method. */
407
+ static VALUE prof_method_call_trees(VALUE self)
518
408
  {
519
- prof_method_t* method = prof_method_get(self);
520
- return method->excluded ? Qtrue : Qfalse;
409
+ prof_method_t* method = prof_get_method(self);
410
+ return prof_call_trees_wrap(method->call_trees);
521
411
  }
522
412
 
523
413
  /* :nodoc: */
524
- static VALUE
525
- prof_method_dump(VALUE self)
414
+ static VALUE prof_method_dump(VALUE self)
526
415
  {
527
- prof_method_t* method_data = DATA_PTR(self);
416
+ prof_method_t* method_data = prof_get_method(self);
528
417
  VALUE result = rb_hash_new();
529
418
 
530
419
  rb_hash_aset(result, ID2SYM(rb_intern("klass_name")), prof_method_klass_name(self));
@@ -532,27 +421,21 @@ prof_method_dump(VALUE self)
532
421
  rb_hash_aset(result, ID2SYM(rb_intern("method_name")), method_data->method_name);
533
422
 
534
423
  rb_hash_aset(result, ID2SYM(rb_intern("key")), INT2FIX(method_data->key));
535
- rb_hash_aset(result, ID2SYM(rb_intern("root")), prof_method_root(self));
536
424
  rb_hash_aset(result, ID2SYM(rb_intern("recursive")), prof_method_recursive(self));
537
- rb_hash_aset(result, ID2SYM(rb_intern("excluded")), prof_method_excluded(self));
538
425
  rb_hash_aset(result, ID2SYM(rb_intern("source_file")), method_data->source_file);
539
426
  rb_hash_aset(result, ID2SYM(rb_intern("source_line")), INT2FIX(method_data->source_line));
540
427
 
428
+ rb_hash_aset(result, ID2SYM(rb_intern("call_trees")), prof_call_trees_wrap(method_data->call_trees));
541
429
  rb_hash_aset(result, ID2SYM(rb_intern("measurement")), prof_measurement_wrap(method_data->measurement));
542
-
543
- rb_hash_aset(result, ID2SYM(rb_intern("callers")), prof_method_callers(self));
544
- rb_hash_aset(result, ID2SYM(rb_intern("callees")), prof_method_callees(self));
545
-
546
430
  rb_hash_aset(result, ID2SYM(rb_intern("allocations")), prof_method_allocations(self));
547
431
 
548
432
  return result;
549
433
  }
550
434
 
551
435
  /* :nodoc: */
552
- static VALUE
553
- prof_method_load(VALUE self, VALUE data)
436
+ static VALUE prof_method_load(VALUE self, VALUE data)
554
437
  {
555
- prof_method_t* method_data = RDATA(self)->data;
438
+ prof_method_t* method_data = prof_get_method(self);
556
439
  method_data->object = self;
557
440
 
558
441
  method_data->klass_name = rb_hash_aref(data, ID2SYM(rb_intern("klass_name")));
@@ -560,42 +443,24 @@ prof_method_load(VALUE self, VALUE data)
560
443
  method_data->method_name = rb_hash_aref(data, ID2SYM(rb_intern("method_name")));
561
444
  method_data->key = FIX2LONG(rb_hash_aref(data, ID2SYM(rb_intern("key"))));
562
445
 
563
- method_data->root = rb_hash_aref(data, ID2SYM(rb_intern("root"))) == Qtrue ? true : false;
564
446
  method_data->recursive = rb_hash_aref(data, ID2SYM(rb_intern("recursive"))) == Qtrue ? true : false;
565
- method_data->excluded = rb_hash_aref(data, ID2SYM(rb_intern("excluded"))) == Qtrue ? true : false;
566
447
 
567
448
  method_data->source_file = rb_hash_aref(data, ID2SYM(rb_intern("source_file")));
568
449
  method_data->source_line = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("source_line"))));
569
450
 
451
+ VALUE call_trees = rb_hash_aref(data, ID2SYM(rb_intern("call_trees")));
452
+ method_data->call_trees = prof_get_call_trees(call_trees);
453
+
570
454
  VALUE measurement = rb_hash_aref(data, ID2SYM(rb_intern("measurement")));
571
455
  method_data->measurement = prof_get_measurement(measurement);
572
456
 
573
- VALUE callers = rb_hash_aref(data, ID2SYM(rb_intern("callers")));
574
- for (int i = 0; i < rb_array_len(callers); i++)
575
- {
576
- VALUE call_info = rb_ary_entry(callers, i);
577
- prof_call_info_t *call_info_data = prof_get_call_info(call_info);
578
- st_data_t key = call_info_data->parent ? call_info_data->parent->key : method_key(Qnil, 0);
579
- call_info_table_insert(method_data->parent_call_infos, key, call_info_data);
580
- }
581
-
582
- VALUE callees = rb_hash_aref(data, ID2SYM(rb_intern("callees")));
583
- for (int i = 0; i < rb_array_len(callees); i++)
584
- {
585
- VALUE call_info = rb_ary_entry(callees, i);
586
- prof_call_info_t *call_info_data = prof_get_call_info(call_info);
587
-
588
- st_data_t key = call_info_data->method ? call_info_data->method->key : method_key(Qnil, 0);
589
- call_info_table_insert(method_data->child_call_infos, key, call_info_data);
590
- }
591
-
592
457
  VALUE allocations = rb_hash_aref(data, ID2SYM(rb_intern("allocations")));
593
458
  for (int i = 0; i < rb_array_len(allocations); i++)
594
459
  {
595
460
  VALUE allocation = rb_ary_entry(allocations, i);
596
461
  prof_allocation_t* allocation_data = prof_allocation_get(allocation);
597
462
 
598
- st_insert(method_data->allocations_table, allocation_data->key, (st_data_t)allocation_data);
463
+ rb_st_insert(method_data->allocations_table, allocation_data->key, (st_data_t)allocation_data);
599
464
  }
600
465
  return data;
601
466
  }
@@ -603,28 +468,24 @@ prof_method_load(VALUE self, VALUE data)
603
468
  void rp_init_method_info()
604
469
  {
605
470
  /* MethodInfo */
606
- cRpMethodInfo = rb_define_class_under(mProf, "MethodInfo", rb_cData);
471
+ cRpMethodInfo = rb_define_class_under(mProf, "MethodInfo", rb_cObject);
607
472
  rb_undef_method(CLASS_OF(cRpMethodInfo), "new");
608
473
  rb_define_alloc_func(cRpMethodInfo, prof_method_allocate);
609
474
 
610
475
  rb_define_method(cRpMethodInfo, "klass_name", prof_method_klass_name, 0);
611
476
  rb_define_method(cRpMethodInfo, "klass_flags", prof_method_klass_flags, 0);
612
-
613
477
  rb_define_method(cRpMethodInfo, "method_name", prof_method_name, 0);
614
-
615
- rb_define_method(cRpMethodInfo, "callers", prof_method_callers, 0);
616
- rb_define_method(cRpMethodInfo, "callees", prof_method_callees, 0);
617
- rb_define_method(cRpMethodInfo, "allocations", prof_method_allocations, 0);
618
478
 
479
+ rb_define_method(cRpMethodInfo, "call_trees", prof_method_call_trees, 0);
480
+
481
+ rb_define_method(cRpMethodInfo, "allocations", prof_method_allocations, 0);
619
482
  rb_define_method(cRpMethodInfo, "measurement", prof_method_measurement, 0);
620
-
483
+
621
484
  rb_define_method(cRpMethodInfo, "source_file", prof_method_source_file, 0);
622
485
  rb_define_method(cRpMethodInfo, "line", prof_method_line, 0);
623
486
 
624
- rb_define_method(cRpMethodInfo, "root?", prof_method_root, 0);
625
487
  rb_define_method(cRpMethodInfo, "recursive?", prof_method_recursive, 0);
626
- rb_define_method(cRpMethodInfo, "excluded?", prof_method_excluded, 0);
627
488
 
628
489
  rb_define_method(cRpMethodInfo, "_dump_data", prof_method_dump, 0);
629
490
  rb_define_method(cRpMethodInfo, "_load_data", prof_method_load, 1);
630
- }
491
+ }