ruby-prof 1.4.3 → 1.6.3

Sign up to get free protection for your applications and to get access to all the features.
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__