winch: catch exceptions - #14180
Conversation
Subscribe to Label ActionDetailsThis issue or pull request has been labeled: "cranelift", "winch"Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
cfallin
left a comment
There was a problem hiding this comment.
Thanks -- this looks pretty much OK to me (and the handler stack with checkpoints appears to be using the same approach that we have in the Wasm-to-CLIF translator, which is good). A few questions around the libcalls/barriers and register management below. It might also be good to get a second pair of eyes (@saulecabrera maybe?) to ensure that all of that is done properly.
| for (field_ty, field_offset) in fields { | ||
| let field_base = match object_addr { | ||
| Some(reg) => reg, | ||
| None => { |
There was a problem hiding this comment.
It seems that we have logic to re-compute object_addr (field_base) every iteration if invalidated. A few thoughts:
- Do we need to initialize
object_addrabove (line 178) if we're going to lazily recompute it ifNonein each iteration? In other words wouldNoneas an initializer work? - Zooming out, why are we recomputing it? It seems that below we set it to
Nonewhen a call (DRC barrier) clobbers registers, but we save the other registers; why do we need to re-deriveobject_addrfrom scratch? Does the read barrier have the option to relocate the heap or similar? - All of these manual register save/restore sequences make me a little squeamish. Do we not have an abstraction to save active registers and restore them around calls?
There was a problem hiding this comment.
Thanks for pointing this out. On revisiting it, I realized the recomputation was there because the barrier was responsible for freeing the storage_base register. I changed the barrier to operate on an already-loaded GC reference, leaving responsibility for freeing the storage_base with the caller. This lets the exception path preserve the already-computed object_addr rather than recomputing it.
I'm not aware of a mechanism available other than the value stack for managing the registers, but these changes simplify the sequence by preserving the already-computed object_addr instead of preserving exception_reg and later reloading the heap metadata to reconstruct the address. If @saulecabrera has any thoughts about some potential helpers that could assist, I'm open to suggestions. Otherwise, the simplified barrier contract may be sufficient.
I will take a look; thanks! |
11521d7 to
1c6f09c
Compare
Adds support for catching exceptions in Winch.
Winch tracks exception handlers in scope, records them in call-site metadata, and emits landing pads when a
try_tableends. When Wasmtime’s unwinder selects a handler, its landing pad restores the expected stack state andVMContext.Support for
catch_refandcatch_all_refis not yet implemented and will be added in follow-up work