mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
reuse cc->call
I noticed that in case of cache misshit, re-calculated cc->me can be the same method entry than the pevious one. That is an okay situation but can't we partially reuse the cache, because cc->call should still be valid then? One thing that has to be special-cased is when the method entry gets amended by some refinements. That happens behind-the-scene of call cache mechanism. We have to check if cc->me->def points to the previously saved one. Calculating ------------------------------------- trunk ours vm2_poly_same_method 1.534M 2.025M i/s - 6.000M times in 3.910203s 2.962752s Comparison: vm2_poly_same_method ours: 2025143.9 i/s trunk: 1534447.2 i/s - 1.32x slower
This commit is contained in:
parent
9fb9f2d318
commit
d74fa8e55c
Notes:
git
2019-09-19 15:18:37 +09:00
4 changed files with 59 additions and 7 deletions
25
benchmark/vm2_poly_same_method.yml
Normal file
25
benchmark/vm2_poly_same_method.yml
Normal file
|
@ -0,0 +1,25 @@
|
|||
prelude: |
|
||||
module AR; end
|
||||
class AR::Base
|
||||
def create_or_update
|
||||
nil
|
||||
end
|
||||
def save
|
||||
create_or_update
|
||||
end
|
||||
end
|
||||
class Foo < AR::Base; end
|
||||
class Bar < AR::Base; end
|
||||
o1 = Foo.new
|
||||
o2 = Bar.new
|
||||
benchmark:
|
||||
vm2_poly_same_method: |
|
||||
o1.save; o2.save;
|
||||
o1.save; o2.save;
|
||||
o1.save; o2.save;
|
||||
o1.save; o2.save;
|
||||
o1.save; o2.save;
|
||||
o1.save; o2.save;
|
||||
o1.save; o2.save;
|
||||
o1.save; o2.save;
|
||||
loop_count: 6000000
|
|
@ -911,7 +911,7 @@ invokeblock
|
|||
// attr rb_snum_t sp_inc = sp_inc_of_invokeblock(ci);
|
||||
{
|
||||
static struct rb_call_cache cc = {
|
||||
0, 0, NULL, vm_invokeblock_i,
|
||||
0, 0, NULL, NULL, vm_invokeblock_i,
|
||||
};
|
||||
|
||||
VALUE bh = VM_BLOCK_HANDLER_NONE;
|
||||
|
|
|
@ -2328,6 +2328,7 @@ enum method_missing_reason {
|
|||
MISSING_NONE = 0x40
|
||||
};
|
||||
struct rb_callable_method_entry_struct;
|
||||
struct rb_method_definition_struct;
|
||||
struct rb_execution_context_struct;
|
||||
struct rb_control_frame_struct;
|
||||
struct rb_calling_info;
|
||||
|
@ -2339,6 +2340,7 @@ struct rb_call_cache {
|
|||
|
||||
/* inline cache: values */
|
||||
const struct rb_callable_method_entry_struct *me;
|
||||
const struct rb_method_definition_struct *def;
|
||||
|
||||
VALUE (*call)(struct rb_execution_context_struct *ec,
|
||||
struct rb_control_frame_struct *cfp,
|
||||
|
|
|
@ -1374,16 +1374,41 @@ vm_expandarray(VALUE *sp, VALUE ary, rb_num_t num, int flag)
|
|||
|
||||
static VALUE vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc);
|
||||
|
||||
#ifdef __has_attribute
|
||||
#if __has_attribute(artificial)
|
||||
__attribute__((__artificial__))
|
||||
#endif
|
||||
#endif
|
||||
static inline vm_call_handler
|
||||
calccall(const struct rb_call_cache *cc, const rb_callable_method_entry_t *me)
|
||||
{
|
||||
if (UNLIKELY(!me)) {
|
||||
return vm_call_general; /* vm_call_method_nome() situation */
|
||||
}
|
||||
else if (LIKELY(cc->me != me)) {
|
||||
return vm_call_general; /* normal cases */
|
||||
}
|
||||
else if (UNLIKELY(cc->def != me->def)) {
|
||||
return vm_call_general; /* cc->me was refined elsewhere */
|
||||
}
|
||||
else {
|
||||
return cc->call;
|
||||
}
|
||||
}
|
||||
|
||||
MJIT_FUNC_EXPORTED void
|
||||
rb_vm_search_method_slowpath(const struct rb_call_info *ci, struct rb_call_cache *cc, VALUE klass)
|
||||
{
|
||||
cc->me = rb_callable_method_entry(klass, ci->mid);
|
||||
const rb_callable_method_entry_t *me =
|
||||
rb_callable_method_entry(klass, ci->mid);
|
||||
*cc = (struct rb_call_cache) {
|
||||
GET_GLOBAL_METHOD_STATE(),
|
||||
RCLASS_SERIAL(klass),
|
||||
me,
|
||||
me ? me->def : NULL,
|
||||
calccall(cc, me),
|
||||
};
|
||||
VM_ASSERT(callable_method_entry_p(cc->me));
|
||||
cc->call = vm_call_general;
|
||||
#if OPT_INLINE_METHOD_CACHE
|
||||
cc->method_state = GET_GLOBAL_METHOD_STATE();
|
||||
cc->class_serial = RCLASS_SERIAL(klass);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Add table
Reference in a new issue