Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
54c4cc1
RuntimeAsync for interpreter phase 1
davidwrighton Nov 13, 2025
024ab55
More fixes
davidwrighton Nov 18, 2025
0064807
Current test tweaks
davidwrighton Nov 18, 2025
cda2252
Fix this pointer in generics issue
davidwrighton Nov 18, 2025
495abdf
Don't overwrite values that shouldn't be overwritten.
davidwrighton Nov 18, 2025
9dc46af
Add support for direct Async2 to Async2 calls, and fix incorrect hand…
davidwrighton Nov 19, 2025
08ea4fd
Add forward support to call stub generator for async methods
davidwrighton Nov 19, 2025
a3c1fdd
Merge branch 'main' of https://github.com/dotnet/runtime into Runtime…
davidwrighton Nov 19, 2025
9fb7e05
Progress towards async calling convention handling in the callstub ge…
davidwrighton Nov 20, 2025
24a3f5c
It all passes the tests!
davidwrighton Nov 20, 2025
9ae0d3b
Remove unnecessary data/dvar from HANDLE_CONTINUATION_RESUME
davidwrighton Nov 20, 2025
cd92605
Re-order InterpAsyncSuspendData for easier future diagnostics
davidwrighton Nov 20, 2025
01adff9
Fix setting methodStartIp
davidwrighton Nov 20, 2025
8b61a6f
Update tests to work for both JIT and interpreter scenarios
davidwrighton Nov 20, 2025
9913e56
Merge branch 'main' of https://github.com/dotnet/runtime into Runtime…
davidwrighton Dec 1, 2025
7cf7c52
Tweak the new CallJittedMethodRetBuffRSI function.
davidwrighton Dec 1, 2025
250ee75
Actually handle the merge details
davidwrighton Dec 1, 2025
9d8bf9d
Fix build on Linux x64
davidwrighton Dec 1, 2025
a5feaac
Remove ProtectValueClassFrame changes as they are not necessary
davidwrighton Dec 1, 2025
3806ea2
Add some documentation on how runtime generated async code generation…
davidwrighton Dec 1, 2025
d99c3f7
Fix WASM build
davidwrighton Dec 2, 2025
ded4f49
Fix Unix X64 stubs
davidwrighton Dec 2, 2025
811e321
Fixup formatting and some missing bits of info.
davidwrighton Dec 2, 2025
4765f06
Fit and finish details
davidwrighton Dec 2, 2025
ffb1656
Integrate with Jakob's changes around calli signature handling, and a…
davidwrighton Dec 2, 2025
1ea976f
Move the JIT copy of dataAsyncResumeInfo to corinfo.h and rename it C…
davidwrighton Dec 2, 2025
c5e0fbb
Fix more code review issues
davidwrighton Dec 3, 2025
c0124af
Apply suggestions from code review
davidwrighton Dec 3, 2025
96a9114
Merge branch 'RuntimeAsync_Interpreter' of https://github.com/davidwr…
davidwrighton Dec 3, 2025
2d74b6b
Fix GCC build break
davidwrighton Dec 3, 2025
354e365
More code review + disable RuntimeAsync by default so we can actually…
davidwrighton Dec 3, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
Expand Down Expand Up @@ -144,6 +145,18 @@ public ref byte GetResultStorageOrNull()

public static partial class AsyncHelpers
{
#if FEATURE_INTERPRETER
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AsyncHelpers_ResumeInterpreterContinuation")]
private static partial void AsyncHelpers_ResumeInterpreterContinuation(ObjectHandleOnStack cont, ref byte resultStorage);

internal static Continuation? ResumeInterpreterContinuation(Continuation cont, ref byte resultStorage)
{
ObjectHandleOnStack contHandle = ObjectHandleOnStack.Create(ref cont);
AsyncHelpers_ResumeInterpreterContinuation(contHandle, ref resultStorage);
return cont;
}
#endif

// This is the "magic" method on which other "Await" methods are built.
// Calling this from an Async method returns the continuation to the caller thus
// explicitly initiates suspension.
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableRiscV64Zbb, W("EnableRiscV64
#endif

// Runtime-async
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RuntimeAsync, W("RuntimeAsync"), 0, "Enables runtime async method support")
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RuntimeAsync, W("RuntimeAsync"), 1, "Enables runtime async method support")

///
/// Uncategorized
Expand Down
1,454 changes: 1,355 additions & 99 deletions src/coreclr/interpreter/compiler.cpp

Large diffs are not rendered by default.

49 changes: 47 additions & 2 deletions src/coreclr/interpreter/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,9 @@ struct InterpBasicBlock
// Number of catch, filter or finally clauses that overlap with this basic block.
int32_t overlappingEHClauseCount;

// Number of try blocks that enclose this basic block.
int32_t enclosingTryBlockCount;

InterpBasicBlock(int32_t index) : InterpBasicBlock(index, 0) { }

InterpBasicBlock(int32_t index, int32_t ilOffset)
Expand All @@ -367,6 +370,7 @@ struct InterpBasicBlock
isFinallyCallIsland = false;
clauseVarIndex = -1;
overlappingEHClauseCount = 0;
enclosingTryBlockCount = -1;
}
};

Expand Down Expand Up @@ -541,6 +545,7 @@ class InterpCompiler
friend class InterpIAllocator;
friend class InterpGcSlotAllocator;
friend class InterpILOpcodePeeps;
friend class InterpAsyncCallPeeps;

private:
CORINFO_METHOD_HANDLE m_methodHnd;
Expand Down Expand Up @@ -609,6 +614,8 @@ class InterpCompiler
// from the interpreter code header during execution.
TArray<void*, MemPoolAllocator> m_dataItems;

TArray<InterpAsyncSuspendData*, MemPoolAllocator> m_asyncSuspendDataItems;

InterpDataItemIndexMap m_genericLookupToDataItemIndex;
int32_t GetDataItemIndex(void* data)
{
Expand Down Expand Up @@ -759,13 +766,22 @@ class InterpCompiler
int32_t m_paramArgIndex = -1; // Index of the type parameter argument in the m_pVars array.
// For each catch or filter clause, we create a variable that holds the exception object.
// This is the index of the first such variable.
int32_t m_continuationArgIndex = -1; // Index of the continuation argument in the m_pVars array for async methods.
int32_t m_clauseVarsIndex = 0;

int32_t m_synchronizedOrAsyncPostFinallyOffset = -1; // If the method is synchronized/async, this is the offset of the instruction after the finally which does the actual return

bool m_isSynchronized = false;
int32_t m_synchronizedFlagVarIndex = -1; // If the method is synchronized, this is the index of the argument that flag indicating if the lock was taken
int32_t m_synchronizedRetValVarIndex = -1; // If the method is synchronized, ret instructions are replaced with a store to this var and a leave to an epilog instruction.
int32_t m_synchronizedOrAsyncRetValVarIndex = -1; // If the method is synchronized, ret instructions are replaced with a store to this var and a leave to an epilog instruction.
int32_t m_synchronizedFinallyStartOffset = -1; // If the method is synchronized, this is the offset of the start of the finally epilog
int32_t m_synchronizedPostFinallyOffset = -1; // If the method is synchronized, this is the offset of the instruction after the finally which does the actual return

int32_t m_execContextVarIndex = -1; // If the method is async, this is the var index of the ExecutionContext local
int32_t m_syncContextVarIndex = -1; // If the method is async, this is the var index of the SynchronizationContext local

void *m_asyncResumeFuncPtr = NULL;
bool m_isAsyncMethodWithContextSaveRestore = false;
int32_t m_asyncFinallyStartOffset = -1; // If the method is async, this is the offset of the start of the fault handler

bool m_shadowCopyOfThisPointerActuallyNeeded = false;
bool m_shadowCopyOfThisPointerHasVar = false;
Expand Down Expand Up @@ -802,6 +818,8 @@ class InterpCompiler
void ConvertFloatingPointStackEntryToStackType(StackInfo* entry, StackType type);

// Opcode peeps
bool FindAndApplyPeep(OpcodePeep* Peeps[]);

bool IsStoreLoadPeep(const uint8_t* ip, OpcodePeepElement* peep, void** computedInfo);
void ApplyStoreLoadPeep(const uint8_t* ip, OpcodePeepElement* peep, void* computedInfo);

Expand All @@ -814,6 +832,21 @@ class InterpCompiler
bool IsTypeValueTypePeep(const uint8_t* ip, OpcodePeepElement* peep, void** outComputedInfo);
void ApplyTypeValueTypePeep(const uint8_t* ip, OpcodePeepElement* peep, void* computedInfo);

enum class ContinuationContextHandling : uint8_t
{
ContinueOnCapturedContext,
ContinueOnThreadPool,
None
};
bool IsRuntimeAsyncCall(const uint8_t* ip, OpcodePeepElement* peep, void** computedInfo);
bool IsRuntimeAsyncCallConfigureAwaitTask(const uint8_t* ip, OpcodePeepElement* peep, void** computedInfo);
bool IsRuntimeAsyncCallConfigureAwaitValueTask(const uint8_t* ip, OpcodePeepElement* peep, void** computedInfo);
bool IsRuntimeAsyncCallConfigureAwaitValueTaskExactStLoc(const uint8_t* ip, OpcodePeepElement* peep, void** computedInfo);

void ApplyRuntimeAsyncCall(const uint8_t* ip, OpcodePeepElement* peep, void* computedInfo) {}
ContinuationContextHandling m_currentContinuationContextHandling = ContinuationContextHandling::None;
CORINFO_RESOLVED_TOKEN m_resolvedAsyncCallToken;

// Code emit
void EmitConv(StackInfo *sp, StackType type, InterpOpcode convOp);
void EmitLoadVar(int var);
Expand All @@ -823,6 +856,7 @@ class InterpCompiler
void EmitShiftOp(int32_t opBase);
void EmitCompareOp(int32_t opBase);
void EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool readonly, bool tailcall, bool newObj, bool isCalli);
void EmitSuspend(const CORINFO_CALL_INFO &callInfo, ContinuationContextHandling ContinuationContextHandling, InterpBasicBlock* pBB);
void EmitCalli(bool isTailCall, void* calliCookie, int callIFunctionPointerVar, CORINFO_SIG_INFO* callSiteSig);
bool EmitNamedIntrinsicCall(NamedIntrinsic ni, bool nonVirtualCall, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO sig);
void EmitLdind(InterpType type, CORINFO_CLASS_HANDLE clsHnd, int32_t offset);
Expand Down Expand Up @@ -852,6 +886,15 @@ class InterpCompiler
void EndActiveCall(InterpInst *call);
void CompactActiveVars(int32_t *current_offset);

TArray<InterpIntervalMapEntry**, MemPoolAllocator> m_varIntervalMaps;
InterpIntervalMapEntry ComputeNextIntervalMapEntry_ForVars(const TArray<int32_t, MemPoolAllocator> &vars, int32_t *pNextIndex);
void AllocateIntervalMapData_ForVars(InterpIntervalMapEntry** ppIntervalMap, const TArray<int32_t, MemPoolAllocator> &vars);

void GetVarSizeAndOffset(const InterpIntervalMapEntry* pVarIntervalMap, int32_t entryIndex, int32_t internalIndex, uint32_t* pVarSize, uint32_t* pVarOffset);
InterpIntervalMapEntry ComputeNextIntervalMapEntry_ForOffsets(const InterpIntervalMapEntry* pVarIntervalMap, int32_t *pNextIndex, int32_t *pInternalIndex);
void ConvertToIntervalMapData_ForOffsets(InterpIntervalMapEntry** ppIntervalMap);
void UpdateLocalIntervalMaps();

// Passes
int32_t* m_pMethodCode;
int32_t m_methodCodeSize; // code size measured in int32_t slots, instead of bytes
Expand Down Expand Up @@ -884,6 +927,7 @@ class InterpCompiler
void PrintInsData(InterpInst *ins, int32_t offset, const int32_t *pData, int32_t opcode);
void PrintCompiledCode();
void PrintCompiledIns(const int32_t *ip, const int32_t *start);
void PrintInterpAsyncSuspendData(InterpAsyncSuspendData* pSuspendInfo);
#ifdef DEBUG
InterpDumpScope m_dumpScope;
TArray<char, MallocAllocator> m_methodName;
Expand All @@ -910,6 +954,7 @@ class InterpCompiler
InterpMethod* CompileMethod();
void BuildGCInfo(InterpMethod *pInterpMethod);
void BuildEHInfo();
void UpdateWithFinalMethodByteCodeAddress(InterpByteCodeStart *pByteCodeStart);

int32_t* GetCode(int32_t *pCodeSize);
};
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/interpreter/compileropt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,4 +453,6 @@ void InterpCompiler::AllocOffsets()

m_globalVarsWithRefsStackTop = globalVarsWithRefsStackTop;
m_totalVarsStackSize = ALIGN_UP_TO(finalVarsStackSize, INTERP_STACK_ALIGNMENT);

UpdateLocalIntervalMaps();
}
1 change: 1 addition & 0 deletions src/coreclr/interpreter/eeinterp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ CorJitResult CILInterp::compileMethod(ICorJitInfo* compHnd,
*(InterpMethod**)args.hotCodeBlockRW = pMethod;
memcpy ((uint8_t*)args.hotCodeBlockRW + sizeof(InterpMethod*), pIRCode, IRCodeSize * sizeof(int32_t));

compiler.UpdateWithFinalMethodByteCodeAddress((InterpByteCodeStart*)args.hotCodeBlock);
*entryAddress = (uint8_t*)args.hotCodeBlock;
*nativeSizeOfCode = sizeOfCode;

Expand Down
50 changes: 50 additions & 0 deletions src/coreclr/interpreter/inc/interpretershared.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct InterpHelperData {

#ifndef INTERPRETER_COMPILER_INTERNAL
class MethodDesc;
class MethodTable;
#endif

struct CallStubHeader;
Expand Down Expand Up @@ -188,4 +189,53 @@ enum class CalliFlags : int32_t
PInvoke = 1 << 2, // The call is a PInvoke call
};

struct InterpIntervalMapEntry
{
uint32_t startOffset;
uint32_t countBytes; // If count is 0 then this is the end marker.
};

struct InterpAsyncSuspendData
{
// ResumeInfo . Keep in sync with dataAsyncResumeInfo in the JIT and System.Runtime.CompilerServices.ResumeInfo
void* resumeFuncPtr; // Pointer to the resume function
void* DiagnosticIP; // IP to report in diagnostic scenarios

#ifdef INTERPRETER_COMPILER_INTERNAL
CORINFO_CLASS_HANDLE ContinuationTypeHnd;
#else
DPTR(MethodTable) ContinuationTypeHnd;
#endif

InterpIntervalMapEntry* zeroedLocalsIntervals; // This will be used for the locals we need to keep live.
InterpIntervalMapEntry* liveLocalsIntervals; // Following the end of this struct is the array of InterpIntervalMapEntry for live locals
CorInfoContinuationFlags flags;
int32_t offsetIntoContinuationTypeForExecutionContext;
int32_t keepAliveOffset; // Only needed if we have a generic context to keep alive
InterpByteCodeStart* methodStartIP;
#ifdef INTERPRETER_COMPILER_INTERNAL
CORINFO_CLASS_HANDLE asyncMethodReturnType;
#else
DPTR(MethodTable) asyncMethodReturnType;
#endif
int32_t asyncMethodReturnTypePrimitiveSize; // 0 if not primitive, otherwise size in bytes
int32_t continuationArgOffset;

#ifdef INTERPRETER_COMPILER_INTERNAL
CORINFO_METHOD_HANDLE pCaptureSyncContextMethod;
#else
DPTR(MethodDesc) pCaptureSyncContextMethod;
#endif
#ifdef INTERPRETER_COMPILER_INTERNAL
CORINFO_METHOD_HANDLE pRestoreExecutionContextMethod;
#else
DPTR(MethodDesc) pRestoreExecutionContextMethod;
#endif
#ifdef INTERPRETER_COMPILER_INTERNAL
CORINFO_METHOD_HANDLE pRestoreContextsMethod;
#else
DPTR(MethodDesc) pRestoreContextsMethod;
#endif
};

#endif
13 changes: 13 additions & 0 deletions src/coreclr/interpreter/inc/intops.def
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ OPDEF(INTOP_SHL_I8, "shl.i8", 4, 1, 2, InterpOpNoArgs)
OPDEF(INTOP_SHR_I4, "shr.i4", 4, 1, 2, InterpOpNoArgs)
OPDEF(INTOP_SHR_I8, "shr.i8", 4, 1, 2, InterpOpNoArgs)

OPDEF(INTOP_CZERO_I, "czero.i", 4, 1, 1, InterpOpNoArgs) // Set dvar to 1 if operand is non-zero otherwise 0 (produces a 32bit int)

OPDEF(INTOP_CEQ_I4, "ceq.i4", 4, 1, 2, InterpOpNoArgs)
OPDEF(INTOP_CEQ_I8, "ceq.i8", 4, 1, 2, InterpOpNoArgs)
OPDEF(INTOP_CEQ_R4, "ceq.r4", 4, 1, 2, InterpOpNoArgs)
Expand Down Expand Up @@ -427,6 +429,17 @@ OPDEF(INTOP_THROW_PNSE, "throw.pnse", 1, 0, 0, InterpOpNoArgs)

OPDEF(INTOP_LOAD_FRAMEVAR, "load.framevar", 2, 1, 0, InterpOpNoArgs)

OPDEF(INTOP_SET_CONTINUATION_NULL, "set.continuation.null", 1, 0, 0, InterpOpNoArgs)
OPDEF(INTOP_SET_CONTINUATION, "set.continuation", 2, 0, 1, InterpOpNoArgs)
OPDEF(INTOP_GET_CONTINUATION, "get.continuation", 2, 1, 0, InterpOpNoArgs)
OPDEF(INTOP_HANDLE_CONTINUATION, "handle.continuation", 4, 1, 0, InterpOpHandleContinuation)
OPDEF(INTOP_HANDLE_CONTINUATION_GENERIC, "handle.continuation.generic", 5, 1, 1, InterpOpHandleContinuation)
OPDEF(INTOP_HANDLE_CONTINUATION_SUSPEND, "handle.continuation.suspend", 3, 0, 1, InterpOpHandleContinuationPt2)
OPDEF(INTOP_HANDLE_CONTINUATION_RESUME, "handle.continuation.resume", 2, 0, 0, InterpOpHandleContinuationPt2)
OPDEF(INTOP_CHECK_FOR_CONTINUATION, "check.for.continuation", 3, 0, 1, InterpOpNoArgs)
OPDEF(INTOP_CAPTURE_CONTEXT_ON_SUSPEND, "capture.context.on.suspend", 4, 1, 1, InterpOpHandleContinuationPt2)
OPDEF(INTOP_RESTORE_CONTEXTS_ON_SUSPEND, "restore.contexts.on.suspend", 6, 1, 3, InterpOpHandleContinuationPt2)

// Intrinsics
OPDEF(INTOP_COMPARE_EXCHANGE_U1, "compare.exchange.u1", 5, 1, 3, InterpOpNoArgs)
OPDEF(INTOP_COMPARE_EXCHANGE_U2, "compare.exchange.u2", 5, 1, 3, InterpOpNoArgs)
Expand Down
5 changes: 4 additions & 1 deletion src/coreclr/interpreter/intops.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ typedef enum
InterpOpPointerHelperFtn,
InterpOpPointerInt,
InterpOpGenericLookupInt,
InterpOpHandleContinuation,
InterpOpHandleContinuationPt2,
} InterpOpArgType;

extern const uint8_t g_interpOpLen[];
Expand Down Expand Up @@ -127,6 +129,7 @@ inline double getR8LittleEndian(const uint8_t* ptr)
// We use a couple of special "intrinsic" tokens to represent these operations.
// These are recognized by our implementation of the CALL opcode.
const uint32_t INTERP_CALL_SYNCHRONIZED_MONITOR_EXIT = 0xFFFFFFFE;
const uint32_t INTERP_LOAD_RETURN_VALUE_FOR_SYNCHRONIZED = 0xFFFFFFFF;
const uint32_t INTERP_LOAD_RETURN_VALUE_FOR_SYNCHRONIZED_OR_ASYNC = 0xFFFFFFFF;
const uint32_t INTERP_RESTORE_CONTEXTS_FOR_ASYNC_METHOD = 0xFFFFFFFD;

#endif
18 changes: 18 additions & 0 deletions src/coreclr/interpreter/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ NamedIntrinsic GetNamedIntrinsic(COMP_HANDLE compHnd, CORINFO_METHOD_HANDLE comp
else if (!strcmp(methodName, "GetMethodTable"))
return NI_System_Runtime_CompilerServices_RuntimeHelpers_GetMethodTable;
}
else if (!strcmp(className, "AsyncHelpers"))
{
if (!strcmp(methodName, "AsyncSuspend"))
return NI_System_Runtime_CompilerServices_AsyncHelpers_AsyncSuspend;
else if (!strcmp(methodName, "AsyncCallContinuation"))
return NI_System_Runtime_CompilerServices_AsyncHelpers_AsyncCallContinuation;
else if (!strcmp(methodName, "Await"))
return NI_System_Runtime_CompilerServices_AsyncHelpers_Await;
}
}
else if (!strcmp(namespaceName, "System.Runtime.InteropServices"))
{
Expand Down Expand Up @@ -147,6 +156,15 @@ NamedIntrinsic GetNamedIntrinsic(COMP_HANDLE compHnd, CORINFO_METHOD_HANDLE comp
return NI_System_Threading_Volatile_WriteBarrier;
}
}
else if (!strcmp(namespaceName, "System.Threading.Tasks"))
{
if (!strcmp(methodName, "ConfigureAwait"))
{
if (!strcmp(className, "Task`1") || !strcmp(className, "Task") ||
!strcmp(className, "ValueTask`1") || !strcmp(className, "ValueTask"))
return NI_System_Threading_Tasks_Task_ConfigureAwait;
}
}

return NI_Illegal;
}
12 changes: 12 additions & 0 deletions src/coreclr/vm/amd64/AsmHelpers.asm
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,8 @@ HaveInterpThreadContext:
lea rax, [rsp + __PWTB_TransitionBlock]
; Copy the arguments to the interpreter stack, invoke the InterpExecMethod and load the return value
call qword ptr [r11]
; Fill in the ContinuationContext register
mov rcx, [rsp + __PWTB_ArgumentRegisters]

EPILOG_WITH_TRANSITION_BLOCK_RETURN

Expand Down Expand Up @@ -1114,6 +1116,8 @@ END_PROLOGUE
mov r11, rcx ; The routines list
mov r10, rdx ; interpreter stack args
call qword ptr [r11]
mov rdx, [rbp + 48]
mov [rdx], rcx
mov rsp, rbp
pop rbp
ret
Expand All @@ -1129,6 +1133,8 @@ END_PROLOGUE
mov r10, rdx ; interpreter stack args
mov rcx, r8 ; return buffer
call qword ptr [r11]
mov rdx, [rbp + 48]
mov [rdx], rcx
mov rsp, rbp
pop rbp
ret
Expand All @@ -1144,6 +1150,8 @@ END_PROLOGUE
mov r10, rdx ; interpreter stack args
mov rdx, r8 ; return buffer
call qword ptr [r11]
mov rdx, [rbp + 48]
mov [rdx], rcx
mov rsp, rbp
pop rbp
ret
Expand All @@ -1161,6 +1169,8 @@ END_PROLOGUE
mov r11, rcx ; The routines list
mov r10, rdx ; interpreter stack args
call qword ptr [r11]
mov rdx, [rbp + 48]
mov [rdx], rcx
mov r8, [rbp - 8]
movsd real8 ptr [r8], xmm0
mov rsp, rbp
Expand All @@ -1179,6 +1189,8 @@ END_PROLOGUE
mov r11, rcx ; The routines list
mov r10, rdx ; interpreter stack args
call qword ptr [r11]
mov rdx, [rbp + 48]
mov [rdx], rcx
mov r8, [rbp - 8]
mov qword ptr [r8], rax
mov rsp, rbp
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/amd64/asmconstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_pInterpThreadContext == offsetof(Threa
#define OFFSETOF__InterpThreadContext__pStackPointer 0x10
ASMCONSTANTS_C_ASSERT(OFFSETOF__InterpThreadContext__pStackPointer == offsetof(InterpThreadContext, pStackPointer))

#define OFFSETOF__CallStubHeader__Routines 0x10
#define OFFSETOF__CallStubHeader__Routines 0x18
ASMCONSTANTS_C_ASSERT(OFFSETOF__CallStubHeader__Routines == offsetof(CallStubHeader, Routines))

#ifdef TARGET_UNIX
Expand Down
Loading
Loading