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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +59 -9
  3. data/{README.rdoc → README.md} +2 -2
  4. data/Rakefile +4 -4
  5. data/bin/ruby-prof +100 -87
  6. data/ext/ruby_prof/rp_allocation.c +140 -85
  7. data/ext/ruby_prof/rp_allocation.h +8 -6
  8. data/ext/ruby_prof/rp_call_tree.c +502 -369
  9. data/ext/ruby_prof/rp_call_tree.h +47 -43
  10. data/ext/ruby_prof/rp_call_trees.c +16 -8
  11. data/ext/ruby_prof/rp_measure_allocations.c +10 -13
  12. data/ext/ruby_prof/rp_measure_memory.c +8 -4
  13. data/ext/ruby_prof/rp_measure_process_time.c +7 -6
  14. data/ext/ruby_prof/rp_measurement.c +147 -20
  15. data/ext/ruby_prof/rp_measurement.h +4 -1
  16. data/ext/ruby_prof/rp_method.c +142 -83
  17. data/ext/ruby_prof/rp_method.h +63 -62
  18. data/ext/ruby_prof/rp_profile.c +933 -900
  19. data/ext/ruby_prof/rp_profile.h +1 -0
  20. data/ext/ruby_prof/rp_thread.c +433 -362
  21. data/ext/ruby_prof/rp_thread.h +39 -39
  22. data/ext/ruby_prof/ruby_prof.c +0 -2
  23. data/ext/ruby_prof/ruby_prof.h +8 -0
  24. data/ext/ruby_prof/vc/ruby_prof.vcxproj +11 -8
  25. data/lib/ruby-prof/assets/call_stack_printer.html.erb +2 -1
  26. data/lib/ruby-prof/compatibility.rb +14 -0
  27. data/lib/ruby-prof/method_info.rb +8 -1
  28. data/lib/ruby-prof/printers/abstract_printer.rb +2 -1
  29. data/lib/ruby-prof/printers/call_tree_printer.rb +4 -10
  30. data/lib/ruby-prof/printers/graph_html_printer.rb +1 -1
  31. data/lib/ruby-prof/printers/multi_printer.rb +17 -17
  32. data/lib/ruby-prof/profile.rb +70 -37
  33. data/lib/ruby-prof/rack.rb +31 -21
  34. data/lib/ruby-prof/version.rb +1 -1
  35. data/lib/ruby-prof.rb +1 -1
  36. data/ruby-prof.gemspec +2 -3
  37. data/test/abstract_printer_test.rb +1 -0
  38. data/test/alias_test.rb +97 -106
  39. data/test/call_tree_builder.rb +126 -0
  40. data/test/call_tree_test.rb +94 -0
  41. data/test/call_tree_visitor_test.rb +1 -6
  42. data/test/call_trees_test.rb +6 -6
  43. data/test/{basic_test.rb → compatibility_test.rb} +8 -2
  44. data/test/duplicate_names_test.rb +5 -5
  45. data/test/dynamic_method_test.rb +24 -15
  46. data/test/enumerable_test.rb +1 -1
  47. data/test/exceptions_test.rb +2 -2
  48. data/test/exclude_methods_test.rb +3 -8
  49. data/test/exclude_threads_test.rb +4 -9
  50. data/test/fiber_test.rb +74 -8
  51. data/test/gc_test.rb +11 -9
  52. data/test/inverse_call_tree_test.rb +33 -34
  53. data/test/line_number_test.rb +37 -61
  54. data/test/marshal_test.rb +16 -3
  55. data/test/measure_allocations.rb +1 -5
  56. data/test/measure_allocations_test.rb +642 -357
  57. data/test/{measure_memory_trace_test.rb → measure_memory_test.rb} +180 -616
  58. data/test/measure_process_time_test.rb +1566 -741
  59. data/test/measure_wall_time_test.rb +179 -193
  60. data/test/measurement_test.rb +82 -0
  61. data/test/merge_test.rb +146 -0
  62. data/test/method_info_test.rb +95 -0
  63. data/test/multi_printer_test.rb +0 -5
  64. data/test/no_method_class_test.rb +1 -1
  65. data/test/pause_resume_test.rb +12 -16
  66. data/test/printer_call_stack_test.rb +2 -2
  67. data/test/printer_call_tree_test.rb +4 -4
  68. data/test/printer_flat_test.rb +1 -1
  69. data/test/printer_graph_html_test.rb +2 -2
  70. data/test/printer_graph_test.rb +2 -2
  71. data/test/printers_test.rb +14 -20
  72. data/test/printing_recursive_graph_test.rb +2 -2
  73. data/test/profile_test.rb +85 -0
  74. data/test/recursive_test.rb +374 -155
  75. data/test/scheduler.rb +363 -0
  76. data/test/singleton_test.rb +1 -1
  77. data/test/stack_printer_test.rb +5 -8
  78. data/test/start_stop_test.rb +11 -14
  79. data/test/test_helper.rb +11 -8
  80. data/test/thread_test.rb +106 -15
  81. data/test/unique_call_path_test.rb +28 -12
  82. data/test/yarv_test.rb +11 -7
  83. metadata +17 -29
  84. data/ext/ruby_prof/rp_aggregate_call_tree.c +0 -59
  85. data/ext/ruby_prof/rp_aggregate_call_tree.h +0 -13
  86. data/test/measure_allocations_trace_test.rb +0 -375
  87. data/test/temp.rb +0 -20
@@ -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
- /* Is this a singleton class acting as a metaclass? */
26
- if (BUILTIN_TYPE(attached) == T_CLASS)
25
+ switch (BUILTIN_TYPE(attached))
27
26
  {
28
- *klass_flags |= kClassSingleton;
29
- result = attached;
30
- }
31
- /* Is this for singleton methods on a module? */
32
- else if (BUILTIN_TYPE(attached) == T_MODULE)
33
- {
34
- *klass_flags |= kModuleSingleton;
35
- result = attached;
36
- }
37
- /* Is this for singleton methods on an object? */
38
- else if (BUILTIN_TYPE(attached) == T_OBJECT)
39
- {
40
- *klass_flags |= kObjectSingleton;
41
- result = rb_class_superclass(klass);
42
- }
43
- /* Ok, this could be other things like an array made put onto
44
- a singleton object (yeah, it happens, see the singleton
45
- objects test case). */
46
- else
47
- {
48
- *klass_flags |= kOtherSingleton;
49
- result = klass;
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(RBASIC(klass)->klass, &dummy);
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 = RBASIC(klass)->klass;
104
+ resolved_klass = RBASIC_CLASS(klass);
98
105
  }
99
106
 
100
- return (resolved_klass << 4) + (msym);
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
- /* ====== Allocation Table ====== */
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 = allocations_table_create();
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
- allocations_table_free(method->allocations_table);
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
- rb_gc_mark(method->profile);
208
+ rb_gc_mark_movable(method->profile);
222
209
 
223
210
  if (method->object != Qnil)
224
- rb_gc_mark(method->object);
211
+ rb_gc_mark_movable(method->object);
225
212
 
226
- rb_gc_mark(method->klass_name);
227
- rb_gc_mark(method->method_name);
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
- rb_st_foreach(method->allocations_table, prof_method_mark_allocations, 0);
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
- VALUE result = rb_ary_new();
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
- return the source file of the method
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 -> string
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 -> string
439
+ method_name -> Symbol
383
440
 
384
- Returns the name of this method in the format Object#method. Singletons
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")), INT2FIX(method_data->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 = FIX2LONG(rb_hash_aref(data, ID2SYM(rb_intern("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
- for (int i = 0; i < rb_array_len(allocations); i++)
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
- rb_undef_method(CLASS_OF(cRpMethodInfo), "new");
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);
@@ -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 unkown 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
- prof_method_t* prof_method_create(VALUE profile, VALUE klass, VALUE msym, VALUE source_file, int source_line);
54
- prof_method_t* prof_get_method(VALUE self);
55
-
56
- VALUE prof_method_wrap(prof_method_t* result);
57
- void prof_method_mark(void* data);
58
-
59
- VALUE resolve_klass(VALUE klass, unsigned int* klass_flags);
60
- VALUE resolve_klass_name(VALUE klass, unsigned int* klass_flags);
61
-
62
- #endif //__RP_METHOD_INFO__
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__