ruby-prof 1.2.0 → 1.3.0
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 +7 -0
- data/ext/ruby_prof/rp_aggregate_call_tree.c +19 -1
- data/ext/ruby_prof/rp_allocation.c +38 -10
- data/ext/ruby_prof/rp_allocation.h +1 -1
- data/ext/ruby_prof/rp_call_tree.c +28 -12
- data/ext/ruby_prof/rp_call_trees.c +33 -11
- data/ext/ruby_prof/rp_call_trees.h +0 -1
- data/ext/ruby_prof/rp_measurement.c +25 -9
- data/ext/ruby_prof/rp_measurement.h +1 -1
- data/ext/ruby_prof/rp_method.c +33 -12
- data/ext/ruby_prof/rp_method.h +23 -24
- data/ext/ruby_prof/rp_profile.c +49 -26
- data/ext/ruby_prof/rp_profile.h +1 -1
- data/ext/ruby_prof/rp_stack.h +2 -2
- data/ext/ruby_prof/rp_thread.c +30 -13
- data/ext/ruby_prof/rp_thread.h +3 -1
- data/lib/ruby-prof/version.rb +1 -1
- data/test/fiber_test.rb +24 -33
- data/test/gc_test.rb +17 -32
- data/test/inverse_call_tree_test.rb +1 -1
- data/test/line_number_test.rb +3 -3
- data/test/measure_wall_time_test.rb +5 -5
- data/test/unique_call_path_test.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 522834d46befbdc0f999e78d9bff9f2f98883c6bf5a15fc8d56444bf34778a72
|
4
|
+
data.tar.gz: b4bf7cc5ec23482ccbcb103b6c7ab87c8614da0076d6a43f4848d6cd8aee3178
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ef3c25b85260c8c3878c3dbfb5d80469731f1070ecb3d5d8c474dc8d5c149578757fcfec91af508742cdd1b1da7500a4cf7dc2670b23f3261d5689f4fcd5f27c
|
7
|
+
data.tar.gz: bc891673567736bef06b12eb72514425261a678ad9d33ad709835e1e1cffd265c4657ba436a2e28486a45fa35fd678117ac2a2882c564fbfb334eb1edcec3918
|
data/CHANGES
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
1.3.0 (2020-02-22)
|
2
|
+
=====================
|
3
|
+
* Update C code to use newer RTypedData API versus older RData API.
|
4
|
+
* Update C code to use rb_cObject versus the older, deprecated, rb_cData.
|
5
|
+
* Update memory management - CallInfo's now keep alive their owning Profile instances. Fixes crashes that
|
6
|
+
could happen in rare instances.
|
7
|
+
|
1
8
|
1.2.0 (2020-01-23)
|
2
9
|
=====================
|
3
10
|
* Fix call stack printer broken in version 1.0.0 (Charlie Savage)
|
@@ -24,11 +24,29 @@ static void prof_aggregate_call_tree_ruby_gc_free(void* data)
|
|
24
24
|
prof_call_tree_free(call_tree);
|
25
25
|
}
|
26
26
|
|
27
|
+
size_t prof_aggregate_call_tree_size(const void* data)
|
28
|
+
{
|
29
|
+
return sizeof(prof_call_tree_t);
|
30
|
+
}
|
31
|
+
|
32
|
+
static const rb_data_type_t aggregate_call_tree_type =
|
33
|
+
{
|
34
|
+
.wrap_struct_name = "Aggregate_CallTree",
|
35
|
+
.function =
|
36
|
+
{
|
37
|
+
.dmark = prof_aggregate_call_tree_mark,
|
38
|
+
.dfree = prof_aggregate_call_tree_ruby_gc_free,
|
39
|
+
.dsize = prof_aggregate_call_tree_size,
|
40
|
+
},
|
41
|
+
.data = NULL,
|
42
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
43
|
+
};
|
44
|
+
|
27
45
|
VALUE prof_aggregate_call_tree_wrap(prof_call_tree_t* call_tree)
|
28
46
|
{
|
29
47
|
if (call_tree->object == Qnil)
|
30
48
|
{
|
31
|
-
call_tree->object =
|
49
|
+
call_tree->object = TypedData_Wrap_Struct(cRpAggregateCallTree, &aggregate_call_tree_type, call_tree);
|
32
50
|
}
|
33
51
|
return call_tree->object;
|
34
52
|
}
|
@@ -43,6 +43,18 @@ prof_allocation_t* prof_allocation_create(void)
|
|
43
43
|
return result;
|
44
44
|
}
|
45
45
|
|
46
|
+
prof_allocation_t* prof_get_allocation(VALUE self)
|
47
|
+
{
|
48
|
+
/* Can't use Data_Get_Struct because that triggers the event hook
|
49
|
+
ending up in endless recursion. */
|
50
|
+
prof_allocation_t* result = RTYPEDDATA_DATA(self);
|
51
|
+
|
52
|
+
if (!result)
|
53
|
+
rb_raise(rb_eRuntimeError, "This RubyProf::Allocation instance has already been freed, likely because its profile has been freed.");
|
54
|
+
|
55
|
+
return result;
|
56
|
+
}
|
57
|
+
|
46
58
|
prof_allocation_t* prof_allocate_increment(prof_method_t* method, rb_trace_arg_t* trace_arg)
|
47
59
|
{
|
48
60
|
VALUE object = rb_tracearg_object(trace_arg);
|
@@ -75,8 +87,11 @@ prof_allocation_t* prof_allocate_increment(prof_method_t* method, rb_trace_arg_t
|
|
75
87
|
|
76
88
|
static void prof_allocation_ruby_gc_free(void* data)
|
77
89
|
{
|
78
|
-
|
79
|
-
|
90
|
+
if (data)
|
91
|
+
{
|
92
|
+
prof_allocation_t* allocation = (prof_allocation_t*)data;
|
93
|
+
allocation->object = Qnil;
|
94
|
+
}
|
80
95
|
}
|
81
96
|
|
82
97
|
void prof_allocation_free(prof_allocation_t* allocation)
|
@@ -85,9 +100,7 @@ void prof_allocation_free(prof_allocation_t* allocation)
|
|
85
100
|
yes clean it up so to avoid a segmentation fault. */
|
86
101
|
if (allocation->object != Qnil)
|
87
102
|
{
|
88
|
-
|
89
|
-
RDATA(allocation->object)->dfree = NULL;
|
90
|
-
RDATA(allocation->object)->data = NULL;
|
103
|
+
RTYPEDDATA(allocation->object)->data = NULL;
|
91
104
|
allocation->object = Qnil;
|
92
105
|
}
|
93
106
|
|
@@ -101,6 +114,8 @@ size_t prof_allocation_size(const void* data)
|
|
101
114
|
|
102
115
|
void prof_allocation_mark(void* data)
|
103
116
|
{
|
117
|
+
if (!data) return;
|
118
|
+
|
104
119
|
prof_allocation_t* allocation = (prof_allocation_t*)data;
|
105
120
|
if (allocation->object != Qnil)
|
106
121
|
rb_gc_mark(allocation->object);
|
@@ -115,11 +130,24 @@ void prof_allocation_mark(void* data)
|
|
115
130
|
rb_gc_mark(allocation->source_file);
|
116
131
|
}
|
117
132
|
|
133
|
+
static const rb_data_type_t allocation_type =
|
134
|
+
{
|
135
|
+
.wrap_struct_name = "Allocation",
|
136
|
+
.function =
|
137
|
+
{
|
138
|
+
.dmark = prof_allocation_mark,
|
139
|
+
.dfree = prof_allocation_ruby_gc_free,
|
140
|
+
.dsize = prof_allocation_size,
|
141
|
+
},
|
142
|
+
.data = NULL,
|
143
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
144
|
+
};
|
145
|
+
|
118
146
|
VALUE prof_allocation_wrap(prof_allocation_t* allocation)
|
119
147
|
{
|
120
148
|
if (allocation->object == Qnil)
|
121
149
|
{
|
122
|
-
allocation->object =
|
150
|
+
allocation->object = TypedData_Wrap_Struct(cRpAllocation, &allocation_type, allocation);
|
123
151
|
}
|
124
152
|
return allocation->object;
|
125
153
|
}
|
@@ -135,7 +163,7 @@ prof_allocation_t* prof_allocation_get(VALUE self)
|
|
135
163
|
{
|
136
164
|
/* Can't use Data_Get_Struct because that triggers the event hook
|
137
165
|
ending up in endless recursion. */
|
138
|
-
prof_allocation_t* result =
|
166
|
+
prof_allocation_t* result = RTYPEDDATA_DATA(self);
|
139
167
|
if (!result)
|
140
168
|
rb_raise(rb_eRuntimeError, "This RubyProf::Allocation instance has already been freed, likely because its profile has been freed.");
|
141
169
|
|
@@ -210,7 +238,7 @@ static VALUE prof_allocation_memory(VALUE self)
|
|
210
238
|
/* :nodoc: */
|
211
239
|
static VALUE prof_allocation_dump(VALUE self)
|
212
240
|
{
|
213
|
-
prof_allocation_t* allocation =
|
241
|
+
prof_allocation_t* allocation = prof_get_allocation(self);
|
214
242
|
|
215
243
|
VALUE result = rb_hash_new();
|
216
244
|
|
@@ -228,7 +256,7 @@ static VALUE prof_allocation_dump(VALUE self)
|
|
228
256
|
/* :nodoc: */
|
229
257
|
static VALUE prof_allocation_load(VALUE self, VALUE data)
|
230
258
|
{
|
231
|
-
prof_allocation_t* allocation =
|
259
|
+
prof_allocation_t* allocation = prof_get_allocation(self);
|
232
260
|
allocation->object = self;
|
233
261
|
|
234
262
|
allocation->key = FIX2LONG(rb_hash_aref(data, ID2SYM(rb_intern("key"))));
|
@@ -244,7 +272,7 @@ static VALUE prof_allocation_load(VALUE self, VALUE data)
|
|
244
272
|
|
245
273
|
void rp_init_allocation(void)
|
246
274
|
{
|
247
|
-
cRpAllocation = rb_define_class_under(mProf, "Allocation",
|
275
|
+
cRpAllocation = rb_define_class_under(mProf, "Allocation", rb_cObject);
|
248
276
|
rb_undef_method(CLASS_OF(cRpAllocation), "new");
|
249
277
|
rb_define_alloc_func(cRpAllocation, prof_allocation_allocate);
|
250
278
|
|
@@ -13,14 +13,12 @@ prof_call_tree_t* prof_call_tree_create(prof_method_t* method, prof_call_tree_t*
|
|
13
13
|
prof_call_tree_t* result = ALLOC(prof_call_tree_t);
|
14
14
|
result->method = method;
|
15
15
|
result->parent = parent;
|
16
|
-
result->children = rb_st_init_numtable();
|
17
16
|
result->object = Qnil;
|
18
|
-
result->measurement = prof_measurement_create();
|
19
|
-
|
20
17
|
result->visits = 0;
|
21
|
-
|
22
18
|
result->source_line = source_line;
|
23
19
|
result->source_file = source_file;
|
20
|
+
result->children = rb_st_init_numtable();
|
21
|
+
result->measurement = prof_measurement_create();
|
24
22
|
|
25
23
|
return result;
|
26
24
|
}
|
@@ -73,6 +71,9 @@ static int prof_call_tree_mark_children(st_data_t key, st_data_t value, st_data_
|
|
73
71
|
|
74
72
|
void prof_call_tree_mark(void* data)
|
75
73
|
{
|
74
|
+
if (!data)
|
75
|
+
return;
|
76
|
+
|
76
77
|
prof_call_tree_t* call_tree = (prof_call_tree_t*)data;
|
77
78
|
|
78
79
|
if (call_tree->object != Qnil)
|
@@ -81,6 +82,7 @@ void prof_call_tree_mark(void* data)
|
|
81
82
|
if (call_tree->source_file != Qnil)
|
82
83
|
rb_gc_mark(call_tree->source_file);
|
83
84
|
|
85
|
+
prof_method_mark(call_tree->method);
|
84
86
|
prof_measurement_mark(call_tree->measurement);
|
85
87
|
|
86
88
|
// Recurse down through the whole call tree but only from the top node
|
@@ -91,8 +93,11 @@ void prof_call_tree_mark(void* data)
|
|
91
93
|
|
92
94
|
static void prof_call_tree_ruby_gc_free(void* data)
|
93
95
|
{
|
94
|
-
|
95
|
-
|
96
|
+
if (data)
|
97
|
+
{
|
98
|
+
prof_call_tree_t* call_tree = (prof_call_tree_t*)data;
|
99
|
+
call_tree->object = Qnil;
|
100
|
+
}
|
96
101
|
}
|
97
102
|
|
98
103
|
static int prof_call_tree_free_children(st_data_t key, st_data_t value, st_data_t data)
|
@@ -108,9 +113,7 @@ void prof_call_tree_free(prof_call_tree_t* call_tree_data)
|
|
108
113
|
yes clean it up so to avoid a segmentation fault. */
|
109
114
|
if (call_tree_data->object != Qnil)
|
110
115
|
{
|
111
|
-
|
112
|
-
RDATA(call_tree_data->object)->dfree = NULL;
|
113
|
-
RDATA(call_tree_data->object)->data = NULL;
|
116
|
+
RTYPEDDATA(call_tree_data->object)->data = NULL;
|
114
117
|
call_tree_data->object = Qnil;
|
115
118
|
}
|
116
119
|
|
@@ -130,11 +133,24 @@ size_t prof_call_tree_size(const void* data)
|
|
130
133
|
return sizeof(prof_call_tree_t);
|
131
134
|
}
|
132
135
|
|
136
|
+
static const rb_data_type_t call_tree_type =
|
137
|
+
{
|
138
|
+
.wrap_struct_name = "CallTree",
|
139
|
+
.function =
|
140
|
+
{
|
141
|
+
.dmark = prof_call_tree_mark,
|
142
|
+
.dfree = prof_call_tree_ruby_gc_free,
|
143
|
+
.dsize = prof_call_tree_size,
|
144
|
+
},
|
145
|
+
.data = NULL,
|
146
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
147
|
+
};
|
148
|
+
|
133
149
|
VALUE prof_call_tree_wrap(prof_call_tree_t* call_tree)
|
134
150
|
{
|
135
151
|
if (call_tree->object == Qnil)
|
136
152
|
{
|
137
|
-
call_tree->object =
|
153
|
+
call_tree->object = TypedData_Wrap_Struct(cRpCallTree, &call_tree_type, call_tree);
|
138
154
|
}
|
139
155
|
return call_tree->object;
|
140
156
|
}
|
@@ -150,7 +166,7 @@ prof_call_tree_t* prof_get_call_tree(VALUE self)
|
|
150
166
|
{
|
151
167
|
/* Can't use Data_Get_Struct because that triggers the event hook
|
152
168
|
ending up in endless recursion. */
|
153
|
-
prof_call_tree_t* result =
|
169
|
+
prof_call_tree_t* result = RTYPEDDATA_DATA(self);
|
154
170
|
|
155
171
|
if (!result)
|
156
172
|
rb_raise(rb_eRuntimeError, "This RubyProf::CallTree instance has already been freed, likely because its profile has been freed.");
|
@@ -335,7 +351,7 @@ static VALUE prof_call_tree_load(VALUE self, VALUE data)
|
|
335
351
|
void rp_init_call_tree()
|
336
352
|
{
|
337
353
|
/* CallTree */
|
338
|
-
cRpCallTree = rb_define_class_under(mProf, "CallTree",
|
354
|
+
cRpCallTree = rb_define_class_under(mProf, "CallTree", rb_cObject);
|
339
355
|
rb_undef_method(CLASS_OF(cRpCallTree), "new");
|
340
356
|
rb_define_alloc_func(cRpCallTree, prof_call_tree_allocate);
|
341
357
|
|
@@ -14,7 +14,7 @@ prof_call_trees_t* prof_get_call_trees(VALUE self)
|
|
14
14
|
{
|
15
15
|
/* Can't use Data_Get_Struct because that triggers the event hook
|
16
16
|
ending up in endless recursion. */
|
17
|
-
prof_call_trees_t* result =
|
17
|
+
prof_call_trees_t* result = RTYPEDDATA_DATA(self);
|
18
18
|
|
19
19
|
if (!result)
|
20
20
|
rb_raise(rb_eRuntimeError, "This RubyProf::CallTrees instance has already been freed, likely because its profile has been freed.");
|
@@ -32,8 +32,11 @@ prof_call_trees_t* prof_call_trees_create()
|
|
32
32
|
return result;
|
33
33
|
}
|
34
34
|
|
35
|
-
void prof_call_trees_mark(
|
35
|
+
void prof_call_trees_mark(void* data)
|
36
36
|
{
|
37
|
+
if (!data) return;
|
38
|
+
|
39
|
+
prof_call_trees_t* call_trees = (prof_call_trees_t*)data;
|
37
40
|
prof_call_tree_t** call_tree;
|
38
41
|
for (call_tree = call_trees->start; call_tree < call_trees->ptr; call_tree++)
|
39
42
|
{
|
@@ -47,9 +50,7 @@ void prof_call_trees_free(prof_call_trees_t* call_trees)
|
|
47
50
|
yes clean it up so to avoid a segmentation fault. */
|
48
51
|
if (call_trees->object != Qnil)
|
49
52
|
{
|
50
|
-
|
51
|
-
RDATA(call_trees->object)->dfree = NULL;
|
52
|
-
RDATA(call_trees->object)->data = NULL;
|
53
|
+
RTYPEDDATA(call_trees->object)->data = NULL;
|
53
54
|
call_trees->object = Qnil;
|
54
55
|
}
|
55
56
|
|
@@ -59,9 +60,12 @@ void prof_call_trees_free(prof_call_trees_t* call_trees)
|
|
59
60
|
|
60
61
|
void prof_call_trees_ruby_gc_free(void* data)
|
61
62
|
{
|
62
|
-
|
63
|
-
|
64
|
-
|
63
|
+
if (data)
|
64
|
+
{
|
65
|
+
// This object gets freed by its owning method
|
66
|
+
prof_call_trees_t* call_trees = (prof_call_trees_t*)data;
|
67
|
+
call_trees->object = Qnil;
|
68
|
+
}
|
65
69
|
}
|
66
70
|
|
67
71
|
static int prof_call_trees_collect_aggregates(st_data_t key, st_data_t value, st_data_t data)
|
@@ -94,11 +98,29 @@ static int prof_call_trees_collect_callees(st_data_t key, st_data_t value, st_da
|
|
94
98
|
return ST_CONTINUE;
|
95
99
|
}
|
96
100
|
|
101
|
+
size_t prof_call_trees_size(const void* data)
|
102
|
+
{
|
103
|
+
return sizeof(prof_call_trees_t);
|
104
|
+
}
|
105
|
+
|
106
|
+
static const rb_data_type_t call_trees_type =
|
107
|
+
{
|
108
|
+
.wrap_struct_name = "CallTrees",
|
109
|
+
.function =
|
110
|
+
{
|
111
|
+
.dmark = prof_call_trees_mark,
|
112
|
+
.dfree = prof_call_trees_ruby_gc_free,
|
113
|
+
.dsize = prof_call_trees_size,
|
114
|
+
},
|
115
|
+
.data = NULL,
|
116
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
117
|
+
};
|
118
|
+
|
97
119
|
VALUE prof_call_trees_wrap(prof_call_trees_t* call_trees)
|
98
120
|
{
|
99
121
|
if (call_trees->object == Qnil)
|
100
122
|
{
|
101
|
-
call_trees->object =
|
123
|
+
call_trees->object = TypedData_Wrap_Struct(cRpCallTrees, &call_trees_type, call_trees);
|
102
124
|
}
|
103
125
|
return call_trees->object;
|
104
126
|
}
|
@@ -235,7 +257,7 @@ VALUE prof_call_trees_dump(VALUE self)
|
|
235
257
|
/* :nodoc: */
|
236
258
|
VALUE prof_call_trees_load(VALUE self, VALUE data)
|
237
259
|
{
|
238
|
-
prof_call_trees_t* call_trees_data =
|
260
|
+
prof_call_trees_t* call_trees_data = prof_get_call_trees(self);
|
239
261
|
call_trees_data->object = self;
|
240
262
|
|
241
263
|
VALUE call_trees = rb_hash_aref(data, ID2SYM(rb_intern("call_trees")));
|
@@ -251,7 +273,7 @@ VALUE prof_call_trees_load(VALUE self, VALUE data)
|
|
251
273
|
|
252
274
|
void rp_init_call_trees()
|
253
275
|
{
|
254
|
-
cRpCallTrees = rb_define_class_under(mProf, "CallTrees",
|
276
|
+
cRpCallTrees = rb_define_class_under(mProf, "CallTrees", rb_cObject);
|
255
277
|
rb_undef_method(CLASS_OF(cRpCallTrees), "new");
|
256
278
|
rb_define_alloc_func(cRpCallTrees, prof_call_trees_allocate);
|
257
279
|
|
@@ -20,7 +20,6 @@ typedef struct prof_call_trees_t
|
|
20
20
|
|
21
21
|
void rp_init_call_trees();
|
22
22
|
prof_call_trees_t* prof_call_trees_create();
|
23
|
-
void prof_call_trees_mark(prof_call_trees_t* call_trees);
|
24
23
|
void prof_call_trees_free(prof_call_trees_t* call_trees);
|
25
24
|
prof_call_trees_t* prof_get_call_trees(VALUE self);
|
26
25
|
void prof_add_call_tree(prof_call_trees_t* call_trees, prof_call_tree_t* call_tree);
|
@@ -53,6 +53,8 @@ prof_measurement_t* prof_measurement_create(void)
|
|
53
53
|
|
54
54
|
void prof_measurement_mark(void* data)
|
55
55
|
{
|
56
|
+
if (!data) return;
|
57
|
+
|
56
58
|
prof_measurement_t* measurement_data = (prof_measurement_t*)data;
|
57
59
|
|
58
60
|
if (measurement_data->object != Qnil)
|
@@ -61,9 +63,12 @@ void prof_measurement_mark(void* data)
|
|
61
63
|
|
62
64
|
static void prof_measurement_ruby_gc_free(void* data)
|
63
65
|
{
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
+
}
|
67
72
|
}
|
68
73
|
|
69
74
|
void prof_measurement_free(prof_measurement_t* measurement)
|
@@ -72,9 +77,7 @@ void prof_measurement_free(prof_measurement_t* measurement)
|
|
72
77
|
yes clean it up so to avoid a segmentation fault. */
|
73
78
|
if (measurement->object != Qnil)
|
74
79
|
{
|
75
|
-
|
76
|
-
RDATA(measurement->object)->dfree = NULL;
|
77
|
-
RDATA(measurement->object)->data = NULL;
|
80
|
+
RTYPEDDATA(measurement->object)->data = NULL;
|
78
81
|
measurement->object = Qnil;
|
79
82
|
}
|
80
83
|
|
@@ -86,11 +89,24 @@ size_t prof_measurement_size(const void* data)
|
|
86
89
|
return sizeof(prof_measurement_t);
|
87
90
|
}
|
88
91
|
|
92
|
+
static const rb_data_type_t measurement_type =
|
93
|
+
{
|
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
|
+
};
|
104
|
+
|
89
105
|
VALUE prof_measurement_wrap(prof_measurement_t* measurement)
|
90
106
|
{
|
91
107
|
if (measurement->object == Qnil)
|
92
108
|
{
|
93
|
-
measurement->object =
|
109
|
+
measurement->object = TypedData_Wrap_Struct(cRpMeasurement, &measurement_type, measurement);
|
94
110
|
}
|
95
111
|
return measurement->object;
|
96
112
|
}
|
@@ -106,7 +122,7 @@ prof_measurement_t* prof_get_measurement(VALUE self)
|
|
106
122
|
{
|
107
123
|
/* Can't use Data_Get_Struct because that triggers the event hook
|
108
124
|
ending up in endless recursion. */
|
109
|
-
prof_measurement_t* result =
|
125
|
+
prof_measurement_t* result = RTYPEDDATA_DATA(self);
|
110
126
|
|
111
127
|
if (!result)
|
112
128
|
rb_raise(rb_eRuntimeError, "This RubyProf::Measurement instance has already been freed, likely because its profile has been freed.");
|
@@ -206,7 +222,7 @@ void rp_init_measure()
|
|
206
222
|
rp_init_measure_allocations();
|
207
223
|
rp_init_measure_memory();
|
208
224
|
|
209
|
-
cRpMeasurement = rb_define_class_under(mProf, "Measurement",
|
225
|
+
cRpMeasurement = rb_define_class_under(mProf, "Measurement", rb_cObject);
|
210
226
|
rb_undef_method(CLASS_OF(cRpMeasurement), "new");
|
211
227
|
rb_define_alloc_func(cRpMeasurement, prof_measurement_allocate);
|
212
228
|
|