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
28 changes: 27 additions & 1 deletion src/coreclr/interpreter/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5789,8 +5789,8 @@ void InterpCompiler::EmitSuspend(const CORINFO_CALL_INFO &callInfo, Continuation
int32_t returnValueVar = -1;
if (stackDepth > 0 && callInfo.sig.retType != CORINFO_TYPE_VOID)
{
// The return value var is written explicitly during resume, it is not included in the set of liveVars
returnValueVar = m_pStackPointer[-1].var;
liveVars.Add(returnValueVar);
}

// Step 1: Collect live IL vars
Expand Down Expand Up @@ -6015,6 +6015,21 @@ void InterpCompiler::EmitSuspend(const CORINFO_CALL_INFO &callInfo, Continuation
suspendData->resumeInfo.DiagnosticIP = (size_t)NULL;
suspendData->methodStartIP = 0; // This is filled in by logic later in emission once we know the final address of the method
suspendData->continuationArgOffset = m_pVars[m_continuationArgIndex].offset;

if (returnValueVar != -1)
{
int32_t alignDummy;
int32_t size = GetInterpTypeStackSize(m_pVars[returnValueVar].clsHnd, m_pVars[returnValueVar].interpType, &alignDummy);
suspendData->returnValueContinuationDataSize = ALIGN_UP_TO(size, INTERP_STACK_SLOT_SIZE);
Comment thread
BrzVlad marked this conversation as resolved.
}
else
{
suspendData->returnValueContinuationDataSize = 0;
}

// Patched up in UpdateLocalIntervalMaps to hold the actual offset of the var
suspendData->returnValueVarStackOffset = returnValueVar;

Comment thread
BrzVlad marked this conversation as resolved.
suspendData->asyncMethodReturnType = NULL;
switch (m_methodInfo->args.retType)
{
Expand Down Expand Up @@ -6323,6 +6338,17 @@ void InterpCompiler::UpdateLocalIntervalMaps()
{
ConvertToIntervalMapData_ForOffsets(m_varIntervalMaps.Get(i));
}

// Fix up return value var stack offsets for async suspend data
for (int32_t i = 0; i < m_asyncSuspendDataItems.GetSize(); i++)
{
InterpAsyncSuspendData* suspendData = m_asyncSuspendDataItems.Get(i);
int32_t varIndex = suspendData->returnValueVarStackOffset;
if (varIndex != -1)
{
suspendData->returnValueVarStackOffset = m_pVars[varIndex].offset;
}
}
}

static int32_t GetStindForType(InterpType interpType)
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/interpreter/inc/interpretershared.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@ struct InterpAsyncSuspendData
COMPILER_SHARED_TYPE(CORINFO_CLASS_HANDLE, DPTR(MethodTable), asyncMethodReturnType);
int32_t asyncMethodReturnTypePrimitiveSize; // 0 if not primitive, otherwise size in bytes
int32_t continuationArgOffset;
int32_t returnValueContinuationDataSize; // Aligned size of the return value in continuation data (0 if void). Live locals start after this offset.
int32_t returnValueVarStackOffset; // Interpreter stack offset of the return value var (valid only when returnValueContinuationDataSize > 0)
Comment thread
BrzVlad marked this conversation as resolved.

COMPILER_SHARED_TYPE(CORINFO_METHOD_HANDLE, DPTR(MethodDesc), captureSyncContextMethod);
COMPILER_SHARED_TYPE(CORINFO_METHOD_HANDLE, DPTR(MethodDesc), restoreExecutionContextMethod);
Expand Down
17 changes: 14 additions & 3 deletions src/coreclr/vm/interpexec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4491,9 +4491,11 @@ do \
}
ip += 3;

// copy locals that need to move to the continuation object
// Copy locals that need to move to the continuation object
// The copied continuation data begins immediately after the
// continuation's result storage.
size_t continuationOffset = OFFSETOF__CORINFO_Continuation__data;
uint8_t *pContinuationDataStart = continuation->GetResultStorage();
uint8_t *pContinuationDataStart = continuation->GetResultStorage() + pAsyncSuspendData->returnValueContinuationDataSize;
uint8_t *pContinuationData = pContinuationDataStart;
size_t bytesTotal = 0;
InterpIntervalMapEntry *pCopyEntry = pAsyncSuspendData->liveLocalsIntervals;
Expand Down Expand Up @@ -4561,7 +4563,7 @@ do \
// Now copy the locals

// copy locals that need to move from the continuation object
uint8_t *pContinuationData = continuation->GetResultStorage();
uint8_t *pContinuationData = continuation->GetResultStorage() + pAsyncSuspendData->returnValueContinuationDataSize;
InterpIntervalMapEntry *pCopyEntry = pAsyncSuspendData->liveLocalsIntervals;
while (pCopyEntry->countBytes != 0)
{
Expand All @@ -4570,6 +4572,15 @@ do \
pCopyEntry++;
}

// Explicitly copy the return value from the continuation's result storage
// to the interpreter stack.
if (pAsyncSuspendData->returnValueContinuationDataSize > 0)
{
memcpy(LOCAL_VAR_ADDR(pAsyncSuspendData->returnValueVarStackOffset, uint8_t),
continuation->GetResultStorage(),
pAsyncSuspendData->returnValueContinuationDataSize);
}

PTR_OBJECTREF pException = continuation->GetExceptionObjectStorageOrNull();
if (pException != NULL)
{
Expand Down
Loading