From ba5ea548cefd82307e96a6308e2b85425030e461 Mon Sep 17 00:00:00 2001 From: shugo Date: Sun, 11 Nov 2012 02:42:04 +0000 Subject: * vm_core.h (rb_call_info_t::refinements), compile.c (new_callinfo): add a new field for inline method cache. * vm_insnhelper.c (vm_search_method): check rb_call_info_t::refinements not to confuse inline method cache when module_eval is used with refinements. * test/ruby/test_refinement.rb: related test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37616 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 11 +++++++++++ compile.c | 1 + test/ruby/test_refinement.rb | 24 ++++++++++++++++++++++++ vm_core.h | 1 + vm_insnhelper.c | 17 ++++++++++++++--- 5 files changed, 51 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index dbeb956f4a..69b1b86361 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Sun Nov 11 11:36:19 2012 Shugo Maeda + + * vm_core.h (rb_call_info_t::refinements), compile.c (new_callinfo): + add a new field for inline method cache. + + * vm_insnhelper.c (vm_search_method): check rb_call_info_t::refinements + not to confuse inline method cache when module_eval is used with + refinements. + + * test/ruby/test_refinement.rb: related test. + Sun Nov 11 08:45:45 2012 Martin Duerst * ruby.c: removed a comma before "before" diff --git a/compile.c b/compile.c index 16bfcefdbb..eb824caf23 100644 --- a/compile.c +++ b/compile.c @@ -954,6 +954,7 @@ new_callinfo(rb_iseq_t *iseq, ID mid, int argc, VALUE block, unsigned long flag) } } ci->vmstat = 0; + ci->refinements = Qundef; ci->blockptr = 0; ci->recv = Qundef; ci->call = 0; /* TODO: should set default function? */ diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index aeb519c18d..12a00bb16c 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -685,4 +685,28 @@ class TestRefinement < Test::Unit::TestCase assert_equal("#", m.refinements[c].inspect) end + + module InlineMethodCache + class C + def foo + "original" + end + end + + module M + refine C do + def foo + "refined" + end + end + end + end + + def test_inline_method_cache + c = InlineMethodCache::C.new + f = Proc.new { c.foo } + assert_equal("original", f.call) + assert_equal("refined", InlineMethodCache::M.module_eval(&f)) + assert_equal("original", f.call) + end end diff --git a/vm_core.h b/vm_core.h index dd9e3872e2..82400a3530 100644 --- a/vm_core.h +++ b/vm_core.h @@ -153,6 +153,7 @@ typedef struct rb_call_info_struct { /* inline cache: keys */ VALUE vmstat; VALUE klass; + VALUE refinements; /* inline cache: values */ const rb_method_entry_t *me; diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 554aad47b1..cf64c14684 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -843,19 +843,30 @@ static void vm_search_method(rb_call_info_t *ci, VALUE recv) { VALUE klass = CLASS_OF(recv); + NODE *cref = rb_vm_cref(); + VALUE refinements = Qnil; + + if (cref && !NIL_P(cref->nd_refinements)) { + refinements = cref->nd_refinements; + } #if OPT_INLINE_METHOD_CACHE - if (LIKELY(GET_VM_STATE_VERSION() == ci->vmstat && klass == ci->klass)) { + if (LIKELY(GET_VM_STATE_VERSION() == ci->vmstat && klass == ci->klass && + refinements == ci->refinements)) { /* cache hit! */ } else { - ci->me = rb_method_entry(klass, ci->mid, &ci->defined_class); + ci->me = rb_method_entry_get_with_refinements(refinements, klass, + ci->mid, + &ci->defined_class); ci->klass = klass; + ci->refinements = refinements; ci->vmstat = GET_VM_STATE_VERSION(); ci->call = vm_call_general; } #else - ci->me = rb_method_entry(klass, ci->mid, &ci->defined_class); + ci->me = rb_method_entry_get_with_refinements(refinements, klass, ci->mid, + &ci->defined_class); ci->call = vm_call_general; ci->klass = klass; #endif -- cgit v1.2.3