зеркало из https://github.com/github/ruby.git
* vm_insnhelper.c (vm_caller_setup_args): save and restore
ci->argc and ci->blockptr before and after method invocations because these method dispatches override call_info. * bootstraptest/test_method.rb: add tests for this fix. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37641 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
db31b3dad5
Коммит
ffd3cbdc75
|
@ -1,3 +1,11 @@
|
|||
Tue Nov 13 17:28:47 2012 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* vm_insnhelper.c (vm_caller_setup_args): save and restore
|
||||
ci->argc and ci->blockptr before and after method invocations
|
||||
because these method dispatches override call_info.
|
||||
|
||||
* bootstraptest/test_method.rb: add tests for this fix.
|
||||
|
||||
Tue Nov 13 16:38:02 2012 NARUSE, Yui <naruse@ruby-lang.org>
|
||||
|
||||
* common.mk (dmyprobes.h): always create for make dist.
|
||||
|
|
|
@ -1204,3 +1204,61 @@ assert_equal 'ok', %q{
|
|||
'ok'
|
||||
end
|
||||
}
|
||||
|
||||
assert_equal 'DC', %q{
|
||||
$result = []
|
||||
|
||||
class C
|
||||
def foo *args
|
||||
$result << 'C'
|
||||
end
|
||||
end
|
||||
class D
|
||||
def foo *args
|
||||
$result << 'D'
|
||||
end
|
||||
end
|
||||
|
||||
o1 = $o1 = C.new
|
||||
o2 = $o2 = D.new
|
||||
|
||||
args = Object.new
|
||||
def args.to_a
|
||||
test1 $o2, nil
|
||||
[]
|
||||
end
|
||||
def test1 o, args
|
||||
o.foo(*args)
|
||||
end
|
||||
test1 o1, args
|
||||
$result.join
|
||||
}
|
||||
|
||||
assert_equal 'DC', %q{
|
||||
$result = []
|
||||
|
||||
class C
|
||||
def foo *args
|
||||
$result << 'C'
|
||||
end
|
||||
end
|
||||
class D
|
||||
def foo *args
|
||||
$result << 'D'
|
||||
end
|
||||
end
|
||||
|
||||
o1 = $o1 = C.new
|
||||
o2 = $o2 = D.new
|
||||
|
||||
block = Object.new
|
||||
def block.to_proc
|
||||
test2 $o2, %w(a, b, c), nil
|
||||
Proc.new{}
|
||||
end
|
||||
def test2 o, args, block
|
||||
o.foo(*args, &block)
|
||||
end
|
||||
test2 o1, [], block
|
||||
$result.join
|
||||
}
|
||||
|
|
|
@ -1036,6 +1036,12 @@ vm_base_ptr(rb_control_frame_t *cfp)
|
|||
static void
|
||||
vm_caller_setup_args(const rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
|
||||
{
|
||||
#define SAVE_RESTORE_CI(expr, ci) do { \
|
||||
int saved_argc = (ci)->argc; rb_block_t *saved_blockptr = (ci)->blockptr; /* save */ \
|
||||
expr; \
|
||||
(ci)->argc = saved_argc; (ci)->blockptr = saved_blockptr; /* restore */ \
|
||||
} while (0)
|
||||
|
||||
if (UNLIKELY(ci->flag & VM_CALL_ARGS_BLOCKARG)) {
|
||||
rb_proc_t *po;
|
||||
VALUE proc;
|
||||
|
@ -1044,7 +1050,10 @@ vm_caller_setup_args(const rb_thread_t *th, rb_control_frame_t *cfp, rb_call_inf
|
|||
|
||||
if (proc != Qnil) {
|
||||
if (!rb_obj_is_proc(proc)) {
|
||||
VALUE b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
|
||||
VALUE b;
|
||||
|
||||
SAVE_RESTORE_CI(b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc"), ci);
|
||||
|
||||
if (NIL_P(b) || !rb_obj_is_proc(b)) {
|
||||
rb_raise(rb_eTypeError,
|
||||
"wrong argument type %s (expected Proc)",
|
||||
|
@ -1069,7 +1078,9 @@ vm_caller_setup_args(const rb_thread_t *th, rb_control_frame_t *cfp, rb_call_inf
|
|||
VALUE ary = *(cfp->sp - 1);
|
||||
VALUE *ptr;
|
||||
int i;
|
||||
VALUE tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a");
|
||||
VALUE tmp;
|
||||
|
||||
SAVE_RESTORE_CI(tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a"), ci);
|
||||
|
||||
if (NIL_P(tmp)) {
|
||||
/* do nothing */
|
||||
|
|
Загрузка…
Ссылка в новой задаче