aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-06-24 08:40:45 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-06-24 08:40:45 +0000
commitadc677eb5cd3aed1986c3316d5b98ed942f544d5 (patch)
tree8c50f9cef922a9fce4f7cc68adce20599b1df35d
parentd1bd418715091794dc207198a0fe4152b5f40cb1 (diff)
downloadruby-adc677eb5cd3aed1986c3316d5b98ed942f544d5.tar.gz
* 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
-rw-r--r--ChangeLog11
-rw-r--r--bootstraptest/test_method.rb27
-rw-r--r--insnhelper.h7
-rw-r--r--insns.def27
-rw-r--r--vm.c62
-rw-r--r--vm_macro.def55
6 files changed, 110 insertions, 79 deletions
diff --git a/ChangeLog b/ChangeLog
index 5b818b9793..09f2f8dc6a 100644
--- a/ChangeLog
+++ b/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>
* proc.c (proc_to_s): used a variable before initialized.
diff --git a/bootstraptest/test_method.rb b/bootstraptest/test_method.rb
index 342803e21b..faf3d4bc58 100644
--- a/bootstraptest/test_method.rb
+++ b/bootstraptest/test_method.rb
@@ -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{
diff --git a/insnhelper.h b/insnhelper.h
index eb6b3ef21b..2eb071df5f 100644
--- a/insnhelper.h
+++ b/insnhelper.h
@@ -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 */
diff --git a/insns.def b/insns.def
index 91607ef952..792c8d40f1 100644
--- a/insns.def
+++ b/insns.def
@@ -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(),
diff --git a/vm.c b/vm.c
index 376b5efc15..f4e37d28a7 100644
--- a/vm.c
+++ b/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 */
static void
diff --git a/vm_macro.def b/vm_macro.def
index 99351efdc5..0d635c55fe 100644
--- a/vm_macro.def
+++ b/vm_macro.def
@@ -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 */