Make backtrace creation more accurate to support GC #268
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
When creating a backtrace while running some continuation
c
with parentp
(another continuation or the main stack), the following happens at the moment:After traversing the stack frames of
c
, we need to traverse the stack frames ofp
. To this end, we look at theStackLimits
object ofp
.The
last_wasm_exit_{fp, pc}
fields therein tell us the frame pointer and program counter at the point where we stopped execution inp
. This must have been at aresume
Wasm instruction that resumedc
. This FP and PC allows us to travese the stack frames ofp
.Note that the fields in
StackLimits
are updated by the various stack switching instructions. Thelast_wasm_exit_{fp,pc}
fields are only ever used for creating backtraces, they do not influence control flow at all.Since #223, the
last_wasm_exit_pc
field inStackLimits
is set onresume
by using the CLIF instructionget_instruction_pointer
, which I introduced specifically for that use case. This CLIF instruction will give us a PC value that will be associated with the Wasmresume
instruction under consideration. This ensures that the backtraces we create mention the right Wasm instructions.That's good enough for our current use case, where backtraces are used mostly to show where things went wrong on a trap. However, in the future, when we want to support GC, we also need to use backtraces to obtain stack maps, do identify live objects on continuation stacks. At that point, the current approach becomes too coarse: Currently, the
last_wasm_exit_pc
value we create is associated with the right Wasm instruction (namely, aresume
), but with the wrong CLIF instruction: The PC saved inlast_wasm_exit_pc
will be associated with theget_instruction_pointer
CLIF instruction that created it. However, logically, it must be associated with thestack_switch
CLIF instruction where execution actually switched fromp
toc
, and where it would subsequently continue if we were to switch back to the parentp
. Only thestack_switch
instruction will have the most recent/correct stack map describing where live values are located in the stack frame that executedresume
.This PR rectifies this situation as follows: Instead of maintaining the fields
last_wasm_exit_{fp, pc}
inStackLimits
, we now load the required PC and FP values directly from the control context of the corresponding Fiber (i.e., the memory area that saves PC, SP, FP used to actually switch stacks). In other words, to create backtraces, we get the necessary information about where execution continues in the parent stack directly from the source of truth (i.e., the control context), rather than duplicating this information inStackLimits
just for backtrace creation.Thus, the fields
last_wasm_exit_{fp, pc}
are removed fromStackLimits
and no longer need to be updated onresume
. Further, theget_instruction_pointer
CLIF instruction, and correspondingGetRip
x64MInst
, which I introduced in #223, are removed.