@@ -87,6 +87,10 @@ namespace rubinius {
87
87
, current_fiber(this , nil<Fiber>())
88
88
, root_fiber(this , nil<Fiber>())
89
89
, waiting_object_(this , cNil)
90
+ , profile_(this , nil<Tuple>())
91
+ , profile_sample_count_(0 )
92
+ , max_profile_entries_(15 )
93
+ , min_profile_call_count_(0 )
90
94
, native_method_environment(NULL )
91
95
, custom_wakeup_(NULL )
92
96
, custom_wakeup_data_(NULL )
@@ -252,6 +256,50 @@ namespace rubinius {
252
256
memory ()->collect_maybe (state);
253
257
}
254
258
259
+ static int profile_compare (const void * a, const void * b) {
260
+ const CompiledCode* c_a = try_as<CompiledCode>(*(const Object**)(a));
261
+ const CompiledCode* c_b = try_as<CompiledCode>(*(const Object**)(b));
262
+
263
+ if (c_a && c_b) {
264
+ return c_a->machine_code ()->call_count - c_b->machine_code ()->call_count ;
265
+ } else if (c_a) {
266
+ return 1 ;
267
+ } else if (c_b) {
268
+ return -1 ;
269
+ } else {
270
+ return 0 ;
271
+ }
272
+ }
273
+
274
+ void VM::update_profile (STATE) {
275
+ profile_sample_count_++;
276
+
277
+ CompiledCode* code = state->vm ()->call_frame ()->compiled_code ;
278
+ code->machine_code ()->sample_count ++;
279
+
280
+ Tuple* profile = profile_.get ();
281
+
282
+ if (profile->nil_p ()) {
283
+ profile = Tuple::create (state, max_profile_entries_);
284
+ profile_.set (profile);
285
+ }
286
+
287
+ ::qsort (reinterpret_cast <void *>(profile->field), profile->num_fields(),
288
+ sizeof(intptr_t ), profile_compare);
289
+
290
+ for (native_int i = 0 ; i < profile->num_fields (); i++) {
291
+ if (code == profile->at (i)) return ;
292
+ }
293
+
294
+ CompiledCode* pcode = try_as<CompiledCode>(profile->at (0 ));
295
+ if (!pcode || (pcode &&
296
+ code->machine_code ()->call_count > pcode->machine_code ()->call_count ))
297
+ {
298
+ profile->put (state, 0 , code);
299
+ min_profile_call_count_ = code->machine_code ()->call_count ;
300
+ }
301
+ }
302
+
255
303
static void suspend_thread () {
256
304
static int i = 0 ;
257
305
static int delay[] = {
0 commit comments