ruby-changes:5579
From: ko1 <ko1@a...>
Date: Wed, 11 Jun 2008 06:47:07 +0900 (JST)
Subject: [ruby-changes:5579] Ruby:r17084 (trunk): * vm.c, eval_intern.h (PASS_PASSED_BLOCK):
ko1 2008-06-11 06:46:43 +0900 (Wed, 11 Jun 2008) New Revision: 17084 Modified files: trunk/ChangeLog trunk/KNOWNBUGS.rb trunk/bootstraptest/test_eval.rb trunk/bootstraptest/test_proc.rb trunk/bootstraptest/test_syntax.rb trunk/bootstraptest/test_thread.rb trunk/eval.c trunk/eval_intern.h trunk/insns.def trunk/proc.c trunk/vm.c trunk/vm.h trunk/vm_core.h trunk/vm_dump.c trunk/vm_eval.c trunk/vm_evalbody.c trunk/vm_insnhelper.c Log: * 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. http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_dump.c?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm.h?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_evalbody.c?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/eval.c?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/bootstraptest/test_proc.rb?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/KNOWNBUGS.rb?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_core.h?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/proc.c?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/bootstraptest/test_thread.rb?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/bootstraptest/test_syntax.rb?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm.c?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_eval.c?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/insns.def?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_insnhelper.c?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/eval_intern.h?r1=17084&r2=17083&diff_format=u http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/bootstraptest/test_eval.rb?r1=17084&r2=17083&diff_format=u Index: eval_intern.h =================================================================== --- eval_intern.h (revision 17083) +++ eval_intern.h (revision 17084) @@ -2,10 +2,16 @@ #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" #include "ruby/util.h" @@ -219,7 +225,7 @@ 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); Index: insns.def =================================================================== --- insns.def (revision 17083) +++ insns.def (revision 17084) @@ -996,7 +996,7 @@ /* 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(); Index: ChangeLog =================================================================== --- ChangeLog (revision 17083) +++ ChangeLog (revision 17084) @@ -1,3 +1,18 @@ +Wed Jun 11 05:53:20 2008 Koichi Sasada <ko1@a...> + + * 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@a...> * ext/tk/tcltklib.c: SEGV when tcltk-stubs is enabled. Index: bootstraptest/test_syntax.rb =================================================================== --- bootstraptest/test_syntax.rb (revision 17083) +++ bootstraptest/test_syntax.rb (revision 17084) @@ -817,3 +817,14 @@ 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! +} + Index: bootstraptest/test_eval.rb =================================================================== --- bootstraptest/test_eval.rb (revision 17083) +++ bootstraptest/test_eval.rb (revision 17084) @@ -282,3 +282,7 @@ :ok end }, '[ruby-core:16796]' + +assert_normal_exit %q{ + eval("", method(:proc).call {}.binding) +} Index: bootstraptest/test_proc.rb =================================================================== --- bootstraptest/test_proc.rb (revision 17083) +++ bootstraptest/test_proc.rb (revision 17084) @@ -259,3 +259,20 @@ 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]' Index: bootstraptest/test_thread.rb =================================================================== --- bootstraptest/test_thread.rb (revision 17083) +++ bootstraptest/test_thread.rb (revision 17084) @@ -1,3 +1,5 @@ +# Thread and Fiber + assert_equal %q{ok}, %q{ Thread.new{ }.join @@ -268,3 +270,35 @@ 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]' Index: vm_core.h =================================================================== --- vm_core.h (revision 17083) +++ vm_core.h (revision 17084) @@ -539,6 +539,29 @@ #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 Index: vm_eval.c =================================================================== --- vm_eval.c (revision 17083) +++ vm_eval.c (revision 17084) @@ -66,7 +66,7 @@ { 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 @@ { 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 @@ 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 */ Index: proc.c =================================================================== --- proc.c (revision 17083) +++ proc.c (revision 17084) @@ -275,10 +275,14 @@ 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 @@ } } 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(); Index: eval.c =================================================================== --- eval.c (revision 17083) +++ eval.c (revision 17084) @@ -17,8 +17,6 @@ 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_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 @@ 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]; Index: KNOWNBUGS.rb =================================================================== --- KNOWNBUGS.rb (revision 17083) +++ KNOWNBUGS.rb (revision 17084) @@ -29,49 +29,6 @@ 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 @@ 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]' Index: vm_evalbody.c =================================================================== --- vm_evalbody.c (revision 17083) +++ vm_evalbody.c (revision 17084) @@ -131,7 +131,7 @@ } } - if (VM_FRAME_TYPE(th->cfp) != FRAME_MAGIC_FINISH) { + if (VM_FRAME_TYPE(th->cfp) != VM_FRAME_MAGIC_FINISH) { rb_bug("cfp consistency error"); } Index: vm.c =================================================================== --- vm.c (revision 17083) +++ vm.c (revision 17084) @@ -52,7 +52,7 @@ 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 @@ /* 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 @@ /* 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 @@ } } +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 @@ { 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 @@ 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 @@ 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 @@ } 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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->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; Index: vm.h =================================================================== --- vm.h (revision 17083) +++ vm.h (revision 17084) @@ -219,27 +219,6 @@ (!((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); \ Index: vm_dump.c =================================================================== --- vm_dump.c (revision 17083) +++ vm_dump.c (revision 17084) @@ -46,34 +46,34 @@ } 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 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 @@ 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 @@ { 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; Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 17083) +++ vm_insnhelper.c (revision 17084) @@ -367,7 +367,7 @@ 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 @@ 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 @@ 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_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_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 @@ 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 @@ 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 @@ 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; } - return svar; + if (NIL_P(*svar)) { + *svar = (VALUE)NEW_IF(Qnil, Qnil, Qnil); + } + return (NODE *)*svar; } static VALUE @@ -1238,7 +1226,7 @@ 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 @@ */ 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; -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/