diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | compile.c | 1 | ||||
-rw-r--r-- | test/ruby/test_refinement.rb | 24 | ||||
-rw-r--r-- | vm_core.h | 1 | ||||
-rw-r--r-- | vm_insnhelper.c | 17 |
5 files changed, 51 insertions, 3 deletions
@@ -1,3 +1,14 @@ +Sun Nov 11 11:36:19 2012 Shugo Maeda <shugo@ruby-lang.org> + + * 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 <duerst@it.aoyama.ac.jp> * ruby.c: removed a comma before "before" @@ -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("#<refinement:#{c.inspect}@#{m.inspect}>", 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 @@ -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 |