Skip to content

Consider changing BBJ_CALLFINALLY/BBJ_ALWAYS representation of call to finally #95355

Closed
@BruceForstall

Description

@BruceForstall

A non-exceptional call to an EH finally clause is represented in RyuJIT by two basic blocks:

  1. a BBJ_CALLFINALLY, whose block target is the finally clause being called
  2. an immediately following BBJ_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 the BBF_KEEP_BBJ_ALWAYS flag. If the JIT can prove that the finally doesn't return (e.g., it always executes a throw), this block won't exist, and the BBJ_CALLFINALLY will have the BBF_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 the BBJ_CALLFINALLY which call it. The finally clause ends with a BBJ_EHFINALLYRET block. Its successors are all the BBJ_ALWAYS blocks paired with BBJ_CALLFINALLY blocks which call that finally. The BBJ_ALWAYS block predecessor is the single BBJ_EHFINALLYRET of the finally clause called by the paired BBJ_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 the BBJ_CALLFINALLY block. Call this bbFinallyContinuation.

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 both BBJ_EHFINALLYRET and non-finally predecessors.

"Retless" BBJ_CALLFINALLY might no longer need the BBF_RETLESS_CALL flag: a null bbFinallyContinuation would be sufficient.

This adds an additional BasicBlock* to the BasicBlock 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 additional BasicBlock* for BBJ_COND "false" (branch not taken) flow, in which case the BBJ_CALLFINALLY can reuse this additional field.

@dotnet/jit-contrib

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions