Skip to content

Conversation

@XrXr
Copy link
Member

@XrXr XrXr commented Jul 8, 2021

Rework tracing for blocks running as methods

The main impetus for this change is to fix [Bug #13392]. Previously, we
fired the "return" TracePoint event after popping the stack frame for
the block running as method (BMETHOD). This gave undesirable source
location outputs as the return event normally fires right before the
frame going away.

The iseq for each block can run both as a block and as a method. To
accommodate that, this commit makes vm_trace() fire call/return events for
instructions that have b_call/b_return events attached when the iseq is
running as a BMETHOD. The logic for rewriting to "trace_*" instruction
is tweaked so that when the user listens to call/return events,
instructions with b_call/b_return become trace variants.

To continue to provide the return value for non-local returns done using
the "return" or "break" keyword inside BMETHODs, the stack unwinding
code is tweaked. b_return events now provide the same return value as
return events for these non-local cases. A pre-existing test deemed not
providing a return value for these b_return events as a limitation.

This commit removes the checks for call/return TracePoint events that
happen when calling into BMETHODs when no TracePoints are active.
Technically, migrating just the return event is enough to fix the bug,
but migrating both call and return removes our reliance on
VM_FRAME_FLAG_FINISH and re-entering the interpreter when the caller
is already in the interpreter.

@XrXr
Copy link
Member Author

XrXr commented Jul 8, 2021

Side note, out of scope for this PR and for fixing the bug, but I did a crude proof of concept for staying in the interpreter (not using VM_FRAME_FLAG_FINISH) and it seems to give a good perf boost:
change: XrXr@9c83b54
benchmark result: XrXr@857d8c3

@XrXr XrXr force-pushed the bmethod-tracing branch from e3c9a7f to b192b7c Compare July 13, 2021 23:11
@XrXr
Copy link
Member Author

XrXr commented Jul 13, 2021

Okay, just pushed V2. I worked through some details about non-local returns and targeting TracePoints.


define_method(:f_break_defined) do
return :f_break_defined
break :f_break_defined
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed this because it was the same as the method above.

@jeremyevans
Copy link
Contributor

@ko1 Could you review this PR and #4588 and decide which approach you would prefer to use?

@XrXr
Copy link
Member Author

XrXr commented Nov 9, 2021

@ko1 review ping. If we want to go with this PR I can try to get it done before release.

@XrXr XrXr requested a review from ko1 November 27, 2021 17:07
Copy link
Contributor

@ko1 ko1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for late.

I spend some days to make my patch but it was failed.
I also have some opinion, but we can modify later, so please merge it.

The main impetus for this change is to fix [Bug ruby#13392]. Previously, we
fired the "return" TracePoint event after popping the stack frame for
the block running as method (BMETHOD). This gave undesirable source
location outputs as the return event normally fires right before the
frame going away.

The iseq for each block can run both as a block and as a method. To
accommodate that, this commit makes vm_trace() fire call/return events for
instructions that have b_call/b_return events attached when the iseq is
running as a BMETHOD. The logic for rewriting to "trace_*" instruction
is tweaked so that when the user listens to call/return events,
instructions with b_call/b_return become trace variants.

To continue to provide the return value for non-local returns done using
the "return" or "break" keyword inside BMETHODs, the stack unwinding
code is tweaked. b_return events now provide the same return value as
return events for these non-local cases. A pre-existing test deemed not
providing a return value for these b_return events as a limitation.

This commit removes the checks for call/return TracePoint events that
happen when calling into BMETHODs when no TracePoints are active.
Technically, migrating just the return event is enough to fix the bug,
but migrating both call and return removes our reliance on
`VM_FRAME_FLAG_FINISH` and re-entering the interpreter when the caller
is already in the interpreter.
@XrXr XrXr merged commit 9121e57 into ruby:master Dec 1, 2021
@XrXr XrXr deleted the bmethod-tracing branch December 1, 2021 22:42
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.

3 participants