1
0
Fork 0
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:
ko1 2007-06-24 08:40:45 +00:00
parent d1bd418715
commit adc677eb5c
6 changed files with 110 additions and 79 deletions

View file

@ -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>
* proc.c (proc_to_s): used a variable before initialized.

View file

@ -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
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
assert_equal %q{[1, 2, :o1, :o2, [], 3, 4, NilClass, nil, nil]}, %q{

View file

@ -127,8 +127,11 @@
#define GET_BLOCK_PTR() \
((rb_block_t *)(GC_GUARDED_PTR_REF(GET_LFP()[0])))
#define CHECK_STACK_OVERFLOW(th, cfp, margin) \
(((VALUE *)(cfp)->sp) + (margin) >= ((VALUE *)cfp))
#define CHECK_STACK_OVERFLOW(cfp, margin) do \
if (((VALUE *)(cfp)->sp) + (margin) >= ((VALUE *)cfp)) { \
rb_exc_raise(sysstack_error); \
} \
while (0)
/**********************************************************/
/* deal with control flow 3: exception */

View file

@ -1156,11 +1156,11 @@ send
VALUE recv;
VALUE klass;
rb_block_t *blockptr = 0;
rb_num_t num = op_argc;
rb_num_t num;
rb_num_t flag = op_flag;
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) {
/* method(...) */
@ -1298,9 +1298,8 @@ invokesuper
/* TODO: */
rb_bug("...");
#else
tmp_num = op_argc;
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)) {
tmp_blockptr = GET_BLOCK_PTR();
}
@ -1329,25 +1328,7 @@ invokeblock
iseq = block->iseq;
if (BUILTIN_TYPE(iseq) != T_NODE) {
if (flag & VM_CALL_ARGS_SPLAT_BIT) {
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);
}
}
argc = caller_setup_args(th, GET_CFP(), flag, argc, 0, 0);
DEC_SP(argc);
argc = th_yield_setup_args(th, iseq, argc, GET_SP(),

62
vm.c
View file

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

View file

@ -2,57 +2,6 @@
/* 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)
{
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;
/* stack overflow check */
if (CHECK_STACK_OVERFLOW(th, GET_CFP(), niseq->stack_max + 0x100)) {
rb_exc_raise(sysstack_error);
}
CHECK_STACK_OVERFLOW(GET_CFP(), niseq->stack_max + 0x10);
if (flag & VM_CALL_TAILCALL_BIT) {
/* copy arguments */