From 9e324fdd3ef0b858f6c5dfea1d0055d77979a3a2 Mon Sep 17 00:00:00 2001 From: ko1 Date: Tue, 10 Jun 2008 21:46:43 +0000 Subject: * 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 --- ChangeLog | 15 +++++++ KNOWNBUGS.rb | 64 ----------------------------- bootstraptest/test_eval.rb | 4 ++ bootstraptest/test_proc.rb | 17 ++++++++ bootstraptest/test_syntax.rb | 11 +++++ bootstraptest/test_thread.rb | 34 ++++++++++++++++ eval.c | 10 ++--- eval_intern.h | 14 +++++-- insns.def | 2 +- proc.c | 11 +++-- vm.c | 95 ++++++++++++++++++++++++++++---------------- vm.h | 21 ---------- vm_core.h | 23 +++++++++++ vm_dump.c | 42 ++++++++++---------- vm_eval.c | 22 ++++++---- vm_evalbody.c | 2 +- vm_insnhelper.c | 44 ++++++++------------ 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 + + * 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 * 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<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<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 = █ - 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 = █ + 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; -- cgit v1.2.3