Skip to content
Merged
2 changes: 1 addition & 1 deletion src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1623,7 +1623,7 @@ void CodeGen::genExitCode(BasicBlock* block)
// genJumpToThrowHlpBlk: Generate code for an out-of-line exception.
//
// Notes:
// For code that uses throw helper blocks, we share the helper blocks created by fgAddCodeRef().
// For code that uses throw helper blocks, we share the helper blocks.
// Otherwise, we generate the 'throw' inline.
//
// Arguments:
Expand Down
4 changes: 0 additions & 4 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4898,10 +4898,6 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
// Insert GC Polls
DoPhase(this, PHASE_INSERT_GC_POLLS, &Compiler::fgInsertGCPolls);

// Create any throw helper blocks that might be needed
//
DoPhase(this, PHASE_CREATE_THROW_HELPERS, &Compiler::fgCreateThrowHelperBlocks);

if (opts.OptimizationEnabled())
{
// Conditional to switch conversion, and switch peeling
Expand Down
11 changes: 5 additions & 6 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -6774,7 +6774,7 @@ class Compiler

struct AddCodeDsc
{
// After fgCreateThrowHelperBlocks, the block to which
// The block to which
// we jump to raise the exception.
BasicBlock* acdDstBlk;

Expand Down Expand Up @@ -6838,16 +6838,15 @@ class Compiler
private:
static unsigned acdHelper(SpecialCodeKind codeKind);

bool fgRngChkThrowAdded = false;
AddCodeDscMap* fgAddCodeDscMap = nullptr;

void fgAddCodeRef(BasicBlock* srcBlk, SpecialCodeKind kind);
PhaseStatus fgCreateThrowHelperBlocks();
AddCodeDsc* fgCreateAddCodeDsc(BasicBlock* fromBlock, SpecialCodeKind kind);
void fgCreateThrowHelperBlock(AddCodeDsc* add);

public:

bool fgRngChkThrowAdded = false;
bool fgHasAddCodeDscMap() const { return fgAddCodeDscMap != nullptr; }
AddCodeDsc* fgFindExcptnTarget(SpecialCodeKind kind, BasicBlock* fromBlock);
AddCodeDsc* fgFindExcptnTarget(SpecialCodeKind kind, BasicBlock* fromBlock, bool createIfNeeded = false);
bool fgUseThrowHelperBlocks();
void fgCreateThrowHelperBlockCode(AddCodeDsc* add);
void fgSequenceLocals(Statement* stmt);
Expand Down
218 changes: 94 additions & 124 deletions src/coreclr/jit/flowgraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3384,7 +3384,7 @@ Compiler::AddCodeDscMap* Compiler::fgGetAddCodeDscMap()
}

//------------------------------------------------------------------------
// fgAddCodeRef: Indicate that a particular throw helper block will
// fgCreateAddCodeDsc: Indicate that a particular throw helper block will
// be needed by the method.
//
// Arguments:
Expand All @@ -3395,42 +3395,18 @@ Compiler::AddCodeDscMap* Compiler::fgGetAddCodeDscMap()
// You can call this method after throw helpers have been created,
// but it will assert if this entails creation of a new helper.
//
void Compiler::fgAddCodeRef(BasicBlock* srcBlk, SpecialCodeKind kind)
Compiler::AddCodeDsc* Compiler::fgCreateAddCodeDsc(BasicBlock* srcBlk, SpecialCodeKind kind)
Comment thread
AndyAyersMS marked this conversation as resolved.
{
// Record that the code will call a THROW_HELPER
// so on Windows Amd64 we can allocate the 4 outgoing
// arg slots on the stack frame if there are no other calls.
//
compUsesThrowHelper = true;

if (!fgUseThrowHelperBlocks() && (kind != SCK_FAIL_FAST))
{
// FailFast will still use a common throw helper, even in debuggable modes.
//
return;
}
assert(!fgRngChkThrowAdded);

// Fetch block data and designator
//
AcdKeyDesignator dsg = AcdKeyDesignator::KD_NONE;
unsigned const refData = (kind == SCK_FAIL_FAST) ? 0 : bbThrowIndex(srcBlk, &dsg);

// Look for an existing entry that matches what we're looking for
//
AddCodeDsc* add = fgFindExcptnTarget(kind, srcBlk);

if (add != nullptr)
{
JITDUMP(FMT_BB " requires throw helper block for %s, sharing ACD%u (data 0x%08x)\n", srcBlk->bbNum,
sckName(kind), add->acdNum, refData);
return;
}

assert(!fgRngChkThrowAdded);

// Allocate a new entry and prepend it to the list
Comment thread
AndyAyersMS marked this conversation as resolved.
Outdated
//
add = new (this, CMK_Unknown) AddCodeDsc;
AddCodeDsc* add = new (this, CMK_BasicBlock) AddCodeDsc;
add->acdDstBlk = nullptr;
Comment thread
AndyAyersMS marked this conversation as resolved.
add->acdTryIndex = srcBlk->bbTryIndex;

Expand Down Expand Up @@ -3467,25 +3443,26 @@ void Compiler::fgAddCodeRef(BasicBlock* srcBlk, SpecialCodeKind kind)
assert(map->Lookup(key2, &add2));
assert(add == add2);
#endif

return add;
}

//------------------------------------------------------------------------
// fgCreateThrowHelperBlocks: create the needed throw helpers
// fgCreateThrowHelperBlock: create a throw helper block
//
// Returns:
// Suitable phase status
// Arguments:
// add -- addCodeDesc describing the block to create
//
// Notes:
// Creates a new block if necessary, and sets the add->acdDstBlk to the new block.
//
PhaseStatus Compiler::fgCreateThrowHelperBlocks()
void Compiler::fgCreateThrowHelperBlock(AddCodeDsc* add)
{
if (fgAddCodeDscMap == nullptr)
if (add->acdDstBlk != nullptr)
{
return PhaseStatus::MODIFIED_NOTHING;
return;
}

// We should not have added throw helper blocks yet.
//
assert(!fgRngChkThrowAdded);

const static BBKinds jumpKinds[] = {
BBJ_ALWAYS, // SCK_NONE
BBJ_THROW, // SCK_RNGCHK_FAIL
Expand All @@ -3499,89 +3476,82 @@ PhaseStatus Compiler::fgCreateThrowHelperBlocks()

noway_assert(sizeof(jumpKinds) == SCK_COUNT); // sanity check

for (AddCodeDsc* const add : AddCodeDscMap::ValueIteration(fgAddCodeDscMap))
{
// Create the target basic block in the region indicated by the acd info
//
assert(add->acdKind != SCK_NONE);
bool const putInFilter = (add->acdKeyDsg == AcdKeyDesignator::KD_FLT);
BasicBlock* const newBlk = fgNewBBinRegion(jumpKinds[add->acdKind], add->acdTryIndex, add->acdHndIndex,
/* nearBlk */ nullptr, putInFilter,
/* runRarely */ true, /* insertAtEnd */ true);
// Create the target basic block in the region indicated by the acd info
//
assert(add->acdKind != SCK_NONE);
bool const putInFilter = (add->acdKeyDsg == AcdKeyDesignator::KD_FLT);
BasicBlock* const newBlk = fgNewBBinRegion(jumpKinds[add->acdKind], add->acdTryIndex, add->acdHndIndex,
/* nearBlk */ nullptr, putInFilter,
/* runRarely */ true, /* insertAtEnd */ true);

// Update the descriptor so future lookups can find the block
//
add->acdDstBlk = newBlk;
// Update the descriptor so future lookups can find the block
//
add->acdDstBlk = newBlk;

#ifdef DEBUG
if (verbose)
if (verbose)
{
const char* msgWhere = "";
switch (add->acdKeyDsg)
{
const char* msgWhere = "";
switch (add->acdKeyDsg)
{
case AcdKeyDesignator::KD_NONE:
msgWhere = "non-EH region";
break;

case AcdKeyDesignator::KD_HND:
msgWhere = "handler";
break;
case AcdKeyDesignator::KD_NONE:
msgWhere = "non-EH region";
break;

case AcdKeyDesignator::KD_TRY:
msgWhere = "try";
break;
case AcdKeyDesignator::KD_HND:
msgWhere = "handler";
break;

case AcdKeyDesignator::KD_FLT:
msgWhere = "filter";
break;
case AcdKeyDesignator::KD_TRY:
msgWhere = "try";
break;

default:
msgWhere = "? unexpected";
}
case AcdKeyDesignator::KD_FLT:
msgWhere = "filter";
break;

const char* msg;
switch (add->acdKind)
{
case SCK_RNGCHK_FAIL:
msg = " for RNGCHK_FAIL";
break;
case SCK_DIV_BY_ZERO:
msg = " for DIV_BY_ZERO";
break;
case SCK_OVERFLOW:
msg = " for OVERFLOW";
break;
case SCK_ARG_EXCPN:
msg = " for ARG_EXCPN";
break;
case SCK_ARG_RNG_EXCPN:
msg = " for ARG_RNG_EXCPN";
break;
case SCK_FAIL_FAST:
msg = " for FAIL_FAST";
break;
case SCK_NULL_CHECK:
msg = " for NULL_CHECK";
break;
default:
msg = " for ??";
break;
}
default:
msgWhere = "? unexpected";
}

printf("\nAdding throw helper " FMT_BB " for ACD%u %s in %s%s\n", newBlk->bbNum, add->acdNum,
sckName(add->acdKind), msgWhere, msg);
const char* msg;
switch (add->acdKind)
{
case SCK_RNGCHK_FAIL:
msg = " for RNGCHK_FAIL";
break;
case SCK_DIV_BY_ZERO:
msg = " for DIV_BY_ZERO";
break;
case SCK_OVERFLOW:
msg = " for OVERFLOW";
break;
case SCK_ARG_EXCPN:
msg = " for ARG_EXCPN";
break;
case SCK_ARG_RNG_EXCPN:
msg = " for ARG_RNG_EXCPN";
break;
case SCK_FAIL_FAST:
msg = " for FAIL_FAST";
break;
case SCK_NULL_CHECK:
msg = " for NULL_CHECK";
break;
default:
msg = " for ??";
break;
}
#endif // DEBUG

// Mark the block as added by the compiler and not removable by future flow
// graph optimizations. Note that no target block points to these blocks.
//
newBlk->SetFlags(BBF_IMPORTED | BBF_DONT_REMOVE);
printf("\nAdding throw helper " FMT_BB " for ACD%u %s in %s%s\n", newBlk->bbNum, add->acdNum,
sckName(add->acdKind), msgWhere, msg);
}
#endif // DEBUG

fgRngChkThrowAdded = true;

return PhaseStatus::MODIFIED_EVERYTHING;
// Mark the block as added by the compiler and not removable by future flow
// graph optimizations. Note that no target block points to these blocks.
//
newBlk->SetFlags(BBF_IMPORTED | BBF_DONT_REMOVE);
}

//------------------------------------------------------------------------
Expand Down Expand Up @@ -3627,6 +3597,10 @@ void Compiler::fgCreateThrowHelperBlockCode(AddCodeDsc* add)
helper = CORINFO_HELP_FAIL_FAST;
break;

case SCK_NULL_CHECK:
helper = CORINFO_HELP_THROWNULLREF;
break;

default:
noway_assert(!"unexpected code addition kind");
}
Expand All @@ -3637,7 +3611,9 @@ void Compiler::fgCreateThrowHelperBlockCode(AddCodeDsc* add)
//
GenTreeCall* tree = gtNewHelperCallNode(helper, TYP_VOID);

// There are no args here but fgMorphArgs has side effects
// For Wasm we may add an arg to the throw helper.
//
// Also fgMorphArgs has side effects
// such as setting the outgoing arg area (which is necessary
// on AMD if there are any calls).
//
Expand All @@ -3651,8 +3627,8 @@ void Compiler::fgCreateThrowHelperBlockCode(AddCodeDsc* add)
}
else
{
LIR::AsRange(block).InsertAtEnd(tree);
LIR::ReadOnlyRange range(tree, tree);
LIR::Range range = LIR::SeqTree(this, tree);
LIR::AsRange(block).InsertAtEnd(std::move(range));
m_pLowering->LowerRange(block, range);
Comment thread
AndyAyersMS marked this conversation as resolved.
Outdated
}
}
Expand All @@ -3668,7 +3644,7 @@ void Compiler::fgCreateThrowHelperBlockCode(AddCodeDsc* add)
// Code descriptor for the appropriate throw helper block, or nullptr if no such
// descriptor exists.
//
Compiler::AddCodeDsc* Compiler::fgFindExcptnTarget(SpecialCodeKind kind, BasicBlock* fromBlock)
Compiler::AddCodeDsc* Compiler::fgFindExcptnTarget(SpecialCodeKind kind, BasicBlock* fromBlock, bool createIfNeeded)
Comment thread
AndyAyersMS marked this conversation as resolved.
Outdated
{
assert(fgUseThrowHelperBlocks() || (kind == SCK_FAIL_FAST));
AddCodeDsc* add = nullptr;
Expand All @@ -3678,20 +3654,14 @@ Compiler::AddCodeDsc* Compiler::fgFindExcptnTarget(SpecialCodeKind kind, BasicBl

if (add == nullptr)
{
// We shouldn't be asking for these blocks late in compilation
// unless we know there are entries to be found.
if (fgRngChkThrowAdded)
{
JITDUMP(FMT_BB ": unexpected request for new throw helper: kind %d (%s), data 0x%08x\n", fromBlock->bbNum,
kind, sckName(kind), key.Data());
add = fgCreateAddCodeDsc(fromBlock, kind);

Comment thread
AndyAyersMS marked this conversation as resolved.
if (kind == SCK_NULL_CHECK)
{
NYI_WASM("Missing null check demand");
}
// Create the block...
//
if (createIfNeeded)
{
fgCreateThrowHelperBlock(add);
Comment thread
AndyAyersMS marked this conversation as resolved.
}

assert(!fgRngChkThrowAdded);
}

return add;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12115,7 +12115,7 @@ void Lowering::FinalizeOutgoingArgSpace()
// Finish computing the outgoing args area size
//
// Need to make sure the MIN_ARG_AREA_FOR_CALL space is added to the frame if:
// 1. there are calls to THROW_HELPER methods.
// 1. there may be calls to THROW_HELPER methods.
// 2. we are generating profiling Enter/Leave/TailCall hooks. This will ensure
// that even methods without any calls will have outgoing arg area space allocated.
// 3. We will be generating calls to PInvoke helpers. TODO: This shouldn't be required because
Expand Down
Loading
Loading