1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

vm_insnhelper.c: iclass as klass in cfp

* vm_insnhelper.c (vm_call_method): follow iclasses as klass in cfp
  but not included modules.  [ruby-core:47241] [Bug #6891]
* vm_insnhelper.c (vm_call_bmethod): pass defined_class to follow
  proper ancestors.  [ruby-core:47241] [Bug #6891]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36736 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2012-08-20 11:36:34 +00:00
parent de83cb9b20
commit ceece4650a
9 changed files with 103 additions and 23 deletions

View file

@ -1,3 +1,19 @@
Mon Aug 20 20:36:30 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* vm_insnhelper.c (vm_call_method): follow iclasses as klass in cfp
but not included modules. [ruby-core:47241] [Bug #6891]
* vm_insnhelper.c (vm_call_bmethod): pass defined_class to follow
proper ancestors. [ruby-core:47241] [Bug #6891]
Mon Aug 20 20:36:13 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* vm_insnhelper.c (vm_call_method): follow iclasses as klass in cfp
but not included modules. [ruby-core:47241] [Bug #6891]
* vm_insnhelper.c (vm_call_bmethod): pass defined_class to follow
proper ancestors. [ruby-core:47241] [Bug #6891]
Mon Aug 20 11:40:27 2012 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
* common.mk: fix failed to make with -j2.

2
cont.c
View file

@ -1161,7 +1161,7 @@ rb_fiber_start(void)
th->root_svar = Qnil;
fib->status = RUNNING;
cont->value = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, 0);
cont->value = rb_vm_invoke_proc(th, proc, argc, argv, 0);
}
TH_POP_TAG();

8
proc.c
View file

@ -558,8 +558,7 @@ proc_call(int argc, VALUE *argv, VALUE procval)
}
}
vret = rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self,
argc, argv, blockptr);
vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, blockptr);
RB_GC_GUARD(procval);
return vret;
}
@ -584,7 +583,7 @@ rb_proc_call(VALUE self, VALUE args)
VALUE vret;
rb_proc_t *proc;
GetProcPtr(self, proc);
vret = rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self,
vret = rb_vm_invoke_proc(GET_THREAD(), proc,
check_argc(RARRAY_LEN(args)), RARRAY_PTR(args), 0);
RB_GC_GUARD(self);
RB_GC_GUARD(args);
@ -605,8 +604,7 @@ rb_proc_call_with_block(VALUE self, int argc, VALUE *argv, VALUE pass_procval)
block = &pass_proc->block;
}
vret = rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self,
argc, argv, block);
vret = rb_vm_invoke_proc(GET_THREAD(), proc, argc, argv, block);
RB_GC_GUARD(self);
RB_GC_GUARD(pass_procval);
return vret;

View file

@ -1398,4 +1398,58 @@ class TestModule < Test::Unit::TestCase
assert_equal([:@@bar, :@@foo], m2.class_variables(true))
assert_equal([:@@bar], m2.class_variables(false))
end
Bug6891 = '[ruby-core:47241]'
def test_extend_module_with_protected_method
list = []
x = Class.new {
@list = list
extend Module.new {
protected
def inherited(klass)
@list << "protected"
super(klass)
end
}
extend Module.new {
def inherited(klass)
@list << "public"
super(klass)
end
}
}
assert_nothing_raised(NoMethodError, Bug6891) {Class.new(x)}
assert_equal(['public', 'protected'], list)
end
def test_extend_module_with_protected_bmethod
list = []
x = Class.new {
extend Module.new {
protected
define_method(:inherited) do |klass|
list << "protected"
super(klass)
end
}
extend Module.new {
define_method(:inherited) do |klass|
list << "public"
super(klass)
end
}
}
assert_nothing_raised(NoMethodError, Bug6891) {Class.new(x)}
assert_equal(['public', 'protected'], list)
end
end

View file

@ -455,7 +455,7 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s
th->errinfo = Qnil;
th->root_lep = rb_vm_ep_local_ep(proc->block.ep);
th->root_svar = Qnil;
th->value = rb_vm_invoke_proc(th, proc, proc->block.self,
th->value = rb_vm_invoke_proc(th, proc,
(int)RARRAY_LEN(args), RARRAY_PTR(args), 0);
}
else {

32
vm.c
View file

@ -61,6 +61,10 @@ rb_vm_control_frame_block_ptr(rb_control_frame_t *cfp)
return VM_CF_BLOCK_PTR(cfp);
}
static VALUE
vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class,
int argc, const VALUE *argv, const rb_block_t *blockptr);
#include "vm_insnhelper.h"
#include "vm_insnhelper.c"
#include "vm_exec.h"
@ -577,7 +581,8 @@ rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass)
static inline VALUE
invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
VALUE self, int argc, const VALUE *argv,
const rb_block_t *blockptr, const NODE *cref)
const rb_block_t *blockptr, const NODE *cref,
VALUE defined_class)
{
if (SPECIAL_CONST_P(block->iseq))
return Qnil;
@ -599,7 +604,7 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
type == VM_FRAME_MAGIC_LAMBDA);
vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH,
self, block->klass, /* th->passed_defined_class, */
self, defined_class,
VM_ENVVAL_PREV_EP_PTR(block->ep),
iseq->iseq_encoded + opt_pc,
cfp->sp + arg_size, iseq->local_size - arg_size,
@ -633,19 +638,21 @@ static inline VALUE
vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref)
{
const rb_block_t *blockptr = check_block(th);
return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, cref);
return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, cref,
blockptr->klass);
}
static inline VALUE
vm_yield(rb_thread_t *th, int argc, const VALUE *argv)
{
const rb_block_t *blockptr = check_block(th);
return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, 0);
return invoke_block_from_c(th, blockptr, blockptr->self, argc, argv, 0, 0,
blockptr->klass);
}
VALUE
rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
int argc, const VALUE *argv, const rb_block_t * blockptr)
static VALUE
vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class,
int argc, const VALUE *argv, const rb_block_t *blockptr)
{
VALUE val = Qundef;
int state;
@ -656,7 +663,8 @@ rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
if (!proc->is_from_method) {
th->safe_level = proc->safe_level;
}
val = invoke_block_from_c(th, &proc->block, self, argc, argv, blockptr, 0);
val = invoke_block_from_c(th, &proc->block, self, argc, argv, blockptr, 0,
defined_class);
}
TH_POP_TAG();
@ -670,6 +678,14 @@ rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
return val;
}
VALUE
rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc,
int argc, const VALUE *argv, const rb_block_t *blockptr)
{
return vm_invoke_proc(th, proc, proc->block.self, proc->block.klass,
argc, argv, blockptr);
}
/* special variable */
static rb_control_frame_t *

View file

@ -731,7 +731,7 @@ VALUE rb_iseq_eval_main(VALUE iseqval);
#endif
int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp);
VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc,
int argc, const VALUE *argv, const rb_block_t *blockptr);
VALUE rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass);
VALUE rb_vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp);

View file

@ -126,7 +126,7 @@ vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv,
case OPTIMIZED_METHOD_TYPE_CALL: {
rb_proc_t *proc;
GetProcPtr(recv, proc);
val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr);
val = rb_vm_invoke_proc(th, proc, argc, argv, blockptr);
break;
}
default:

View file

@ -466,7 +466,7 @@ vm_call_bmethod(rb_thread_t *th, VALUE recv, int argc, const VALUE *argv,
/* control block frame */
th->passed_me = me;
GetProcPtr(me->def->body.proc, proc);
val = rb_vm_invoke_proc(th, proc, recv, argc, argv, blockptr);
val = vm_invoke_proc(th, proc, recv, defined_class, argc, argv, blockptr);
EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, recv, me->called_id, me->klass);
@ -655,7 +655,7 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp,
MEMCPY(argv, cfp->sp - num, VALUE, num);
cfp->sp -= num + 1;
val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr);
val = rb_vm_invoke_proc(th, proc, argc, argv, blockptr);
break;
}
default:
@ -683,10 +683,6 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp,
val = vm_method_missing(th, id, recv, num, blockptr, stat);
}
else if (!(flag & VM_CALL_OPT_SEND_BIT) && (me->flag & NOEX_MASK) & NOEX_PROTECTED) {
if (RB_TYPE_P(defined_class, T_ICLASS)) {
defined_class = RBASIC(defined_class)->klass;
}
if (!rb_obj_is_kind_of(cfp->self, defined_class)) {
val = vm_method_missing(th, id, recv, num, blockptr, NOEX_PROTECTED);
}