DONE:
+#if defined(JIT32_GCENCODER)
// If we are inserting into a filter and the best block is the end of the filter region, we need to
- // insert after its predecessor instead: the CLR ABI states that the terminal block of a filter region
- // is its exit block. If the filter region consists of a single block, a new block cannot be inserted
- // without either splitting the single block before inserting a new block or inserting the new block
- // before the single block and updating the filter description such that the inserted block is marked
- // as the entry block for the filter. This work must be done by the caller; this function returns
- // `nullptr` to indicate this case.
- if (insertingIntoFilter && (bestBlk == endBlk->bbPrev) && (bestBlk == startBlk))
+ // insert after its predecessor instead: the JIT32 GC encoding used by the x86 CLR ABI states that the
+ // terminal block of a filter region is its exit block. If the filter region consists of a single block,
+ // a new block cannot be inserted without either splitting the single block before inserting a new block
+ // or inserting the new block before the single block and updating the filter description such that the
+ // inserted block is marked as the entry block for the filter. Becuase this sort of split can be complex
+ // (especially given that it must ensure that the liveness of the exception object is properly tracked),
+ // we avoid this situation by never generating single-block filters on x86 (see impPushCatchArgOnStack).
+ if (insertingIntoFilter && (bestBlk == endBlk->bbPrev))
{
- assert(bestBlk != nullptr);
- assert(bestBlk->bbJumpKind == BBJ_EHFILTERRET);
- bestBlk = nullptr;
+ assert(bestBlk != startBlk);
+ bestBlk = bestBlk->bbPrev;
}
+#endif // defined(JIT32_GCENCODER)
return bestBlk;
}
// Now find the insertion point.
afterBlk = fgFindInsertPoint(regionIndex, putInTryRegion, startBlk, endBlk, nearBlk, nullptr, runRarely);
- // If afterBlk is nullptr, we must be inserting into a single-block filter region. Because the CLR ABI requires
- // that control exits a filter via the last instruction in the filter range, this situation requires logically
- // splitting the single block. In practice, we simply insert a new block at the beginning of the filter region
- // that transfers control flow to the existing single block.
- if (afterBlk == nullptr)
- {
- assert(putInFilter);
-
- BasicBlock* newFilterEntryBlock = fgNewBBbefore(BBJ_ALWAYS, startBlk, true);
- newFilterEntryBlock->bbJumpDest = startBlk;
- fgAddRefPred(startBlk, newFilterEntryBlock);
-
- afterBlk = newFilterEntryBlock;
- }
-
_FoundAfterBlk:;
/* We have decided to insert the block after 'afterBlk'. */
* Returns the basic block of the actual handler.
*/
-BasicBlock* Compiler::impPushCatchArgOnStack(BasicBlock* hndBlk, CORINFO_CLASS_HANDLE clsHnd)
+BasicBlock* Compiler::impPushCatchArgOnStack(BasicBlock* hndBlk, CORINFO_CLASS_HANDLE clsHnd, bool isSingleBlockFilter)
{
// Do not inject the basic block twice on reimport. This should be
// hit only under JIT stress. See if the block is the one we injected.
* moved around since it is tied to a fixed location (EAX) */
arg->gtFlags |= GTF_ORDER_SIDEEFF;
+#if defined(JIT32_GCENCODER)
+ const bool forceInsertNewBlock = isSingleBlockFilter || compStressCompile(STRESS_CATCH_ARG, 5);
+#else
+ const bool forceInsertNewBlock = compStressCompile(STRESS_CATCH_ARG, 5);
+#endif // defined(JIT32_GCENCODER)
+
/* Spill GT_CATCH_ARG to a temp if there are jumps to the beginning of the handler */
- if (hndBlk->bbRefs > 1 || compStressCompile(STRESS_CATCH_ARG, 5))
+ if (hndBlk->bbRefs > 1 || forceInsertNewBlock)
{
if (hndBlk->bbRefs == 1)
{
// push catch arg the stack, spill to a temp if necessary
// Note: can update HBtab->ebdHndBeg!
- hndBegBB = impPushCatchArgOnStack(hndBegBB, clsHnd);
+ hndBegBB = impPushCatchArgOnStack(hndBegBB, clsHnd, false);
}
// Queue up the handler for importing
// push catch arg the stack, spill to a temp if necessary
// Note: can update HBtab->ebdFilter!
- filterBB = impPushCatchArgOnStack(filterBB, impGetObjectClass());
+ const bool isSingleBlockFilter = (filterBB->bbNext == hndBegBB);
+ filterBB = impPushCatchArgOnStack(filterBB, impGetObjectClass(), isSingleBlockFilter);
impImportBlockPending(filterBB);
}