summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-06-10 21:46:43 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-06-10 21:46:43 +0000
commit9e324fdd3ef0b858f6c5dfea1d0055d77979a3a2 (patch)
tree7c83dc40c7b9a926cf9efc8f0abef1cd7267b3d4
parente6697a6405f1330ef071220396b8afef1cd1079a (diff)
* vm.c, eval_intern.h (PASS_PASSED_BLOCK):
set a VM_FRAME_FLAG_PASSED flag to skip this frame when searching ruby-level-cfp. * eval.c, eval_intern.h, proc.c: fix to check cfp. if there is no valid ruby-level-cfp, cause RuntimeError exception. [ruby-dev:34128] * vm_core.h, vm_evalbody.c, vm.c, vm_dump.c, vm_insnhelper.c, insns.def: rename FRAME_MAGIC_* to VM_FRAME_MAGIC_*. * KNOWNBUGS.rb, bootstraptest/test*.rb: move solved bugs. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17084 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog15
-rw-r--r--KNOWNBUGS.rb64
-rw-r--r--bootstraptest/test_eval.rb4
-rw-r--r--bootstraptest/test_proc.rb17
-rw-r--r--bootstraptest/test_syntax.rb11
-rw-r--r--bootstraptest/test_thread.rb34
-rw-r--r--eval.c10
-rw-r--r--eval_intern.h14
-rw-r--r--insns.def2
-rw-r--r--proc.c11
-rw-r--r--vm.c95
-rw-r--r--vm.h21
-rw-r--r--vm_core.h23
-rw-r--r--vm_dump.c42
-rw-r--r--vm_eval.c22
-rw-r--r--vm_evalbody.c2
-rw-r--r--vm_insnhelper.c44
17 files changed, 241 insertions, 190 deletions
diff --git a/ChangeLog b/ChangeLog
index f200a3cd1b..c43afdedc3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Wed Jun 11 05:53:20 2008 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c, eval_intern.h (PASS_PASSED_BLOCK):
+ set a VM_FRAME_FLAG_PASSED flag to skip this frame when
+ searching ruby-level-cfp.
+
+ * eval.c, eval_intern.h, proc.c: fix to check cfp. if there is
+ no valid ruby-level-cfp, cause RuntimeError exception.
+ [ruby-dev:34128]
+
+ * vm_core.h, vm_evalbody.c, vm.c, vm_dump.c, vm_insnhelper.c,
+ insns.def: rename FRAME_MAGIC_* to VM_FRAME_MAGIC_*.
+
+ * KNOWNBUGS.rb, bootstraptest/test*.rb: move solved bugs.
+
Wed Jun 11 05:55:31 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* ext/tk/tcltklib.c: SEGV when tcltk-stubs is enabled.
diff --git a/KNOWNBUGS.rb b/KNOWNBUGS.rb
index f907467651..54ae030f66 100644
--- a/KNOWNBUGS.rb
+++ b/KNOWNBUGS.rb
@@ -29,49 +29,6 @@ assert_equal 'ok', %q{
C.new.foo
}, '[ruby-core:14813]'
-assert_equal 'ok', %q{
- a = lambda {|x, y, &b| b }
- b = a.curry[1]
- if b.call(2){} == nil
- :ng
- else
- :ok
- end
-}, '[ruby-core:15551]'
-
-assert_normal_exit %q{
- g = Module.enum_for(:new)
- loop { g.next }
-}, '[ruby-dev:34128]'
-
-assert_normal_exit %q{
- Fiber.new(&Object.method(:class_eval)).resume("foo")
-}, '[ruby-dev:34128]'
-
-assert_normal_exit %q{
- Thread.new("foo", &Object.method(:class_eval)).join
-}, '[ruby-dev:34128]'
-
-assert_normal_exit %q{
- g = enum_for(:local_variables)
- loop { g.next }
-}, '[ruby-dev:34128]'
-
-assert_normal_exit %q{
- g = enum_for(:block_given?)
- loop { g.next }
-}, '[ruby-dev:34128]'
-
-assert_normal_exit %q{
- g = enum_for(:binding)
- loop { g.next }
-}, '[ruby-dev:34128]'
-
-assert_normal_exit %q{
- g = "abc".enum_for(:scan, /./)
- loop { g.next }
-}, '[ruby-dev:34128]'
-
assert_equal %q{[:bar, :foo]}, %q{
def foo
klass = Class.new do
@@ -84,24 +41,3 @@ assert_equal %q{[:bar, :foo]}, %q{
foo
}, "[ ruby-Bugs-19304 ]"
-assert_equal 'ok', %q{
- lambda {
- break :ok
- :ng
- }.call
-}, '[ruby-dev:34646]'
-
-assert_normal_exit %q{
- eval("", method(:proc).call {}.binding)
-}
-
-assert_normal_exit %q{
- a = []
- 100.times {|i| a << i << nil << nil }
- p a.compact!
-}
-
-assert_equal 'ok', %q{
- a = [false]
- (a[0] &&= true) == false ? :ok : :ng
-}, '[ruby-dev:34679]'
diff --git a/bootstraptest/test_eval.rb b/bootstraptest/test_eval.rb
index 7fdfda8272..8b99c7968c 100644
--- a/bootstraptest/test_eval.rb
+++ b/bootstraptest/test_eval.rb
@@ -282,3 +282,7 @@ assert_equal 'ok', %q{
:ok
end
}, '[ruby-core:16796]'
+
+assert_normal_exit %q{
+ eval("", method(:proc).call {}.binding)
+}
diff --git a/bootstraptest/test_proc.rb b/bootstraptest/test_proc.rb
index ab309fe534..51c69448c8 100644
--- a/bootstraptest/test_proc.rb
+++ b/bootstraptest/test_proc.rb
@@ -259,3 +259,20 @@ assert_equal %Q{ok\n}, %q{
GC.start
block.call
}, '[ruby-core:14885]'
+
+assert_equal 'ok', %q{
+ a = lambda {|x, y, &b| b }
+ b = a.curry[1]
+ if b.call(2){} == nil
+ :ng
+ else
+ :ok
+ end
+}, '[ruby-core:15551]'
+
+assert_equal 'ok', %q{
+ lambda {
+ break :ok
+ :ng
+ }.call
+}, '[ruby-dev:34646]'
diff --git a/bootstraptest/test_syntax.rb b/bootstraptest/test_syntax.rb
index 5479de0573..a9005a4292 100644
--- a/bootstraptest/test_syntax.rb
+++ b/bootstraptest/test_syntax.rb
@@ -817,3 +817,14 @@ assert_equal 'ok', %q{
end
}, '[ruby-core:14537]'
+assert_equal 'ok', %q{
+ a = [false]
+ (a[0] &&= true) == false ? :ok : :ng
+}, '[ruby-dev:34679]'
+
+assert_normal_exit %q{
+ a = []
+ 100.times {|i| a << i << nil << nil }
+ p a.compact!
+}
+
diff --git a/bootstraptest/test_thread.rb b/bootstraptest/test_thread.rb
index 3b1fa3f2a8..66b53634ac 100644
--- a/bootstraptest/test_thread.rb
+++ b/bootstraptest/test_thread.rb
@@ -1,3 +1,5 @@
+# Thread and Fiber
+
assert_equal %q{ok}, %q{
Thread.new{
}.join
@@ -268,3 +270,35 @@ assert_normal_exit %q{
at_exit { Fiber.new{}.resume }
}
+assert_normal_exit %q{
+ g = enum_for(:local_variables)
+ loop { g.next }
+}, '[ruby-dev:34128]'
+
+assert_normal_exit %q{
+ g = enum_for(:block_given?)
+ loop { g.next }
+}, '[ruby-dev:34128]'
+
+assert_normal_exit %q{
+ g = enum_for(:binding)
+ loop { g.next }
+}, '[ruby-dev:34128]'
+
+assert_normal_exit %q{
+ g = "abc".enum_for(:scan, /./)
+ loop { g.next }
+}, '[ruby-dev:34128]'
+
+assert_normal_exit %q{
+ g = Module.enum_for(:new)
+ loop { g.next }
+}, '[ruby-dev:34128]'
+
+assert_normal_exit %q{
+ Fiber.new(&Object.method(:class_eval)).resume("foo")
+}, '[ruby-dev:34128]'
+
+assert_normal_exit %q{
+ Thread.new("foo", &Object.method(:class_eval)).join
+}, '[ruby-dev:34128]'
diff --git a/eval.c b/eval.c
index 635d60cd6b..bb1e43bb73 100644
--- a/eval.c
+++ b/eval.c
@@ -17,8 +17,6 @@ VALUE proc_invoke(VALUE, VALUE, VALUE, VALUE);
VALUE rb_binding_new(void);
NORETURN(void rb_raise_jump(VALUE));
-VALUE rb_f_block_given_p(void);
-
ID rb_frame_callee(void);
VALUE rb_eLocalJumpError;
VALUE rb_eSysStackError;
@@ -586,9 +584,9 @@ rb_f_block_given_p(void)
{
rb_thread_t *th = GET_THREAD();
rb_control_frame_t *cfp = th->cfp;
- cfp = vm_get_ruby_level_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
+ cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
- if (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
+ if (cfp != 0 && GC_GUARDED_PTR_REF(cfp->lfp[0])) {
return Qtrue;
}
else {
@@ -1089,10 +1087,10 @@ rb_f_local_variables(void)
VALUE ary = rb_ary_new();
rb_thread_t *th = GET_THREAD();
rb_control_frame_t *cfp =
- vm_get_ruby_level_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
+ vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
int i;
- while (1) {
+ while (cfp) {
if (cfp->iseq) {
for (i = 0; i < cfp->iseq->local_table_size; i++) {
ID lid = cfp->iseq->local_table[i];
diff --git a/eval_intern.h b/eval_intern.h
index a8727d230c..7bc42f8de3 100644
--- a/eval_intern.h
+++ b/eval_intern.h
@@ -2,9 +2,15 @@
#ifndef RUBY_EVAL_INTERN_H
#define RUBY_EVAL_INTERN_H
-#define PASS_PASSED_BLOCK() \
- (GET_THREAD()->passed_block = \
- GC_GUARDED_PTR_REF((rb_block_t *)GET_THREAD()->cfp->lfp[0]))
+#define PASS_PASSED_BLOCK_TH(th) do { \
+ (th)->passed_block = GC_GUARDED_PTR_REF((rb_block_t *)(th)->cfp->lfp[0]); \
+ (th)->cfp->flag |= VM_FRAME_FLAG_PASSED; \
+} while (0)
+
+#define PASS_PASSED_BLOCK() do { \
+ rb_thread_t * const __th__ = GET_THREAD(); \
+ PASS_PASSED_BLOCK_TH(__th__); \
+} while (0)
#include "ruby/ruby.h"
#include "ruby/node.h"
@@ -219,7 +225,7 @@ NORETURN(void vm_jump_tag_but_local_jump(int, VALUE));
VALUE vm_make_jump_tag_but_local_jump(int state, VALUE val);
NODE *vm_cref(void);
-rb_control_frame_t *vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp);
+rb_control_frame_t *vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp);
VALUE rb_obj_is_proc(VALUE);
VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, const rb_block_t *blockptr, VALUE filename);
void rb_thread_terminate_all(void);
diff --git a/insns.def b/insns.def
index da1f19b939..0a23525a01 100644
--- a/insns.def
+++ b/insns.def
@@ -996,7 +996,7 @@ defineclass
/* enter scope */
vm_push_frame(th, class_iseq,
- FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02,
+ VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02,
class_iseq->iseq_encoded, GET_SP(), 0,
class_iseq->local_size);
RESTORE_REGS();
diff --git a/proc.c b/proc.c
index f681f46bc9..3234c0e03c 100644
--- a/proc.c
+++ b/proc.c
@@ -275,10 +275,14 @@ VALUE
rb_binding_new(void)
{
rb_thread_t *th = GET_THREAD();
- rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+ rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
VALUE bindval = binding_alloc(rb_cBinding);
rb_binding_t *bind;
+ if (cfp == 0) {
+ rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber.");
+ }
+
GetBindingPtr(bindval, bind);
bind->env = vm_make_env_object(th, cfp);
return bindval;
@@ -1187,11 +1191,12 @@ rb_method_call(int argc, VALUE *argv, VALUE method)
}
}
if ((state = EXEC_TAG()) == 0) {
+ rb_thread_t *th = GET_THREAD();
VALUE rb_vm_call(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
int argc, const VALUE *argv, const NODE *body, int nosuper);
- PASS_PASSED_BLOCK();
- result = rb_vm_call(GET_THREAD(), data->oclass, data->recv, data->id, data->oid,
+ PASS_PASSED_BLOCK_TH(th);
+ result = rb_vm_call(th, data->oclass, data->recv, data->id, data->oid,
argc, argv, data->body, 0);
}
POP_TAG();
diff --git a/vm.c b/vm.c
index 545bf3a52b..29804bc48c 100644
--- a/vm.c
+++ b/vm.c
@@ -52,7 +52,7 @@ rb_vm_change_state(void)
static inline VALUE
rb_vm_set_finish_env(rb_thread_t * th)
{
- vm_push_frame(th, 0, FRAME_MAGIC_FINISH,
+ vm_push_frame(th, 0, VM_FRAME_MAGIC_FINISH,
Qnil, th->cfp->lfp[0], 0,
th->cfp->sp, 0, 1);
th->cfp->pc = (VALUE *)&finish_insn_seq[0];
@@ -72,7 +72,7 @@ vm_set_top_stack(rb_thread_t * th, VALUE iseqval)
/* for return */
rb_vm_set_finish_env(th);
- vm_push_frame(th, iseq, FRAME_MAGIC_TOP,
+ vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP,
th->top_self, 0, iseq->iseq_encoded,
th->cfp->sp, 0, iseq->local_size);
}
@@ -86,7 +86,7 @@ vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref)
/* for return */
rb_vm_set_finish_env(th);
- vm_push_frame(th, iseq, FRAME_MAGIC_EVAL, block->self,
+ vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL, block->self,
GC_GUARDED_PTR(block->dfp), iseq->iseq_encoded,
th->cfp->sp, block->lfp, iseq->local_size);
@@ -95,13 +95,35 @@ vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref)
}
}
+static rb_control_frame_t *
+vm_get_ruby_level_next_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
+{
+ while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
+ if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
+ return cfp;
+ }
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+ }
+ return 0;
+}
+
rb_control_frame_t *
-vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
+vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
{
+ if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
+ return cfp;
+ }
+
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+
while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
return cfp;
}
+
+ if ((cfp->flag & VM_FRAME_FLAG_PASSED) == 0) {
+ break;
+ }
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
return 0;
@@ -322,7 +344,7 @@ vm_make_env_object(rb_thread_t * th, rb_control_frame_t *cfp)
{
VALUE envval;
- if (VM_FRAME_FLAG(cfp->flag) == FRAME_MAGIC_FINISH) {
+ if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_FINISH) {
/* for method_missing */
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
@@ -340,7 +362,7 @@ void
vm_stack_to_heap(rb_thread_t * const th)
{
rb_control_frame_t *cfp = th->cfp;
- while ((cfp = vm_get_ruby_level_cfp(th, cfp)) != 0) {
+ while ((cfp = vm_get_ruby_level_next_cfp(th, cfp)) != 0) {
vm_make_env_object(th, cfp);
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
@@ -423,7 +445,8 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
const rb_iseq_t *iseq = block->iseq;
const rb_control_frame_t *cfp = th->cfp;
int i, opt_pc, arg_size = iseq->arg_size;
- int type = block_proc_is_lambda(block->proc) ? FRAME_MAGIC_LAMBDA : FRAME_MAGIC_BLOCK;
+ int type = block_proc_is_lambda(block->proc) ?
+ VM_FRAME_MAGIC_LAMBDA : VM_FRAME_MAGIC_BLOCK;
rb_vm_set_finish_env(th);
@@ -434,7 +457,7 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
}
opt_pc = vm_yield_setup_args(th, iseq, argc, cfp->sp, blockptr,
- type == FRAME_MAGIC_LAMBDA);
+ type == VM_FRAME_MAGIC_LAMBDA);
vm_push_frame(th, iseq, type,
self, GC_GUARDED_PTR(block->dfp),
@@ -521,22 +544,30 @@ vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
/* special variable */
-static VALUE
-vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key)
+static rb_control_frame_t *
+vm_normal_frame(rb_thread_t *th, rb_control_frame_t *cfp)
{
while (cfp->pc == 0) {
- cfp++;
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+ if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
+ return 0;
+ }
}
- return lfp_svar_get(th, cfp->lfp, key);
+ return cfp;
+}
+
+static VALUE
+vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key)
+{
+ cfp = vm_normal_frame(th, cfp);
+ return lfp_svar_get(th, cfp ? cfp->lfp : 0, key);
}
static void
vm_cfp_svar_set(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key, const VALUE val)
{
- while (cfp->pc == 0) {
- cfp++;
- }
- lfp_svar_set(th, cfp->lfp, key, val);
+ cfp = vm_normal_frame(th, cfp);
+ lfp_svar_set(th, cfp ? cfp->lfp : 0, key, val);
}
static VALUE
@@ -663,7 +694,7 @@ const char *
rb_sourcefile(void)
{
rb_thread_t *th = GET_THREAD();
- rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+ rb_control_frame_t *cfp = vm_get_ruby_level_next_cfp(th, th->cfp);
if (cfp) {
return RSTRING_PTR(cfp->iseq->filename);
@@ -677,7 +708,7 @@ int
rb_sourceline(void)
{
rb_thread_t *th = GET_THREAD();
- rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+ rb_control_frame_t *cfp = vm_get_ruby_level_next_cfp(th, th->cfp);
if (cfp) {
return vm_get_sourceline(cfp);
@@ -691,7 +722,7 @@ NODE *
vm_cref(void)
{
rb_thread_t *th = GET_THREAD();
- rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+ rb_control_frame_t *cfp = vm_get_ruby_level_next_cfp(th, th->cfp);
return vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
}
@@ -710,12 +741,15 @@ debug_cref(NODE *cref)
static NODE *
vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
{
+ rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
NODE *cref = NEW_BLOCK(klass);
- rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
-
cref->nd_file = 0;
- cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
cref->nd_visi = noex;
+
+ if (cfp) {
+ cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
+ }
+
return cref;
}
@@ -739,7 +773,8 @@ VALUE
rb_vm_cbase(void)
{
rb_thread_t *th = GET_THREAD();
- rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+ rb_control_frame_t *cfp = vm_get_ruby_level_next_cfp(th, th->cfp);
+
return vm_get_cbase(cfp->iseq, cfp->lfp, cfp->dfp);
}
@@ -1183,7 +1218,7 @@ vm_eval_body(rb_thread_t *th)
/* push block frame */
cfp->sp[0] = err;
- vm_push_frame(th, catch_iseq, FRAME_MAGIC_BLOCK,
+ vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_BLOCK,
cfp->self, (VALUE)cfp->dfp, catch_iseq->iseq_encoded,
cfp->sp + 1 /* push value */, cfp->lfp, catch_iseq->local_size - 1);
@@ -1297,7 +1332,7 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg,
volatile VALUE iseqval = rb_iseq_new(0, filename, filename, 0, ISEQ_TYPE_TOP);
VALUE val;
- vm_push_frame(th, DATA_PTR(iseqval), FRAME_MAGIC_TOP,
+ vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP,
recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
val = (*func)(arg);
@@ -1306,14 +1341,6 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg,
return val;
}
-int
-rb_vm_cfunc_funcall_p(const rb_control_frame_t *cfp)
-{
- if (vm_cfunc_flags(cfp) & (VM_CALL_FCALL_BIT | VM_CALL_VCALL_BIT))
- return Qtrue;
- return Qfalse;
-}
-
/* vm */
static void
@@ -1548,7 +1575,7 @@ th_init2(rb_thread_t *th)
th->cfp = (void *)(th->stack + th->stack_size);
- vm_push_frame(th, 0, FRAME_MAGIC_TOP, Qnil, 0, 0,
+ vm_push_frame(th, 0, VM_FRAME_MAGIC_TOP, Qnil, 0, 0,
th->stack, 0, 1);
th->status = THREAD_RUNNABLE;
diff --git a/vm.h b/vm.h
index cb2db329d4..c485cae80b 100644
--- a/vm.h
+++ b/vm.h
@@ -219,27 +219,6 @@ default: \
(!((th)->stack < (env) && (env) < ((th)->stack + (th)->stack_size)))
#define ENV_VAL(env) ((env)[1])
-#define FRAME_MAGIC_METHOD 0x11
-#define FRAME_MAGIC_BLOCK 0x21
-#define FRAME_MAGIC_CLASS 0x31
-#define FRAME_MAGIC_TOP 0x41
-#define FRAME_MAGIC_FINISH 0x51
-#define FRAME_MAGIC_CFUNC 0x61
-#define FRAME_MAGIC_PROC 0x71
-#define FRAME_MAGIC_IFUNC 0x81
-#define FRAME_MAGIC_EVAL 0x91
-#define FRAME_MAGIC_LAMBDA 0xa1
-#define FRAME_MAGIC_MASK_BITS 8
-#define FRAME_MAGIC_MASK (~(~0<<FRAME_MAGIC_MASK_BITS))
-
-#define VM_FRAME_FLAG(type) ((VALUE)((type) & FRAME_MAGIC_MASK))
-
-#define VM_FRAME_TYPE(cfp) \
- ((cfp)->flag & FRAME_MAGIC_MASK)
-
-#define RUBYVM_CFUNC_FRAME_P(cfp) \
- (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_CFUNC)
-
#if OPT_CALL_THREADED_CODE
#define THROW_EXCEPTION(exc) do { \
th->errinfo = (VALUE)(exc); \
diff --git a/vm_core.h b/vm_core.h
index 4e62bb5d8f..03644dc29b 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -539,6 +539,29 @@ typedef struct {
#define VM_CALL_SUPER_BIT (0x01 << 7)
#define VM_CALL_SEND_BIT (0x01 << 8)
+#define VM_FRAME_MAGIC_METHOD 0x11
+#define VM_FRAME_MAGIC_BLOCK 0x21
+#define VM_FRAME_MAGIC_CLASS 0x31
+#define VM_FRAME_MAGIC_TOP 0x41
+#define VM_FRAME_MAGIC_FINISH 0x51
+#define VM_FRAME_MAGIC_CFUNC 0x61
+#define VM_FRAME_MAGIC_PROC 0x71
+#define VM_FRAME_MAGIC_IFUNC 0x81
+#define VM_FRAME_MAGIC_EVAL 0x91
+#define VM_FRAME_MAGIC_LAMBDA 0xa1
+#define VM_FRAME_MAGIC_MASK_BITS 8
+#define VM_FRAME_MAGIC_MASK (~(~0<<VM_FRAME_MAGIC_MASK_BITS))
+
+#define VM_FRAME_TYPE(cfp) ((cfp)->flag & VM_FRAME_MAGIC_MASK)
+
+/* other frame flag */
+#define VM_FRAME_FLAG_PASSED 0x0100
+
+
+#define RUBYVM_CFUNC_FRAME_P(cfp) \
+ (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC)
+
+
/* inline (method|const) cache */
#define NEW_INLINE_CACHE_ENTRY() NEW_WHILE(Qundef, 0, 0)
#define ic_class u1.value
diff --git a/vm_dump.c b/vm_dump.c
index 80bb13eb77..2d606b313c 100644
--- a/vm_dump.c
+++ b/vm_dump.c
@@ -46,34 +46,34 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
}
switch (VM_FRAME_TYPE(cfp)) {
- case FRAME_MAGIC_TOP:
+ case VM_FRAME_MAGIC_TOP:
magic = "TOP";
break;
- case FRAME_MAGIC_METHOD:
+ case VM_FRAME_MAGIC_METHOD:
magic = "METHOD";
break;
- case FRAME_MAGIC_CLASS:
+ case VM_FRAME_MAGIC_CLASS:
magic = "CLASS";
break;
- case FRAME_MAGIC_BLOCK:
+ case VM_FRAME_MAGIC_BLOCK:
magic = "BLOCK";
break;
- case FRAME_MAGIC_FINISH:
+ case VM_FRAME_MAGIC_FINISH:
magic = "FINISH";
break;
- case FRAME_MAGIC_CFUNC:
+ case VM_FRAME_MAGIC_CFUNC:
magic = "CFUNC";
break;
- case FRAME_MAGIC_PROC:
+ case VM_FRAME_MAGIC_PROC:
magic = "PROC";
break;
- case FRAME_MAGIC_LAMBDA:
+ case VM_FRAME_MAGIC_LAMBDA:
magic = "LAMBDA";
break;
- case FRAME_MAGIC_IFUNC:
+ case VM_FRAME_MAGIC_IFUNC:
magic = "IFUNC";
break;
- case FRAME_MAGIC_EVAL:
+ case VM_FRAME_MAGIC_EVAL:
magic = "EVAL";
break;
case 0:
@@ -271,15 +271,15 @@ stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp)
/* stack trace header */
- if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_METHOD ||
- VM_FRAME_TYPE(cfp) == FRAME_MAGIC_TOP ||
- VM_FRAME_TYPE(cfp) == FRAME_MAGIC_BLOCK ||
- VM_FRAME_TYPE(cfp) == FRAME_MAGIC_CLASS ||
- VM_FRAME_TYPE(cfp) == FRAME_MAGIC_PROC ||
- VM_FRAME_TYPE(cfp) == FRAME_MAGIC_LAMBDA ||
- VM_FRAME_TYPE(cfp) == FRAME_MAGIC_CFUNC ||
- VM_FRAME_TYPE(cfp) == FRAME_MAGIC_IFUNC ||
- VM_FRAME_TYPE(cfp) == FRAME_MAGIC_EVAL) {
+ if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_METHOD ||
+ VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_TOP ||
+ VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_BLOCK ||
+ VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CLASS ||
+ VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_PROC ||
+ VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA ||
+ VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC ||
+ VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_IFUNC ||
+ VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_EVAL) {
VALUE *ptr = dfp - local_size;
@@ -312,7 +312,7 @@ stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp)
ptr - th->stack);
}
}
- else if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_FINISH) {
+ else if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_FINISH) {
if ((th)->stack + (th)->stack_size > (VALUE *)(cfp + 2)) {
stack_dump_each(th, cfp + 1);
}
@@ -362,7 +362,7 @@ debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp)
{
rb_iseq_t *iseq = cfp->iseq;
- if (iseq != 0 && VM_FRAME_TYPE(cfp) != FRAME_MAGIC_FINISH) {
+ if (iseq != 0 && VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_FINISH) {
VALUE *seq = iseq->iseq;
int pc = cfp->pc - iseq->iseq_encoded;
diff --git a/vm_eval.c b/vm_eval.c
index a00b33bdce..7f01781d3b 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -66,7 +66,7 @@ vm_call0(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
{
rb_control_frame_t *reg_cfp = th->cfp;
rb_control_frame_t *cfp =
- vm_push_frame(th, 0, FRAME_MAGIC_CFUNC,
+ vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
cfp->method_id = id;
@@ -412,13 +412,15 @@ send_internal(int argc, VALUE *argv, VALUE recv, int scope)
{
VALUE vid;
VALUE self = RUBY_VM_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp)->self;
+ rb_thread_t *th = GET_THREAD();
if (argc == 0) {
rb_raise(rb_eArgError, "no method name given");
}
vid = *argv++; argc--;
- PASS_PASSED_BLOCK();
+ PASS_PASSED_BLOCK_TH(th);
+
return rb_call0(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, scope, self);
}
@@ -687,11 +689,17 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char
th->base_block = &env->block;
}
else {
- rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
- block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
- th->base_block = &block;
- th->base_block->self = self;
- th->base_block->iseq = cfp->iseq; /* TODO */
+ rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
+
+ if (cfp != 0) {
+ block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
+ th->base_block = &block;
+ th->base_block->self = self;
+ th->base_block->iseq = cfp->iseq; /* TODO */
+ }
+ else {
+ rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
+ }
}
/* make eval iseq */
diff --git a/vm_evalbody.c b/vm_evalbody.c
index 19029030c5..65f2964180 100644
--- a/vm_evalbody.c
+++ b/vm_evalbody.c
@@ -131,7 +131,7 @@ vm_eval(rb_thread_t *th, VALUE initial)
}
}
- if (VM_FRAME_TYPE(th->cfp) != FRAME_MAGIC_FINISH) {
+ if (VM_FRAME_TYPE(th->cfp) != VM_FRAME_MAGIC_FINISH) {
rb_bug("cfp consistency error");
}
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 05555427dc..cf3bd07220 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -367,7 +367,7 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp,
EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass);
{
rb_control_frame_t *cfp =
- vm_push_frame(th, 0, FRAME_MAGIC_CFUNC | (flag << FRAME_MAGIC_MASK_BITS),
+ vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1);
cfp->method_id = id;
@@ -380,6 +380,7 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp,
if (reg_cfp != th->cfp + 1) {
rb_bug("cfp consistency error - send");
}
+
vm_pop_frame(th);
}
EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, id, klass);
@@ -387,14 +388,6 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp,
return val;
}
-static inline int
-vm_cfunc_flags(const rb_control_frame_t *cfp)
-{
- if (RUBYVM_CFUNC_FRAME_P(cfp))
- return cfp->flag >> FRAME_MAGIC_MASK_BITS;
- return 0;
-}
-
static inline VALUE
vm_call_bmethod(rb_thread_t *th, ID id, VALUE procval, VALUE recv,
VALUE klass, int argc, VALUE *argv, rb_block_t *blockptr)
@@ -455,7 +448,7 @@ vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
}
vm_push_frame(th, iseq,
- FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
+ VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
iseq->iseq_encoded + opt_pc, sp, 0, 0);
cfp->sp = rsp - 1 /* recv */;
@@ -478,7 +471,7 @@ vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
}
vm_push_frame(th, iseq,
- FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
+ VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
iseq->iseq_encoded + opt_pc, sp, 0, 0);
}
}
@@ -675,7 +668,7 @@ vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block,
blockarg = Qnil;
}
- vm_push_frame(th, 0, FRAME_MAGIC_IFUNC,
+ vm_push_frame(th, 0, VM_FRAME_MAGIC_IFUNC,
self, (VALUE)block->dfp,
0, th->cfp->sp, block->lfp, 1);
@@ -831,7 +824,7 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_n
block_proc_is_lambda(block->proc));
vm_push_frame(th, iseq,
- FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp,
+ VM_FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp,
iseq->iseq_encoded + opt_pc, rsp + arg_size, block->lfp,
iseq->local_size - arg_size);
@@ -849,23 +842,18 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_n
static inline NODE *
lfp_svar_place(rb_thread_t *th, VALUE *lfp)
{
- NODE *svar;
+ VALUE *svar;
- if (th->local_lfp != lfp) {
- svar = (NODE *)lfp[-1];
- if ((VALUE)svar == Qnil) {
- svar = NEW_IF(Qnil, Qnil, Qnil);
- lfp[-1] = (VALUE)svar;
- }
+ if (lfp && th->local_lfp != lfp) {
+ svar = &lfp[-1];
}
else {
- svar = (NODE *)th->local_svar;
- if ((VALUE)svar == Qnil) {
- svar = NEW_IF(Qnil, Qnil, Qnil);
- th->local_svar = (VALUE)svar;
- }
+ svar = &th->local_svar;
+ }
+ if (NIL_P(*svar)) {
+ *svar = (VALUE)NEW_IF(Qnil, Qnil, Qnil);
}
- return svar;
+ return (NODE *)*svar;
}
static VALUE
@@ -1238,7 +1226,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
rb_bug("VM (throw): can't find break base.");
}
- if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_LAMBDA) {
+ if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
/* lambda{... break ...} */
is_orphan = 0;
pt = GET_LFP();
@@ -1297,7 +1285,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
*/
while ((VALUE *) cfp < th->stack + th->stack_size) {
if (GET_DFP() == dfp) {
- if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_LAMBDA) {
+ if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
/* in lambda */
is_orphan = 0;
break;