diff options
author | Jiyoung Yun <jy910.yun@samsung.com> | 2017-04-27 16:54:50 +0900 |
---|---|---|
committer | Jiyoung Yun <jy910.yun@samsung.com> | 2017-04-27 16:54:50 +0900 |
commit | 5b975f8233e8c8d17b215372f89ca713b45d6a0b (patch) | |
tree | 0267bcc331458a01f4c26fafd28110a72273beb3 /src/jit/flowgraph.cpp | |
parent | a56e30c8d33048216567753d9d3fefc2152af8ac (diff) | |
download | coreclr-5b975f8233e8c8d17b215372f89ca713b45d6a0b.tar.gz coreclr-5b975f8233e8c8d17b215372f89ca713b45d6a0b.tar.bz2 coreclr-5b975f8233e8c8d17b215372f89ca713b45d6a0b.zip |
Imported Upstream version 2.0.0.11599upstream/2.0.0.11599
Diffstat (limited to 'src/jit/flowgraph.cpp')
-rw-r--r-- | src/jit/flowgraph.cpp | 123 |
1 files changed, 99 insertions, 24 deletions
diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp index 3374b8c820..0c57862768 100644 --- a/src/jit/flowgraph.cpp +++ b/src/jit/flowgraph.cpp @@ -3189,9 +3189,15 @@ void Compiler::fgComputePreds() if (ehDsc->HasFilter()) { ehDsc->ebdFilter->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL; + + // The first block of a filter has an artifical extra refcount. + ehDsc->ebdFilter->bbRefs++; } ehDsc->ebdHndBeg->bbFlags |= BBF_JMP_TARGET | BBF_HAS_LABEL; + + // The first block of a handler has an artificial extra refcount. + ehDsc->ebdHndBeg->bbRefs++; } fgModified = false; @@ -5455,15 +5461,15 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, B if (!impIsTailCallILPattern(tailCall, opcode, codeAddr + sz, codeEndp, isRecursive, &isCallPopAndRet)) { -#ifdef _TARGET_AMD64_ +#if !defined(FEATURE_CORECLR) && defined(_TARGET_AMD64_) BADCODE3("tail call not followed by ret or pop+ret", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp)); #else BADCODE3("tail call not followed by ret", " at offset %04X", (IL_OFFSET)(codeAddr - codeBegp)); -#endif //_TARGET_AMD64_ +#endif // !FEATURE_CORECLR && _TARGET_AMD64_ } -#ifdef _TARGET_AMD64_ +#if !defined(FEATURE_CORECLR) && defined(_TARGET_AMD64_) if (isCallPopAndRet) { // By breaking here, we let pop and ret opcodes to be @@ -5472,7 +5478,7 @@ unsigned Compiler::fgMakeBasicBlocks(const BYTE* codeAddr, IL_OFFSET codeSize, B // in fgMorphCall(). break; } -#endif //_TARGET_AMD64_ +#endif // !FEATURE_CORECLR && _TARGET_AMD64_ } else { @@ -9124,7 +9130,7 @@ void Compiler::fgSimpleLowering() else { con = gtNewIconNode(arrLen->ArrLenOffset(), TYP_I_IMPL); - con->gtRsvdRegs = 0; + con->gtRsvdRegs = RBM_NONE; add = gtNewOperNode(GT_ADD, TYP_REF, arr, con); add->gtRsvdRegs = arr->gtRsvdRegs; @@ -12081,12 +12087,6 @@ void Compiler::fgInsertFuncletPrologBlock(BasicBlock* block) fgExtendEHRegionBefore(block); // Update the EH table to make the prolog block the first block in the block's EH // block. - // fgExtendEHRegionBefore mucks with the bbRefs without updating the pred list, which we will - // do below for this block. So, undo that change. - assert(newHead->bbRefs > 0); - newHead->bbRefs--; - block->bbRefs++; - // Distribute the pred list between newHead and block. Incoming edges coming from outside // the handler go to the prolog. Edges coming from with the handler are back-edges, and // go to the existing 'block'. @@ -12618,10 +12618,8 @@ bool Compiler::fgMightHaveLoop() { BitVecOps::AddElemD(&blockVecTraits, blocksSeen, block->bbNum); - AllSuccessorIter succsEnd = block->GetAllSuccs(this).end(); - for (AllSuccessorIter succs = block->GetAllSuccs(this).begin(); succs != succsEnd; ++succs) + for (BasicBlock* succ : block->GetAllSuccs(this)) { - BasicBlock* succ = (*succs); if (BitVecOps::IsMember(&blockVecTraits, blocksSeen, succ->bbNum)) { return true; @@ -16569,6 +16567,7 @@ void Compiler::fgExtendEHRegionBefore(BasicBlock* block) #endif // DEBUG HBtab->ebdTryBeg = bPrev; bPrev->bbFlags |= BBF_TRY_BEG | BBF_DONT_REMOVE | BBF_HAS_LABEL; + // clear the TryBeg flag unless it begins another try region if (!bbIsTryBeg(block)) { @@ -16591,6 +16590,16 @@ void Compiler::fgExtendEHRegionBefore(BasicBlock* block) HBtab->ebdHndBeg = bPrev; bPrev->bbFlags |= BBF_DONT_REMOVE | BBF_HAS_LABEL; + +#if FEATURE_EH_FUNCLETS + if (fgFuncletsCreated) + { + assert((block->bbFlags & BBF_FUNCLET_BEG) != 0); + bPrev->bbFlags |= BBF_FUNCLET_BEG; + block->bbFlags &= ~BBF_FUNCLET_BEG; + } +#endif // FEATURE_EH_FUNCLETS + bPrev->bbRefs++; // If this is a handler for a filter, the last block of the filter will end with @@ -16630,6 +16639,16 @@ void Compiler::fgExtendEHRegionBefore(BasicBlock* block) HBtab->ebdFilter = bPrev; bPrev->bbFlags |= BBF_DONT_REMOVE | BBF_HAS_LABEL; + +#if FEATURE_EH_FUNCLETS + if (fgFuncletsCreated) + { + assert((block->bbFlags & BBF_FUNCLET_BEG) != 0); + bPrev->bbFlags |= BBF_FUNCLET_BEG; + block->bbFlags &= ~BBF_FUNCLET_BEG; + } +#endif // FEATURE_EH_FUNCLETS + bPrev->bbRefs++; } } @@ -17036,8 +17055,8 @@ bool Compiler::fgCheckEHCanInsertAfterBlock(BasicBlock* blk, unsigned regionInde // // Return Value: // A block with the desired characteristics, so the new block will be inserted after this one. -// If there is no suitable location, return nullptr. This should basically never happen. - +// If there is no suitable location, return nullptr. This should basically never happen except in the case of +// single-block filters. BasicBlock* Compiler::fgFindInsertPoint(unsigned regionIndex, bool putInTryRegion, BasicBlock* startBlk, @@ -17069,6 +17088,13 @@ BasicBlock* Compiler::fgFindInsertPoint(unsigned regionIndex, regionIndex, dspBool(putInTryRegion), startBlk->bbNum, (endBlk == nullptr) ? 0 : endBlk->bbNum, (nearBlk == nullptr) ? 0 : nearBlk->bbNum, (jumpBlk == nullptr) ? 0 : jumpBlk->bbNum, dspBool(runRarely)); + bool insertingIntoFilter = false; + if (!putInTryRegion) + { + EHblkDsc* const dsc = ehGetDsc(regionIndex - 1); + insertingIntoFilter = dsc->HasFilter() && (startBlk == dsc->ebdFilter) && (endBlk == dsc->ebdHndBeg); + } + bool reachedNear = false; // Have we reached 'nearBlk' in our search? If not, we'll keep searching. bool inFilter = false; // Are we in a filter region that we need to skip? BasicBlock* bestBlk = @@ -17110,9 +17136,7 @@ BasicBlock* Compiler::fgFindInsertPoint(unsigned regionIndex, { // Record the fact that we entered a filter region, so we don't insert into filters... // Unless the caller actually wanted the block inserted in this exact filter region. - // Detect this by the fact that startBlk and endBlk point to the filter begin and end. - if (putInTryRegion || (blk != startBlk) || (startBlk != ehGetDsc(regionIndex - 1)->ebdFilter) || - (endBlk != ehGetDsc(regionIndex - 1)->ebdHndBeg)) + if (!insertingIntoFilter || (blk != startBlk)) { inFilter = true; } @@ -17258,7 +17282,21 @@ BasicBlock* Compiler::fgFindInsertPoint(unsigned regionIndex, bestBlk = goodBlk; } -DONE:; +DONE: + + // 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)) + { + assert(bestBlk != nullptr); + assert(bestBlk->bbJumpKind == BBJ_EHFILTERRET); + bestBlk = nullptr; + } return bestBlk; } @@ -17437,6 +17475,21 @@ BasicBlock* Compiler::fgNewBBinRegion(BBjumpKinds jumpKind, // 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'. */ @@ -20508,7 +20561,28 @@ void Compiler::fgDebugCheckBBlist(bool checkBBNum /* = false */, bool checkBBRef } /* Check the bbRefs */ - noway_assert(!checkBBRefs || block->bbRefs == blockRefs); + if (checkBBRefs) + { + if (block->bbRefs != blockRefs) + { + // Check to see if this block is the beginning of a filter or a handler and adjust the ref count + // appropriately. + for (EHblkDsc *HBtab = compHndBBtab, *HBtabEnd = &compHndBBtab[compHndBBtabCount]; HBtab != HBtabEnd; + HBtab++) + { + if (HBtab->ebdHndBeg == block) + { + blockRefs++; + } + if (HBtab->HasFilter() && (HBtab->ebdFilter == block)) + { + blockRefs++; + } + } + } + + assert(block->bbRefs == blockRefs); + } /* Check that BBF_HAS_HANDLER is valid bbTryIndex */ if (block->hasTryIndex()) @@ -21809,8 +21883,8 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* inlineRe noway_assert(opts.OptEnabled(CLFLG_INLINING)); // This is the InlineInfo struct representing a method to be inlined. - InlineInfo inlineInfo = {nullptr}; - + InlineInfo inlineInfo; + memset(&inlineInfo, 0, sizeof(inlineInfo)); CORINFO_METHOD_HANDLE fncHandle = call->gtCallMethHnd; inlineInfo.fncHandle = fncHandle; @@ -21850,7 +21924,8 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* inlineRe CORINFO_METHOD_HANDLE fncHandle; InlineCandidateInfo* inlineCandidateInfo; InlineInfo* inlineInfo; - } param = {nullptr}; + } param; + memset(¶m, 0, sizeof(param)); param.pThis = this; param.call = call; |