summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-06-17 19:27:24 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-06-17 19:27:24 +0000
commit00e4fd42f36fa23de04cccb9cea3c3e5d14c9ae9 (patch)
tree0012d083c6af5721147cdd7ed7d21d260f38b811 /vm_insnhelper.c
parente2f37fb9c6c9df54b2be78d09de00aa7da0d694f (diff)
* 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
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c28
1 files changed, 16 insertions, 12 deletions
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");