summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-06-19 02:46:02 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-06-19 02:46:02 +0000
commitc3e619c83dcd3223cb6d17d5a1884039b5d0cc4f (patch)
tree23b44f107b689200bd77efb32606455f56e65529 /vm_insnhelper.c
parent33e5cfee7b90ec800e4546c6a0c0a73c2a66d73c (diff)
* vm_insnhelper.c (vm_throw): fix "return" process from "lambda".
* bootstraptest/test_proc.rb: add a test. * bootstraptest/pending.rb: add a pending bug. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17421 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c34
1 files changed, 18 insertions, 16 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 864801be97..bdccfd1ca1 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1279,34 +1279,36 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
else if (state == TAG_RETURN) {
rb_control_frame_t *cfp = GET_CFP();
VALUE *dfp = GET_DFP();
- int is_orphan = 1;
+ VALUE * const lfp = GET_LFP();
- /**
- * check orphan:
- */
+ /* check orphan and get dfp */
while ((VALUE *) cfp < th->stack + th->stack_size) {
- if (dfp == cfp->dfp) {
+ if (cfp->lfp == lfp) {
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
- /* in lambda */
- is_orphan = 0;
- break;
- }
+ VALUE *tdfp = dfp;
- if (GET_LFP() == dfp && cfp->iseq->type == ISEQ_TYPE_METHOD) {
- is_orphan = 0;
- break;
+ while (lfp != tdfp) {
+ if (cfp->dfp == tdfp) {
+ /* in lambda */
+ dfp = cfp->dfp;
+ goto valid_return;
+ }
+ tdfp = GC_GUARDED_PTR_REF((VALUE *)*dfp);
+ }
}
+ }
- dfp = GC_GUARDED_PTR_REF(dfp[0]);
+ if (cfp->dfp == lfp && cfp->iseq->type == ISEQ_TYPE_METHOD) {
+ dfp = lfp;
+ goto valid_return;
}
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
- if (is_orphan) {
- vm_localjump_error("unexpected return", throwobj, TAG_RETURN);
- }
+ vm_localjump_error("unexpected return", throwobj, TAG_RETURN);
+ valid_return:
pt = dfp;
}
else {