-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Consider changing BBJ_CALLFINALLY/BBJ_ALWAYS representation of call to finally #95355
Comments
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue DetailsA non-exceptional call to an EH
The flow graph is constructed as follows. The single successor of Having these two blocks, paired, leads to a lot of special case code in the JIT, including checking for ProposalConsider removing the paired In the flow graph, the successor of the "Retless" This adds an additional @dotnet/jit-contrib
|
While this proposal will eliminate the BBJ_CALLFINALLY/BBJ_ALWAYS pairing, it introduces new problems for flow graph maintenance, as follows:
|
In light of the above problems, I'm planning to abandon this proposal. Instead, I propose a much more incremental change that should help reduce the confusion around the ALWAYS block of the CALLFINALLY/ALWAYS pair: Proposal 2Currently, we have BBJ_CALLFINALLY/BBJ_ALWAYS pairs. Create a new block kind, call it BBJ_CALLFINALLYRET, and use it instead of BBJ_ALWAYS in these pairs. Thus, we would have BBJ_CALLFINALLY/BBJ_CALLFINALLYRET pairs. The RET stands for "return", as in, "this block targets where the finally block should return, aka, the continuation". With this change, BBJ_ALWAYS semantics would not be muddied by its use in BBJ_CALLFINALLY/BBJ_ALWAYS pairs. Asserts and checks should be easier. E.g., we would have:
We could get rid of The block table dump would be slightly more explicit/clearer. This proposal doesn't introduce any new capability that couldn't be done with the current flowgraph, but it makes these special BBJ_ALWAYS blocks more explicit and separates them from "normal" uses. |
This is a partial implementation of the original proposal in dotnet#95355 It has run up against difficult-to-solve issues, and has been abandoned.
I'm going to consider this "done" with #95945 |
Actually, I want to keep this open until |
This is complete with #96159 |
A non-exceptional call to an EH
finally
clause is represented in RyuJIT by two basic blocks:BBJ_CALLFINALLY
, whose block target is the finally clause being calledBBJ_ALWAYS
which represents the block to which the finally clause should return (also called the "continuation" or "finally continuation"). This block must be empty (of code). It is marked with theBBF_KEEP_BBJ_ALWAYS
flag. If the JIT can prove that the finally doesn't return (e.g., it always executes athrow
), this block won't exist, and theBBJ_CALLFINALLY
will have theBBF_RETLESS_CALL
flag.The flow graph is constructed as follows. The single successor of
BBJ_CALLFINALLY
is its finally clause target. The predecessors of a finally clause entry are all theBBJ_CALLFINALLY
which call it. The finally clause ends with aBBJ_EHFINALLYRET
block. Its successors are all the BBJ_ALWAYS blocks paired withBBJ_CALLFINALLY
blocks which call that finally. TheBBJ_ALWAYS
block predecessor is the single BBJ_EHFINALLYRET of the finally clause called by the pairedBBJ_CALLFINALLY
.Having these two blocks, paired, leads to a lot of special case code in the JIT, including checking for
isBBCallAlwaysPair
,isBBCallAlwaysPairTail
, etc.Proposal
Consider removing the paired
BBJ_ALWAYS
block and adding the continuation target as an additional field of theBBJ_CALLFINALLY
block. Call thisbbFinallyContinuation
.In the flow graph, the successor of the
BBJ_EHFINALLYRET
would no longer by the BBJ_ALWAYS; it would be all the finally continuation blocks. The finally continuation block predecessors would include bothBBJ_EHFINALLYRET
and non-finally predecessors."Retless"
BBJ_CALLFINALLY
might no longer need theBBF_RETLESS_CALL
flag: a nullbbFinallyContinuation
would be sufficient.This adds an additional
BasicBlock*
to theBasicBlock
type that will not be used by most blocks. It's possible that the elimination of bbNext as "fall through" flow will lead to introducing an additionalBasicBlock*
forBBJ_COND
"false" (branch not taken) flow, in which case theBBJ_CALLFINALLY
can reuse this additional field.@dotnet/jit-contrib
The text was updated successfully, but these errors were encountered: