-
Notifications
You must be signed in to change notification settings - Fork 5.3k
[Wasm RyuJit] throw helper / null check preliminaries #123053
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
base: main
Are you sure you want to change the base?
Conversation
On Wasm null checks must be explicit and exceptions raised via helper call. Set up some of the mechanism we'll need for this: * Add null check special code kind * Track Wasm ACD entries by handler region only (instead of by try or handler). The code address of the helper cannot be used in Wasm to infer EH region containment; we will use use the virtual IP for that. So we need at most one throw helper (per kind) in each funclet and in the main method region. * Ensure throw helper blocks have Wasm labels that are always on the stack in their regions by putting the throw helpers at the end of the region RPO and pretending there is a branch from the region entry. * Add plausible codegen for GT_NULLCHECK
|
FYI @dotnet/jit-contrib (still WIP, need to see how much of this is testable) See #123021 (comment) for some context. |
|
I don't have the code to make |
SingleAccretion
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have the code to make SCK_NULLCHECK demands in place yet. Seeing as nullchecks get generated in many places it seems less than ideal to track all these sites all down and add code to each one. I wonder if we can just do this in lower or similar.
+1. In fact I don't see the point of this two-phase setup that exists. Why not add all the blocks late (in stack setter or lower) and remove the handling from morph?
| bool Compiler::fgUseThrowHelperBlocks() | ||
| { | ||
| #if defined(TARGET_WASM) | ||
| return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a strong reason to make WASM special here. Unique "native" code addresses still matter for "native" stacks produced by engines. It is helpful to make them (more) useful with debug code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose it is not so hard -- if we have say GT_NULLCHECK(x) we can produce
block
local.get x
i32.const null-limit-value
i32.gt
br_if 0
call <helper-idx> ; THROW NULL CHECK
unreachable ;
end
and this will properly nest wherever we happen to emit it, even if we've pended other operands already. The main difference being we need to know a bit earlier if there's a common helper block we can use.
src/coreclr/jit/codegenwasm.cpp
Outdated
| { | ||
| assert(compiler->fgUseThrowHelperBlocks()); | ||
| genConsumeOperand(tree->Addr()); | ||
| GetEmitter()->Ins(INS_i32_eqz); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ref #123053 (comment) for what value this should check against.
src/coreclr/jit/codegenwasm.cpp
Outdated
| void CodeGen::genCodeForNullCheck(GenTreeIndir* tree) | ||
| { | ||
| assert(compiler->fgUseThrowHelperBlocks()); | ||
| genConsumeOperand(tree->Addr()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| genConsumeOperand(tree->Addr()); | |
| genConsumeAddress(tree->Addr()); |
| // For WASM we want one throw helper per funclet | ||
| // So we ignore any try region nesting. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would also be hardcoding the "one catch per funclet (with nested trys)" scheme, right? Otherwise we still need the nesting for proper resumption.
Apart from that, the comment could be improved to talk about "why" we want this.
I think this is just a long-standing practice that we've never reexamined. Perhaps it is time. |
|
Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara |
On Wasm null checks must be explicit and exceptions raised via helper call.
Set up some of the mechanism we'll need for this: