From 00e4fd42f36fa23de04cccb9cea3c3e5d14c9ae9 Mon Sep 17 00:00:00 2001 From: ko1 Date: Tue, 17 Jun 2008 19:27:24 +0000 Subject: * vm.c, vm_insnhelper.c: fix escape process with "braek" and "return" syntax in "lambda". [ ruby-Bugs-19304 ], [ruby-core:17164] * KNOWNBUGS.rb, bootstraptest/test_proc.rb: add/move solved test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17390 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 ++++ KNOWNBUGS.rb | 21 ++++++----- bootstraptest/test_proc.rb | 88 ++++++++++++++++++++++++++++++++++++++++++++++ vm.c | 4 +-- vm_insnhelper.c | 28 ++++++++------- 5 files changed, 125 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ee8ec32c2..d6fad04f4c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed Jun 18 04:24:20 2008 Koichi Sasada + + * vm.c, vm_insnhelper.c: fix escape process with "braek" and "return" + syntax in "lambda". [ ruby-Bugs-19304 ], [ruby-core:17164] + + * KNOWNBUGS.rb, bootstraptest/test_proc.rb: add/move solved test. + Wed Jun 18 01:51:10 2008 Hidetoshi NAGAI * ext/tk/lib/multi-tk.rb: cannot access class variable from diff --git a/KNOWNBUGS.rb b/KNOWNBUGS.rb index 7f6fa9274a..e3ac86776d 100644 --- a/KNOWNBUGS.rb +++ b/KNOWNBUGS.rb @@ -3,15 +3,18 @@ # So all tests will cause failure. # -assert_equal %q{[:bar, :foo]}, %q{ - def foo - klass = Class.new do - define_method(:bar) do - return :bar - end +assert_equal 'A', %q{ + class A + @@a = 'A' + def a=(x) + @@a = x + end + def a + @@a end - [klass.new.bar, :foo] end - foo -}, "[ ruby-Bugs-19304 ]" + B = A.dup + B.new.a = 'B' + A.new.a +} diff --git a/bootstraptest/test_proc.rb b/bootstraptest/test_proc.rb index 51c69448c8..1ffd5c08ac 100644 --- a/bootstraptest/test_proc.rb +++ b/bootstraptest/test_proc.rb @@ -276,3 +276,91 @@ assert_equal 'ok', %q{ :ng }.call }, '[ruby-dev:34646]' + +assert_equal %q{[:bar, :foo]}, %q{ + def foo + klass = Class.new do + define_method(:bar) do + return :bar + end + end + [klass.new.bar, :foo] + end + foo +}, "[ ruby-Bugs-19304 ]" + +assert_equal 'ok', %q{ + $x = :ok + def def7(x, y) + x[y] + $x = :ng + end + def test_def7 + def7(lambda {|x| x.call}, Proc.new {return}) + $x = :ng + end + test_def7 + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + lambda { a = lambda { return }; $x = :ng; a[]; $x = :ok }.call + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + lambda { a = lambda { break }; $x = :ng; a[]; $x = :ok }.call + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + def def8 + $x = :ng + lambda { a = Proc.new { return }; a[]}.call + $x = :ok + end + def8 + $x +}, '[ruby-core:17164]' + + +assert_equal 'ok', %q{ + def def9 + lambda {|a| $x = :ok; a[]; $x = :ng }.call(Proc.new { return }) + $x = :ng + end + def9 + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + def def10 + $x = :ng + lambda { 1.times { return } }.call + $x = :ok + end + $x = :ok + def10 + $x +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + def def11 + yield + end + begin + lambda { def11 { return } }.call + rescue LocalJumpError + :ng + else + :ok + end +}, '[ruby-core:17164]' + +assert_equal 'ok', %q{ + def def12 + b = Proc.new { $x = :ng; lambda { return }.call; $x = :ok }.call + end + def12 + $x +}, '[ruby-core:17164]' diff --git a/vm.c b/vm.c index bb1ba4cb59..83b6ea9bd4 100644 --- a/vm.c +++ b/vm.c @@ -525,9 +525,9 @@ vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, if (state == TAG_RETURN && proc->is_lambda) { VALUE err = th->errinfo; VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err); - VALUE *cdfp = proc->block.dfp; - if (escape_dfp == cdfp) { + if (escape_dfp == cfp->dfp) { + printf("ok\n"); state = 0; th->errinfo = Qnil; th->cfp = cfp; diff --git a/vm_insnhelper.c b/vm_insnhelper.c index cf3bd07220..864801be97 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1044,7 +1044,8 @@ vm_get_cvar_base(NODE *cref) { VALUE klass; - while (cref && cref->nd_next && (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) { + while (cref && cref->nd_next && + (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) { cref = cref->nd_next; if (!cref->nd_next) { @@ -1221,7 +1222,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, if (cfp->dfp == dfp) { goto search_parent; } - cfp++; + cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } rb_bug("VM (throw): can't find break base."); } @@ -1229,7 +1230,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) { /* lambda{... break ...} */ is_orphan = 0; - pt = GET_LFP(); + pt = cfp->dfp; state = TAG_RETURN; } else { @@ -1261,7 +1262,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, is_orphan = 0; break; } - cfp++; + cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } } @@ -1284,26 +1285,29 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, * check orphan: */ while ((VALUE *) cfp < th->stack + th->stack_size) { - if (GET_DFP() == dfp) { + if (dfp == cfp->dfp) { if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) { /* in lambda */ is_orphan = 0; break; } + + if (GET_LFP() == dfp && cfp->iseq->type == ISEQ_TYPE_METHOD) { + is_orphan = 0; + break; + } + + dfp = GC_GUARDED_PTR_REF(dfp[0]); } - if (GET_LFP() == cfp->lfp && - cfp->iseq->type == ISEQ_TYPE_METHOD) { - is_orphan = 0; - break; - } - cfp++; + + cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } if (is_orphan) { vm_localjump_error("unexpected return", throwobj, TAG_RETURN); } - pt = GET_LFP(); + pt = dfp; } else { rb_bug("isns(throw): unsupport throw type"); -- cgit v1.2.3