Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@

#include <minipal/guid.h>

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}
Comment thread
jakobbotsch marked this conversation as resolved.
};

#endif // JIT_EE_VERSIONING_GUID_H
37 changes: 28 additions & 9 deletions src/coreclr/inc/patchpointinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/inc/readytoruninstructionset.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ enum ReadyToRunInstructionSet
READYTORUN_INSTRUCTION_PackedSimd=92,
READYTORUN_INSTRUCTION_Cssc=93,
READYTORUN_INSTRUCTION_Zicond=94,

Comment thread
jakobbotsch marked this conversation as resolved.
};

#endif // READYTORUNINSTRUCTIONSET_H
61 changes: 22 additions & 39 deletions src/coreclr/jit/async.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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 = {};
Expand Down Expand Up @@ -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));
}

Expand Down Expand Up @@ -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
{
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/jit/codegenarm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/jit/codegenarmarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 12 additions & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down
4 changes: 1 addition & 3 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/jit/compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/lclmorph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1526,7 +1526,7 @@ class LocalAddressVisitor final : public GenTreeVisitor<LocalAddressVisitor>
CallArg* asyncResumedDef = callUser->gtArgs.FindWellKnownArg(WellKnownArg::AsyncResumedDef);
if ((asyncResumedDef != nullptr) && (val.Node() == asyncResumedDef->GetNode()))
{
defSize = 1;
defSize = TARGET_POINTER_SIZE;
}
}

Expand Down
18 changes: 13 additions & 5 deletions src/coreclr/jit/lclvars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -5857,15 +5857,25 @@ 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,
lvaLclStackHomeSize(lvaAsyncThreadObjectVar), 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);
}

Expand All @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/gc_unwind_x86.inl
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Loading