Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix returning from LEAVE to surrounding scope #1785

Merged
merged 1 commit into from
Jul 6, 2024

Conversation

patrickbkr
Copy link
Member

When a LEAVE phaser is run during an unwind, there is no valid return_address set in the LEAVE phasers caller frame. (It return_address is actually set to cur_op which is still the one that started the unwind in some unrelated frame.) Thus when a return in a LEAVE happens, the handler of the outer frame is missed, because search_frame_handlers_lex() validates that the return_address lies in the handlers area. Luckily there is a flag set on the LEAVE's outer frame:
MVM_FRAME_FLAG_EXIT_HAND_RUN. We can simply check for that flag and ignore the frame handlers area. This is fine to do, because frames that have an exit handler attached can not be inlined. This fixes:

sub s() {
    LEAVE return 5;
    return 7;
}
s()

which before this fix printed

Attempt to return outside of any Routine
in sub s at leave-bug.raku line 2
in block at leave-bug.raku line 5

Fixes #1784

patrickbkr pushed a commit to patrickbkr/roast that referenced this pull request Jan 27, 2024
@patrickbkr
Copy link
Member Author

I believe this works reliably. So I guess it's ready for review.

@patrickbkr patrickbkr marked this pull request as ready for review January 27, 2024 17:37
@patrickbkr
Copy link
Member Author

The general question of what return in LEAVE should do is explored over in Raku/problem-solving#417.

Technically this PR is unreladed to that issue. Can this PR thus be merged?

Again, who's best to ping? @MasterDuke17 @niner

patrickbkr pushed a commit to patrickbkr/roast that referenced this pull request May 21, 2024
src/core/exceptions.c Outdated Show resolved Hide resolved
When a LEAVE phaser is run during an unwind, there is no valid
return_address set in the LEAVE phasers outer frame. (It's return_address is
actually set to interp_cur_op which is still the one that started the unwind
in some unrelated frame.) Thus when a `return` in a LEAVE happens, the
handler of the outer frame is missed, because `search_frame_handlers_lex()`
validates that the `return_address` lies in the handlers area. Luckily
there is a flag set on the LEAVE's outer frame:
MVM_FRAME_FLAG_EXIT_HAND_RUN. We can simply check for that flag and ignore
the frame handlers area. This is fine to do, because frames that have an
exit handler attached can not be inlined. This fixes:

    sub s() {
        LEAVE return 5;
        return 7;
    }
    s()

which before this fix printed

    Attempt to return outside of any Routine
    in sub s at leave-bug.raku line 2
    in block at leave-bug.raku line 5

Fixes MoarVM#1784
@patrickbkr patrickbkr force-pushed the leave-return-handler-miss-fix branch from 03f2ea8 to 2c866ae Compare May 28, 2024 21:01
patrickbkr pushed a commit to patrickbkr/roast that referenced this pull request May 28, 2024
@patrickbkr patrickbkr merged commit 08848c7 into MoarVM:main Jul 6, 2024
20 of 24 checks passed
@patrickbkr patrickbkr deleted the leave-return-handler-miss-fix branch July 6, 2024 11:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

return in LEAVE misses handler in directly surounding scope
2 participants