diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index ed763baa880121..46f88959ccb836 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -37,11 +37,11 @@ #include -constexpr GUID JITEEVersionIdentifier = { /* 134b051a-e1ec-4f52-a1bf-f919908aa33c */ - 0x134b051a, - 0xe1ec, - 0x4f52, - {0xa1, 0xbf, 0xf9, 0x19, 0x90, 0x8a, 0xa3, 0x3c} +constexpr GUID JITEEVersionIdentifier = { /* 2712d834-36d1-475f-97b9-3b2eeb4533b0 */ + 0x2712d834, + 0x36d1, + 0x475f, + {0x97, 0xb9, 0x3b, 0x2e, 0xeb, 0x45, 0x33, 0xb0} }; #endif // JIT_EE_VERSIONING_GUID_H diff --git a/src/coreclr/inc/patchpointinfo.h b/src/coreclr/inc/patchpointinfo.h index 53bd8ab26d9f4b..5592cece541570 100644 --- a/src/coreclr/inc/patchpointinfo.h +++ b/src/coreclr/inc/patchpointinfo.h @@ -47,6 +47,7 @@ struct PatchpointInfo m_keptAliveThisOffset = -1; m_securityCookieOffset = -1; m_monitorAcquiredOffset = -1; + m_resumedIndicatorOffset = -1; m_asyncThreadObjectOffset = -1; m_asyncExecutionContextOffset = -1; m_asyncSynchronizationContextOffset = -1; @@ -61,6 +62,7 @@ struct PatchpointInfo m_keptAliveThisOffset = original->m_keptAliveThisOffset; m_securityCookieOffset = original->m_securityCookieOffset; m_monitorAcquiredOffset = original->m_monitorAcquiredOffset; + m_resumedIndicatorOffset = original->m_resumedIndicatorOffset; m_asyncThreadObjectOffset = original->m_asyncThreadObjectOffset; m_asyncExecutionContextOffset = original->m_asyncExecutionContextOffset; m_asyncSynchronizationContextOffset = original->m_asyncSynchronizationContextOffset; @@ -153,6 +155,22 @@ struct PatchpointInfo m_monitorAcquiredOffset = offset; } + // Original method FP relative offset for resumed indicator + int32_t ResumedIndicatorOffset() const + { + return m_resumedIndicatorOffset; + } + + bool HasResumedIndicator() const + { + return m_resumedIndicatorOffset != -1; + } + + void SetResumedIndicatorOffset(int32_t offset) + { + m_resumedIndicatorOffset = offset; + } + // Original method FP relative offset for async thread/contexts int32_t AsyncThreadOffset() const { @@ -251,15 +269,16 @@ struct PatchpointInfo uint64_t m_calleeSaveRegisters; PCODE m_tier0Version; uint32_t m_numberOfLocals; - int32_t m_totalFrameSize; - int32_t m_genericContextArgOffset; - int32_t m_keptAliveThisOffset; - int32_t m_securityCookieOffset; - int32_t m_monitorAcquiredOffset; - int32_t m_asyncThreadObjectOffset; - int32_t m_asyncExecutionContextOffset; - int32_t m_asyncSynchronizationContextOffset; - int32_t m_offsetAndExposureData[]; + int32_t m_totalFrameSize; + int32_t m_genericContextArgOffset; + int32_t m_keptAliveThisOffset; + int32_t m_securityCookieOffset; + int32_t m_monitorAcquiredOffset; + int32_t m_resumedIndicatorOffset; + int32_t m_asyncThreadObjectOffset; + int32_t m_asyncExecutionContextOffset; + int32_t m_asyncSynchronizationContextOffset; + int32_t m_offsetAndExposureData[]; }; typedef DPTR(struct PatchpointInfo) PTR_PatchpointInfo; diff --git a/src/coreclr/inc/readytoruninstructionset.h b/src/coreclr/inc/readytoruninstructionset.h index 19ffdad8863f2e..2afbe10ef26e0f 100644 --- a/src/coreclr/inc/readytoruninstructionset.h +++ b/src/coreclr/inc/readytoruninstructionset.h @@ -102,6 +102,7 @@ enum ReadyToRunInstructionSet READYTORUN_INSTRUCTION_PackedSimd=92, READYTORUN_INSTRUCTION_Cssc=93, READYTORUN_INSTRUCTION_Zicond=94, + }; #endif // READYTORUNINSTRUCTIONSET_H diff --git a/src/coreclr/jit/async.cpp b/src/coreclr/jit/async.cpp index 6a47dcacc6a77b..82471f412f2d58 100644 --- a/src/coreclr/jit/async.cpp +++ b/src/coreclr/jit/async.cpp @@ -66,21 +66,20 @@ PhaseStatus Compiler::SaveAsyncContexts() return PhaseStatus::MODIFIED_NOTHING; } - // Create locals for Thread, ExecutionContext and SynchronizationContext - lvaAsyncThreadObjectVar = lvaGrabTemp(false DEBUGARG("Async Thread")); - lvaGetDesc(lvaAsyncThreadObjectVar)->lvType = TYP_REF; - - lvaAsyncExecutionContextVar = lvaGrabTemp(false DEBUGARG("Async ExecutionContext")); - lvaGetDesc(lvaAsyncExecutionContextVar)->lvType = TYP_REF; - - lvaAsyncSynchronizationContextVar = lvaGrabTemp(false DEBUGARG("Async SynchronizationContext")); + // Create locals for indicator, Thread, ExecutionContext and SynchronizationContext + lvaResumedIndicator = lvaGrabTemp(false DEBUGARG("Async Resumed")); + lvaAsyncThreadObjectVar = lvaGrabTemp(false DEBUGARG("Async Thread")); + lvaAsyncExecutionContextVar = lvaGrabTemp(false DEBUGARG("Async ExecutionContext")); + lvaAsyncSynchronizationContextVar = lvaGrabTemp(false DEBUGARG("Async SynchronizationContext")); + + lvaGetDesc(lvaResumedIndicator)->lvType = TYP_I_IMPL; + lvaGetDesc(lvaAsyncThreadObjectVar)->lvType = TYP_REF; + lvaGetDesc(lvaAsyncExecutionContextVar)->lvType = TYP_REF; lvaGetDesc(lvaAsyncSynchronizationContextVar)->lvType = TYP_REF; - lvaResumedIndicator = lvaGrabTemp(false DEBUGARG("Async Resumed")); - lvaGetDesc(lvaResumedIndicator)->lvType = TYP_UBYTE; - if (opts.IsOSR()) { + lvaGetDesc(lvaResumedIndicator)->lvIsOSRLocal = true; lvaGetDesc(lvaAsyncThreadObjectVar)->lvIsOSRLocal = true; lvaGetDesc(lvaAsyncExecutionContextVar)->lvIsOSRLocal = true; lvaGetDesc(lvaAsyncSynchronizationContextVar)->lvIsOSRLocal = true; @@ -168,17 +167,7 @@ PhaseStatus Compiler::SaveAsyncContexts() // Insert CaptureContexts call before the try (keep it before so the // try/finally can be removed if there is no exception side effects). // For OSR, we did this in the tier0 method. - if (opts.IsOSR()) - { - // In the OSR method we compute the initial value of the resumption indicator based on the continuation arg. - GenTree* continuation = gtNewLclVarNode(lvaAsyncContinuationArg, TYP_REF); - GenTree* null = gtNewNull(); - GenTree* contNeNull = gtNewOperNode(GT_NE, TYP_INT, continuation, null); - GenTree* storeIndicator = gtNewStoreLclVarNode(lvaResumedIndicator, contNeNull); - Statement* storeIndicatorStmt = fgNewStmtFromTree(storeIndicator); - fgInsertStmtAtBeg(fgFirstBB, storeIndicatorStmt); - } - else + if (!opts.IsOSR()) { GenTreeCall* captureCall = gtNewUserCallNode(asyncInfo->captureContextsMethHnd, TYP_VOID); captureCall->gtArgs.PushFront(this, @@ -207,7 +196,7 @@ PhaseStatus Compiler::SaveAsyncContexts() if ((inALoop && !isReturn) || !impInlineRoot()->info.compInitMem) { - GenTree* storeIndicator = gtNewStoreLclVarNode(lvaResumedIndicator, gtNewIconNode(0)); + GenTree* storeIndicator = gtNewStoreLclVarNode(lvaResumedIndicator, gtNewIconNode(0, TYP_I_IMPL)); Statement* storeIndicatorStmt = fgNewStmtFromTree(storeIndicator); fgInsertStmtAtBeg(fgFirstBB, storeIndicatorStmt); @@ -221,15 +210,12 @@ PhaseStatus Compiler::SaveAsyncContexts() } // Insert RestoreContexts call in fault (exceptional case) - // First argument: resumed = (continuation != null) - GenTree* resumed = gtNewLclvNode(lvaResumedIndicator, TYP_INT); - GenTreeCall* restoreCall = gtNewUserCallNode(asyncInfo->restoreContextsMethHnd, TYP_VOID); restoreCall->gtArgs.PushFront(this, NewCallArg::Primitive(gtNewLclVarNode(lvaAsyncSynchronizationContextVar, TYP_REF))); restoreCall->gtArgs.PushFront(this, NewCallArg::Primitive(gtNewLclVarNode(lvaAsyncExecutionContextVar, TYP_REF))); restoreCall->gtArgs.PushFront(this, NewCallArg::Primitive(gtNewLclVarNode(lvaAsyncThreadObjectVar, TYP_REF))); - restoreCall->gtArgs.PushFront(this, NewCallArg::Primitive(resumed)); + restoreCall->gtArgs.PushFront(this, NewCallArg::Primitive(gtNewLclVarNode(lvaResumedIndicator, TYP_INT))); Statement* restoreStmt = fgNewStmtFromTree(restoreCall); fgInsertStmtAtEnd(faultBB, restoreStmt); @@ -385,16 +371,13 @@ BasicBlock* Compiler::CreateReturnBB(unsigned* mergedReturnLcl) JITDUMP("Created new BBJ_RETURN block " FMT_BB "\n", newReturnBB->bbNum); // Insert "restore" call - CORINFO_ASYNC_INFO* asyncInfo = eeGetAsyncInfo(); - - GenTree* resumed = gtNewLclvNode(lvaResumedIndicator, TYP_INT); - - GenTreeCall* restoreCall = gtNewUserCallNode(asyncInfo->restoreContextsMethHnd, TYP_VOID); + CORINFO_ASYNC_INFO* asyncInfo = eeGetAsyncInfo(); + GenTreeCall* restoreCall = gtNewUserCallNode(asyncInfo->restoreContextsMethHnd, TYP_VOID); restoreCall->gtArgs.PushFront(this, NewCallArg::Primitive(gtNewLclVarNode(lvaAsyncSynchronizationContextVar, TYP_REF))); restoreCall->gtArgs.PushFront(this, NewCallArg::Primitive(gtNewLclVarNode(lvaAsyncExecutionContextVar, TYP_REF))); restoreCall->gtArgs.PushFront(this, NewCallArg::Primitive(gtNewLclVarNode(lvaAsyncThreadObjectVar, TYP_REF))); - restoreCall->gtArgs.PushFront(this, NewCallArg::Primitive(resumed)); + restoreCall->gtArgs.PushFront(this, NewCallArg::Primitive(gtNewLclVarNode(lvaResumedIndicator, TYP_INT))); // This restore is an inline candidate (unlike the fault one) CORINFO_CALL_INFO callInfo = {}; @@ -3072,14 +3055,14 @@ void AsyncTransformation::StoreResumedDef(GenTreeLclVarCommon* resumedDef, Basic LclVarDsc* varDsc = m_compiler->lvaGetDesc(resumedDef); GenTree* store; - if ((resumedDef->GetLclOffs() == 0) && varDsc->TypeIs(TYP_UBYTE)) + if ((resumedDef->GetLclOffs() == 0) && varDsc->TypeIs(TYP_I_IMPL)) { - store = m_compiler->gtNewStoreLclVarNode(resumedDef->GetLclNum(), m_compiler->gtNewIconNode(1)); + store = m_compiler->gtNewStoreLclVarNode(resumedDef->GetLclNum(), m_compiler->gtNewIconNode(1, TYP_I_IMPL)); } else { - store = m_compiler->gtNewStoreLclFldNode(resumedDef->GetLclNum(), TYP_UBYTE, resumedDef->GetLclOffs(), - m_compiler->gtNewIconNode(1)); + store = m_compiler->gtNewStoreLclFldNode(resumedDef->GetLclNum(), TYP_I_IMPL, resumedDef->GetLclOffs(), + m_compiler->gtNewIconNode(1, TYP_I_IMPL)); m_compiler->lvaSetVarDoNotEnregister(resumedDef->GetLclNum() DEBUGARG(DoNotEnregisterReason::LocalField)); } @@ -3622,10 +3605,10 @@ BasicBlock* AsyncTransformation::CreateSharedFinishContextHandlingBB(SuspensionC { m_sharedFinishContextHandlingResumedVar = m_compiler->lvaGrabTemp(false DEBUGARG("'resumed' for shared finish context handling")); - m_compiler->lvaGetDesc(m_sharedFinishContextHandlingResumedVar)->lvType = TYP_UBYTE; + m_compiler->lvaGetDesc(m_sharedFinishContextHandlingResumedVar)->lvType = TYP_INT; } - resumed = m_compiler->gtNewLclVarNode(m_sharedFinishContextHandlingResumedVar, TYP_UBYTE); + resumed = m_compiler->gtNewLclVarNode(m_sharedFinishContextHandlingResumedVar, TYP_INT); } else { diff --git a/src/coreclr/jit/codegenarm.cpp b/src/coreclr/jit/codegenarm.cpp index 2bae2090b07035..f1418dd07bd231 100644 --- a/src/coreclr/jit/codegenarm.cpp +++ b/src/coreclr/jit/codegenarm.cpp @@ -2396,6 +2396,10 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() { saveSizeWithPSP += TARGET_POINTER_SIZE; } + if (m_compiler->lvaResumedIndicator != BAD_VAR_NUM) + { + saveSizeWithPSP += TARGET_POINTER_SIZE; + } if (m_compiler->lvaAsyncThreadObjectVar != BAD_VAR_NUM) { saveSizeWithPSP += TARGET_POINTER_SIZE; diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index 04f48619cfa8a7..b1dfa28f51720f 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -1731,6 +1731,11 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() saveRegsSize += m_compiler->lvaLclStackHomeSize(m_compiler->lvaMonAcquired); } + if ((m_compiler->lvaResumedIndicator != BAD_VAR_NUM) && !m_compiler->opts.IsOSR()) + { + saveRegsSize += m_compiler->lvaLclStackHomeSize(m_compiler->lvaResumedIndicator); + } + if ((m_compiler->lvaAsyncThreadObjectVar != BAD_VAR_NUM) && !m_compiler->opts.IsOSR()) { saveRegsSize += m_compiler->lvaLclStackHomeSize(m_compiler->lvaAsyncThreadObjectVar); diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 91527e38610c1d..e1801ae7432c77 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -3928,6 +3928,13 @@ void CodeGen::genCreateAndStoreGCInfo(unsigned codeSize, assert(m_compiler->lvaGetCallerSPRelativeOffset(m_compiler->lvaMonAcquired) == -preservedAreaSize); } + if (m_compiler->lvaResumedIndicator != BAD_VAR_NUM) + { + preservedAreaSize += TARGET_POINTER_SIZE; + + assert(m_compiler->lvaGetCallerSPRelativeOffset(m_compiler->lvaResumedIndicator) == -preservedAreaSize); + } + if (m_compiler->lvaAsyncThreadObjectVar != BAD_VAR_NUM) { preservedAreaSize += TARGET_POINTER_SIZE; diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 5308e680efa374..81eddf480ec367 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -8374,6 +8374,13 @@ void CodeGen::genCreateAndStoreGCInfoX64(unsigned codeSize, unsigned prologSize assert(m_compiler->lvaGetCallerSPRelativeOffset(m_compiler->lvaMonAcquired) == -preservedAreaSize); } + if (m_compiler->lvaResumedIndicator != BAD_VAR_NUM) + { + preservedAreaSize += TARGET_POINTER_SIZE; + + assert(m_compiler->lvaGetCallerSPRelativeOffset(m_compiler->lvaResumedIndicator) == -preservedAreaSize); + } + if (m_compiler->lvaAsyncThreadObjectVar != BAD_VAR_NUM) { preservedAreaSize += TARGET_POINTER_SIZE; diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 2ba637e907092f..60fae26c756cad 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -5720,6 +5720,14 @@ void Compiler::generatePatchpointInfo() patchpointInfo->MonitorAcquiredOffset()); } + if (lvaResumedIndicator != BAD_VAR_NUM) + { + LclVarDsc* const varDsc = lvaGetDesc(lvaResumedIndicator); + patchpointInfo->SetResumedIndicatorOffset(varDsc->GetStackOffset() + offsetAdjust); + JITDUMP("--OSR-- resumed indicator V%02u virtual offset is %d\n", lvaResumedIndicator, + patchpointInfo->ResumedIndicatorOffset()); + } + if (lvaAsyncThreadObjectVar != BAD_VAR_NUM) { LclVarDsc* const varDsc = lvaGetDesc(lvaAsyncThreadObjectVar); @@ -10422,6 +10430,10 @@ int Compiler::lvaOSRLocalTier0FrameOffset(unsigned varNum) { return info.compPatchpointInfo->MonitorAcquiredOffset(); } + if (varNum == lvaResumedIndicator) + { + return info.compPatchpointInfo->ResumedIndicatorOffset(); + } if (varNum == lvaAsyncThreadObjectVar) { return info.compPatchpointInfo->AsyncThreadOffset(); diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index f9cf55b8feeecb..5760671b9174ec 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4344,6 +4344,7 @@ class Compiler unsigned lvaMonAcquired = BAD_VAR_NUM; // boolean variable introduced into in synchronized methods // that tracks whether the lock has been taken + unsigned lvaResumedIndicator = BAD_VAR_NUM; // Variable representing "have we resumed?" for async methods unsigned lvaAsyncThreadObjectVar = BAD_VAR_NUM; // Thread local for async methods unsigned lvaAsyncExecutionContextVar = BAD_VAR_NUM; // ExecutionContext local for async methods unsigned lvaAsyncSynchronizationContextVar = BAD_VAR_NUM; // SynchronizationContext local for async methods @@ -4389,9 +4390,6 @@ class Compiler // Variable representing async continuation argument passed. unsigned lvaAsyncContinuationArg = BAD_VAR_NUM; - // Variable representing "have we resumed?" for async methods - unsigned lvaResumedIndicator = BAD_VAR_NUM; - #if defined(DEBUG) && defined(TARGET_XARCH) unsigned lvaReturnSpCheck = BAD_VAR_NUM; // Stores SP to confirm it is not corrupted on return. diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index 31c17ca2eb5e34..ff316205567597 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -4642,10 +4642,10 @@ GenTree::VisitResult GenTree::VisitLocalDefs(Compiler* comp, TVisitor visitor) GenTreeLclVarCommon* asyncResumedLclAddr = comp->gtCallGetDefinedAsyncResumedLclAddr(call); if (asyncResumedLclAddr != nullptr) { - bool isEntire = comp->lvaLclExactSize(asyncResumedLclAddr->GetLclNum()) == 1; + bool isEntire = comp->lvaLclExactSize(asyncResumedLclAddr->GetLclNum()) == TARGET_POINTER_SIZE; - RETURN_IF_ABORT( - visitor(LocalDef(asyncResumedLclAddr, isEntire, asyncResumedLclAddr->GetLclOffs(), ValueSize(1)))); + RETURN_IF_ABORT(visitor(LocalDef(asyncResumedLclAddr, isEntire, asyncResumedLclAddr->GetLclOffs(), + ValueSize(TARGET_POINTER_SIZE)))); } GenTreeLclVarCommon* retBufLclAddr = comp->gtCallGetDefinedRetBufLclAddr(call); diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 8c96b0d5c166be..6cafff96b2d7a7 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -1526,7 +1526,7 @@ class LocalAddressVisitor final : public GenTreeVisitor CallArg* asyncResumedDef = callUser->gtArgs.FindWellKnownArg(WellKnownArg::AsyncResumedDef); if ((asyncResumedDef != nullptr) && (val.Node() == asyncResumedDef->GetNode())) { - defSize = 1; + defSize = TARGET_POINTER_SIZE; } } diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 703e2f0b35c25d..578958d7f4c402 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -5328,7 +5328,7 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() continue; } - if ((lclNum == lvaMonAcquired) || (lclNum == lvaAsyncThreadObjectVar) || + if ((lclNum == lvaMonAcquired) || (lclNum == lvaResumedIndicator) || (lclNum == lvaAsyncThreadObjectVar) || (lclNum == lvaAsyncExecutionContextVar) || (lclNum == lvaAsyncSynchronizationContextVar)) { continue; @@ -5857,6 +5857,18 @@ int Compiler::lvaAllocLocalAndSetVirtualOffset(unsigned lclNum, unsigned size, i // int Compiler::lvaAllocAsyncContexts(int stkOffs) { + if (lvaResumedIndicator != BAD_VAR_NUM) + { + stkOffs = + lvaAllocLocalAndSetVirtualOffset(lvaResumedIndicator, lvaLclStackHomeSize(lvaResumedIndicator), stkOffs); + } + else + { + // For x86 EnC the VM expects that we always allocate stack space + // for these locals when contexts were saved. + assert((info.compMethodInfo->options & CORINFO_ASYNC_SAVE_CONTEXTS) == 0); + } + if (lvaAsyncThreadObjectVar != BAD_VAR_NUM) { stkOffs = lvaAllocLocalAndSetVirtualOffset(lvaAsyncThreadObjectVar, @@ -5864,8 +5876,6 @@ int Compiler::lvaAllocAsyncContexts(int stkOffs) } else { - // For x86 EnC the VM expects that we always allocate stack space - // for this local when contexts were saved. assert((info.compMethodInfo->options & CORINFO_ASYNC_SAVE_CONTEXTS) == 0); } @@ -5876,8 +5886,6 @@ int Compiler::lvaAllocAsyncContexts(int stkOffs) } else { - // For x86 EnC the VM expects that we always allocate stack space - // for this local when contexts were saved. assert((info.compMethodInfo->options & CORINFO_ASYNC_SAVE_CONTEXTS) == 0); } diff --git a/src/coreclr/vm/gc_unwind_x86.inl b/src/coreclr/vm/gc_unwind_x86.inl index 30866e5a2ac137..ec99912bd15d8f 100644 --- a/src/coreclr/vm/gc_unwind_x86.inl +++ b/src/coreclr/vm/gc_unwind_x86.inl @@ -556,7 +556,7 @@ inline size_t GetSizeOfFrameHeaderForEnC(MethodDesc* pMD, hdrInfo * info) info->localloc + info->genericsContext + // For CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG ((info->syncStartOffset != INVALID_SYNC_OFFSET) ? 1 : 0) + // Is this method synchronized - (pMD->RequiresAsyncContextSaveAndRestore() ? 3 : 0) + // Does this method save thread + async contexts? + (pMD->RequiresAsyncContextSaveAndRestore() ? 4 : 0) + // Does this method save indicator + thread + async contexts? 1; // for ebpFrame return position * sizeof(TADDR); }