ruby-prof 1.4.3 → 1.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES +59 -9
- data/{README.rdoc → README.md} +2 -2
- data/Rakefile +4 -4
- data/bin/ruby-prof +100 -87
- data/ext/ruby_prof/rp_allocation.c +140 -85
- data/ext/ruby_prof/rp_allocation.h +8 -6
- data/ext/ruby_prof/rp_call_tree.c +502 -369
- data/ext/ruby_prof/rp_call_tree.h +47 -43
- data/ext/ruby_prof/rp_call_trees.c +16 -8
- data/ext/ruby_prof/rp_measure_allocations.c +10 -13
- data/ext/ruby_prof/rp_measure_memory.c +8 -4
- data/ext/ruby_prof/rp_measure_process_time.c +7 -6
- data/ext/ruby_prof/rp_measurement.c +147 -20
- data/ext/ruby_prof/rp_measurement.h +4 -1
- data/ext/ruby_prof/rp_method.c +142 -83
- data/ext/ruby_prof/rp_method.h +63 -62
- data/ext/ruby_prof/rp_profile.c +933 -900
- data/ext/ruby_prof/rp_profile.h +1 -0
- data/ext/ruby_prof/rp_thread.c +433 -362
- data/ext/ruby_prof/rp_thread.h +39 -39
- data/ext/ruby_prof/ruby_prof.c +0 -2
- data/ext/ruby_prof/ruby_prof.h +8 -0
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +11 -8
- data/lib/ruby-prof/assets/call_stack_printer.html.erb +2 -1
- data/lib/ruby-prof/compatibility.rb +14 -0
- data/lib/ruby-prof/method_info.rb +8 -1
- data/lib/ruby-prof/printers/abstract_printer.rb +2 -1
- data/lib/ruby-prof/printers/call_tree_printer.rb +4 -10
- data/lib/ruby-prof/printers/graph_html_printer.rb +1 -1
- data/lib/ruby-prof/printers/multi_printer.rb +17 -17
- data/lib/ruby-prof/profile.rb +70 -37
- data/lib/ruby-prof/rack.rb +31 -21
- data/lib/ruby-prof/version.rb +1 -1
- data/lib/ruby-prof.rb +1 -1
- data/ruby-prof.gemspec +2 -3
- data/test/abstract_printer_test.rb +1 -0
- data/test/alias_test.rb +97 -106
- data/test/call_tree_builder.rb +126 -0
- data/test/call_tree_test.rb +94 -0
- data/test/call_tree_visitor_test.rb +1 -6
- data/test/call_trees_test.rb +6 -6
- data/test/{basic_test.rb → compatibility_test.rb} +8 -2
- data/test/duplicate_names_test.rb +5 -5
- data/test/dynamic_method_test.rb +24 -15
- data/test/enumerable_test.rb +1 -1
- data/test/exceptions_test.rb +2 -2
- data/test/exclude_methods_test.rb +3 -8
- data/test/exclude_threads_test.rb +4 -9
- data/test/fiber_test.rb +74 -8
- data/test/gc_test.rb +11 -9
- data/test/inverse_call_tree_test.rb +33 -34
- data/test/line_number_test.rb +37 -61
- data/test/marshal_test.rb +16 -3
- data/test/measure_allocations.rb +1 -5
- data/test/measure_allocations_test.rb +642 -357
- data/test/{measure_memory_trace_test.rb → measure_memory_test.rb} +180 -616
- data/test/measure_process_time_test.rb +1566 -741
- data/test/measure_wall_time_test.rb +179 -193
- data/test/measurement_test.rb +82 -0
- data/test/merge_test.rb +146 -0
- data/test/method_info_test.rb +95 -0
- data/test/multi_printer_test.rb +0 -5
- data/test/no_method_class_test.rb +1 -1
- data/test/pause_resume_test.rb +12 -16
- data/test/printer_call_stack_test.rb +2 -2
- data/test/printer_call_tree_test.rb +4 -4
- data/test/printer_flat_test.rb +1 -1
- data/test/printer_graph_html_test.rb +2 -2
- data/test/printer_graph_test.rb +2 -2
- data/test/printers_test.rb +14 -20
- data/test/printing_recursive_graph_test.rb +2 -2
- data/test/profile_test.rb +85 -0
- data/test/recursive_test.rb +374 -155
- data/test/scheduler.rb +363 -0
- data/test/singleton_test.rb +1 -1
- data/test/stack_printer_test.rb +5 -8
- data/test/start_stop_test.rb +11 -14
- data/test/test_helper.rb +11 -8
- data/test/thread_test.rb +106 -15
- data/test/unique_call_path_test.rb +28 -12
- data/test/yarv_test.rb +11 -7
- metadata +17 -29
- data/ext/ruby_prof/rp_aggregate_call_tree.c +0 -59
- data/ext/ruby_prof/rp_aggregate_call_tree.h +0 -13
- data/test/measure_allocations_trace_test.rb +0 -375
- data/test/temp.rb +0 -20
data/ext/ruby_prof/rp_method.c
CHANGED
@@ -22,31 +22,38 @@ VALUE resolve_klass(VALUE klass, unsigned int* klass_flags)
|
|
22
22
|
figure out what it is attached to.*/
|
23
23
|
VALUE attached = rb_iv_get(klass, "__attached__");
|
24
24
|
|
25
|
-
|
26
|
-
if (BUILTIN_TYPE(attached) == T_CLASS)
|
25
|
+
switch (BUILTIN_TYPE(attached))
|
27
26
|
{
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
27
|
+
/* Is this a singleton class acting as a metaclass? */
|
28
|
+
case T_CLASS:
|
29
|
+
{
|
30
|
+
*klass_flags |= kClassSingleton;
|
31
|
+
result = attached;
|
32
|
+
break;
|
33
|
+
}
|
34
|
+
/* Is this for singleton methods on a module? */
|
35
|
+
case T_MODULE:
|
36
|
+
{
|
37
|
+
*klass_flags |= kModuleSingleton;
|
38
|
+
result = attached;
|
39
|
+
break;
|
40
|
+
}
|
41
|
+
/* Is this for singleton methods on an object? */
|
42
|
+
case T_OBJECT:
|
43
|
+
{
|
44
|
+
*klass_flags |= kObjectSingleton;
|
45
|
+
result = rb_class_superclass(klass);
|
46
|
+
break;
|
47
|
+
}
|
48
|
+
/* Ok, this could be other things like an array put onto
|
49
|
+
a singleton object (yeah, it happens, see the singleton
|
50
|
+
objects test case). */
|
51
|
+
default:
|
52
|
+
{
|
53
|
+
*klass_flags |= kOtherSingleton;
|
54
|
+
result = klass;
|
55
|
+
break;
|
56
|
+
}
|
50
57
|
}
|
51
58
|
}
|
52
59
|
/* Is this an include for a module? If so get the actual
|
@@ -56,7 +63,7 @@ VALUE resolve_klass(VALUE klass, unsigned int* klass_flags)
|
|
56
63
|
{
|
57
64
|
unsigned int dummy;
|
58
65
|
*klass_flags |= kModuleIncludee;
|
59
|
-
result = resolve_klass(
|
66
|
+
result = resolve_klass(RBASIC_CLASS(klass), &dummy);
|
60
67
|
}
|
61
68
|
return result;
|
62
69
|
}
|
@@ -94,43 +101,15 @@ st_data_t method_key(VALUE klass, VALUE msym)
|
|
94
101
|
}
|
95
102
|
else if (BUILTIN_TYPE(klass) == T_ICLASS)
|
96
103
|
{
|
97
|
-
resolved_klass =
|
104
|
+
resolved_klass = RBASIC_CLASS(klass);
|
98
105
|
}
|
99
106
|
|
100
|
-
|
101
|
-
|
107
|
+
st_data_t hash = rb_hash_start(0);
|
108
|
+
hash = rb_hash_uint(hash, resolved_klass);
|
109
|
+
hash = rb_hash_uint(hash, msym);
|
110
|
+
hash = rb_hash_end(hash);
|
102
111
|
|
103
|
-
|
104
|
-
st_table* allocations_table_create()
|
105
|
-
{
|
106
|
-
return rb_st_init_numtable();
|
107
|
-
}
|
108
|
-
|
109
|
-
static int allocations_table_free_iterator(st_data_t key, st_data_t value, st_data_t dummy)
|
110
|
-
{
|
111
|
-
prof_allocation_free((prof_allocation_t*)value);
|
112
|
-
return ST_CONTINUE;
|
113
|
-
}
|
114
|
-
|
115
|
-
static int prof_method_collect_allocations(st_data_t key, st_data_t value, st_data_t result)
|
116
|
-
{
|
117
|
-
prof_allocation_t* allocation = (prof_allocation_t*)value;
|
118
|
-
VALUE arr = (VALUE)result;
|
119
|
-
rb_ary_push(arr, prof_allocation_wrap(allocation));
|
120
|
-
return ST_CONTINUE;
|
121
|
-
}
|
122
|
-
|
123
|
-
static int prof_method_mark_allocations(st_data_t key, st_data_t value, st_data_t data)
|
124
|
-
{
|
125
|
-
prof_allocation_t* allocation = (prof_allocation_t*)value;
|
126
|
-
prof_allocation_mark(allocation);
|
127
|
-
return ST_CONTINUE;
|
128
|
-
}
|
129
|
-
|
130
|
-
void allocations_table_free(st_table* table)
|
131
|
-
{
|
132
|
-
rb_st_foreach(table, allocations_table_free_iterator, 0);
|
133
|
-
rb_st_free_table(table);
|
112
|
+
return hash;
|
134
113
|
}
|
135
114
|
|
136
115
|
/* ================ prof_method_t =================*/
|
@@ -162,7 +141,7 @@ prof_method_t* prof_method_create(VALUE profile, VALUE klass, VALUE msym, VALUE
|
|
162
141
|
result->measurement = prof_measurement_create();
|
163
142
|
|
164
143
|
result->call_trees = prof_call_trees_create();
|
165
|
-
result->allocations_table =
|
144
|
+
result->allocations_table = prof_allocations_create();
|
166
145
|
|
167
146
|
result->visits = 0;
|
168
147
|
result->recursive = false;
|
@@ -175,6 +154,14 @@ prof_method_t* prof_method_create(VALUE profile, VALUE klass, VALUE msym, VALUE
|
|
175
154
|
return result;
|
176
155
|
}
|
177
156
|
|
157
|
+
prof_method_t* prof_method_copy(prof_method_t* other)
|
158
|
+
{
|
159
|
+
prof_method_t* result = prof_method_create(other->profile, other->klass, other->method_name, other->source_file, other->source_line);
|
160
|
+
result->measurement = prof_measurement_copy(other->measurement);
|
161
|
+
|
162
|
+
return result;
|
163
|
+
}
|
164
|
+
|
178
165
|
/* The underlying c structures are freed when the parent profile is freed.
|
179
166
|
However, on shutdown the Ruby GC frees objects in any will-nilly order.
|
180
167
|
That means the ruby thread object wrapping the c thread struct may
|
@@ -200,7 +187,7 @@ static void prof_method_free(prof_method_t* method)
|
|
200
187
|
method->object = Qnil;
|
201
188
|
}
|
202
189
|
|
203
|
-
|
190
|
+
prof_allocations_free(method->allocations_table);
|
204
191
|
prof_call_trees_free(method->call_trees);
|
205
192
|
prof_measurement_free(method->measurement);
|
206
193
|
xfree(method);
|
@@ -218,21 +205,29 @@ void prof_method_mark(void* data)
|
|
218
205
|
prof_method_t* method = (prof_method_t*)data;
|
219
206
|
|
220
207
|
if (method->profile != Qnil)
|
221
|
-
|
208
|
+
rb_gc_mark_movable(method->profile);
|
222
209
|
|
223
210
|
if (method->object != Qnil)
|
224
|
-
|
211
|
+
rb_gc_mark_movable(method->object);
|
225
212
|
|
226
|
-
|
227
|
-
|
213
|
+
rb_gc_mark_movable(method->klass_name);
|
214
|
+
rb_gc_mark_movable(method->method_name);
|
228
215
|
rb_gc_mark(method->source_file);
|
229
216
|
|
230
217
|
if (method->klass != Qnil)
|
231
218
|
rb_gc_mark(method->klass);
|
232
219
|
|
233
220
|
prof_measurement_mark(method->measurement);
|
221
|
+
prof_allocations_mark(method->allocations_table);
|
222
|
+
}
|
234
223
|
|
235
|
-
|
224
|
+
void prof_method_compact(void* data)
|
225
|
+
{
|
226
|
+
prof_method_t* method = (prof_method_t*)data;
|
227
|
+
method->object = rb_gc_location(method->object);
|
228
|
+
method->profile = rb_gc_location(method->profile);
|
229
|
+
method->klass_name = rb_gc_location(method->klass_name);
|
230
|
+
method->method_name = rb_gc_location(method->method_name);
|
236
231
|
}
|
237
232
|
|
238
233
|
static VALUE prof_method_allocate(VALUE klass)
|
@@ -250,6 +245,7 @@ static const rb_data_type_t method_info_type =
|
|
250
245
|
.dmark = prof_method_mark,
|
251
246
|
.dfree = prof_method_ruby_gc_free,
|
252
247
|
.dsize = prof_method_size,
|
248
|
+
.dcompact = prof_method_compact
|
253
249
|
},
|
254
250
|
.data = NULL,
|
255
251
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
@@ -286,6 +282,30 @@ size_t method_table_insert(st_table* table, st_data_t key, prof_method_t* val)
|
|
286
282
|
return rb_st_insert(table, (st_data_t)key, (st_data_t)val);
|
287
283
|
}
|
288
284
|
|
285
|
+
static int prof_method_table_merge_internal(st_data_t key, st_data_t value, st_data_t data)
|
286
|
+
{
|
287
|
+
st_table* self_table = (st_table*)data;
|
288
|
+
prof_method_t* other_child = (prof_method_t*)value;
|
289
|
+
|
290
|
+
prof_method_t* self_child = method_table_lookup(self_table, other_child->key);
|
291
|
+
if (self_child)
|
292
|
+
{
|
293
|
+
prof_measurement_merge_internal(self_child->measurement, other_child->measurement);
|
294
|
+
}
|
295
|
+
else
|
296
|
+
{
|
297
|
+
prof_method_t* copy = prof_method_copy(other_child);
|
298
|
+
method_table_insert(self_table, copy->key, copy);
|
299
|
+
}
|
300
|
+
|
301
|
+
return ST_CONTINUE;
|
302
|
+
}
|
303
|
+
|
304
|
+
void prof_method_table_merge(st_table* self, st_table* other)
|
305
|
+
{
|
306
|
+
rb_st_foreach(other, prof_method_table_merge_internal, (st_data_t)self);
|
307
|
+
}
|
308
|
+
|
289
309
|
prof_method_t* method_table_lookup(st_table* table, st_data_t key)
|
290
310
|
{
|
291
311
|
st_data_t val;
|
@@ -309,6 +329,45 @@ created. RubyProf::MethodInfo objects can be accessed via
|
|
309
329
|
the RubyProf::Profile object.
|
310
330
|
*/
|
311
331
|
|
332
|
+
/* call-seq:
|
333
|
+
new(klass, method_name) -> method_info
|
334
|
+
|
335
|
+
Creates a new MethodInfo instance. +Klass+ should be a reference to
|
336
|
+
a Ruby class and +method_name+ a symbol identifying one of its instance methods.*/
|
337
|
+
static VALUE prof_method_initialize(VALUE self, VALUE klass, VALUE method_name)
|
338
|
+
{
|
339
|
+
prof_method_t* method_ptr = prof_get_method(self);
|
340
|
+
method_ptr->klass = klass;
|
341
|
+
method_ptr->method_name = method_name;
|
342
|
+
|
343
|
+
// Setup method key
|
344
|
+
method_ptr->key = method_key(klass, method_name);
|
345
|
+
|
346
|
+
// Get method object
|
347
|
+
VALUE ruby_method = rb_funcall(klass, rb_intern("instance_method"), 1, method_name);
|
348
|
+
|
349
|
+
// Get source file and line number
|
350
|
+
VALUE location_array = rb_funcall(ruby_method, rb_intern("source_location"), 0);
|
351
|
+
if (location_array != Qnil && RARRAY_LEN(location_array) == 2)
|
352
|
+
{
|
353
|
+
method_ptr->source_file = rb_ary_entry(location_array, 0);
|
354
|
+
method_ptr->source_line = NUM2INT(rb_ary_entry(location_array, 1));
|
355
|
+
}
|
356
|
+
|
357
|
+
return self;
|
358
|
+
}
|
359
|
+
|
360
|
+
/* call-seq:
|
361
|
+
hash -> hash
|
362
|
+
|
363
|
+
Returns the hash key for this method info. The hash key is calculated based on the
|
364
|
+
klass name and method name */
|
365
|
+
static VALUE prof_method_hash(VALUE self)
|
366
|
+
{
|
367
|
+
prof_method_t* method_ptr = prof_get_method(self);
|
368
|
+
return ULL2NUM(method_ptr->key);
|
369
|
+
}
|
370
|
+
|
312
371
|
/* call-seq:
|
313
372
|
allocations -> array
|
314
373
|
|
@@ -316,9 +375,7 @@ Returns an array of allocation information.*/
|
|
316
375
|
static VALUE prof_method_allocations(VALUE self)
|
317
376
|
{
|
318
377
|
prof_method_t* method = prof_get_method(self);
|
319
|
-
|
320
|
-
rb_st_foreach(method->allocations_table, prof_method_collect_allocations, result);
|
321
|
-
return result;
|
378
|
+
return prof_allocations_wrap(method->allocations_table);
|
322
379
|
}
|
323
380
|
|
324
381
|
/* call-seq:
|
@@ -334,7 +391,7 @@ static VALUE prof_method_measurement(VALUE self)
|
|
334
391
|
/* call-seq:
|
335
392
|
source_file => string
|
336
393
|
|
337
|
-
|
394
|
+
Returns the source file of the method
|
338
395
|
*/
|
339
396
|
static VALUE prof_method_source_file(VALUE self)
|
340
397
|
{
|
@@ -353,7 +410,7 @@ static VALUE prof_method_line(VALUE self)
|
|
353
410
|
}
|
354
411
|
|
355
412
|
/* call-seq:
|
356
|
-
klass_name ->
|
413
|
+
klass_name -> String
|
357
414
|
|
358
415
|
Returns the name of this method's class. Singleton classes
|
359
416
|
will have the form <Object::Object>. */
|
@@ -379,9 +436,9 @@ static VALUE prof_method_klass_flags(VALUE self)
|
|
379
436
|
}
|
380
437
|
|
381
438
|
/* call-seq:
|
382
|
-
method_name ->
|
439
|
+
method_name -> Symbol
|
383
440
|
|
384
|
-
Returns the name of this method in the format Object#method.
|
441
|
+
Returns the name of this method in the format Object#method. Singletons
|
385
442
|
methods will be returned in the format <Object::Object>#method.*/
|
386
443
|
|
387
444
|
static VALUE prof_method_name(VALUE self)
|
@@ -420,7 +477,7 @@ static VALUE prof_method_dump(VALUE self)
|
|
420
477
|
rb_hash_aset(result, ID2SYM(rb_intern("klass_flags")), INT2FIX(method_data->klass_flags));
|
421
478
|
rb_hash_aset(result, ID2SYM(rb_intern("method_name")), method_data->method_name);
|
422
479
|
|
423
|
-
rb_hash_aset(result, ID2SYM(rb_intern("key")),
|
480
|
+
rb_hash_aset(result, ID2SYM(rb_intern("key")), ULL2NUM(method_data->key));
|
424
481
|
rb_hash_aset(result, ID2SYM(rb_intern("recursive")), prof_method_recursive(self));
|
425
482
|
rb_hash_aset(result, ID2SYM(rb_intern("source_file")), method_data->source_file);
|
426
483
|
rb_hash_aset(result, ID2SYM(rb_intern("source_line")), INT2FIX(method_data->source_line));
|
@@ -441,7 +498,7 @@ static VALUE prof_method_load(VALUE self, VALUE data)
|
|
441
498
|
method_data->klass_name = rb_hash_aref(data, ID2SYM(rb_intern("klass_name")));
|
442
499
|
method_data->klass_flags = FIX2INT(rb_hash_aref(data, ID2SYM(rb_intern("klass_flags"))));
|
443
500
|
method_data->method_name = rb_hash_aref(data, ID2SYM(rb_intern("method_name")));
|
444
|
-
method_data->key =
|
501
|
+
method_data->key = RB_NUM2ULL(rb_hash_aref(data, ID2SYM(rb_intern("key"))));
|
445
502
|
|
446
503
|
method_data->recursive = rb_hash_aref(data, ID2SYM(rb_intern("recursive"))) == Qtrue ? true : false;
|
447
504
|
|
@@ -455,13 +512,7 @@ static VALUE prof_method_load(VALUE self, VALUE data)
|
|
455
512
|
method_data->measurement = prof_get_measurement(measurement);
|
456
513
|
|
457
514
|
VALUE allocations = rb_hash_aref(data, ID2SYM(rb_intern("allocations")));
|
458
|
-
|
459
|
-
{
|
460
|
-
VALUE allocation = rb_ary_entry(allocations, i);
|
461
|
-
prof_allocation_t* allocation_data = prof_allocation_get(allocation);
|
462
|
-
|
463
|
-
rb_st_insert(method_data->allocations_table, allocation_data->key, (st_data_t)allocation_data);
|
464
|
-
}
|
515
|
+
prof_allocations_unwrap(method_data->allocations_table, allocations);
|
465
516
|
return data;
|
466
517
|
}
|
467
518
|
|
@@ -469,8 +520,16 @@ void rp_init_method_info()
|
|
469
520
|
{
|
470
521
|
/* MethodInfo */
|
471
522
|
cRpMethodInfo = rb_define_class_under(mProf, "MethodInfo", rb_cObject);
|
472
|
-
|
523
|
+
|
524
|
+
rb_define_const(cRpMethodInfo, "MODULE_INCLUDEE", INT2NUM(kModuleIncludee));
|
525
|
+
rb_define_const(cRpMethodInfo, "CLASS_SINGLETON", INT2NUM(kClassSingleton));
|
526
|
+
rb_define_const(cRpMethodInfo, "MODULE_SINGLETON", INT2NUM(kModuleSingleton));
|
527
|
+
rb_define_const(cRpMethodInfo, "OBJECT_SINGLETON", INT2NUM(kObjectSingleton));
|
528
|
+
rb_define_const(cRpMethodInfo, "OTHER_SINGLETON", INT2NUM(kOtherSingleton));
|
529
|
+
|
473
530
|
rb_define_alloc_func(cRpMethodInfo, prof_method_allocate);
|
531
|
+
rb_define_method(cRpMethodInfo, "initialize", prof_method_initialize, 2);
|
532
|
+
rb_define_method(cRpMethodInfo, "hash", prof_method_hash, 0);
|
474
533
|
|
475
534
|
rb_define_method(cRpMethodInfo, "klass_name", prof_method_klass_name, 0);
|
476
535
|
rb_define_method(cRpMethodInfo, "klass_flags", prof_method_klass_flags, 0);
|
data/ext/ruby_prof/rp_method.h
CHANGED
@@ -1,62 +1,63 @@
|
|
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
|
-
#ifndef __RP_METHOD_INFO__
|
5
|
-
#define __RP_METHOD_INFO__
|
6
|
-
|
7
|
-
#include "ruby_prof.h"
|
8
|
-
#include "rp_measurement.h"
|
9
|
-
|
10
|
-
extern VALUE cRpMethodInfo;
|
11
|
-
|
12
|
-
// Source relation bit offsets.
|
13
|
-
enum {
|
14
|
-
kModuleIncludee = 0x1, // Included in module
|
15
|
-
kClassSingleton = 0x2, // Singleton of a class
|
16
|
-
kModuleSingleton = 0x4, // Singleton of a module
|
17
|
-
kObjectSingleton = 0x8, // Singleton of an object
|
18
|
-
kOtherSingleton = 0x10 // Singleton of
|
19
|
-
};
|
20
|
-
|
21
|
-
// Profiling information for each method.
|
22
|
-
// Excluded methods have no call_trees, source_klass, or source_file.
|
23
|
-
typedef struct prof_method_t
|
24
|
-
{
|
25
|
-
VALUE profile; // Profile this method is associated with - needed for mark phase
|
26
|
-
struct prof_call_trees_t* call_trees; // Call infos that call this method
|
27
|
-
st_table* allocations_table; // Tracks object allocations
|
28
|
-
|
29
|
-
st_data_t key; // Table key
|
30
|
-
unsigned int klass_flags; // Information about the type of class
|
31
|
-
VALUE klass; // Resolved klass
|
32
|
-
VALUE klass_name; // Resolved klass name for this method
|
33
|
-
VALUE method_name; // Resolved method name for this method
|
34
|
-
|
35
|
-
VALUE object; // Cached ruby object
|
36
|
-
|
37
|
-
bool recursive;
|
38
|
-
int visits; // Current visits on the stack
|
39
|
-
VALUE source_file; // Source file
|
40
|
-
int source_line; // Line number
|
41
|
-
|
42
|
-
prof_measurement_t* measurement; // Stores measurement data for this method
|
43
|
-
} prof_method_t;
|
44
|
-
|
45
|
-
void rp_init_method_info(void);
|
46
|
-
|
47
|
-
st_data_t method_key(VALUE klass, VALUE msym);
|
48
|
-
|
49
|
-
st_table* method_table_create(void);
|
50
|
-
prof_method_t* method_table_lookup(st_table* table, st_data_t key);
|
51
|
-
size_t method_table_insert(st_table* table, st_data_t key, prof_method_t* val);
|
52
|
-
void method_table_free(st_table* table);
|
53
|
-
|
54
|
-
prof_method_t*
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
VALUE
|
61
|
-
|
62
|
-
|
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
|
+
#ifndef __RP_METHOD_INFO__
|
5
|
+
#define __RP_METHOD_INFO__
|
6
|
+
|
7
|
+
#include "ruby_prof.h"
|
8
|
+
#include "rp_measurement.h"
|
9
|
+
|
10
|
+
extern VALUE cRpMethodInfo;
|
11
|
+
|
12
|
+
// Source relation bit offsets.
|
13
|
+
enum {
|
14
|
+
kModuleIncludee = 0x1, // Included in module
|
15
|
+
kClassSingleton = 0x2, // Singleton of a class
|
16
|
+
kModuleSingleton = 0x4, // Singleton of a module
|
17
|
+
kObjectSingleton = 0x8, // Singleton of an object
|
18
|
+
kOtherSingleton = 0x10 // Singleton of unknown object
|
19
|
+
};
|
20
|
+
|
21
|
+
// Profiling information for each method.
|
22
|
+
// Excluded methods have no call_trees, source_klass, or source_file.
|
23
|
+
typedef struct prof_method_t
|
24
|
+
{
|
25
|
+
VALUE profile; // Profile this method is associated with - needed for mark phase
|
26
|
+
struct prof_call_trees_t* call_trees; // Call infos that call this method
|
27
|
+
st_table* allocations_table; // Tracks object allocations
|
28
|
+
|
29
|
+
st_data_t key; // Table key
|
30
|
+
unsigned int klass_flags; // Information about the type of class
|
31
|
+
VALUE klass; // Resolved klass
|
32
|
+
VALUE klass_name; // Resolved klass name for this method
|
33
|
+
VALUE method_name; // Resolved method name for this method
|
34
|
+
|
35
|
+
VALUE object; // Cached ruby object
|
36
|
+
|
37
|
+
bool recursive;
|
38
|
+
int visits; // Current visits on the stack
|
39
|
+
VALUE source_file; // Source file
|
40
|
+
int source_line; // Line number
|
41
|
+
|
42
|
+
prof_measurement_t* measurement; // Stores measurement data for this method
|
43
|
+
} prof_method_t;
|
44
|
+
|
45
|
+
void rp_init_method_info(void);
|
46
|
+
|
47
|
+
st_data_t method_key(VALUE klass, VALUE msym);
|
48
|
+
|
49
|
+
st_table* method_table_create(void);
|
50
|
+
prof_method_t* method_table_lookup(st_table* table, st_data_t key);
|
51
|
+
size_t method_table_insert(st_table* table, st_data_t key, prof_method_t* val);
|
52
|
+
void method_table_free(st_table* table);
|
53
|
+
void prof_method_table_merge(st_table* self, st_table* other);
|
54
|
+
prof_method_t* prof_method_create(VALUE profile, VALUE klass, VALUE msym, VALUE source_file, int source_line);
|
55
|
+
prof_method_t* prof_get_method(VALUE self);
|
56
|
+
|
57
|
+
VALUE prof_method_wrap(prof_method_t* result);
|
58
|
+
void prof_method_mark(void* data);
|
59
|
+
|
60
|
+
VALUE resolve_klass(VALUE klass, unsigned int* klass_flags);
|
61
|
+
VALUE resolve_klass_name(VALUE klass, unsigned int* klass_flags);
|
62
|
+
|
63
|
+
#endif //__RP_METHOD_INFO__
|