mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* insnhelper.h: change CHECK_STACK_OVERFLOW() to throw exception.
* vm.c (caller_setup_arg), vm_macro.def: remove macro_eval_setup_send_arguments and add caller_setup_arg(). * insns.def: ditto. * bootstraptest/test_method.rb: add splat arg tests. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12596 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
d1bd418715
commit
adc677eb5c
6 changed files with 110 additions and 79 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
Sun Jun 24 17:28:52 2007 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
|
* insnhelper.h: change CHECK_STACK_OVERFLOW() to throw exception.
|
||||||
|
|
||||||
|
* vm.c (caller_setup_arg), vm_macro.def: remove
|
||||||
|
macro_eval_setup_send_arguments and add caller_setup_arg().
|
||||||
|
|
||||||
|
* insns.def: ditto.
|
||||||
|
|
||||||
|
* bootstraptest/test_method.rb: add splat arg tests.
|
||||||
|
|
||||||
Sun Jun 24 16:35:46 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Sun Jun 24 16:35:46 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* proc.c (proc_to_s): used a variable before initialized.
|
* proc.c (proc_to_s): used a variable before initialized.
|
||||||
|
|
|
@ -318,6 +318,33 @@ assert_equal '1', %q( class C; def m() 7 end; private :m end
|
||||||
assert_equal '1', %q( class C; def m() 1 end; private :m end
|
assert_equal '1', %q( class C; def m() 1 end; private :m end
|
||||||
C.new.funcall(:m) )
|
C.new.funcall(:m) )
|
||||||
|
|
||||||
|
# splat and block arguments
|
||||||
|
assert_equal %q{[[[:x, :y, :z], NilClass], [[1, :x, :y, :z], NilClass], [[1, 2, :x, :y, :z], NilClass], [[:obj], NilClass], [[1, :obj], NilClass], [[1, 2, :obj], NilClass], [[], Proc], [[1], Proc], [[1, 2], Proc], [[], Proc], [[1], Proc], [[1, 2], Proc], [[:x, :y, :z], Proc], [[1, :x, :y, :z], Proc], [[1, 2, :x, :y, :z], Proc]]}, %q{
|
||||||
|
def m(*args, &b)
|
||||||
|
$result << [args, b.class]
|
||||||
|
end
|
||||||
|
$result = []
|
||||||
|
ary = [:x, :y, :z]
|
||||||
|
obj = :obj
|
||||||
|
b = Proc.new{}
|
||||||
|
|
||||||
|
m(*ary)
|
||||||
|
m(1,*ary)
|
||||||
|
m(1,2,*ary)
|
||||||
|
m(*obj)
|
||||||
|
m(1,*obj)
|
||||||
|
m(1,2,*obj)
|
||||||
|
m(){}
|
||||||
|
m(1){}
|
||||||
|
m(1,2){}
|
||||||
|
m(&b)
|
||||||
|
m(1,&b)
|
||||||
|
m(1,2,&b)
|
||||||
|
m(*ary,&b)
|
||||||
|
m(1,*ary,&b)
|
||||||
|
m(1,2,*ary,&b)
|
||||||
|
$result
|
||||||
|
}
|
||||||
|
|
||||||
# post test
|
# post test
|
||||||
assert_equal %q{[1, 2, :o1, :o2, [], 3, 4, NilClass, nil, nil]}, %q{
|
assert_equal %q{[1, 2, :o1, :o2, [], 3, 4, NilClass, nil, nil]}, %q{
|
||||||
|
|
|
@ -127,8 +127,11 @@
|
||||||
#define GET_BLOCK_PTR() \
|
#define GET_BLOCK_PTR() \
|
||||||
((rb_block_t *)(GC_GUARDED_PTR_REF(GET_LFP()[0])))
|
((rb_block_t *)(GC_GUARDED_PTR_REF(GET_LFP()[0])))
|
||||||
|
|
||||||
#define CHECK_STACK_OVERFLOW(th, cfp, margin) \
|
#define CHECK_STACK_OVERFLOW(cfp, margin) do \
|
||||||
(((VALUE *)(cfp)->sp) + (margin) >= ((VALUE *)cfp))
|
if (((VALUE *)(cfp)->sp) + (margin) >= ((VALUE *)cfp)) { \
|
||||||
|
rb_exc_raise(sysstack_error); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
/**********************************************************/
|
/**********************************************************/
|
||||||
/* deal with control flow 3: exception */
|
/* deal with control flow 3: exception */
|
||||||
|
|
27
insns.def
27
insns.def
|
@ -1156,11 +1156,11 @@ send
|
||||||
VALUE recv;
|
VALUE recv;
|
||||||
VALUE klass;
|
VALUE klass;
|
||||||
rb_block_t *blockptr = 0;
|
rb_block_t *blockptr = 0;
|
||||||
rb_num_t num = op_argc;
|
rb_num_t num;
|
||||||
rb_num_t flag = op_flag;
|
rb_num_t flag = op_flag;
|
||||||
ID id = op_id;
|
ID id = op_id;
|
||||||
|
|
||||||
macro_eval_setup_send_arguments(num, blockptr, flag, blockiseq);
|
num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &blockptr);
|
||||||
|
|
||||||
if (flag & VM_CALL_FCALL_BIT) {
|
if (flag & VM_CALL_FCALL_BIT) {
|
||||||
/* method(...) */
|
/* method(...) */
|
||||||
|
@ -1298,9 +1298,8 @@ invokesuper
|
||||||
/* TODO: */
|
/* TODO: */
|
||||||
rb_bug("...");
|
rb_bug("...");
|
||||||
#else
|
#else
|
||||||
tmp_num = op_argc;
|
|
||||||
tmp_blockptr = 0;
|
tmp_blockptr = 0;
|
||||||
macro_eval_setup_send_arguments(tmp_num, tmp_blockptr, flag, blockiseq);
|
tmp_num = caller_setup_args(th, GET_CFP(), flag, op_argc, blockiseq, &tmp_blockptr);
|
||||||
if (!tmp_blockptr && !(flag & VM_CALL_ARGS_BLOCKARG_BIT)) {
|
if (!tmp_blockptr && !(flag & VM_CALL_ARGS_BLOCKARG_BIT)) {
|
||||||
tmp_blockptr = GET_BLOCK_PTR();
|
tmp_blockptr = GET_BLOCK_PTR();
|
||||||
}
|
}
|
||||||
|
@ -1329,25 +1328,7 @@ invokeblock
|
||||||
iseq = block->iseq;
|
iseq = block->iseq;
|
||||||
|
|
||||||
if (BUILTIN_TYPE(iseq) != T_NODE) {
|
if (BUILTIN_TYPE(iseq) != T_NODE) {
|
||||||
if (flag & VM_CALL_ARGS_SPLAT_BIT) {
|
argc = caller_setup_args(th, GET_CFP(), flag, argc, 0, 0);
|
||||||
VALUE ary = TOPN(0);
|
|
||||||
ary = rb_check_convert_type(ary, T_ARRAY, "Array", "to_splat");
|
|
||||||
|
|
||||||
if (NIL_P(ary)) {
|
|
||||||
/* not a [BUG] */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
VALUE *ptr = RARRAY_PTR(ary);
|
|
||||||
VALUE *dst = GET_SP() - 1;
|
|
||||||
int i, len = RARRAY_LEN(ary);
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
dst[i] = ptr[i];
|
|
||||||
}
|
|
||||||
argc += i - 1;
|
|
||||||
INC_SP(i - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEC_SP(argc);
|
DEC_SP(argc);
|
||||||
argc = th_yield_setup_args(th, iseq, argc, GET_SP(),
|
argc = th_yield_setup_args(th, iseq, argc, GET_SP(),
|
||||||
|
|
62
vm.c
62
vm.c
|
@ -282,6 +282,68 @@ callee_setup_arg(rb_thread_t *th, rb_iseq_t *iseq,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
caller_setup_args(rb_thread_t *th, rb_control_frame_t *cfp,
|
||||||
|
VALUE flag, int argc, rb_iseq_t *blockiseq, rb_block_t **block)
|
||||||
|
{
|
||||||
|
rb_block_t *blockptr = 0;
|
||||||
|
|
||||||
|
if (flag & VM_CALL_ARGS_BLOCKARG_BIT) {
|
||||||
|
rb_proc_t *po;
|
||||||
|
VALUE proc;
|
||||||
|
|
||||||
|
proc = *(--cfp->sp);
|
||||||
|
|
||||||
|
if (proc != Qnil) {
|
||||||
|
if (!rb_obj_is_proc(proc)) {
|
||||||
|
proc = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
|
||||||
|
if (!rb_obj_is_proc(proc)) {
|
||||||
|
rb_raise(rb_eTypeError,
|
||||||
|
"wrong argument type %s (expected Proc)",
|
||||||
|
rb_obj_classname(proc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GetProcPtr(proc, po);
|
||||||
|
blockptr = &po->block;
|
||||||
|
RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp)->proc = proc;
|
||||||
|
*block = blockptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (blockiseq) {
|
||||||
|
blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
|
||||||
|
blockptr->iseq = blockiseq;
|
||||||
|
blockptr->proc = 0;
|
||||||
|
*block = blockptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expand top of stack? */
|
||||||
|
if (flag & VM_CALL_ARGS_SPLAT_BIT) {
|
||||||
|
VALUE ary = *(cfp->sp - 1);
|
||||||
|
VALUE *ptr, *dst;
|
||||||
|
int i;
|
||||||
|
VALUE tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_splat");
|
||||||
|
|
||||||
|
if (NIL_P(tmp)) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int len = RARRAY_LEN(tmp);
|
||||||
|
ptr = RARRAY_PTR(tmp);
|
||||||
|
cfp->sp -= 1;
|
||||||
|
|
||||||
|
CHECK_STACK_OVERFLOW(cfp, len);
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
*cfp->sp++ = ptr[i];
|
||||||
|
}
|
||||||
|
argc += i-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Env */
|
/* Env */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
55
vm_macro.def
55
vm_macro.def
|
@ -2,57 +2,6 @@
|
||||||
/* do not use C++ style comment */
|
/* do not use C++ style comment */
|
||||||
/* */
|
/* */
|
||||||
|
|
||||||
MACRO macro_eval_setup_send_arguments(num, blockptr, flag, blockiseq)
|
|
||||||
{
|
|
||||||
if (flag & VM_CALL_ARGS_BLOCKARG_BIT) {
|
|
||||||
rb_proc_t *po;
|
|
||||||
VALUE proc;
|
|
||||||
|
|
||||||
proc = TOPN(0);
|
|
||||||
if (proc != Qnil) {
|
|
||||||
if (!rb_obj_is_proc(proc)) {
|
|
||||||
proc = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
|
|
||||||
if (!rb_obj_is_proc(proc)) {
|
|
||||||
rb_raise(rb_eTypeError,
|
|
||||||
"wrong argument type %s (expected Proc)",
|
|
||||||
rb_obj_classname(proc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GetProcPtr(proc, po);
|
|
||||||
blockptr = &po->block;
|
|
||||||
RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp)->proc = proc;
|
|
||||||
}
|
|
||||||
INC_SP(-1);
|
|
||||||
}
|
|
||||||
else if (blockiseq) {
|
|
||||||
blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp);
|
|
||||||
blockptr->iseq = blockiseq;
|
|
||||||
blockptr->proc = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* expand top of stack? */
|
|
||||||
if (flag & VM_CALL_ARGS_SPLAT_BIT) {
|
|
||||||
VALUE ary = TOPN(0);
|
|
||||||
VALUE *ptr, *dst;
|
|
||||||
int i;
|
|
||||||
VALUE tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_splat");
|
|
||||||
|
|
||||||
if (NIL_P(tmp)) {
|
|
||||||
tmp = rb_ary_new3(1, ary);
|
|
||||||
}
|
|
||||||
ary = tmp;
|
|
||||||
|
|
||||||
ptr = RARRAY_PTR(ary);
|
|
||||||
dst = GET_SP() - 1;
|
|
||||||
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
|
||||||
dst[i] = ptr[i];
|
|
||||||
}
|
|
||||||
num += i - 1;
|
|
||||||
INC_SP(i - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MACRO macro_eval_invoke_cfunc(num, id, recv, klass, mn, blockptr)
|
MACRO macro_eval_invoke_cfunc(num, id, recv, klass, mn, blockptr)
|
||||||
{
|
{
|
||||||
EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass);
|
EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass);
|
||||||
|
@ -93,9 +42,7 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num)
|
||||||
sp = rsp + niseq->arg_size;
|
sp = rsp + niseq->arg_size;
|
||||||
|
|
||||||
/* stack overflow check */
|
/* stack overflow check */
|
||||||
if (CHECK_STACK_OVERFLOW(th, GET_CFP(), niseq->stack_max + 0x100)) {
|
CHECK_STACK_OVERFLOW(GET_CFP(), niseq->stack_max + 0x10);
|
||||||
rb_exc_raise(sysstack_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flag & VM_CALL_TAILCALL_BIT) {
|
if (flag & VM_CALL_TAILCALL_BIT) {
|
||||||
/* copy arguments */
|
/* copy arguments */
|
||||||
|
|
Loading…
Add table
Reference in a new issue