From 15cde1fd7bd863da1b34ebd89e9f98fccf9ba6fb Mon Sep 17 00:00:00 2001 From: Pat Gavlin Date: Thu, 30 Mar 2017 15:02:10 -0700 Subject: [PATCH] Fix Issue dotnet/coreclr#10022. (dotnet/coreclr#10587) This issue occurred because the JIT currently inserts the P/Invoke method prolog into the first block of a function without ensuring that this block will only execute once. This is not safe, as executing the P/Invoke prolog multiple times can create cycles in the frame list and casue the stack unwinder to hang. This change ensures that lowering inserts a new, single-entry basic block at the beginning of the function for functions that require P/Invoke prologs. Commit migrated from https://github.com/dotnet/coreclr/commit/9b342387cd8e75249609d30ab79f05193f714e80 --- src/coreclr/src/jit/flowgraph.cpp | 14 ++++++++++++++ src/coreclr/src/jit/lower.cpp | 13 +++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/coreclr/src/jit/flowgraph.cpp b/src/coreclr/src/jit/flowgraph.cpp index 6b13fd1..00068c6 100644 --- a/src/coreclr/src/jit/flowgraph.cpp +++ b/src/coreclr/src/jit/flowgraph.cpp @@ -420,6 +420,9 @@ BasicBlock* Compiler::fgNewBasicBlock(BBjumpKinds jumpKind) void Compiler::fgEnsureFirstBBisScratch() { + // This method does not update predecessor lists and so must only be called before they are computed. + assert(!fgComputePredsDone); + // Have we already allocated a scratch block? if (fgFirstBBisScratch()) @@ -438,6 +441,7 @@ void Compiler::fgEnsureFirstBBisScratch() { block->inheritWeight(fgFirstBB); } + fgInsertBBbefore(fgFirstBB, block); } else @@ -8064,6 +8068,16 @@ void Compiler::fgAddInternal() { noway_assert(!compIsForInlining()); +#ifndef LEGACY_BACKEND + // The RyuJIT backend requires a scratch BB into which it can safely insert a P/Invoke method prolog if one is + // required. Create it here. + if (info.compCallUnmanaged != 0) + { + fgEnsureFirstBBisScratch(); + fgFirstBB->bbFlags |= BBF_DONT_REMOVE; + } +#endif // !LEGACY_BACKEND + /* VSW441487 diff --git a/src/coreclr/src/jit/lower.cpp b/src/coreclr/src/jit/lower.cpp index a6dd563..573de3a 100644 --- a/src/coreclr/src/jit/lower.cpp +++ b/src/coreclr/src/jit/lower.cpp @@ -2835,6 +2835,9 @@ void Lowering::InsertPInvokeMethodProlog() JITDUMP("======= Inserting PInvoke method prolog\n"); + // The first BB must be a scratch BB in order for us to be able to safely insert the P/Invoke prolog. + assert(comp->fgFirstBBisScratch()); + LIR::Range& firstBlockRange = LIR::AsRange(comp->fgFirstBB); const CORINFO_EE_INFO* pInfo = comp->eeGetEEInfo(); @@ -2869,10 +2872,8 @@ void Lowering::InsertPInvokeMethodProlog() store->gtOp.gtOp1 = call; store->gtFlags |= GTF_VAR_DEF; - GenTree* insertionPoint = firstBlockRange.FirstNonPhiOrCatchArgNode(); - comp->fgMorphTree(store); - firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, store)); + firstBlockRange.InsertAtEnd(LIR::SeqTree(comp, store)); DISPTREERANGE(firstBlockRange, store); #if !defined(_TARGET_X86_) && !defined(_TARGET_ARM_) @@ -2886,7 +2887,7 @@ void Lowering::InsertPInvokeMethodProlog() GenTreeLclFld(GT_STORE_LCL_FLD, TYP_I_IMPL, comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfCallSiteSP); storeSP->gtOp1 = PhysReg(REG_SPBASE); - firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, storeSP)); + firstBlockRange.InsertAtEnd(LIR::SeqTree(comp, storeSP)); DISPTREERANGE(firstBlockRange, storeSP); #endif // !defined(_TARGET_X86_) && !defined(_TARGET_ARM_) @@ -2902,7 +2903,7 @@ void Lowering::InsertPInvokeMethodProlog() callFrameInfo.offsetOfCalleeSavedFP); storeFP->gtOp1 = PhysReg(REG_FPBASE); - firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, storeFP)); + firstBlockRange.InsertAtEnd(LIR::SeqTree(comp, storeFP)); DISPTREERANGE(firstBlockRange, storeFP); #endif // !defined(_TARGET_ARM_) @@ -2917,7 +2918,7 @@ void Lowering::InsertPInvokeMethodProlog() // Push a frame - if we are NOT in an IL stub, this is done right before the call // The init routine sets InlinedCallFrame's m_pNext, so we just set the thead's top-of-stack GenTree* frameUpd = CreateFrameLinkUpdate(PushFrame); - firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, frameUpd)); + firstBlockRange.InsertAtEnd(LIR::SeqTree(comp, frameUpd)); DISPTREERANGE(firstBlockRange, frameUpd); } #endif // _TARGET_64BIT_ -- 2.7.4