* 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:
ko1 2012-11-13 08:34:43 +00:00
Родитель db31b3dad5
Коммит ffd3cbdc75
3 изменённых файлов: 79 добавлений и 2 удалений

Просмотреть файл

@ -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 */