From 0e778d7accdf17366cb2c7637002469e921114f9 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Tue, 22 Nov 2016 13:32:26 -0500 Subject: [PATCH 01/24] [Arm64/Unix] Update arm64 *.S files to match *.asm --- src/debug/ee/arm64/dbghelpers.S | 36 ++- src/debug/ee/wks/CMakeLists.txt | 2 +- src/pal/inc/unixasmmacrosarm64.inc | 75 ++--- src/vm/arm64/asmhelpers.S | 427 ++++++++++++++++++++++++---- src/vm/arm64/asmhelpers.asm | 2 +- src/vm/arm64/calldescrworkerarm64.S | 30 +- src/vm/arm64/pinvokestubs.S | 45 +-- 7 files changed, 473 insertions(+), 144 deletions(-) diff --git a/src/debug/ee/arm64/dbghelpers.S b/src/debug/ee/arm64/dbghelpers.S index 07ed04acd5d9..5328d69ef7f5 100644 --- a/src/debug/ee/arm64/dbghelpers.S +++ b/src/debug/ee/arm64/dbghelpers.S @@ -4,22 +4,46 @@ #include "unixasmmacros.inc" -NESTED_ENTRY FuncEvalHijack, _TEXT, FuncEvalHijackPersonalityRoutine +// +// hijacking stub used to perform a func-eval, see Debugger::FuncEvalSetup() for use. +// +// on entry: +// x0 : pointer to DebuggerEval object +// + +// @dbgtodo- once we port Funceval, use the ExceptionHijack stub instead of this func-eval stub. +NESTED_ENTRY FuncEvalHijack, _TEXT, UnhandledExceptionHandlerUnix // NOTE: FuncEvalHijackPersonalityRoutine is dependent on the stack layout so if // you change the prolog you will also need to update the personality routine. // push arg to the stack so our personality routine can find it // push lr to get good stacktrace in debugger - -PROLOG_SAVE_REG_PAIR fp, lr, #-32 - + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-32 str x0, [sp, #16] // FuncEvalHijackWorker returns the address we should jump to. bl FuncEvalHijackWorker EPILOG_STACK_FREE 32 EPILOG_BRANCH_REG x0 -NESTED_END FuncEvalHijack, _TEXT +NESTED_END FuncEvalHijack + +// This is the general purpose hijacking stub. The DacDbi Hijack primitive will +// set up the stack and then set the IP here, and so this just makes the call. +NESTED_ENTRY ExceptionHijack, _TEXT, UnhandledExceptionHandlerUnix + + // make the call + bl ExceptionHijackWorker + + // effective NOP to terminate unwind + mov x3, x3 + + // *** should never get here *** + EMIT_BREAKPOINT + +// exported label so the debugger knows where the end of this function is +PATCH_LABEL ExceptionHijackEnd + +NESTED_END ExceptionHijack, _TEXT + -//NESTED_ENTRY ExceptionHijack,,ExceptionHijackPersonalityRoutine \ No newline at end of file diff --git a/src/debug/ee/wks/CMakeLists.txt b/src/debug/ee/wks/CMakeLists.txt index 1088355f1276..4c4c53760779 100644 --- a/src/debug/ee/wks/CMakeLists.txt +++ b/src/debug/ee/wks/CMakeLists.txt @@ -58,7 +58,7 @@ add_compile_options(-fPIC) if(CLR_CMAKE_PLATFORM_ARCH_AMD64 OR CLR_CMAKE_PLATFORM_ARCH_ARM OR CLR_CMAKE_PLATFORM_ARCH_ARM64 OR CLR_CMAKE_PLATFORM_ARCH_I386) add_library_clr(cordbee_wks ${CORDBEE_SOURCES_WKS} ../${ARCH_SOURCES_DIR}/dbghelpers.S) elseif(CLR_CMAKE_PLATFORM_ARCH_ARM64) - add_library_clr(cordbee_wks ${CORDBEE_SOURCES_WKS}) + add_library_clr(cordbee_wks ${CORDBEE_SOURCES_WKS} ../${ARCH_SOURCES_DIR}/dbghelpers.S) else() message(FATAL_ERROR "Only ARM and AMD64 is supported") endif() diff --git a/src/pal/inc/unixasmmacrosarm64.inc b/src/pal/inc/unixasmmacrosarm64.inc index 359f27f87813..9414be70a9a1 100644 --- a/src/pal/inc/unixasmmacrosarm64.inc +++ b/src/pal/inc/unixasmmacrosarm64.inc @@ -94,14 +94,14 @@ C_FUNC(\Name\()_End): //----------------------------------------------------------------------------- // Define the prolog for a TransitionFrame-based method. This macro should be called first in the method and -// comprises the entire prolog (i.e. don't modify SP after calling this).The locals must be 8 byte aligned +// comprises the entire prolog (i.e. don't modify SP after calling this).The locals must be 8 byte aligned // // Stack layout: // // (stack parameters) // ... // fp -// lr +// lr // CalleeSavedRegisters::x28 // CalleeSavedRegisters::x27 // CalleeSavedRegisters::x26 @@ -133,6 +133,7 @@ C_FUNC(\Name\()_End): .macro PROLOG_WITH_TRANSITION_BLOCK extraLocals = 0, SaveFPArgs = 1 __PWTB_FloatArgumentRegisters = \extraLocals + __PWTB_SaveFPArgs = \SaveFPArgs .if ((__PWTB_FloatArgumentRegisters % 16) != 0) __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 8 @@ -140,40 +141,40 @@ C_FUNC(\Name\()_End): __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters - .if \SaveFPArgs > 0 + .if (__PWTB_SaveFPArgs == 1) __PWTB_TransitionBlock = __PWTB_TransitionBlock + SIZEOF__FloatArgumentRegisters .endif __PWTB_StackAlloc = __PWTB_TransitionBlock - __PWTB_ArgumentRegisters = __PWTB_StackAlloc + 96 + __PWTB_ArgumentRegisters = __PWTB_StackAlloc + 96 - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-160 - // Spill callee saved registers + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-176 + // Spill callee saved registers PROLOG_SAVE_REG_PAIR x19, x20, #16 PROLOG_SAVE_REG_PAIR x21, x22, #32 PROLOG_SAVE_REG_PAIR x23, x24, #48 PROLOG_SAVE_REG_PAIR x25, x26, #64 PROLOG_SAVE_REG_PAIR x27, x28, #80 - + // Allocate space for the rest of the frame PROLOG_STACK_ALLOC __PWTB_StackAlloc - + // Spill argument registers. SAVE_ARGUMENT_REGISTERS sp, __PWTB_ArgumentRegisters - .if \SaveFPArgs > 0 + .if (__PWTB_SaveFPArgs == 1) SAVE_FLOAT_ARGUMENT_REGISTERS sp, \extraLocals .endif .endm //----------------------------------------------------------------------------- -// The Following sets of SAVE_*_REGISTERS expect the memory to be reserved and +// The Following sets of SAVE_*_REGISTERS expect the memory to be reserved and // base address to be passed in $reg // // Reserve 64 bytes of memory before calling SAVE_ARGUMENT_REGISTERS -.macro SAVE_ARGUMENT_REGISTERS reg, ofs +.macro SAVE_ARGUMENT_REGISTERS reg, ofs stp x0, x1, [\reg, #(\ofs)] stp x2, x3, [\reg, #(\ofs + 16)] @@ -183,7 +184,7 @@ C_FUNC(\Name\()_End): .endm // Reserve 64 bytes of memory before calling SAVE_FLOAT_ARGUMENT_REGISTERS -.macro SAVE_FLOAT_ARGUMENT_REGISTERS reg, ofs +.macro SAVE_FLOAT_ARGUMENT_REGISTERS reg, ofs stp d0, d1, [\reg, #(\ofs)] stp d2, d3, [\reg, #(\ofs + 16)] @@ -192,7 +193,7 @@ C_FUNC(\Name\()_End): .endm -.macro RESTORE_ARGUMENT_REGISTERS reg, ofs +.macro RESTORE_ARGUMENT_REGISTERS reg, ofs ldp x0, x1, [\reg, #(\ofs)] ldp x2, x3, [\reg, #(\ofs + 16)] @@ -201,7 +202,7 @@ C_FUNC(\Name\()_End): .endm -.macro RESTORE_FLOAT_ARGUMENT_REGISTERS reg, ofs +.macro RESTORE_FLOAT_ARGUMENT_REGISTERS reg, ofs ldp d0, d1, [\reg, #(\ofs)] ldp d2, d3, [\reg, #(\ofs + 16)] @@ -210,46 +211,52 @@ C_FUNC(\Name\()_End): .endm +.macro EPILOG_BRANCH Target + b \Target +.endm + .macro EPILOG_BRANCH_REG reg br \reg .endm -//----------------------------------------------------------------------------- -// Provides a matching epilog to PROLOG_WITH_TRANSITION_BLOCK and ends by preparing for tail-calling. -// Since this is a tail call argument registers are restored. -// -.macro EPILOG_WITH_TRANSITION_BLOCK_TAILCALL extraLocals = 0, SaveFPArgs =1 - __PWTB_FloatArgumentRegisters = \extraLocals +.macro EPILOG_WITH_TRANSITION_BLOCK_RETURN - .if ((__PWTB_FloatArgumentRegisters % 16) != 0) - __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 8 - .endif + EPILOG_STACK_FREE __PWTB_StackAlloc - __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters + EPILOG_RESTORE_REG_PAIR x19, x20, #16 + EPILOG_RESTORE_REG_PAIR x21, x22, #32 + EPILOG_RESTORE_REG_PAIR x23, x24, #48 + EPILOG_RESTORE_REG_PAIR x25, x26, #64 + EPILOG_RESTORE_REG_PAIR x27, x28, #80 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #176 + ret - .if \SaveFPArgs > 0 - __PWTB_TransitionBlock = __PWTB_TransitionBlock + SIZEOF__FloatArgumentRegisters - .endif +.endm - __PWTB_StackAlloc = __PWTB_TransitionBlock - __PWTB_ArgumentRegisters = __PWTB_StackAlloc + 96 - .if \SaveFPArgs > 0 - RESTORE_FLOAT_ARGUMENT_REGISTERS sp, __PWTB_FloatArgumentRegisters +//----------------------------------------------------------------------------- +// Provides a matching epilog to PROLOG_WITH_TRANSITION_BLOCK and ends by preparing for tail-calling. +// Since this is a tail call argument registers are restored. +// +.macro EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + + .if (__PWTB_SaveFPArgs == 1) + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, __PWTB_FloatArgumentRegisters .endif RESTORE_ARGUMENT_REGISTERS sp, __PWTB_ArgumentRegisters + EPILOG_STACK_FREE __PWTB_StackAlloc - + EPILOG_RESTORE_REG_PAIR x19, x20, #16 EPILOG_RESTORE_REG_PAIR x21, x22, #32 EPILOG_RESTORE_REG_PAIR x23, x24, #48 EPILOG_RESTORE_REG_PAIR x25, x26, #64 EPILOG_RESTORE_REG_PAIR x27, x28, #80 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #160 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #176 .endm @@ -274,7 +281,7 @@ __RedirectionFuncName SETS "|?RedirectedHandledJITCaseFor":CC:"$reason":CC:"@Thr NESTED_ENTRY $__RedirectionStubFuncName PROLOG_SAVE_REG_PAIR fp, lr, #-16 - sub sp, sp, #16 // stack slot for CONTEXT * and padding + sub sp, sp, #16 // stack slot for CONTEXT * and padding //REDIRECTSTUB_SP_OFFSET_CONTEXT is defined in asmconstants.h and is used in GetCONTEXTFromRedirectedStubStackFrame //If CONTEXT is not saved at 0 offset from SP it must be changed as well. diff --git a/src/vm/arm64/asmhelpers.S b/src/vm/arm64/asmhelpers.S index d92e91cfd7e7..7c83627bba8e 100644 --- a/src/vm/arm64/asmhelpers.S +++ b/src/vm/arm64/asmhelpers.S @@ -120,18 +120,18 @@ LEAF_END HelperMethodFrameRestoreState, _TEXT // The call in ndirect import precode points to this function. NESTED_ENTRY NDirectImportThunk, _TEXT, NoHandler - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-144 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-160 SAVE_ARGUMENT_REGISTERS sp, 16 - SAVE_FLOAT_ARGUMENT_REGISTERS sp, 80 + SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88 mov x0, x12 bl NDirectImportWorker mov x12, x0 // pop the stack and restore original register state - RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 80 + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88 RESTORE_ARGUMENT_REGISTERS sp, 16 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #144 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #160 // If we got back from NDirectImportWorker, the MD has been successfully // linked. Proceed to execute the original DLL call. @@ -140,8 +140,14 @@ NESTED_ENTRY NDirectImportThunk, _TEXT, NoHandler NESTED_END NDirectImportThunk, _TEXT // ------------------------------------------------------------------ -// ARM64TODO: Implement PrecodeFixupThunk when PreCode is Enabled +// The call in fixup precode initally points to this function. +// The pupose of this function is to load the MethodDesc and forward the call to prestub. NESTED_ENTRY PrecodeFixupThunk, _TEXT, NoHandler + // x12 = FixupPrecode * + // On Exit + // x12 = MethodDesc* + // x13, x14 Trashed + // Inline computation done by FixupPrecode::GetMethodDesc() ldrb w13, [x12, #Offset_PrecodeChunkIndex] //m_PrecodeChunkIndex ldrb w14, [x12, #Offset_MethodDescChunkIndex] // m_MethodDescChunkIndex @@ -181,34 +187,6 @@ C_FUNC(ThePreStubPatchLabel): LEAF_END ThePreStubPatch, _TEXT -// ------------------------------------------------------------------ -// void ResolveWorkerAsmStub(args in regs x0-x7 & stack, x11:IndirectionCellAndFlags, x12:DispatchToken) -// -// The stub dispatch thunk which transfers control to VSD_ResolveWorker. -NESTED_ENTRY ResolveWorkerAsmStub, _TEXT, NoHandler - - PROLOG_WITH_TRANSITION_BLOCK - - add x0, sp, #__PWTB_TransitionBlock // pTransitionBlock - and x1, x11, #-4 // Indirection cell - mov x2, x12 // DispatchToken - and x3, x11, #3 // flag - bl C_FUNC(VSD_ResolveWorker) - mov x9, x0 - - EPILOG_WITH_TRANSITION_BLOCK_TAILCALL - - EPILOG_BRANCH_REG x9 - -NESTED_END ResolveWorkerAsmStub, _TEXT - -NESTED_ENTRY ResolveWorkerChainLookupAsmStub, _TEXT, NoHandler - - // ARMSTUB TODO: implement chained lookup - b C_FUNC(ResolveWorkerAsmStub) - -NESTED_END ResolveWorkerChainLookupAsmStub, _TEXT - //----------------------------------------------------------------------------- // The following Macros help in WRITE_BARRIER Implemetations // WRITE_BARRIER_ENTRY @@ -288,6 +266,49 @@ WRITE_BARRIER_ENTRY JIT_WriteBarrier dmb ST str x15, [x14] +#ifdef WRITE_BARRIER_CHECK + // Update GC Shadow Heap + + // need temporary registers. Save them before using. + stp x12, x13, [sp, #-16]! + + // Compute address of shadow heap location: + // pShadow = g_GCShadow + (x14 - g_lowest_address) + ldr x12, =g_lowest_address + ldr x12, [x12] + sub x12, x14, x12 + ldr x13, =g_GCShadow + ldr x13, [x13] + add x12, x13, x12 + + // if (pShadow >= g_GCShadowEnd) goto end + ldr x13, =g_GCShadowEnd + ldr x13, [x13] + cmp x12, x13 + bhs LOCAL_LABEL(shadowupdateend) + + // *pShadow = x15 + str x15, [x12] + + // Ensure that the write to the shadow heap occurs before the read from the GC heap so that race + // conditions are caught by INVALIDGCVALUE. + dmb sy + + // if ([x14] == x15) goto end + ldr x13, [x14] + cmp x13, x15 + beq LOCAL_LABEL(shadowupdateend) + + // *pShadow = INVALIDGCVALUE (0xcccccccd) + mov x13, #0 + movk x13, #0xcccd + movk x13, #0xcccc, LSL #16 + str x13, [x12] + +LOCAL_LABEL(shadowupdateend): + ldp x12, x13, [sp],#16 +#endif + // Branch to Exit if the reference is not in the Gen0 heap // PREPARE_EXTERNAL_VAR g_ephemeral_low, x12 @@ -347,9 +368,9 @@ LEAF_END JIT_PatchedCodeLast, _TEXT NESTED_ENTRY VirtualMethodFixupStub, _TEXT, NoHandler // Save arguments and return address - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-144 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-160 SAVE_ARGUMENT_REGISTERS sp, 16 - SAVE_FLOAT_ARGUMENT_REGISTERS sp, 80 + SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88 // Refer to ZapImportVirtualThunk::Save // for details on this. @@ -366,8 +387,8 @@ NESTED_ENTRY VirtualMethodFixupStub, _TEXT, NoHandler // pop the stack and restore original register state RESTORE_ARGUMENT_REGISTERS sp, 16 - RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 80 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #144 + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #160 PATCH_LABEL VirtualMethodFixupPatchLabel @@ -425,15 +446,161 @@ LOCAL_LABEL(LNullThis): LEAF_END SinglecastDelegateInvokeStub, _TEXT +#ifdef FEATURE_COMINTEROP + +#define ComCallPreStub_FrameSize (SIZEOF__GSCookie + SIZEOF__ComMethodFrame) +#define ComCallPreStub_FirstStackAdjust (SIZEOF__ArgumentRegisters + 2 * 8) // reg args , fp & lr already pushed +#define ComCallPreStub_StackAlloc0 (ComCallPreStub_FrameSize - ComCallPreStub_FirstStackAdjust) +#define ComCallPreStub_StackAlloc1 (ComCallPreStub_StackAlloc0 + SIZEOF__FloatArgumentRegisters + 8)// 8 for ErrorReturn +#define ComCallPreStub_StackAlloc (ComCallPreStub_StackAlloc1 + (ComCallPreStub_StackAlloc1 & 8)) + +#define ComCallPreStub_FrameOffset (ComCallPreStub_StackAlloc - (SIZEOF__ComMethodFrame - ComCallPreStub_FirstStackAdjust)) +#define ComCallPreStub_ErrorReturnOffset0 SIZEOF__FloatArgumentRegisters + +#define ComCallPreStub_FirstStackAdjust (ComCallPreStub_ErrorReturnOffset0 + (ComCallPreStub_ErrorReturnOffset0 & 8)) + +// ------------------------------------------------------------------ +// COM to CLR stub called the first time a particular method is invoked.// +// +// On entry: +// x12 : ComCallMethodDesc* provided by prepad thunk +// plus user arguments in registers and on the stack +// +// On exit: +// tail calls to real method +// + NESTED_ENTRY ComCallPreStub, _TEXT, NoHandler + + // Save arguments and return address + PROLOG_SAVE_REG_PAIR fp, lr, #-ComCallPreStub_FirstStackAdjust! + PROLOG_STACK_ALLOC ComCallPreStub_StackAlloc + + SAVE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc) + + SAVE_FLOAT_ARGUMENT_REGISTERS sp, 0 + + str x12, [sp, #(ComCallPreStub_FrameOffset + UnmanagedToManagedFrame__m_pvDatum)] + add x0, sp, #(ComCallPreStub_FrameOffset) + add x1, sp, #(ComCallPreStub_ErrorReturnOffset) + bl ComPreStubWorker + + cbz x0, ComCallPreStub_ErrorExit + + mov x12, x0 + + // pop the stack and restore original register state + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 0 + RESTORE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc) + + EPILOG_STACK_FREE ComCallPreStub_StackAlloc + EPILOG_RESTORE_REG_PAIR fp, lr, #ComCallPreStub_FirstStackAdjust! + + // and tailcall to the actual method + EPILOG_BRANCH_REG x12 + +ComCallPreStub_ErrorExit + ldr x0, [sp, #(ComCallPreStub_ErrorReturnOffset)] // ErrorReturn + + // pop the stack + EPILOG_STACK_FREE ComCallPreStub_StackAlloc + EPILOG_RESTORE_REG_PAIR fp, lr, #ComCallPreStub_FirstStackAdjust! + + EPILOG_RETURN + + NESTED_END ComCallPreStub, _TEXT + +// ------------------------------------------------------------------ +// COM to CLR stub which sets up a ComMethodFrame and calls COMToCLRWorker. +// +// On entry: +// x12 : ComCallMethodDesc* provided by prepad thunk +// plus user arguments in registers and on the stack +// +// On exit: +// Result in x0/d0 as per the real method being called +// + NESTED_ENTRY GenericComCallStub, _TEXT, NoHandler + + // Save arguments and return address + PROLOG_SAVE_REG_PAIR fp, lr, #-GenericComCallStub_FirstStackAdjust! + PROLOG_STACK_ALLOC GenericComCallStub_StackAlloc + + SAVE_ARGUMENT_REGISTERS sp, (16+GenericComCallStub_StackAlloc) + SAVE_FLOAT_ARGUMENT_REGISTERS sp, 0 + + str x12, [sp, #(GenericComCallStub_FrameOffset + UnmanagedToManagedFrame__m_pvDatum)] + add x1, sp, #GenericComCallStub_FrameOffset + bl COMToCLRWorker + + // pop the stack + EPILOG_STACK_FREE GenericComCallStub_StackAlloc + EPILOG_RESTORE_REG_PAIR fp, lr, #GenericComCallStub_FirstStackAdjust! + + EPILOG_RETURN + + NESTED_END GenericComCallStub, _TEXT + +// ------------------------------------------------------------------ +// COM to CLR stub called from COMToCLRWorker that actually dispatches to the real managed method. +// +// On entry: +// x0 : dwStackSlots, count of argument stack slots to copy +// x1 : pFrame, ComMethodFrame pushed by GenericComCallStub above +// x2 : pTarget, address of code to call +// x3 : pSecretArg, hidden argument passed to target above in x12 +// x4 : pDangerousThis, managed 'this' reference +// +// On exit: +// Result in x0/d0 as per the real method being called +// + NESTED_ENTRY COMToCLRDispatchHelper, _TEXT,CallDescrWorkerUnwindFrameChainHandler + + PROLOG_SAVE_REG_PAIR fp, lr, #-16! + + cbz x0, COMToCLRDispatchHelper_RegSetup + + add x9, x1, #SIZEOF__ComMethodFrame + add x9, x9, x0, LSL #3 +COMToCLRDispatchHelper_StackLoop + ldr x8, [x9, #-8]! + str x8, [sp, #-8]! + sub x0, x0, #1 + cbnz x0, COMToCLRDispatchHelper_StackLoop + +COMToCLRDispatchHelper_RegSetup + + RESTORE_FLOAT_ARGUMENT_REGISTERS x1, -1 * GenericComCallStub_FrameOffset + + mov lr, x2 + mov x12, x3 + + mov x0, x4 + + ldp x2, x3, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 16)] + ldp x4, x5, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 32)] + ldp x6, x7, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 48)] + ldr x8, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 64)] + + ldr x1, [x1, #(SIZEOF__ComMethodFrame - SIZEOF__ArgumentRegisters + 8)] + + blr lr + + EPILOG_STACK_RESTORE + EPILOG_RESTORE_REG_PAIR fp, lr, #16! + EPILOG_RETURN + + NESTED_END COMToCLRDispatchHelper, _TEXT + +#endif // FEATURE_COMINTEROP // // x12 = UMEntryThunk* // NESTED_ENTRY TheUMEntryPrestub, _TEXT, UnhandledExceptionHandlerUnix // Save arguments and return address - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-144 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-160 SAVE_ARGUMENT_REGISTERS sp, 16 - SAVE_FLOAT_ARGUMENT_REGISTERS sp, 80 + SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88 mov x0, x12 bl C_FUNC(TheUMEntryPrestubWorker) @@ -443,8 +610,8 @@ NESTED_ENTRY TheUMEntryPrestub, _TEXT, UnhandledExceptionHandlerUnix // pop the stack and restore original register state RESTORE_ARGUMENT_REGISTERS sp, 16 - RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 80 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #144 + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #160 // and tailcall to the actual method EPILOG_BRANCH_REG x12 @@ -457,14 +624,14 @@ NESTED_END TheUMEntryPrestub, _TEXT NESTED_ENTRY UMThunkStub, _TEXT, UnhandledExceptionHandlerUnix // Save arguments and return address - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-96 // 64 for regArgs, 8 for x19 & 8 for x12 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-112 // 72 for regArgs, 8 for x19 & 8 for x12 // save callee saved reg x19. x19 is used in the method to store thread* - PROLOG_SAVE_REG x19, #88 + PROLOG_SAVE_REG x19, #96 SAVE_ARGUMENT_REGISTERS sp, 16 -#define UMThunkStub_HiddenArg 80 // offset of saved UMEntryThunk * -#define UMThunkStub_StackArgs 96 // offset of original stack args (total size of UMThunkStub frame) +#define UMThunkStub_HiddenArg 88 // offset of saved UMEntryThunk * +#define UMThunkStub_StackArgs 112 // offset of original stack args (total size of UMThunkStub frame) // save UMEntryThunk* str x12, [sp, #UMThunkStub_HiddenArg] @@ -542,8 +709,8 @@ LOCAL_LABEL(UMThunkStub_PostCall): str w4, [x19, #Thread__m_fPreemptiveGCDisabled] EPILOG_STACK_RESTORE - EPILOG_RESTORE_REG x19, #88 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #96 + EPILOG_RESTORE_REG x19, #96 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #112 EPILOG_RETURN @@ -581,7 +748,7 @@ LOCAL_LABEL(UMThunkStub_WrongAppDomain): bl C_FUNC(UM2MDoADCallBack) // restore integral return value - ldr x0, [fp, #16] + ldp x0, x1, [fp, #16] // restore FP or HFA return value RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 0 @@ -659,7 +826,8 @@ LOCAL_LABEL(UM2MThunk_WrapperHelper_RegArgumentsSetup): blr x16 // save integral return value - str x0, [x19] + stp x0, x1, [x19] + // save FP/HFA return values SAVE_FLOAT_ARGUMENT_REGISTERS x19, -1 * (SIZEOF__FloatArgumentRegisters + 16) @@ -675,7 +843,7 @@ NESTED_END UM2MThunk_WrapperHelper, _TEXT // ------------------------------------------------------------------ // Hijack function for functions which return a scalar type or a struct (value type) NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler - PROLOG_SAVE_REG_PAIR fp, lr, #-144 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-144 // Spill callee saved registers PROLOG_SAVE_REG_PAIR x19, x20, #16 PROLOG_SAVE_REG_PAIR x21, x22, #32 @@ -705,7 +873,7 @@ NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler EPILOG_RESTORE_REG_PAIR x23, x24, #48 EPILOG_RESTORE_REG_PAIR x25, x26, #64 EPILOG_RESTORE_REG_PAIR x27, x28, #80 - EPILOG_RESTORE_REG_PAIR fp, lr, #144 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #144 EPILOG_RETURN NESTED_END OnHijackTripThread, _TEXT @@ -750,6 +918,7 @@ NESTED_ENTRY CallEHFunclet, _TEXT, NoHandler // X3 = address of the location where the SP of funclet's caller (i.e. this helper) should be saved. // // Save the SP of this function + mov fp, sp str fp, [x3] ldr fp, [x2, #80] // offset of fp in CONTEXT relative to X19 @@ -850,15 +1019,117 @@ NESTED_ENTRY NakedThrowHelper2, _TEXT ,FixContextHandler NESTED_END NakedThrowHelper2, _TEXT + GenerateRedirectedStubWithFrame NakedThrowHelper, NakedThrowHelper2 +// ------------------------------------------------------------------ +// ResolveWorkerChainLookupAsmStub +// +// This method will perform a quick chained lookup of the entry if the +// initial cache lookup fails. +// +// On Entry: +// x9 contains the pointer to the current ResolveCacheElem +// x11 contains the address of the indirection (and the flags in the low two bits) +// x12 contains our contract the DispatchToken +// Must be preserved: +// x0 contains the instance object ref that we are making an interface call on +// x9 Must point to a ResolveCacheElem [For Sanity] +// [x1-x7] contains any additional register arguments for the interface method +// +// Loaded from x0 +// x13 contains our type the MethodTable (from object ref in x0) +// +// On Exit: +// x0, [x1-x7] arguments for the interface implementation target +// +// On Exit (to ResolveWorkerAsmStub): +// x11 contains the address of the indirection and the flags in the low two bits. +// x12 contains our contract (DispatchToken) +// x16,x17 will be trashed +// + +#define BACKPATCH_FLAG 1 +#define PROMOTE_CHAIN_FLAG 2 + + NESTED_ENTRY ResolveWorkerChainLookupAsmStub, _TEXT, NoHandler + + tst x11, #BACKPATCH_FLAG // First we check if x11 has the BACKPATCH_FLAG set + bne LOCAL_LABEL(Fail) // If the BACKPATCH_FLAGS is set we will go directly to the ResolveWorkerAsmStub + + ldr x13, [x0] // retrieve the MethodTable from the object ref in x0 +LOCAL_LABEL(MainLoop): + ldr x9, [x9, #ResolveCacheElem__pNext] // x9 <= the next entry in the chain + cmp x9, #0 + beq LOCAL_LABEL(Fail) + + ldp x16, x17, [x9] + cmp x16, x13 // compare our MT with the one in the ResolveCacheElem + bne LOCAL_LABEL(MainLoop) + + cmp x17, x12 // compare our DispatchToken with one in the ResolveCacheElem + bne LOCAL_LABEL(MainLoop) + +LOCAL_LABEL(Success): + ldr x13, =g_dispatch_cache_chain_success_counter + ldr x16, [x13] + subs x16, x16, #1 + str x16, [x13] + blt LOCAL_LABEL(Promote) + + ldr x16, [x9, #ResolveCacheElem__target] // get the ImplTarget + br x16 // branch to interface implemenation target + +LOCAL_LABEL(Promote): + // Move this entry to head postion of the chain + mov x16, #256 + str x16, [x13] // be quick to reset the counter so we don't get a bunch of contending threads + orr x11, x11, #PROMOTE_CHAIN_FLAG // set PROMOTE_CHAIN_FLAG + +LOCAL_LABEL(Fail): + b ResolveWorkerAsmStub // call the ResolveWorkerAsmStub method to transition into the VM + + NESTED_END ResolveWorkerChainLookupAsmStub, _TEXT + +// ------------------------------------------------------------------ +// void ResolveWorkerAsmStub(args in regs x0-x7 & stack and possibly retbuf arg in x8, x11:IndirectionCellAndFlags, x12:DispatchToken) +// +// The stub dispatch thunk which transfers control to VSD_ResolveWorker. + NESTED_ENTRY ResolveWorkerAsmStub, _TEXT, NoHandler + + PROLOG_WITH_TRANSITION_BLOCK + + add x0, sp, #__PWTB_TransitionBlock // pTransitionBlock + and x1, x11, #-4 // Indirection cell + mov x2, x12 // DispatchToken + and x3, x11, #3 // flag + bl VSD_ResolveWorker + mov x9, x0 + + EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + + EPILOG_BRANCH_REG x9 + + NESTED_END ResolveWorkerAsmStub, _TEXT + #ifdef FEATURE_READYTORUN NESTED_ENTRY DelayLoad_MethodCall_FakeProlog, _TEXT, NoHandler DelayLoad_MethodCall: .global DelayLoad_MethodCall + PROLOG_WITH_TRANSITION_BLOCK + + add x0, sp, #__PWTB_TransitionBlock // pTransitionBlock + mov x1, x11 // Indirection cell + mov x2, x9 // sectionIndex + mov x3, x10 // Module* + bl ExternalMethodFixupWorker + mov x12, x0 + + EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + // Share patch label + b ExternalMethodFixupPatchLabel - EMIT_BREAKPOINT NESTED_END DelayLoad_MethodCall_FakeProlog, _TEXT @@ -867,7 +1138,21 @@ NESTED_END DelayLoad_MethodCall_FakeProlog, _TEXT DelayLoad_Helper\suffix: .global DelayLoad_Helper\suffix - EMIT_BREAKPOINT + PROLOG_WITH_TRANSITION_BLOCK + + add x0, sp, #__PWTB_TransitionBlock // pTransitionBlock + mov x1, x11 // Indirection cell + mov x2, x9 // sectionIndex + mov x3, x10 // Module* + mov x4, \frameFlags + bl DynamicHelperWorker + cbnz x0, LOCAL_LABEL(FakeProlog\suffix\()_0) + ldr x0, [sp, #__PWTB_ArgumentRegisters] + EPILOG_WITH_TRANSITION_BLOCK_RETURN +LOCAL_LABEL(FakeProlog\suffix\()_0): + mov x12, x0 + EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + EPILOG_BRANCH_REG x12 NESTED_END DelayLoad_Helper\suffix\()_FakeProlog, _TEXT .endm @@ -875,7 +1160,6 @@ DelayLoad_Helper\suffix: DynamicHelper DynamicHelperFrameFlags_Default DynamicHelper DynamicHelperFrameFlags_ObjectArg, _Obj DynamicHelper DynamicHelperFrameFlags_ObjectArg | DynamicHelperFrameFlags_ObjectArg2, _ObjObj - #endif #ifdef FEATURE_PREJIT @@ -891,7 +1175,7 @@ NESTED_ENTRY StubDispatchFixupStub, _TEXT, NoHandler and x1, x11, #-4 // Indirection cell mov x2, #0 // sectionIndex mov x3, #0 // pModule - bl StubDispatchFixupWorker + bl C_FUNC(StubDispatchFixupWorker) mov x9, x0 EPILOG_WITH_TRANSITION_BLOCK_TAILCALL @@ -900,3 +1184,36 @@ NESTED_ENTRY StubDispatchFixupStub, _TEXT, NoHandler NESTED_END StubDispatchFixupStub, _TEXT #endif + +#ifdef FEATURE_COMINTEROP + +// Function used by COM interop to get floating point return value (since it's not in the same +// register(s) as non-floating point values). +// +// On entry// +// x0 : size of the FP result (4 or 8 bytes) +// x1 : pointer to 64-bit buffer to receive result +// +// On exit: +// buffer pointed to by x1 on entry contains the float or double argument as appropriate +// + LEAF_ENTRY getFPReturn + str d0, [x1] + LEAF_END + +// ------------------------------------------------------------------ +// Function used by COM interop to set floating point return value (since it's not in the same +// register(s) as non-floating point values). +// +// On entry: +// x0 : size of the FP result (4 or 8 bytes) +// x1 : 32-bit or 64-bit FP result +// +// On exit: +// s0 : float result if x0 == 4 +// d0 : double result if x0 == 8 +// + LEAF_ENTRY setFPReturn + fmov d0, x1 + LEAF_END +#endif diff --git a/src/vm/arm64/asmhelpers.asm b/src/vm/arm64/asmhelpers.asm index 2fc6a6a0c1d8..d76076588577 100644 --- a/src/vm/arm64/asmhelpers.asm +++ b/src/vm/arm64/asmhelpers.asm @@ -1311,4 +1311,4 @@ Fail #endif ; Must be at very end of file - END \ No newline at end of file + END diff --git a/src/vm/arm64/calldescrworkerarm64.S b/src/vm/arm64/calldescrworkerarm64.S index 803b94998d5b..7481fc74575c 100644 --- a/src/vm/arm64/calldescrworkerarm64.S +++ b/src/vm/arm64/calldescrworkerarm64.S @@ -46,27 +46,27 @@ LOCAL_LABEL(donestack): // If FP arguments are supplied in registers (x8 != NULL) then initialize all of them from the pointer // given in x8. - ldr x8, [x19,#CallDescrData__pFloatArgumentRegisters] - cbz x8, LOCAL_LABEL(NoFloatingPoint) - ldp d0, d1, [x8] - ldp d2, d3, [x8, #16] - ldp d4, d5, [x8, #32] - ldp d6, d7, [x8, #48] + ldr x9, [x19,#CallDescrData__pFloatArgumentRegisters] + cbz x9, LOCAL_LABEL(NoFloatingPoint) + ldp d0, d1, [x9] + ldp d2, d3, [x9, #16] + ldp d4, d5, [x9, #32] + ldp d6, d7, [x9, #48] LOCAL_LABEL(NoFloatingPoint): // Copy [pArgumentRegisters, ..., pArgumentRegisters + 56] // into x0, ..., x7 - ldr x8, [x19,#CallDescrData__pArgumentRegisters] - ldp x0, x1, [x8] - ldp x2, x3, [x8, #16] - ldp x4, x5, [x8, #32] - ldp x6, x7, [x8, #48] + ldr x9, [x19,#CallDescrData__pArgumentRegisters] + ldp x0, x1, [x9] + ldp x2, x3, [x9, #16] + ldp x4, x5, [x9, #32] + ldp x6, x7, [x9, #48] + ldr x8, [x9, #64] - // ARM64TODO: => see if anything special needs to be done for remoting // call pTarget - ldr x8, [x19,#CallDescrData__pTarget] - blr x8 + ldr x9, [x19,#CallDescrData__pTarget] + blr x9 ldr w3, [x19,#CallDescrData__fpReturnSize] @@ -110,7 +110,7 @@ LOCAL_LABEL(NoDoubleHFAReturn): LOCAL_LABEL(IntReturn): // Save return value into retbuf for int - str x0, [x19, #(CallDescrData__returnValue + 0)] + stp x0, x1, [x19, #(CallDescrData__returnValue + 0)] LOCAL_LABEL(ReturnDone): diff --git a/src/vm/arm64/pinvokestubs.S b/src/vm/arm64/pinvokestubs.S index f6c33ba4c280..c87e8004f07a 100644 --- a/src/vm/arm64/pinvokestubs.S +++ b/src/vm/arm64/pinvokestubs.S @@ -21,44 +21,28 @@ // $VASigCookieReg : register which contains the VASigCookie // $SaveFPArgs : "Yes" or "No" . For varidic functions FP Args are not present in FP regs // So need not save FP Args registers for vararg Pinvoke -.macro PINVOKE_STUB FuncPrefix,VASigCookieReg,HiddenArg,SaveFPArgs +.macro PINVOKE_STUB __PInvokeStubFuncName,__PInvokeGenStubFuncName,__PInvokeStubWorkerName,VASigCookieReg,HiddenArg,SaveFPArgs -#if NOTYET - GBLS __PInvokeStubFuncName - GBLS __PInvokeGenStubFuncName - GBLS __PInvokeStubWorkerName - IF "\FuncPrefix" == "GenericPInvokeCalli" -__PInvokeStubFuncName SETS "\FuncPrefix":CC:"Helper" - ELSE -__PInvokeStubFuncName SETS "\FuncPrefix":CC:"Stub" - ENDIF -__PInvokeGenStubFuncName SETS "\FuncPrefix":CC:"GenILStub" -__PInvokeStubWorkerName SETS "\FuncPrefix":CC:"StubWorker" - - IF "\VASigCookieReg" == "x1" -__PInvokeStubFuncName SETS "\__PInvokeStubFuncName":CC:"_RetBuffArg" -__PInvokeGenStubFuncName SETS "\__PInvokeGenStubFuncName":CC:"_RetBuffArg" - ENDIF - - NESTED_ENTRY \__PInvokeStubFuncName + NESTED_ENTRY \__PInvokeStubFuncName, _TEXT, NoHandler // get the stub ldr x9, [\VASigCookieReg, #VASigCookie__pNDirectILStub] // if null goto stub generation - cbz x9, %0 + cbz x9, LOCAL_LABEL(\__PInvokeStubFuncName\()_0) EPILOG_BRANCH_REG x9 -0 +LOCAL_LABEL(\__PInvokeStubFuncName\()_0): + EPILOG_BRANCH \__PInvokeGenStubFuncName - NESTED_END + NESTED_END \__PInvokeStubFuncName, _TEXT - NESTED_ENTRY \__PInvokeGenStubFuncName + NESTED_ENTRY \__PInvokeGenStubFuncName, _TEXT, NoHandler PROLOG_WITH_TRANSITION_BLOCK 0, \SaveFPArgs @@ -66,9 +50,9 @@ __PInvokeGenStubFuncName SETS "\__PInvokeGenStubFuncName":CC:"_RetBuffArg" mov x2, \HiddenArg // x1 = VaSigCookie - IF "\VASigCookieReg" != "x1" + .ifnc \VASigCookieReg, x1 mov x1, \VASigCookieReg - ENDIF + .endif // x0 = pTransitionBlock add x0, sp, #__PWTB_TransitionBlock @@ -86,10 +70,7 @@ __PInvokeGenStubFuncName SETS "\__PInvokeGenStubFuncName":CC:"_RetBuffArg" EPILOG_BRANCH \__PInvokeStubFuncName - NESTED_END -#else - EMIT_BREAKPOINT -#endif + NESTED_END \__PInvokeGenStubFuncName, _TEXT .endm // ------------------------------------------------------------------ @@ -100,7 +81,7 @@ __PInvokeGenStubFuncName SETS "\__PInvokeGenStubFuncName":CC:"_RetBuffArg" // x0 = VASigCookie* // x12 = MethodDesc * // -PINVOKE_STUB VarargPInvoke, x0, x12, 1 +PINVOKE_STUB VarargPInvokeStub, VarargPInvokeGenILStub, VarargPInvokeStubWorker, x0, x12, 0 // ------------------------------------------------------------------ @@ -111,7 +92,7 @@ PINVOKE_STUB VarargPInvoke, x0, x12, 1 // x15 = VASigCookie* // x14 = Unmanaged target // -PINVOKE_STUB GenericPInvokeCalli, x15, x14, 1 +PINVOKE_STUB GenericPInvokeCalliHelper, GenericPInvokeCalliGenILStub, GenericPInvokeCalliStubWorker, x15, x14, 1 // ------------------------------------------------------------------ // VarargPInvokeStub_RetBuffArg & VarargPInvokeGenILStub_RetBuffArg @@ -121,4 +102,4 @@ PINVOKE_STUB GenericPInvokeCalli, x15, x14, 1 // x1 = VASigCookie* // x12 = MethodDesc* // -PINVOKE_STUB VarargPInvoke, x1, x12, 0 +PINVOKE_STUB VarargPInvokeStub_RetBuffArg, VarargPInvokeGenILStub_RetBuffArg, VarargPInvokeStubWorker, x1, x12, 0 From 6caae84cb176cf2d68c16c2be9ce0996b55553ad Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Thu, 1 Dec 2016 14:06:29 -0500 Subject: [PATCH 02/24] [Arm64/Unix] Fix CONTEXTToNativeContext() --- src/pal/src/include/pal/context.h | 3 +-- src/pal/src/thread/context.cpp | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pal/src/include/pal/context.h b/src/pal/src/include/pal/context.h index 6857c130ee43..08fa05da7dd4 100644 --- a/src/pal/src/include/pal/context.h +++ b/src/pal/src/include/pal/context.h @@ -248,8 +248,7 @@ inline void *FPREG_Xstate_Ymmh(const ucontext_t *uc) #define MCREG_Sp(mc) ((mc).sp) #define MCREG_Pc(mc) ((mc).pc) -#define MCREG_PState(mc) ((mc).pstate) -#define MCREG_Cpsr(mc) ((mc).cpsr) +#define MCREG_Cpsr(mc) ((mc).pstate) #else // For FreeBSD, as found in x86/ucontext.h #define MCREG_Rbp(mc) ((mc).mc_rbp) diff --git a/src/pal/src/thread/context.cpp b/src/pal/src/thread/context.cpp index 0449df568b10..bdce0d578b1a 100644 --- a/src/pal/src/thread/context.cpp +++ b/src/pal/src/thread/context.cpp @@ -127,6 +127,8 @@ typedef int __ptrace_request; ASSIGN_REG(R12) #elif defined(_ARM64_) #define ASSIGN_CONTROL_REGS \ + ASSIGN_REG(Cpsr) \ + ASSIGN_REG(Fp) \ ASSIGN_REG(Sp) \ ASSIGN_REG(Lr) \ ASSIGN_REG(Pc) From 2e7f2d1299af2d1e8a692be401dbea5e8aac20ff Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Thu, 1 Dec 2016 14:08:22 -0500 Subject: [PATCH 03/24] [Arm64/Unix] ThrowExceptionFromContextInternal --- src/pal/src/arch/arm64/asmconstants.h | 81 ++++++++++++++++++++++++ src/pal/src/arch/arm64/context2.S | 76 +--------------------- src/pal/src/arch/arm64/exceptionhelper.S | 30 ++++++++- 3 files changed, 112 insertions(+), 75 deletions(-) create mode 100644 src/pal/src/arch/arm64/asmconstants.h diff --git a/src/pal/src/arch/arm64/asmconstants.h b/src/pal/src/arch/arm64/asmconstants.h new file mode 100644 index 000000000000..5bc77ad45a8e --- /dev/null +++ b/src/pal/src/arch/arm64/asmconstants.h @@ -0,0 +1,81 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __PAL_ARM64_ASMCONSTANTS_H__ +#define __PAL_ARM64_ASMCONSTANTS_H__ + + +#define CONTEXT_ContextFlags 0 +#define CONTEXT_Cpsr CONTEXT_ContextFlags+4 +#define CONTEXT_X0 CONTEXT_Cpsr+4 +#define CONTEXT_X1 CONTEXT_X0+8 +#define CONTEXT_X2 CONTEXT_X1+8 +#define CONTEXT_X3 CONTEXT_X2+8 +#define CONTEXT_X4 CONTEXT_X3+8 +#define CONTEXT_X5 CONTEXT_X4+8 +#define CONTEXT_X6 CONTEXT_X5+8 +#define CONTEXT_X7 CONTEXT_X6+8 +#define CONTEXT_X8 CONTEXT_X7+8 +#define CONTEXT_X9 CONTEXT_X8+8 +#define CONTEXT_X10 CONTEXT_X9+8 +#define CONTEXT_X11 CONTEXT_X10+8 +#define CONTEXT_X12 CONTEXT_X11+8 +#define CONTEXT_X13 CONTEXT_X12+8 +#define CONTEXT_X14 CONTEXT_X13+8 +#define CONTEXT_X15 CONTEXT_X14+8 +#define CONTEXT_X16 CONTEXT_X15+8 +#define CONTEXT_X17 CONTEXT_X16+8 +#define CONTEXT_X18 CONTEXT_X17+8 +#define CONTEXT_X19 CONTEXT_X18+8 +#define CONTEXT_X20 CONTEXT_X19+8 +#define CONTEXT_X21 CONTEXT_X20+8 +#define CONTEXT_X22 CONTEXT_X21+8 +#define CONTEXT_X23 CONTEXT_X22+8 +#define CONTEXT_X24 CONTEXT_X23+8 +#define CONTEXT_X25 CONTEXT_X24+8 +#define CONTEXT_X26 CONTEXT_X25+8 +#define CONTEXT_X27 CONTEXT_X26+8 +#define CONTEXT_X28 CONTEXT_X27+8 +#define CONTEXT_Fp CONTEXT_X28+8 +#define CONTEXT_Lr CONTEXT_Fp+8 +#define CONTEXT_Sp CONTEXT_Lr+8 +#define CONTEXT_Pc CONTEXT_Sp+8 +#define CONTEXT_NEON_OFFSET CONTEXT_Pc+8 +#define CONTEXT_V0 0 +#define CONTEXT_V1 CONTEXT_V0+16 +#define CONTEXT_V2 CONTEXT_V1+16 +#define CONTEXT_V3 CONTEXT_V2+16 +#define CONTEXT_V4 CONTEXT_V3+16 +#define CONTEXT_V5 CONTEXT_V4+16 +#define CONTEXT_V6 CONTEXT_V5+16 +#define CONTEXT_V7 CONTEXT_V6+16 +#define CONTEXT_V8 CONTEXT_V7+16 +#define CONTEXT_V9 CONTEXT_V8+16 +#define CONTEXT_V10 CONTEXT_V9+16 +#define CONTEXT_V11 CONTEXT_V10+16 +#define CONTEXT_V12 CONTEXT_V11+16 +#define CONTEXT_V13 CONTEXT_V12+16 +#define CONTEXT_V14 CONTEXT_V13+16 +#define CONTEXT_V15 CONTEXT_V14+16 +#define CONTEXT_V16 CONTEXT_V15+16 +#define CONTEXT_V17 CONTEXT_V16+16 +#define CONTEXT_V18 CONTEXT_V17+16 +#define CONTEXT_V19 CONTEXT_V18+16 +#define CONTEXT_V20 CONTEXT_V19+16 +#define CONTEXT_V21 CONTEXT_V20+16 +#define CONTEXT_V22 CONTEXT_V21+16 +#define CONTEXT_V23 CONTEXT_V22+16 +#define CONTEXT_V24 CONTEXT_V23+16 +#define CONTEXT_V25 CONTEXT_V24+16 +#define CONTEXT_V26 CONTEXT_V25+16 +#define CONTEXT_V27 CONTEXT_V26+16 +#define CONTEXT_V28 CONTEXT_V27+16 +#define CONTEXT_V29 CONTEXT_V28+16 +#define CONTEXT_V30 CONTEXT_V29+16 +#define CONTEXT_V31 CONTEXT_V30+16 +#define CONTEXT_FLOAT_CONTROL_OFFSET CONTEXT_V31 +#define CONTEXT_Fpcr 0 +#define CONTEXT_Fpsr CONTEXT_Fpcr+4 + +#endif diff --git a/src/pal/src/arch/arm64/context2.S b/src/pal/src/arch/arm64/context2.S index a64e62c94d54..4c8675c3a7ea 100644 --- a/src/pal/src/arch/arm64/context2.S +++ b/src/pal/src/arch/arm64/context2.S @@ -8,6 +8,7 @@ // #include "unixasmmacros.inc" +#include "asmconstants.h" #define CONTEXT_ARM64 0x00400000L @@ -18,77 +19,6 @@ #define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) -#define CONTEXT_ContextFlags 0 -#define CONTEXT_Cpsr CONTEXT_ContextFlags+4 -#define CONTEXT_X0 CONTEXT_Cpsr+4 -#define CONTEXT_X1 CONTEXT_X0+8 -#define CONTEXT_X2 CONTEXT_X1+8 -#define CONTEXT_X3 CONTEXT_X2+8 -#define CONTEXT_X4 CONTEXT_X3+8 -#define CONTEXT_X5 CONTEXT_X4+8 -#define CONTEXT_X6 CONTEXT_X5+8 -#define CONTEXT_X7 CONTEXT_X6+8 -#define CONTEXT_X8 CONTEXT_X7+8 -#define CONTEXT_X9 CONTEXT_X8+8 -#define CONTEXT_X10 CONTEXT_X9+8 -#define CONTEXT_X11 CONTEXT_X10+8 -#define CONTEXT_X12 CONTEXT_X11+8 -#define CONTEXT_X13 CONTEXT_X12+8 -#define CONTEXT_X14 CONTEXT_X13+8 -#define CONTEXT_X15 CONTEXT_X14+8 -#define CONTEXT_X16 CONTEXT_X15+8 -#define CONTEXT_X17 CONTEXT_X16+8 -#define CONTEXT_X18 CONTEXT_X17+8 -#define CONTEXT_X19 CONTEXT_X18+8 -#define CONTEXT_X20 CONTEXT_X19+8 -#define CONTEXT_X21 CONTEXT_X20+8 -#define CONTEXT_X22 CONTEXT_X21+8 -#define CONTEXT_X23 CONTEXT_X22+8 -#define CONTEXT_X24 CONTEXT_X23+8 -#define CONTEXT_X25 CONTEXT_X24+8 -#define CONTEXT_X26 CONTEXT_X25+8 -#define CONTEXT_X27 CONTEXT_X26+8 -#define CONTEXT_X28 CONTEXT_X27+8 -#define CONTEXT_Fp CONTEXT_X28+8 -#define CONTEXT_Lr CONTEXT_Fp+8 -#define CONTEXT_Sp CONTEXT_Lr+8 -#define CONTEXT_Pc CONTEXT_Sp+8 -#define CONTEXT_NEON_OFFSET CONTEXT_Pc+8 -#define CONTEXT_V0 0 -#define CONTEXT_V1 CONTEXT_V0+16 -#define CONTEXT_V2 CONTEXT_V1+16 -#define CONTEXT_V3 CONTEXT_V2+16 -#define CONTEXT_V4 CONTEXT_V3+16 -#define CONTEXT_V5 CONTEXT_V4+16 -#define CONTEXT_V6 CONTEXT_V5+16 -#define CONTEXT_V7 CONTEXT_V6+16 -#define CONTEXT_V8 CONTEXT_V7+16 -#define CONTEXT_V9 CONTEXT_V8+16 -#define CONTEXT_V10 CONTEXT_V9+16 -#define CONTEXT_V11 CONTEXT_V10+16 -#define CONTEXT_V12 CONTEXT_V11+16 -#define CONTEXT_V13 CONTEXT_V12+16 -#define CONTEXT_V14 CONTEXT_V13+16 -#define CONTEXT_V15 CONTEXT_V14+16 -#define CONTEXT_V16 CONTEXT_V15+16 -#define CONTEXT_V17 CONTEXT_V16+16 -#define CONTEXT_V18 CONTEXT_V17+16 -#define CONTEXT_V19 CONTEXT_V18+16 -#define CONTEXT_V20 CONTEXT_V19+16 -#define CONTEXT_V21 CONTEXT_V20+16 -#define CONTEXT_V22 CONTEXT_V21+16 -#define CONTEXT_V23 CONTEXT_V22+16 -#define CONTEXT_V24 CONTEXT_V23+16 -#define CONTEXT_V25 CONTEXT_V24+16 -#define CONTEXT_V26 CONTEXT_V25+16 -#define CONTEXT_V27 CONTEXT_V26+16 -#define CONTEXT_V28 CONTEXT_V27+16 -#define CONTEXT_V29 CONTEXT_V28+16 -#define CONTEXT_V30 CONTEXT_V29+16 -#define CONTEXT_V31 CONTEXT_V30+16 -#define CONTEXT_FLOAT_CONTROL_OFFSET CONTEXT_V31 -#define CONTEXT_Fpcr 0 -#define CONTEXT_Fpsr CONTEXT_Fpcr+4 // Incoming: // x0: Context* @@ -115,10 +45,8 @@ LEAF_ENTRY CONTEXT_CaptureContext, _TEXT ldr x2, [sp, 24] str w2, [x0, CONTEXT_Cpsr] stp fp, lr, [x0, CONTEXT_Fp] - add sp, sp, #32 - mov x2, sp + add x2, sp, #32 stp x2, lr, [x0, CONTEXT_Sp] - sub sp, sp, #32 LOCAL_LABEL(Done_CONTEXT_CONTROL): // we dont clobber x1 in the CONTEXT_CONTROL case diff --git a/src/pal/src/arch/arm64/exceptionhelper.S b/src/pal/src/arch/arm64/exceptionhelper.S index 4fdcfc5eb1da..80075ae8ec51 100644 --- a/src/pal/src/arch/arm64/exceptionhelper.S +++ b/src/pal/src/arch/arm64/exceptionhelper.S @@ -3,7 +3,35 @@ // See the LICENSE file in the project root for more information. #include "unixasmmacros.inc" +#include "asmconstants.h" +////////////////////////////////////////////////////////////////////////// +// +// This function creates a stack frame right below the target frame, restores all callee +// saved registers, SP, and LR from the passed in context. +// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. +// EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT - EMIT_BREAKPOINT + // Save the FP & LR to the stack so that the unwind can work at the instruction after + // loading the FP from the context, but before loading the SP from the context. + stp fp, lr, [sp, -16]! + + ldr x19, [x0, #(CONTEXT_X19)] + ldr x20, [x0, #(CONTEXT_X20)] + ldr x21, [x0, #(CONTEXT_X21)] + ldr x22, [x0, #(CONTEXT_X22)] + ldr x23, [x0, #(CONTEXT_X23)] + ldr x24, [x0, #(CONTEXT_X24)] + ldr x25, [x0, #(CONTEXT_X25)] + ldr x26, [x0, #(CONTEXT_X26)] + ldr x27, [x0, #(CONTEXT_X27)] + ldr x28, [x0, #(CONTEXT_X28)] + ldr fp, [x0, #(CONTEXT_Fp)] + ldr lr, [x0, #(CONTEXT_Pc)] + ldr x2, [x0, #(CONTEXT_Sp)] + mov sp, x2 + + // The PAL_SEHException pointer + mov x0, x1 + b EXTERNAL_C_FUNC(ThrowExceptionHelper) LEAF_END ThrowExceptionFromContextInternal, _TEXT From 86cfff3355cbbe8de94022a24a6b291cbc60763d Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Wed, 7 Dec 2016 14:43:55 -0500 Subject: [PATCH 04/24] [Arm64/Unix] Preserve x8 argument register --- src/pal/inc/unixasmmacrosarm64.inc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pal/inc/unixasmmacrosarm64.inc b/src/pal/inc/unixasmmacrosarm64.inc index 9414be70a9a1..522c7adb4390 100644 --- a/src/pal/inc/unixasmmacrosarm64.inc +++ b/src/pal/inc/unixasmmacrosarm64.inc @@ -180,6 +180,7 @@ C_FUNC(\Name\()_End): stp x2, x3, [\reg, #(\ofs + 16)] stp x4, x5, [\reg, #(\ofs + 32)] stp x6, x7, [\reg, #(\ofs + 48)] + str x8, [\reg, #(\ofs + 64)] .endm @@ -199,6 +200,7 @@ C_FUNC(\Name\()_End): ldp x2, x3, [\reg, #(\ofs + 16)] ldp x4, x5, [\reg, #(\ofs + 32)] ldp x6, x7, [\reg, #(\ofs + 48)] + ldr x8, [\reg, #(\ofs + 64)] .endm From 2fad44a3fd79fbdae951fd0bab9d3e4916b36692 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Thu, 22 Dec 2016 11:14:32 -0500 Subject: [PATCH 05/24] [ARM64/Unix] Add CFI directives Add native unwind info --- src/debug/ee/arm64/dbghelpers.S | 27 +++++---- src/pal/inc/unixasmmacrosarm64.inc | 88 ++++++++++++++++++++------- src/vm/arm64/asmhelpers.S | 92 ++++++++++++++--------------- src/vm/arm64/calldescrworkerarm64.S | 8 +-- 4 files changed, 132 insertions(+), 83 deletions(-) diff --git a/src/debug/ee/arm64/dbghelpers.S b/src/debug/ee/arm64/dbghelpers.S index 5328d69ef7f5..64932f322be1 100644 --- a/src/debug/ee/arm64/dbghelpers.S +++ b/src/debug/ee/arm64/dbghelpers.S @@ -1,7 +1,8 @@ -//Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#include "asmconstants.h" #include "unixasmmacros.inc" // @@ -14,18 +15,18 @@ // @dbgtodo- once we port Funceval, use the ExceptionHijack stub instead of this func-eval stub. NESTED_ENTRY FuncEvalHijack, _TEXT, UnhandledExceptionHandlerUnix -// NOTE: FuncEvalHijackPersonalityRoutine is dependent on the stack layout so if -// you change the prolog you will also need to update the personality routine. - -// push arg to the stack so our personality routine can find it -// push lr to get good stacktrace in debugger - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-32 - str x0, [sp, #16] - // FuncEvalHijackWorker returns the address we should jump to. - bl FuncEvalHijackWorker - - EPILOG_STACK_FREE 32 - EPILOG_BRANCH_REG x0 + // NOTE: FuncEvalHijackPersonalityRoutine is dependent on the stack layout so if + // you change the prolog you will also need to update the personality routine. + + // push arg to the stack so our personality routine can find it + // push lr to get good stacktrace in debugger + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -32 + str x0, [sp, #16] + // FuncEvalHijackWorker returns the address we should jump to. + bl FuncEvalHijackWorker + + EPILOG_STACK_FREE 32 + EPILOG_BRANCH_REG x0 NESTED_END FuncEvalHijack // This is the general purpose hijacking stub. The DacDbi Hijack primitive will diff --git a/src/pal/inc/unixasmmacrosarm64.inc b/src/pal/inc/unixasmmacrosarm64.inc index 522c7adb4390..ed73748e41ad 100644 --- a/src/pal/inc/unixasmmacrosarm64.inc +++ b/src/pal/inc/unixasmmacrosarm64.inc @@ -31,8 +31,8 @@ C_FUNC(\Name): .endm .macro LEAF_END_MARKED Name, Section - .global C_FUNC(\Name\()_End) C_FUNC(\Name\()_End): + .global C_FUNC(\Name\()_End) LEAF_END \Name, \Section .endm @@ -48,18 +48,23 @@ C_FUNC(\Name\()_End): .macro EPILOG_STACK_FREE Size add sp, sp, \Size + .cfi_adjust_cfa_offset -\Size .endm .macro EPILOG_STACK_RESTORE mov sp, fp + .cfi_restore sp .endm .macro PROLOG_SAVE_REG reg, ofs str \reg, [sp, \ofs] + .cfi_rel_offset \reg, \ofs .endm .macro PROLOG_SAVE_REG_PAIR reg1, reg2, ofs stp \reg1, \reg2, [sp, \ofs] + .cfi_rel_offset \reg1, \ofs + .cfi_rel_offset \reg2, \ofs + 8 .ifc \reg1, fp mov fp, sp .endif @@ -67,6 +72,9 @@ C_FUNC(\Name\()_End): .macro PROLOG_SAVE_REG_PAIR_INDEXED reg1, reg2, ofs stp \reg1, \reg2, [sp, \ofs]! + .cfi_adjust_cfa_offset -\ofs + .cfi_rel_offset \reg1, 0 + .cfi_rel_offset \reg2, 8 .ifc \reg1, fp mov fp, sp .endif @@ -74,14 +82,20 @@ C_FUNC(\Name\()_End): .macro EPILOG_RESTORE_REG reg, ofs ldr \reg, [sp, \ofs] + .cfi_restore \reg1 .endm .macro EPILOG_RESTORE_REG_PAIR reg1, reg2, ofs ldp \reg1, \reg2, [sp, \ofs] + .cfi_restore \reg1 + .cfi_restore \reg2 .endm .macro EPILOG_RESTORE_REG_PAIR_INDEXED reg1, reg2, ofs ldp \reg1, \reg2, [sp], \ofs + .cfi_restore \reg1 + .cfi_restore \reg2 + .cfi_adjust_cfa_offset -\ofs .endm .macro EPILOG_RETURN @@ -148,13 +162,13 @@ C_FUNC(\Name\()_End): __PWTB_StackAlloc = __PWTB_TransitionBlock __PWTB_ArgumentRegisters = __PWTB_StackAlloc + 96 - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-176 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -176 // Spill callee saved registers - PROLOG_SAVE_REG_PAIR x19, x20, #16 - PROLOG_SAVE_REG_PAIR x21, x22, #32 - PROLOG_SAVE_REG_PAIR x23, x24, #48 - PROLOG_SAVE_REG_PAIR x25, x26, #64 - PROLOG_SAVE_REG_PAIR x27, x28, #80 + PROLOG_SAVE_REG_PAIR x19, x20, 16 + PROLOG_SAVE_REG_PAIR x21, x22, 32 + PROLOG_SAVE_REG_PAIR x23, x24, 48 + PROLOG_SAVE_REG_PAIR x25, x26, 64 + PROLOG_SAVE_REG_PAIR x27, x28, 80 // Allocate space for the rest of the frame PROLOG_STACK_ALLOC __PWTB_StackAlloc @@ -177,10 +191,19 @@ C_FUNC(\Name\()_End): .macro SAVE_ARGUMENT_REGISTERS reg, ofs stp x0, x1, [\reg, #(\ofs)] + .cfi_rel_offset x0, \ofs + .cfi_rel_offset x1, \ofs + 8 stp x2, x3, [\reg, #(\ofs + 16)] + .cfi_rel_offset x2, \ofs + 16 + .cfi_rel_offset x3, \ofs + 24 stp x4, x5, [\reg, #(\ofs + 32)] + .cfi_rel_offset x4, \ofs + 32 + .cfi_rel_offset x5, \ofs + 40 stp x6, x7, [\reg, #(\ofs + 48)] + .cfi_rel_offset x6, \ofs + 48 + .cfi_rel_offset x7, \ofs + 56 str x8, [\reg, #(\ofs + 64)] + .cfi_rel_offset x8, \ofs + 64 .endm @@ -188,28 +211,53 @@ C_FUNC(\Name\()_End): .macro SAVE_FLOAT_ARGUMENT_REGISTERS reg, ofs stp d0, d1, [\reg, #(\ofs)] + .cfi_rel_offset d0, \ofs + 0 + .cfi_rel_offset d1, \ofs + 8 stp d2, d3, [\reg, #(\ofs + 16)] + .cfi_rel_offset d2, \ofs + 16 + .cfi_rel_offset d3, \ofs + 24 stp d4, d5, [\reg, #(\ofs + 32)] + .cfi_rel_offset d4, \ofs + 32 + .cfi_rel_offset d5, \ofs + 40 stp d6, d7, [\reg, #(\ofs + 48)] + .cfi_rel_offset d6, \ofs + 48 + .cfi_rel_offset d7, \ofs + 56 .endm .macro RESTORE_ARGUMENT_REGISTERS reg, ofs ldp x0, x1, [\reg, #(\ofs)] + .cfi_restore x0 + .cfi_restore x1 ldp x2, x3, [\reg, #(\ofs + 16)] + .cfi_restore x2 + .cfi_restore x3 ldp x4, x5, [\reg, #(\ofs + 32)] + .cfi_restore x4 + .cfi_restore x5 ldp x6, x7, [\reg, #(\ofs + 48)] + .cfi_restore x6 + .cfi_restore x7 ldr x8, [\reg, #(\ofs + 64)] + .cfi_restore x8 .endm .macro RESTORE_FLOAT_ARGUMENT_REGISTERS reg, ofs ldp d0, d1, [\reg, #(\ofs)] + .cfi_restore d0 + .cfi_restore d1 ldp d2, d3, [\reg, #(\ofs + 16)] + .cfi_restore d2 + .cfi_restore d3 ldp d4, d5, [\reg, #(\ofs + 32)] + .cfi_restore d4 + .cfi_restore d5 ldp d6, d7, [\reg, #(\ofs + 48)] + .cfi_restore d6 + .cfi_restore d7 .endm @@ -228,12 +276,12 @@ C_FUNC(\Name\()_End): EPILOG_STACK_FREE __PWTB_StackAlloc - EPILOG_RESTORE_REG_PAIR x19, x20, #16 - EPILOG_RESTORE_REG_PAIR x21, x22, #32 - EPILOG_RESTORE_REG_PAIR x23, x24, #48 - EPILOG_RESTORE_REG_PAIR x25, x26, #64 - EPILOG_RESTORE_REG_PAIR x27, x28, #80 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #176 + EPILOG_RESTORE_REG_PAIR x19, x20, 16 + EPILOG_RESTORE_REG_PAIR x21, x22, 32 + EPILOG_RESTORE_REG_PAIR x23, x24, 48 + EPILOG_RESTORE_REG_PAIR x25, x26, 64 + EPILOG_RESTORE_REG_PAIR x27, x28, 80 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 176 ret .endm @@ -253,12 +301,12 @@ C_FUNC(\Name\()_End): EPILOG_STACK_FREE __PWTB_StackAlloc - EPILOG_RESTORE_REG_PAIR x19, x20, #16 - EPILOG_RESTORE_REG_PAIR x21, x22, #32 - EPILOG_RESTORE_REG_PAIR x23, x24, #48 - EPILOG_RESTORE_REG_PAIR x25, x26, #64 - EPILOG_RESTORE_REG_PAIR x27, x28, #80 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #176 + EPILOG_RESTORE_REG_PAIR x19, x20, 16 + EPILOG_RESTORE_REG_PAIR x21, x22, 32 + EPILOG_RESTORE_REG_PAIR x23, x24, 48 + EPILOG_RESTORE_REG_PAIR x25, x26, 64 + EPILOG_RESTORE_REG_PAIR x27, x28, 80 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 176 .endm @@ -282,7 +330,7 @@ __RedirectionFuncName SETS "|?RedirectedHandledJITCaseFor":CC:"$reason":CC:"@Thr IMPORT $__RedirectionFuncName NESTED_ENTRY $__RedirectionStubFuncName - PROLOG_SAVE_REG_PAIR fp, lr, #-16 + PROLOG_SAVE_REG_PAIR fp, lr, -16 sub sp, sp, #16 // stack slot for CONTEXT * and padding //REDIRECTSTUB_SP_OFFSET_CONTEXT is defined in asmconstants.h and is used in GetCONTEXTFromRedirectedStubStackFrame diff --git a/src/vm/arm64/asmhelpers.S b/src/vm/arm64/asmhelpers.S index 7c83627bba8e..265d74d9ac0a 100644 --- a/src/vm/arm64/asmhelpers.S +++ b/src/vm/arm64/asmhelpers.S @@ -120,7 +120,7 @@ LEAF_END HelperMethodFrameRestoreState, _TEXT // The call in ndirect import precode points to this function. NESTED_ENTRY NDirectImportThunk, _TEXT, NoHandler - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-160 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -160 SAVE_ARGUMENT_REGISTERS sp, 16 SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88 @@ -131,7 +131,7 @@ NESTED_ENTRY NDirectImportThunk, _TEXT, NoHandler // pop the stack and restore original register state RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88 RESTORE_ARGUMENT_REGISTERS sp, 16 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #160 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 160 // If we got back from NDirectImportWorker, the MD has been successfully // linked. Proceed to execute the original DLL call. @@ -264,7 +264,7 @@ WRITE_BARRIER_END JIT_CheckedWriteBarrier // WRITE_BARRIER_ENTRY JIT_WriteBarrier dmb ST - str x15, [x14] + str x15, [x14] #ifdef WRITE_BARRIER_CHECK // Update GC Shadow Heap @@ -368,7 +368,7 @@ LEAF_END JIT_PatchedCodeLast, _TEXT NESTED_ENTRY VirtualMethodFixupStub, _TEXT, NoHandler // Save arguments and return address - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-160 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -160 SAVE_ARGUMENT_REGISTERS sp, 16 SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88 @@ -388,7 +388,7 @@ NESTED_ENTRY VirtualMethodFixupStub, _TEXT, NoHandler // pop the stack and restore original register state RESTORE_ARGUMENT_REGISTERS sp, 16 RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #160 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 160 PATCH_LABEL VirtualMethodFixupPatchLabel @@ -472,7 +472,7 @@ LEAF_END SinglecastDelegateInvokeStub, _TEXT NESTED_ENTRY ComCallPreStub, _TEXT, NoHandler // Save arguments and return address - PROLOG_SAVE_REG_PAIR fp, lr, #-ComCallPreStub_FirstStackAdjust! + PROLOG_SAVE_REG_PAIR fp, lr, -ComCallPreStub_FirstStackAdjust! PROLOG_STACK_ALLOC ComCallPreStub_StackAlloc SAVE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc) @@ -493,7 +493,7 @@ LEAF_END SinglecastDelegateInvokeStub, _TEXT RESTORE_ARGUMENT_REGISTERS sp, (16+ComCallPreStub_StackAlloc) EPILOG_STACK_FREE ComCallPreStub_StackAlloc - EPILOG_RESTORE_REG_PAIR fp, lr, #ComCallPreStub_FirstStackAdjust! + EPILOG_RESTORE_REG_PAIR fp, lr, ComCallPreStub_FirstStackAdjust! // and tailcall to the actual method EPILOG_BRANCH_REG x12 @@ -503,7 +503,7 @@ ComCallPreStub_ErrorExit // pop the stack EPILOG_STACK_FREE ComCallPreStub_StackAlloc - EPILOG_RESTORE_REG_PAIR fp, lr, #ComCallPreStub_FirstStackAdjust! + EPILOG_RESTORE_REG_PAIR fp, lr, ComCallPreStub_FirstStackAdjust! EPILOG_RETURN @@ -522,7 +522,7 @@ ComCallPreStub_ErrorExit NESTED_ENTRY GenericComCallStub, _TEXT, NoHandler // Save arguments and return address - PROLOG_SAVE_REG_PAIR fp, lr, #-GenericComCallStub_FirstStackAdjust! + PROLOG_SAVE_REG_PAIR fp, lr, -GenericComCallStub_FirstStackAdjust! PROLOG_STACK_ALLOC GenericComCallStub_StackAlloc SAVE_ARGUMENT_REGISTERS sp, (16+GenericComCallStub_StackAlloc) @@ -534,7 +534,7 @@ ComCallPreStub_ErrorExit // pop the stack EPILOG_STACK_FREE GenericComCallStub_StackAlloc - EPILOG_RESTORE_REG_PAIR fp, lr, #GenericComCallStub_FirstStackAdjust! + EPILOG_RESTORE_REG_PAIR fp, lr, GenericComCallStub_FirstStackAdjust! EPILOG_RETURN @@ -555,7 +555,7 @@ ComCallPreStub_ErrorExit // NESTED_ENTRY COMToCLRDispatchHelper, _TEXT,CallDescrWorkerUnwindFrameChainHandler - PROLOG_SAVE_REG_PAIR fp, lr, #-16! + PROLOG_SAVE_REG_PAIR fp, lr, -16! cbz x0, COMToCLRDispatchHelper_RegSetup @@ -586,7 +586,7 @@ COMToCLRDispatchHelper_RegSetup blr lr EPILOG_STACK_RESTORE - EPILOG_RESTORE_REG_PAIR fp, lr, #16! + EPILOG_RESTORE_REG_PAIR fp, lr, 16! EPILOG_RETURN NESTED_END COMToCLRDispatchHelper, _TEXT @@ -598,7 +598,7 @@ COMToCLRDispatchHelper_RegSetup NESTED_ENTRY TheUMEntryPrestub, _TEXT, UnhandledExceptionHandlerUnix // Save arguments and return address - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-160 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -160 SAVE_ARGUMENT_REGISTERS sp, 16 SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88 @@ -611,7 +611,7 @@ NESTED_ENTRY TheUMEntryPrestub, _TEXT, UnhandledExceptionHandlerUnix // pop the stack and restore original register state RESTORE_ARGUMENT_REGISTERS sp, 16 RESTORE_FLOAT_ARGUMENT_REGISTERS sp, 88 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #160 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 160 // and tailcall to the actual method EPILOG_BRANCH_REG x12 @@ -624,9 +624,9 @@ NESTED_END TheUMEntryPrestub, _TEXT NESTED_ENTRY UMThunkStub, _TEXT, UnhandledExceptionHandlerUnix // Save arguments and return address - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-112 // 72 for regArgs, 8 for x19 & 8 for x12 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -112 // 72 for regArgs, 8 for x19 & 8 for x12 // save callee saved reg x19. x19 is used in the method to store thread* - PROLOG_SAVE_REG x19, #96 + PROLOG_SAVE_REG x19, 96 SAVE_ARGUMENT_REGISTERS sp, 16 @@ -709,8 +709,8 @@ LOCAL_LABEL(UMThunkStub_PostCall): str w4, [x19, #Thread__m_fPreemptiveGCDisabled] EPILOG_STACK_RESTORE - EPILOG_RESTORE_REG x19, #96 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #112 + EPILOG_RESTORE_REG x19, 96 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 112 EPILOG_RETURN @@ -768,8 +768,8 @@ NESTED_END UMThunkStub, _TEXT NESTED_ENTRY UM2MThunk_WrapperHelper, _TEXT, NoHandler - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-32 - PROLOG_SAVE_REG x19, #16 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -32 + PROLOG_SAVE_REG x19, 16 // save pThunkArgs in non-volatile reg. It is required after return from call to ILStub @@ -832,8 +832,8 @@ LOCAL_LABEL(UM2MThunk_WrapperHelper_RegArgumentsSetup): SAVE_FLOAT_ARGUMENT_REGISTERS x19, -1 * (SIZEOF__FloatArgumentRegisters + 16) EPILOG_STACK_RESTORE - EPILOG_RESTORE_REG x19, #16 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #32 + EPILOG_RESTORE_REG x19, 16 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 32 EPILOG_RETURN NESTED_END UM2MThunk_WrapperHelper, _TEXT @@ -842,14 +842,14 @@ NESTED_END UM2MThunk_WrapperHelper, _TEXT #ifdef FEATURE_HIJACK // ------------------------------------------------------------------ // Hijack function for functions which return a scalar type or a struct (value type) -NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-144 - // Spill callee saved registers - PROLOG_SAVE_REG_PAIR x19, x20, #16 - PROLOG_SAVE_REG_PAIR x21, x22, #32 - PROLOG_SAVE_REG_PAIR x23, x24, #48 - PROLOG_SAVE_REG_PAIR x25, x26, #64 - PROLOG_SAVE_REG_PAIR x27, x28, #80 + NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -144 + // Spill callee saved registers + PROLOG_SAVE_REG_PAIR x19, x20, 16 + PROLOG_SAVE_REG_PAIR x21, x22, 32 + PROLOG_SAVE_REG_PAIR x23, x24, 48 + PROLOG_SAVE_REG_PAIR x25, x26, 64 + PROLOG_SAVE_REG_PAIR x27, x28, 80 // save any integral return value(s) stp x0, x1, [sp, #96] @@ -860,7 +860,7 @@ NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler mov x0, sp bl OnHijackWorker - + // restore any integral return value(s) ldp x0, x1, [sp, #96] @@ -868,14 +868,14 @@ NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler ldp d0, d1, [sp, #112] ldp d2, d3, [sp, #128] - EPILOG_RESTORE_REG_PAIR x19, x20, #16 - EPILOG_RESTORE_REG_PAIR x21, x22, #32 - EPILOG_RESTORE_REG_PAIR x23, x24, #48 - EPILOG_RESTORE_REG_PAIR x25, x26, #64 - EPILOG_RESTORE_REG_PAIR x27, x28, #80 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #144 + EPILOG_RESTORE_REG_PAIR x19, x20, 16 + EPILOG_RESTORE_REG_PAIR x21, x22, 32 + EPILOG_RESTORE_REG_PAIR x23, x24, 48 + EPILOG_RESTORE_REG_PAIR x25, x26, 64 + EPILOG_RESTORE_REG_PAIR x27, x28, 80 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 144 EPILOG_RETURN -NESTED_END OnHijackTripThread, _TEXT + NESTED_END OnHijackTripThread, _TEXT #endif // FEATURE_HIJACK @@ -906,9 +906,9 @@ NESTED_ENTRY CallEHFunclet, _TEXT, NoHandler // sp in fp. If sp is saved in fp in prolog then it is not expected that fp can change in the body // of method. However, this method needs to be able to change fp before calling funclet. // This is required to access locals in funclet. - PROLOG_SAVE_REG_PAIR_INDEXED x19,x20, #-16 - PROLOG_SAVE_REG fp, #0 - PROLOG_SAVE_REG lr, #8 + PROLOG_SAVE_REG_PAIR_INDEXED x19,x20, -16 + PROLOG_SAVE_REG fp, 0 + PROLOG_SAVE_REG lr, 8 // On entry: // @@ -927,7 +927,7 @@ NESTED_ENTRY CallEHFunclet, _TEXT, NoHandler blr x1 nop - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #16 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 16 EPILOG_RETURN NESTED_END CallEHFunclet, _TEXT @@ -936,7 +936,7 @@ NESTED_END CallEHFunclet, _TEXT // frame pointer for accessing the locals in the parent method. NESTED_ENTRY CallEHFilterFunclet, _TEXT, NoHandler - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-16 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -16 // On entry: // @@ -950,7 +950,7 @@ NESTED_ENTRY CallEHFilterFunclet, _TEXT, NoHandler // Invoke the filter funclet blr x2 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #16 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 16 EPILOG_RETURN NESTED_END CallEHFilterFunclet, _TEXT @@ -969,7 +969,7 @@ NESTED_END CallEHFilterFunclet, _TEXT // IN: lr: original IP before redirect // - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-16 + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -16 PROLOG_STACK_ALLOC FaultingExceptionFrame_StackAlloc // At this point, the stack maybe misaligned if the thread abort was asynchronously @@ -1007,7 +1007,7 @@ NESTED_END CallEHFilterFunclet, _TEXT // NESTED_ENTRY NakedThrowHelper2, _TEXT ,FixContextHandler - PROLOG_SAVE_REG_PAIR_INDEXED fp,lr, #-16 + PROLOG_SAVE_REG_PAIR_INDEXED fp,lr, -16 // On entry: // diff --git a/src/vm/arm64/calldescrworkerarm64.S b/src/vm/arm64/calldescrworkerarm64.S index 7481fc74575c..90b763940ab3 100644 --- a/src/vm/arm64/calldescrworkerarm64.S +++ b/src/vm/arm64/calldescrworkerarm64.S @@ -12,8 +12,8 @@ //void CallDescrWorkerInternal(CallDescrData * pCallDescrData); NESTED_ENTRY CallDescrWorkerInternal, _TEXT, UnhandledExceptionHandlerUnix - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, #-32 - PROLOG_SAVE_REG x19, #16 //the stack slot at sp+24 is empty for 16 byte alligment + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -32 + PROLOG_SAVE_REG x19, 16 //the stack slot at sp+24 is empty for 16 byte alligment mov x19, x0 // save pCallDescrData in x19 @@ -122,7 +122,7 @@ LOCAL_LABEL(ReturnDone): #endif EPILOG_STACK_RESTORE - EPILOG_RESTORE_REG x19, #16 //the stack slot at sp+24 is empty for 16 byte alligment - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, #32 + EPILOG_RESTORE_REG x19, 16 //the stack slot at sp+24 is empty for 16 byte alligment + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 32 EPILOG_RETURN NESTED_END CallDescrWorkerInternal, _TEXT From 011e693c3d88c4cff3ac51e30181abd45b61865c Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Thu, 22 Dec 2016 13:43:32 -0500 Subject: [PATCH 06/24] [Arm64/Unix] Fix RtlRestoreContext --- src/pal/src/arch/arm64/context2.S | 41 +++++++++++-------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/src/pal/src/arch/arm64/context2.S b/src/pal/src/arch/arm64/context2.S index 4c8675c3a7ea..3d1136ced21f 100644 --- a/src/pal/src/arch/arm64/context2.S +++ b/src/pal/src/arch/arm64/context2.S @@ -12,10 +12,15 @@ #define CONTEXT_ARM64 0x00400000L -#define CONTEXT_CONTROL (CONTEXT_ARM64 | 0x1L) -#define CONTEXT_INTEGER (CONTEXT_ARM64 | 0x2L) -#define CONTEXT_FLOATING_POINT (CONTEXT_ARM64 | 0x4L) -#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARM64 | 0x8L) +#define CONTEXT_CONTROL_BIT (0) +#define CONTEXT_INTEGER_BIT (1) +#define CONTEXT_FLOATING_POINT_BIT (2) +#define CONTEXT_DEBUG_REGISTERS_BIT (3) + +#define CONTEXT_CONTROL (CONTEXT_ARM64 | (1L << CONTEXT_CONTROL_BIT)) +#define CONTEXT_INTEGER (CONTEXT_ARM64 | (1 << CONTEXT_INTEGER_BIT)) +#define CONTEXT_FLOATING_POINT (CONTEXT_ARM64 | (1 << CONTEXT_FLOATING_POINT_BIT)) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARM64 | (1 << CONTEXT_DEBUG_REGISTERS_BIT)) #define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) @@ -152,14 +157,8 @@ LEAF_ENTRY RtlRestoreContext, _TEXT // since we potentially clobber x0 below, we'll bank it in x16 mov x16, x0 - ldr w2, [x16, CONTEXT_ContextFlags] - // clangs assembler doesn't seem to support the mov Wx, imm32 yet - movz w3, #0x40, lsl #16 - movk w3, #0x4 - mov w4, w3 - and w3, w2, w3 - cmp w3, w4 - b.ne LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT) + ldr w17, [x16, CONTEXT_ContextFlags] + tbz w17, #CONTEXT_FLOATING_POINT_BIT, LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT) add x16, x16, CONTEXT_NEON_OFFSET ldp q0, q1, [x16, CONTEXT_V0] @@ -184,12 +183,7 @@ LEAF_ENTRY RtlRestoreContext, _TEXT sub x16, x16, CONTEXT_NEON_OFFSET LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT): - movz w2, #0x40, lsl #16 - movk w2, #0x2 - mov w3, w2 - and w2, w1, w2 - cmp w2, w3 - b.ne LOCAL_LABEL(No_Restore_CONTEXT_INTEGER) + tbz w17, #CONTEXT_INTEGER_BIT, LOCAL_LABEL(No_Restore_CONTEXT_INTEGER) ldp x0, x1, [x16, CONTEXT_X0] ldp x2, x3, [x16, CONTEXT_X2] @@ -207,12 +201,7 @@ LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT): ldr x28, [x16, CONTEXT_X28] LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): - movz w2, #0x40, lsl #16 - movk w2, #0x2 - mov w3, w2 - and w2, w1, w2 - cmp w2, w3 - b.ne LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) + tbz w17, #CONTEXT_CONTROL_BIT, LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) ldr w17, [x16, CONTEXT_Cpsr] msr nzcv, x17 @@ -221,8 +210,8 @@ LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): mov sp, x17 ldr x17, [x16, CONTEXT_Pc] br x17 - + LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): - ret + ret LEAF_END RtlRestoreContext, _TEXT From efb56636180e388364a5d5655a46b6007e5539fb Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Thu, 29 Dec 2016 20:15:53 -0500 Subject: [PATCH 07/24] [Arm64/Unix] Restore FP from CurrentContextPointers --- src/vm/exceptionhandling.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp index 262d3526eb15..76af03723b00 100644 --- a/src/vm/exceptionhandling.cpp +++ b/src/vm/exceptionhandling.cpp @@ -448,14 +448,7 @@ void ExceptionTracker::UpdateNonvolatileRegisters(CONTEXT *pContextRecord, REGDI UPDATEREG(X26); UPDATEREG(X27); UPDATEREG(X28); - // Obtain value of Fp from CurrentContext instead of from CurrentContextPointers - // It should not matter. CurrentContextPointers does not have value of FP as this will - // require changes in MachState to also store pointer of FP which it does not do currently. - pContextRecord->Fp = pRegDisplay->pCurrentContext->Fp; - if (pAbortContext) - { - pAbortContext->Fp = pContextRecord->Fp; - } + UPDATEREG(Fp); #else PORTABILITY_ASSERT("ExceptionTracker::UpdateNonvolatileRegisters"); From 745ae83cdd54e607141bbe70dbd65c70bec18c48 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Wed, 4 Jan 2017 02:29:48 -0500 Subject: [PATCH 08/24] [Arm64/Unix] fix pointer math --- src/unwinder/arm64/unwinder_arm64.cpp | 6 +++--- src/vm/arm64/stubs.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/unwinder/arm64/unwinder_arm64.cpp b/src/unwinder/arm64/unwinder_arm64.cpp index e13c7b917d7a..c3b7102e7a62 100644 --- a/src/unwinder/arm64/unwinder_arm64.cpp +++ b/src/unwinder/arm64/unwinder_arm64.cpp @@ -215,7 +215,7 @@ Return Value: for (RegIndex = 0; RegIndex < 18; RegIndex++) { UPDATE_CONTEXT_POINTERS(UnwindParams, RegIndex, SourceAddress); #ifdef __clang__ - *(&ContextRecord->X0 + (RegIndex * sizeof(void*))) = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + *(&ContextRecord->X0 + RegIndex) = MEMORY_READ_QWORD(UnwindParams, SourceAddress); #else ContextRecord->X[RegIndex] = MEMORY_READ_QWORD(UnwindParams, SourceAddress); #endif @@ -295,7 +295,7 @@ Return Value: for (RegIndex = 0; RegIndex < 29; RegIndex++) { UPDATE_CONTEXT_POINTERS(UnwindParams, RegIndex, SourceAddress); #ifdef __clang__ - *(&ContextRecord->X0 + (RegIndex * sizeof(void*))) = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + *(&ContextRecord->X0 + RegIndex) = MEMORY_READ_QWORD(UnwindParams, SourceAddress); #else ContextRecord->X[RegIndex] = MEMORY_READ_QWORD(UnwindParams, SourceAddress); #endif @@ -481,7 +481,7 @@ Return Value: for (RegIndex = 0; RegIndex < RegisterCount; RegIndex++) { UPDATE_CONTEXT_POINTERS(UnwindParams, RegIndex, CurAddress); #ifdef __clang__ - *(&ContextRecord->X0 + (RegIndex * sizeof(void*))) = MEMORY_READ_QWORD(UnwindParams, CurAddress); + *(&ContextRecord->X0 + FirstRegister + RegIndex) = MEMORY_READ_QWORD(UnwindParams, CurAddress); #else ContextRecord->X[FirstRegister + RegIndex] = MEMORY_READ_QWORD(UnwindParams, CurAddress); #endif diff --git a/src/vm/arm64/stubs.cpp b/src/vm/arm64/stubs.cpp index 9c9b6a8a6816..a9c7364f5b4f 100644 --- a/src/vm/arm64/stubs.cpp +++ b/src/vm/arm64/stubs.cpp @@ -767,7 +767,7 @@ void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD) ArgumentRegisters *pArgRegs = GetArgumentRegisters(); for (int i = 0; i < ARGUMENTREGISTERS_SIZE; i++) #ifdef __clang__ - *(&pRD->pCurrentContext->X0 + (sizeof(void*)*i)) = pArgRegs->x[i]; + *(&pRD->pCurrentContext->X0 + i) = pArgRegs->x[i]; #else pRD->pCurrentContext->X[i] = pArgRegs->x[i]; #endif From da3093a0254c8178984b3e4cbca130f05b14ae05 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Sat, 7 Jan 2017 00:03:41 +0000 Subject: [PATCH 09/24] [Arm64/Unix] Fix CallDescrWorkerInternal personality --- src/vm/arm64/calldescrworkerarm64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/arm64/calldescrworkerarm64.S b/src/vm/arm64/calldescrworkerarm64.S index 90b763940ab3..71e0cb6186fc 100644 --- a/src/vm/arm64/calldescrworkerarm64.S +++ b/src/vm/arm64/calldescrworkerarm64.S @@ -11,7 +11,7 @@ //----------------------------------------------------------------------------- //void CallDescrWorkerInternal(CallDescrData * pCallDescrData); -NESTED_ENTRY CallDescrWorkerInternal, _TEXT, UnhandledExceptionHandlerUnix +NESTED_ENTRY CallDescrWorkerInternal, _TEXT, NoHandler PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -32 PROLOG_SAVE_REG x19, 16 //the stack slot at sp+24 is empty for 16 byte alligment From d05be2c8b051e76570676e9b9d39f43961b8d814 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Tue, 10 Jan 2017 23:23:53 +0000 Subject: [PATCH 10/24] [Arm64/Unix] More Fp fixups --- src/pal/src/exception/seh-unwind.cpp | 1 + src/vm/arm64/asmhelpers.S | 1 + 2 files changed, 2 insertions(+) diff --git a/src/pal/src/exception/seh-unwind.cpp b/src/pal/src/exception/seh-unwind.cpp index e3fa09f7c8f3..ba43c2e72567 100644 --- a/src/pal/src/exception/seh-unwind.cpp +++ b/src/pal/src/exception/seh-unwind.cpp @@ -243,6 +243,7 @@ static void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, GetContextPointer(cursor, unwContext, UNW_AARCH64_X26, &contextPointers->X26); GetContextPointer(cursor, unwContext, UNW_AARCH64_X27, &contextPointers->X27); GetContextPointer(cursor, unwContext, UNW_AARCH64_X28, &contextPointers->X28); + GetContextPointer(cursor, unwContext, UNW_AARCH64_X29, &contextPointers->Fp); #else #error unsupported architecture #endif diff --git a/src/vm/arm64/asmhelpers.S b/src/vm/arm64/asmhelpers.S index 265d74d9ac0a..cc5c4f76e2be 100644 --- a/src/vm/arm64/asmhelpers.S +++ b/src/vm/arm64/asmhelpers.S @@ -107,6 +107,7 @@ LEAF_ENTRY HelperMethodFrameRestoreState, _TEXT RestoreRegMS 26, X26 RestoreRegMS 27, X27 RestoreRegMS 28, X28 + RestoreRegMS 29, X29 LOCAL_LABEL(Done): // Its imperative that the return value of HelperMethodFrameRestoreState is zero // as it is used in the state machine to loop until it becomes zero. From 6e4d21953717abfa3cc6ff65b2204e54884fdb59 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Fri, 13 Jan 2017 19:28:28 +0000 Subject: [PATCH 11/24] [Arm64/Unix] CallEHFunclet machine state Restore non-volatile machine state in CallEHFunclet --- src/vm/arm64/asmhelpers.S | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/vm/arm64/asmhelpers.S b/src/vm/arm64/asmhelpers.S index cc5c4f76e2be..deb2a98973e0 100644 --- a/src/vm/arm64/asmhelpers.S +++ b/src/vm/arm64/asmhelpers.S @@ -901,16 +901,6 @@ GenerateRedirectedHandledJITCaseStub GCStress // This helper enables us to call into a funclet after restoring Fp register NESTED_ENTRY CallEHFunclet, _TEXT, NoHandler - - // Using below prolog instead of PROLOG_SAVE_REG_PAIR fp,lr, #-16 - // is intentional. Above statement would also emit instruction to save - // sp in fp. If sp is saved in fp in prolog then it is not expected that fp can change in the body - // of method. However, this method needs to be able to change fp before calling funclet. - // This is required to access locals in funclet. - PROLOG_SAVE_REG_PAIR_INDEXED x19,x20, -16 - PROLOG_SAVE_REG fp, 0 - PROLOG_SAVE_REG lr, 8 - // On entry: // // X0 = throwable @@ -918,17 +908,36 @@ NESTED_ENTRY CallEHFunclet, _TEXT, NoHandler // X2 = address of X19 register in CONTEXT record// used to restore the non-volatile registers of CrawlFrame // X3 = address of the location where the SP of funclet's caller (i.e. this helper) should be saved. // - // Save the SP of this function - mov fp, sp - str fp, [x3] + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -96 + // Spill callee saved registers + PROLOG_SAVE_REG_PAIR x19, x20, 16 + PROLOG_SAVE_REG_PAIR x21, x22, 32 + PROLOG_SAVE_REG_PAIR x23, x24, 48 + PROLOG_SAVE_REG_PAIR x25, x26, 64 + PROLOG_SAVE_REG_PAIR x27, x28, 80 + + // Save the SP of this function + mov x4, sp + str x4, [x3] + + ldp x19, x20, [x2, #0] + ldp x21, x22, [x2, #16] + ldp x23, x24, [x2, #32] + ldp x25, x26, [x2, #48] + ldp x27, x28, [x2, #64] ldr fp, [x2, #80] // offset of fp in CONTEXT relative to X19 // Invoke the funclet blr x1 nop - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 16 + EPILOG_RESTORE_REG_PAIR x19, x20, 16 + EPILOG_RESTORE_REG_PAIR x21, x22, 32 + EPILOG_RESTORE_REG_PAIR x23, x24, 48 + EPILOG_RESTORE_REG_PAIR x25, x26, 64 + EPILOG_RESTORE_REG_PAIR x27, x28, 80 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 96 EPILOG_RETURN NESTED_END CallEHFunclet, _TEXT From 775fd5a75ba20e55ee84ad90b337bfb27dba3e1c Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Wed, 18 Jan 2017 20:43:20 +0000 Subject: [PATCH 12/24] [Arm64/Unix] CallDescrWorkerInternal Use empty stack slot to save argument --- src/vm/arm64/calldescrworkerarm64.S | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/vm/arm64/calldescrworkerarm64.S b/src/vm/arm64/calldescrworkerarm64.S index 71e0cb6186fc..92ee30fb4b38 100644 --- a/src/vm/arm64/calldescrworkerarm64.S +++ b/src/vm/arm64/calldescrworkerarm64.S @@ -13,7 +13,8 @@ NESTED_ENTRY CallDescrWorkerInternal, _TEXT, NoHandler PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -32 - PROLOG_SAVE_REG x19, 16 //the stack slot at sp+24 is empty for 16 byte alligment + PROLOG_SAVE_REG x19, 16 + PROLOG_SAVE_REG x0, 24 mov x19, x0 // save pCallDescrData in x19 @@ -68,6 +69,8 @@ LOCAL_LABEL(NoFloatingPoint): ldr x9, [x19,#CallDescrData__pTarget] blr x9 + ldr x19, [fp, 24] // Fixup corrupted X19 caller preserved register + ldr w3, [x19,#CallDescrData__fpReturnSize] // Int return case From da460d63cc60a242854351913f426284b96327d7 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Fri, 20 Jan 2017 05:21:59 +0000 Subject: [PATCH 13/24] [Arm64/Unix] RtlVirtualUnwind update pointers --- src/unwinder/arm64/unwinder_arm64.cpp | 43 ++++++++++++++++++++------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/unwinder/arm64/unwinder_arm64.cpp b/src/unwinder/arm64/unwinder_arm64.cpp index c3b7102e7a62..36f7de1aad26 100644 --- a/src/unwinder/arm64/unwinder_arm64.cpp +++ b/src/unwinder/arm64/unwinder_arm64.cpp @@ -109,16 +109,37 @@ typedef struct _ARM64_VFP_STATE typedef struct _ARM64_UNWIND_PARAMS { - ULONG_PTR ControlPc; - PULONG_PTR LowLimit; - PULONG_PTR HighLimit; PKNONVOLATILE_CONTEXT_POINTERS ContextPointers; } ARM64_UNWIND_PARAMS, *PARM64_UNWIND_PARAMS; #define UNWIND_PARAMS_SET_TRAP_FRAME(Params, Address, Size) -#define UPDATE_CONTEXT_POINTERS(Params, RegisterNumber, Address) -#define UPDATE_FP_CONTEXT_POINTERS(Params, RegisterNumber, Address) +#define UPDATE_CONTEXT_POINTERS(Params, RegisterNumber, Address) \ +do { \ + if (ARGUMENT_PRESENT(Params)) { \ + PKNONVOLATILE_CONTEXT_POINTERS ContextPointers = (Params)->ContextPointers; \ + if (ARGUMENT_PRESENT(ContextPointers)) { \ + if (RegisterNumber >= 19 && RegisterNumber <= 30) { \ + (&ContextPointers->X19)[RegisterNumber - 19] = (PDWORD64)Address; \ + } \ + } \ + } \ +} while (0) + + +#define UPDATE_FP_CONTEXT_POINTERS(Params, RegisterNumber, Address) \ +do { \ + if (ARGUMENT_PRESENT(Params)) { \ + PKNONVOLATILE_CONTEXT_POINTERS ContextPointers = (Params)->ContextPointers; \ + if (ARGUMENT_PRESENT(ContextPointers) && \ + (RegisterNumber >= 8) && \ + (RegisterNumber <= 15)) { \ + \ + (&ContextPointers->D8)[RegisterNumber - 8] = (PDWORD64)Address; \ + } \ + } \ +} while (0) + #define VALIDATE_STACK_ADDRESS_EX(Params, Context, Address, DataSize, Alignment, OutStatus) #define VALIDATE_STACK_ADDRESS(Params, Context, DataSize, Alignment, OutStatus) @@ -479,7 +500,7 @@ Return Value: // for (RegIndex = 0; RegIndex < RegisterCount; RegIndex++) { - UPDATE_CONTEXT_POINTERS(UnwindParams, RegIndex, CurAddress); + UPDATE_CONTEXT_POINTERS(UnwindParams, FirstRegister + RegIndex, CurAddress); #ifdef __clang__ *(&ContextRecord->X0 + FirstRegister + RegIndex) = MEMORY_READ_QWORD(UnwindParams, CurAddress); #else @@ -555,7 +576,7 @@ Return Value: // for (RegIndex = 0; RegIndex < RegisterCount; RegIndex++) { - UPDATE_FP_CONTEXT_POINTERS(UnwindParams, RegIndex, CurAddress); + UPDATE_FP_CONTEXT_POINTERS(UnwindParams, FirstRegister + RegIndex, CurAddress); ContextRecord->V[FirstRegister + RegIndex].Low = MEMORY_READ_QWORD(UnwindParams, CurAddress); CurAddress += 8; } @@ -1591,7 +1612,6 @@ BOOL DacUnwindStackFrame(T_CONTEXT *pContext, T_KNONVOLATILE_CONTEXT_POINTERS* p } #if defined(FEATURE_PAL) -//TODO: Fix the context pointers PEXCEPTION_ROUTINE RtlVirtualUnwind( IN ULONG HandlerType, @@ -1615,6 +1635,9 @@ RtlVirtualUnwind( rfe.BeginAddress = FunctionEntry->BeginAddress; rfe.UnwindData = FunctionEntry->UnwindData; + ARM64_UNWIND_PARAMS unwindParams; + unwindParams.ContextPointers = ContextPointers; + if ((rfe.UnwindData & 3) != 0) { hr = RtlpUnwindFunctionCompact(ControlPc - ImageBase, @@ -1623,7 +1646,7 @@ RtlVirtualUnwind( EstablisherFrame, &handlerRoutine, HandlerData, - NULL); + &unwindParams); } else @@ -1635,7 +1658,7 @@ RtlVirtualUnwind( EstablisherFrame, &handlerRoutine, HandlerData, - NULL); + &unwindParams); } _ASSERTE(SUCCEEDED(hr)); From dfca815e4c385591dc6f37ce2d2ea94195715cb1 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Fri, 20 Jan 2017 16:11:21 +0000 Subject: [PATCH 14/24] [Arm64] LazyMachState fixes --- src/vm/arm64/asmconstants.h | 4 +++ src/vm/arm64/gmscpu.h | 44 ++++++++++++++++------- src/vm/arm64/stubs.cpp | 71 +++++++++++++++++++++++++++++++++---- 3 files changed, 100 insertions(+), 19 deletions(-) diff --git a/src/vm/arm64/asmconstants.h b/src/vm/arm64/asmconstants.h index b0300ca32492..df4c5d9703ea 100644 --- a/src/vm/arm64/asmconstants.h +++ b/src/vm/arm64/asmconstants.h @@ -89,7 +89,11 @@ ASMCONSTANTS_C_ASSERT(MachState__isValid == offsetof(MachState, _isValid)) #define LazyMachState_captureX19_X29 MachState__captureX19_X29 ASMCONSTANTS_C_ASSERT(LazyMachState_captureX19_X29 == offsetof(LazyMachState, captureX19_X29)) +#ifdef FEATURE_PAL +#define LazyMachState_captureSp (MachState__isValid+8+12*8) // padding for alignment & m_Unwound +#else #define LazyMachState_captureSp (MachState__isValid+8) // padding for alignment +#endif ASMCONSTANTS_C_ASSERT(LazyMachState_captureSp == offsetof(LazyMachState, captureSp)) #define LazyMachState_captureIp (LazyMachState_captureSp+8) diff --git a/src/vm/arm64/gmscpu.h b/src/vm/arm64/gmscpu.h index e95ef63d7dd8..9a16487c8ecd 100644 --- a/src/vm/arm64/gmscpu.h +++ b/src/vm/arm64/gmscpu.h @@ -29,6 +29,13 @@ struct MachState { BOOL isValid() { LIMITED_METHOD_DAC_CONTRACT; return _isValid; } TADDR GetRetAddr() { LIMITED_METHOD_DAC_CONTRACT; return _pc; } + +#ifdef FEATURE_PAL + // On PAL, we don't always have the context pointers available due to + // a limitation of an unwinding library. In such case, preserve + // the unwound values. + CalleeSavedRegisters m_Unwound; +#endif }; struct LazyMachState : public MachState{ @@ -56,25 +63,38 @@ inline void LazyMachState::setLazyStateFromUnwind(MachState* copy) _sp = copy->_sp; _pc = copy->_pc; - // Now copy the preserved register pointers. Note that some of the pointers could be - // pointing to copy->captureX19_X29[]. If that is case then while copying to destination - // ensure that they point to corresponding element in captureX19_X29[] of destination. - ULONG64* srcLowerBound = ©->captureX19_X29[0]; - ULONG64* srcUpperBound = (ULONG64*)((BYTE*)copy + offsetof(MachState, ptrX19_X29)); +#ifdef FEATURE_PAL + this->m_Unwound = copy->m_Unwound; +#endif + + // Capture* has already been set, so there is no need to touch it + + // loop over the nonvolatile context pointers and make + // sure to properly copy interior pointers into the + // new struct + + PULONG64* pSrc = (PULONG64 *)©->ptrX19_X29; + PULONG64* pDst = (PULONG64 *)&this->ptrX19_X29; + const PULONG64 LowerBoundDst = (PULONG64) this; + const PULONG64 LowerBoundSrc = (PULONG64) copy; - for (int i = 0; iptrX19_X29[i] >= srcLowerBound && copy->ptrX19_X29[i] < srcUpperBound) - { - ptrX19_X29[i] = (PTR_ULONG64)((BYTE*)copy->ptrX19_X29[i] - (BYTE*)srcLowerBound + (BYTE*)captureX19_X29); - } - else + PULONG64 valueSrc = *pSrc++; + + if ((LowerBoundSrc <= valueSrc) && (valueSrc < UpperBoundSrc)) { - ptrX19_X29[i] = copy->ptrX19_X29[i]; + // make any pointer interior to 'src' interior to 'dst' + valueSrc = (PULONG64)((BYTE*)valueSrc - (BYTE*)LowerBoundSrc + (BYTE*)LowerBoundDst); } + + *pDst++ = valueSrc; } + // this has to be last because we depend on write ordering to // synchronize the race implicit in updating this struct VolatileStore(&_isValid, TRUE); diff --git a/src/vm/arm64/stubs.cpp b/src/vm/arm64/stubs.cpp index a9c7364f5b4f..c8b3ddef7558 100644 --- a/src/vm/arm64/stubs.cpp +++ b/src/vm/arm64/stubs.cpp @@ -371,6 +371,20 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState, } } while (true); +#ifdef FEATURE_PAL + unwoundstate->captureX19_X29[0] = context.X19; + unwoundstate->captureX19_X29[1] = context.X20; + unwoundstate->captureX19_X29[2] = context.X21; + unwoundstate->captureX19_X29[3] = context.X22; + unwoundstate->captureX19_X29[4] = context.X23; + unwoundstate->captureX19_X29[5] = context.X24; + unwoundstate->captureX19_X29[6] = context.X25; + unwoundstate->captureX19_X29[7] = context.X26; + unwoundstate->captureX19_X29[8] = context.X27; + unwoundstate->captureX19_X29[9] = context.X28; + unwoundstate->captureX19_X29[10] = context.Fp; +#endif + #ifdef DACCESS_COMPILE // For DAC builds, we update the registers directly since we dont have context pointers unwoundstate->captureX19_X29[0] = context.X19; @@ -450,6 +464,20 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pCurrentContext->X28 = (DWORD64)(pUnwoundState->captureX19_X29[9]); pRD->pCurrentContext->Fp = (DWORD64)(pUnwoundState->captureX19_X29[10]); pRD->pCurrentContext->Lr = NULL; // Unwind again to get Caller's PC + + pRD->pCurrentContextPointers->X19 = pUnwoundState->ptrX19_X29[0]; + pRD->pCurrentContextPointers->X20 = pUnwoundState->ptrX19_X29[1]; + pRD->pCurrentContextPointers->X21 = pUnwoundState->ptrX19_X29[2]; + pRD->pCurrentContextPointers->X22 = pUnwoundState->ptrX19_X29[3]; + pRD->pCurrentContextPointers->X23 = pUnwoundState->ptrX19_X29[4]; + pRD->pCurrentContextPointers->X24 = pUnwoundState->ptrX19_X29[5]; + pRD->pCurrentContextPointers->X25 = pUnwoundState->ptrX19_X29[6]; + pRD->pCurrentContextPointers->X26 = pUnwoundState->ptrX19_X29[7]; + pRD->pCurrentContextPointers->X27 = pUnwoundState->ptrX19_X29[8]; + pRD->pCurrentContextPointers->X28 = pUnwoundState->ptrX19_X29[9]; + pRD->pCurrentContextPointers->Fp = pUnwoundState->ptrX19_X29[10]; + pRD->pCurrentContextPointers->Lr = NULL; + return; } #endif // DACCESS_COMPILE @@ -462,6 +490,20 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pCurrentContext->Pc = pRD->ControlPC; pRD->pCurrentContext->Sp = pRD->SP; +#ifdef FEATURE_PAL + pRD->pCurrentContext->X19 = m_MachState.ptrX19_X29[0] ? *m_MachState.ptrX19_X29[0] : m_MachState.captureX19_X29[0]; + pRD->pCurrentContext->X20 = m_MachState.ptrX19_X29[1] ? *m_MachState.ptrX19_X29[1] : m_MachState.captureX19_X29[1]; + pRD->pCurrentContext->X21 = m_MachState.ptrX19_X29[2] ? *m_MachState.ptrX19_X29[2] : m_MachState.captureX19_X29[2]; + pRD->pCurrentContext->X22 = m_MachState.ptrX19_X29[3] ? *m_MachState.ptrX19_X29[3] : m_MachState.captureX19_X29[3]; + pRD->pCurrentContext->X23 = m_MachState.ptrX19_X29[4] ? *m_MachState.ptrX19_X29[4] : m_MachState.captureX19_X29[4]; + pRD->pCurrentContext->X24 = m_MachState.ptrX19_X29[5] ? *m_MachState.ptrX19_X29[5] : m_MachState.captureX19_X29[5]; + pRD->pCurrentContext->X25 = m_MachState.ptrX19_X29[6] ? *m_MachState.ptrX19_X29[6] : m_MachState.captureX19_X29[6]; + pRD->pCurrentContext->X26 = m_MachState.ptrX19_X29[7] ? *m_MachState.ptrX19_X29[7] : m_MachState.captureX19_X29[7]; + pRD->pCurrentContext->X27 = m_MachState.ptrX19_X29[8] ? *m_MachState.ptrX19_X29[8] : m_MachState.captureX19_X29[8]; + pRD->pCurrentContext->X28 = m_MachState.ptrX19_X29[9] ? *m_MachState.ptrX19_X29[9] : m_MachState.captureX19_X29[9]; + pRD->pCurrentContext->Fp = m_MachState.ptrX19_X29[10] ? *m_MachState.ptrX19_X29[10] : m_MachState.captureX19_X29[10]; + pRD->pCurrentContext->Lr = NULL; // Unwind again to get Caller's PC +#else // FEATURE_PAL pRD->pCurrentContext->X19 = *m_MachState.ptrX19_X29[0]; pRD->pCurrentContext->X20 = *m_MachState.ptrX19_X29[1]; pRD->pCurrentContext->X21 = *m_MachState.ptrX19_X29[2]; @@ -474,6 +516,7 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pCurrentContext->X28 = *m_MachState.ptrX19_X29[9]; pRD->pCurrentContext->Fp = *m_MachState.ptrX19_X29[10]; pRD->pCurrentContext->Lr = NULL; // Unwind again to get Caller's PC +#endif #if !defined(DACCESS_COMPILE) pRD->pCurrentContextPointers->X19 = m_MachState.ptrX19_X29[0]; @@ -790,6 +833,7 @@ void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD) } + #endif #ifndef CROSSGEN_COMPILE @@ -858,20 +902,33 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD) return; } - // reset pContext; it's only valid for active (top-most) frame - pRD->pContext = NULL; + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; + + pRD->pCurrentContext->Pc = *(DWORD64 *)&m_pCallerReturnAddress; + pRD->pCurrentContext->Sp = *(DWORD64 *)&m_pCallSiteSP; + pRD->pCurrentContext->Fp = *(DWORD64 *)&m_pCalleeSavedFP; + + pRD->pCurrentContextPointers->X19 = NULL; + pRD->pCurrentContextPointers->X20 = NULL; + pRD->pCurrentContextPointers->X21 = NULL; + pRD->pCurrentContextPointers->X22 = NULL; + pRD->pCurrentContextPointers->X23 = NULL; + pRD->pCurrentContextPointers->X24 = NULL; + pRD->pCurrentContextPointers->X25 = NULL; + pRD->pCurrentContextPointers->X26 = NULL; + pRD->pCurrentContextPointers->X27 = NULL; + pRD->pCurrentContextPointers->X28 = NULL; pRD->ControlPC = m_pCallerReturnAddress; pRD->SP = (DWORD) dac_cast(m_pCallSiteSP); - pRD->IsCallerContextValid = FALSE; - pRD->IsCallerSPValid = FALSE; + // reset pContext; it's only valid for active (top-most) frame + pRD->pContext = NULL; + - pRD->pCurrentContext->Pc = m_pCallerReturnAddress; - pRD->pCurrentContext->Sp = pRD->SP; // Update the frame pointer in the current context. - pRD->pCurrentContext->Fp = m_pCalleeSavedFP; pRD->pCurrentContextPointers->Fp = &m_pCalleeSavedFP; RETURN; From dccb0d3e02564c1cf69ea4dcb78de7a67080a1f9 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Tue, 31 Jan 2017 23:09:36 -0500 Subject: [PATCH 15/24] [Arm64/Unix] disable USE_REDIRECT_FOR_GCSTRESS When FEATURE_PAL is enableds USE_REDIRECT_FOR_GCSTRESS is not supported --- src/vm/arm64/cgencpu.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vm/arm64/cgencpu.h b/src/vm/arm64/cgencpu.h index be3e34d35c2d..a17602850967 100644 --- a/src/vm/arm64/cgencpu.h +++ b/src/vm/arm64/cgencpu.h @@ -14,7 +14,9 @@ #define INSTRFMT_K64 #include +#ifndef FEATURE_PAL #define USE_REDIRECT_FOR_GCSTRESS +#endif // FEATURE_PAL EXTERN_C void getFPReturn(int fpSize, INT64 *pRetVal); EXTERN_C void setFPReturn(int fpSize, INT64 retVal); From 1bf23c06546121389bb95ee2f29b1f238320ddec Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Tue, 31 Jan 2017 23:13:09 -0500 Subject: [PATCH 16/24] [Arm64] ClearRegDisplayArgumentAndScratchRegisters() --- src/vm/arm64/stubs.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/vm/arm64/stubs.cpp b/src/vm/arm64/stubs.cpp index c8b3ddef7558..662159a5b1b2 100644 --- a/src/vm/arm64/stubs.cpp +++ b/src/vm/arm64/stubs.cpp @@ -268,6 +268,12 @@ static BYTE gLoadFromLabelIF[sizeof(LoadFromLabelInstructionFormat)]; #endif +void ClearRegDisplayArgumentAndScratchRegisters(REGDISPLAY * pRD) +{ + for (int i=0; i < 18; i++) + pRD->volatileCurrContextPointers.X[i] = NULL; +} + #ifndef CROSSGEN_COMPILE void LazyMachState::unwindLazyState(LazyMachState* baseState, MachState* unwoundstate, @@ -532,6 +538,8 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pCurrentContextPointers->Fp = m_MachState.ptrX19_X29[10]; pRD->pCurrentContextPointers->Lr = NULL; // Unwind again to get Caller's PC #endif + + ClearRegDisplayArgumentAndScratchRegisters(pRD); } #endif // CROSSGEN_COMPILE @@ -819,6 +827,8 @@ void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD) CalleeSavedRegisters *pCalleeSaved = GetCalleeSavedRegisters(); UpdateRegDisplayFromCalleeSavedRegisters(pRD, pCalleeSaved); + ClearRegDisplayArgumentAndScratchRegisters(pRD); + // copy the control registers pRD->pCurrentContext->Fp = pCalleeSaved->x29; pRD->pCurrentContext->Lr = pCalleeSaved->x30; @@ -877,6 +887,8 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pCurrentContextPointers->Fp = (PDWORD64)&m_ctx.Fp; pRD->pCurrentContextPointers->Lr = (PDWORD64)&m_ctx.Lr; + ClearRegDisplayArgumentAndScratchRegisters(pRD); + pRD->IsCallerContextValid = FALSE; pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. } @@ -926,6 +938,7 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD) // reset pContext; it's only valid for active (top-most) frame pRD->pContext = NULL; + ClearRegDisplayArgumentAndScratchRegisters(pRD); // Update the frame pointer in the current context. From 72a38968e5758c6990501435e6423bf22b2d25b8 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Tue, 31 Jan 2017 23:14:55 -0500 Subject: [PATCH 17/24] [Arm64] Remove unnecesary copy in TransitionFrame --- src/vm/arm64/stubs.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/vm/arm64/stubs.cpp b/src/vm/arm64/stubs.cpp index 662159a5b1b2..852f8ed0b311 100644 --- a/src/vm/arm64/stubs.cpp +++ b/src/vm/arm64/stubs.cpp @@ -810,19 +810,9 @@ void UpdateRegDisplayFromCalleeSavedRegisters(REGDISPLAY * pRD, CalleeSavedRegis void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD) { - pRD->IsCallerContextValid = FALSE; pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. - // copy the argumetn registers - ArgumentRegisters *pArgRegs = GetArgumentRegisters(); - for (int i = 0; i < ARGUMENTREGISTERS_SIZE; i++) -#ifdef __clang__ - *(&pRD->pCurrentContext->X0 + i) = pArgRegs->x[i]; -#else - pRD->pCurrentContext->X[i] = pArgRegs->x[i]; -#endif - // copy the callee saved regs CalleeSavedRegisters *pCalleeSaved = GetCalleeSavedRegisters(); UpdateRegDisplayFromCalleeSavedRegisters(pRD, pCalleeSaved); From 3e9676cfdc77ef125510b5b9c90f81f10aa48c44 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Mon, 13 Feb 2017 21:24:21 +0000 Subject: [PATCH 18/24] [Arm64/Unix] Fix comment per review --- src/vm/arm64/calldescrworkerarm64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm/arm64/calldescrworkerarm64.S b/src/vm/arm64/calldescrworkerarm64.S index 92ee30fb4b38..2210d7052379 100644 --- a/src/vm/arm64/calldescrworkerarm64.S +++ b/src/vm/arm64/calldescrworkerarm64.S @@ -45,7 +45,7 @@ LOCAL_LABEL(stackloop): bne LOCAL_LABEL(stackloop) LOCAL_LABEL(donestack): - // If FP arguments are supplied in registers (x8 != NULL) then initialize all of them from the pointer + // If FP arguments are supplied in registers (x9 != NULL) then initialize all of them from the pointer // given in x8. ldr x9, [x19,#CallDescrData__pFloatArgumentRegisters] cbz x9, LOCAL_LABEL(NoFloatingPoint) From b8be0a537b8a22dfd5018718fb41016ad5a938f4 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Mon, 13 Feb 2017 21:28:22 +0000 Subject: [PATCH 19/24] [Arm64/Unix] move constants per review --- src/pal/src/arch/arm64/asmconstants.h | 14 ++++++++++++++ src/pal/src/arch/arm64/context2.S | 15 --------------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/pal/src/arch/arm64/asmconstants.h b/src/pal/src/arch/arm64/asmconstants.h index 5bc77ad45a8e..b2bf74461f20 100644 --- a/src/pal/src/arch/arm64/asmconstants.h +++ b/src/pal/src/arch/arm64/asmconstants.h @@ -5,6 +5,20 @@ #ifndef __PAL_ARM64_ASMCONSTANTS_H__ #define __PAL_ARM64_ASMCONSTANTS_H__ +#define CONTEXT_ARM64 0x00400000L + +#define CONTEXT_CONTROL_BIT (0) +#define CONTEXT_INTEGER_BIT (1) +#define CONTEXT_FLOATING_POINT_BIT (2) +#define CONTEXT_DEBUG_REGISTERS_BIT (3) + +#define CONTEXT_CONTROL (CONTEXT_ARM64 | (1L << CONTEXT_CONTROL_BIT)) +#define CONTEXT_INTEGER (CONTEXT_ARM64 | (1 << CONTEXT_INTEGER_BIT)) +#define CONTEXT_FLOATING_POINT (CONTEXT_ARM64 | (1 << CONTEXT_FLOATING_POINT_BIT)) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARM64 | (1 << CONTEXT_DEBUG_REGISTERS_BIT)) + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + #define CONTEXT_ContextFlags 0 #define CONTEXT_Cpsr CONTEXT_ContextFlags+4 diff --git a/src/pal/src/arch/arm64/context2.S b/src/pal/src/arch/arm64/context2.S index 3d1136ced21f..e62a9ac4d96e 100644 --- a/src/pal/src/arch/arm64/context2.S +++ b/src/pal/src/arch/arm64/context2.S @@ -10,21 +10,6 @@ #include "unixasmmacros.inc" #include "asmconstants.h" -#define CONTEXT_ARM64 0x00400000L - -#define CONTEXT_CONTROL_BIT (0) -#define CONTEXT_INTEGER_BIT (1) -#define CONTEXT_FLOATING_POINT_BIT (2) -#define CONTEXT_DEBUG_REGISTERS_BIT (3) - -#define CONTEXT_CONTROL (CONTEXT_ARM64 | (1L << CONTEXT_CONTROL_BIT)) -#define CONTEXT_INTEGER (CONTEXT_ARM64 | (1 << CONTEXT_INTEGER_BIT)) -#define CONTEXT_FLOATING_POINT (CONTEXT_ARM64 | (1 << CONTEXT_FLOATING_POINT_BIT)) -#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARM64 | (1 << CONTEXT_DEBUG_REGISTERS_BIT)) - -#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) - - // Incoming: // x0: Context* // From fb41fca95f3cdabaa45647a282db1f18d7d48bff Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Mon, 13 Feb 2017 21:34:00 +0000 Subject: [PATCH 20/24] [Arm64/Unix] Use ldp per review Also fix indentation --- src/pal/src/arch/arm64/exceptionhelper.S | 27 ++++++++++-------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/pal/src/arch/arm64/exceptionhelper.S b/src/pal/src/arch/arm64/exceptionhelper.S index 80075ae8ec51..480846eb61a6 100644 --- a/src/pal/src/arch/arm64/exceptionhelper.S +++ b/src/pal/src/arch/arm64/exceptionhelper.S @@ -14,24 +14,19 @@ LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT // Save the FP & LR to the stack so that the unwind can work at the instruction after // loading the FP from the context, but before loading the SP from the context. - stp fp, lr, [sp, -16]! + stp fp, lr, [sp, -16]! - ldr x19, [x0, #(CONTEXT_X19)] - ldr x20, [x0, #(CONTEXT_X20)] - ldr x21, [x0, #(CONTEXT_X21)] - ldr x22, [x0, #(CONTEXT_X22)] - ldr x23, [x0, #(CONTEXT_X23)] - ldr x24, [x0, #(CONTEXT_X24)] - ldr x25, [x0, #(CONTEXT_X25)] - ldr x26, [x0, #(CONTEXT_X26)] - ldr x27, [x0, #(CONTEXT_X27)] - ldr x28, [x0, #(CONTEXT_X28)] - ldr fp, [x0, #(CONTEXT_Fp)] - ldr lr, [x0, #(CONTEXT_Pc)] - ldr x2, [x0, #(CONTEXT_Sp)] + ldp x19,x20, [x0, #(CONTEXT_X19)] + ldp x21,x22, [x0, #(CONTEXT_X21)] + ldp x23,x24, [x0, #(CONTEXT_X23)] + ldp x24,x25, [x0, #(CONTEXT_X24)] + ldp x26,x27, [x0, #(CONTEXT_X26)] + ldp x28,fp, [x0, #(CONTEXT_X28)] + ldr lr, [x0, #(CONTEXT_Pc)] + ldr x2, [x0, #(CONTEXT_Sp)] mov sp, x2 // The PAL_SEHException pointer - mov x0, x1 - b EXTERNAL_C_FUNC(ThrowExceptionHelper) + mov x0, x1 + b EXTERNAL_C_FUNC(ThrowExceptionHelper) LEAF_END ThrowExceptionFromContextInternal, _TEXT From 1f5e9a7f37353b751151c110e7532758dad1e842 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Mon, 13 Feb 2017 22:10:33 +0000 Subject: [PATCH 21/24] [Arm64/Unix] Fix indentation per review --- src/vm/arm64/asmhelpers.S | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/vm/arm64/asmhelpers.S b/src/vm/arm64/asmhelpers.S index deb2a98973e0..5e7fabe1b73e 100644 --- a/src/vm/arm64/asmhelpers.S +++ b/src/vm/arm64/asmhelpers.S @@ -265,49 +265,49 @@ WRITE_BARRIER_END JIT_CheckedWriteBarrier // WRITE_BARRIER_ENTRY JIT_WriteBarrier dmb ST - str x15, [x14] + str x15, [x14] #ifdef WRITE_BARRIER_CHECK // Update GC Shadow Heap // need temporary registers. Save them before using. - stp x12, x13, [sp, #-16]! + stp x12, x13, [sp, #-16]! // Compute address of shadow heap location: // pShadow = g_GCShadow + (x14 - g_lowest_address) - ldr x12, =g_lowest_address - ldr x12, [x12] - sub x12, x14, x12 - ldr x13, =g_GCShadow - ldr x13, [x13] - add x12, x13, x12 + ldr x12, =g_lowest_address + ldr x12, [x12] + sub x12, x14, x12 + ldr x13, =g_GCShadow + ldr x13, [x13] + add x12, x13, x12 // if (pShadow >= g_GCShadowEnd) goto end - ldr x13, =g_GCShadowEnd - ldr x13, [x13] - cmp x12, x13 - bhs LOCAL_LABEL(shadowupdateend) + ldr x13, =g_GCShadowEnd + ldr x13, [x13] + cmp x12, x13 + bhs LOCAL_LABEL(shadowupdateend) // *pShadow = x15 - str x15, [x12] + str x15, [x12] // Ensure that the write to the shadow heap occurs before the read from the GC heap so that race // conditions are caught by INVALIDGCVALUE. - dmb sy + dmb sy // if ([x14] == x15) goto end - ldr x13, [x14] - cmp x13, x15 + ldr x13, [x14] + cmp x13, x15 beq LOCAL_LABEL(shadowupdateend) // *pShadow = INVALIDGCVALUE (0xcccccccd) - mov x13, #0 - movk x13, #0xcccd - movk x13, #0xcccc, LSL #16 - str x13, [x12] + mov x13, #0 + movk x13, #0xcccd + movk x13, #0xcccc, LSL #16 + str x13, [x12] LOCAL_LABEL(shadowupdateend): - ldp x12, x13, [sp],#16 + ldp x12, x13, [sp],#16 #endif // Branch to Exit if the reference is not in the Gen0 heap @@ -843,7 +843,7 @@ NESTED_END UM2MThunk_WrapperHelper, _TEXT #ifdef FEATURE_HIJACK // ------------------------------------------------------------------ // Hijack function for functions which return a scalar type or a struct (value type) - NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler +NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -144 // Spill callee saved registers PROLOG_SAVE_REG_PAIR x19, x20, 16 @@ -876,7 +876,7 @@ NESTED_END UM2MThunk_WrapperHelper, _TEXT EPILOG_RESTORE_REG_PAIR x27, x28, 80 EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 144 EPILOG_RETURN - NESTED_END OnHijackTripThread, _TEXT +NESTED_END OnHijackTripThread, _TEXT #endif // FEATURE_HIJACK From ce64cbb85e76a822462a26073edbfada0bad4c11 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Mon, 13 Feb 2017 22:43:57 +0000 Subject: [PATCH 22/24] [Arm64/Unix] Remove m_Unwound per review comments --- src/vm/arm64/asmconstants.h | 4 ---- src/vm/arm64/gmscpu.h | 11 ----------- 2 files changed, 15 deletions(-) diff --git a/src/vm/arm64/asmconstants.h b/src/vm/arm64/asmconstants.h index df4c5d9703ea..b0300ca32492 100644 --- a/src/vm/arm64/asmconstants.h +++ b/src/vm/arm64/asmconstants.h @@ -89,11 +89,7 @@ ASMCONSTANTS_C_ASSERT(MachState__isValid == offsetof(MachState, _isValid)) #define LazyMachState_captureX19_X29 MachState__captureX19_X29 ASMCONSTANTS_C_ASSERT(LazyMachState_captureX19_X29 == offsetof(LazyMachState, captureX19_X29)) -#ifdef FEATURE_PAL -#define LazyMachState_captureSp (MachState__isValid+8+12*8) // padding for alignment & m_Unwound -#else #define LazyMachState_captureSp (MachState__isValid+8) // padding for alignment -#endif ASMCONSTANTS_C_ASSERT(LazyMachState_captureSp == offsetof(LazyMachState, captureSp)) #define LazyMachState_captureIp (LazyMachState_captureSp+8) diff --git a/src/vm/arm64/gmscpu.h b/src/vm/arm64/gmscpu.h index 9a16487c8ecd..7785daf219e7 100644 --- a/src/vm/arm64/gmscpu.h +++ b/src/vm/arm64/gmscpu.h @@ -29,13 +29,6 @@ struct MachState { BOOL isValid() { LIMITED_METHOD_DAC_CONTRACT; return _isValid; } TADDR GetRetAddr() { LIMITED_METHOD_DAC_CONTRACT; return _pc; } - -#ifdef FEATURE_PAL - // On PAL, we don't always have the context pointers available due to - // a limitation of an unwinding library. In such case, preserve - // the unwound values. - CalleeSavedRegisters m_Unwound; -#endif }; struct LazyMachState : public MachState{ @@ -63,10 +56,6 @@ inline void LazyMachState::setLazyStateFromUnwind(MachState* copy) _sp = copy->_sp; _pc = copy->_pc; -#ifdef FEATURE_PAL - this->m_Unwound = copy->m_Unwound; -#endif - // Capture* has already been set, so there is no need to touch it // loop over the nonvolatile context pointers and make From 87b96cbded11fb191964473822cb90ac81b9d2d6 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Fri, 17 Feb 2017 15:39:11 +0000 Subject: [PATCH 23/24] [Arm64/Unix] Use PREPARE_EXTERNAL_VAR to access globals --- src/vm/arm64/asmhelpers.S | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vm/arm64/asmhelpers.S b/src/vm/arm64/asmhelpers.S index 5e7fabe1b73e..ebf706f8c17f 100644 --- a/src/vm/arm64/asmhelpers.S +++ b/src/vm/arm64/asmhelpers.S @@ -275,15 +275,15 @@ WRITE_BARRIER_ENTRY JIT_WriteBarrier // Compute address of shadow heap location: // pShadow = g_GCShadow + (x14 - g_lowest_address) - ldr x12, =g_lowest_address + PREPARE_EXTERNAL_VAR g_lowest_address, x12 ldr x12, [x12] sub x12, x14, x12 - ldr x13, =g_GCShadow + PREPARE_EXTERNAL_VAR g_GCShadow, x13 ldr x13, [x13] add x12, x13, x12 // if (pShadow >= g_GCShadowEnd) goto end - ldr x13, =g_GCShadowEnd + PREPARE_EXTERNAL_VAR g_GCShadowEnd, x13 ldr x13, [x13] cmp x12, x13 bhs LOCAL_LABEL(shadowupdateend) @@ -1081,7 +1081,7 @@ LOCAL_LABEL(MainLoop): bne LOCAL_LABEL(MainLoop) LOCAL_LABEL(Success): - ldr x13, =g_dispatch_cache_chain_success_counter + PREPARE_EXTERNAL_VAR g_dispatch_cache_chain_success_counter, x13 ldr x16, [x13] subs x16, x16, #1 str x16, [x13] From d18c6d3e5ecf674525f4256b9f1e76d7f0a28ed4 Mon Sep 17 00:00:00 2001 From: "Steve MacLean, Qualcomm Datacenter Technologies, Inc" Date: Fri, 17 Feb 2017 15:52:38 +0000 Subject: [PATCH 24/24] [Arm64/Unix] Fix more whitespace per earlier review comments --- src/vm/arm64/asmhelpers.S | 112 +++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/src/vm/arm64/asmhelpers.S b/src/vm/arm64/asmhelpers.S index ebf706f8c17f..dd28c3e212a1 100644 --- a/src/vm/arm64/asmhelpers.S +++ b/src/vm/arm64/asmhelpers.S @@ -470,7 +470,7 @@ LEAF_END SinglecastDelegateInvokeStub, _TEXT // On exit: // tail calls to real method // - NESTED_ENTRY ComCallPreStub, _TEXT, NoHandler +NESTED_ENTRY ComCallPreStub, _TEXT, NoHandler // Save arguments and return address PROLOG_SAVE_REG_PAIR fp, lr, -ComCallPreStub_FirstStackAdjust! @@ -508,7 +508,7 @@ ComCallPreStub_ErrorExit EPILOG_RETURN - NESTED_END ComCallPreStub, _TEXT +NESTED_END ComCallPreStub, _TEXT // ------------------------------------------------------------------ // COM to CLR stub which sets up a ComMethodFrame and calls COMToCLRWorker. @@ -1062,65 +1062,65 @@ GenerateRedirectedStubWithFrame NakedThrowHelper, NakedThrowHelper2 #define BACKPATCH_FLAG 1 #define PROMOTE_CHAIN_FLAG 2 - NESTED_ENTRY ResolveWorkerChainLookupAsmStub, _TEXT, NoHandler +NESTED_ENTRY ResolveWorkerChainLookupAsmStub, _TEXT, NoHandler - tst x11, #BACKPATCH_FLAG // First we check if x11 has the BACKPATCH_FLAG set - bne LOCAL_LABEL(Fail) // If the BACKPATCH_FLAGS is set we will go directly to the ResolveWorkerAsmStub + tst x11, #BACKPATCH_FLAG // First we check if x11 has the BACKPATCH_FLAG set + bne LOCAL_LABEL(Fail) // If the BACKPATCH_FLAGS is set we will go directly to the ResolveWorkerAsmStub - ldr x13, [x0] // retrieve the MethodTable from the object ref in x0 + ldr x13, [x0] // retrieve the MethodTable from the object ref in x0 LOCAL_LABEL(MainLoop): - ldr x9, [x9, #ResolveCacheElem__pNext] // x9 <= the next entry in the chain - cmp x9, #0 - beq LOCAL_LABEL(Fail) + ldr x9, [x9, #ResolveCacheElem__pNext] // x9 <= the next entry in the chain + cmp x9, #0 + beq LOCAL_LABEL(Fail) - ldp x16, x17, [x9] - cmp x16, x13 // compare our MT with the one in the ResolveCacheElem - bne LOCAL_LABEL(MainLoop) + ldp x16, x17, [x9] + cmp x16, x13 // compare our MT with the one in the ResolveCacheElem + bne LOCAL_LABEL(MainLoop) - cmp x17, x12 // compare our DispatchToken with one in the ResolveCacheElem - bne LOCAL_LABEL(MainLoop) + cmp x17, x12 // compare our DispatchToken with one in the ResolveCacheElem + bne LOCAL_LABEL(MainLoop) LOCAL_LABEL(Success): - PREPARE_EXTERNAL_VAR g_dispatch_cache_chain_success_counter, x13 - ldr x16, [x13] - subs x16, x16, #1 - str x16, [x13] - blt LOCAL_LABEL(Promote) + PREPARE_EXTERNAL_VAR g_dispatch_cache_chain_success_counter, x13 + ldr x16, [x13] + subs x16, x16, #1 + str x16, [x13] + blt LOCAL_LABEL(Promote) - ldr x16, [x9, #ResolveCacheElem__target] // get the ImplTarget - br x16 // branch to interface implemenation target + ldr x16, [x9, #ResolveCacheElem__target] // get the ImplTarget + br x16 // branch to interface implemenation target LOCAL_LABEL(Promote): - // Move this entry to head postion of the chain - mov x16, #256 - str x16, [x13] // be quick to reset the counter so we don't get a bunch of contending threads - orr x11, x11, #PROMOTE_CHAIN_FLAG // set PROMOTE_CHAIN_FLAG + // Move this entry to head postion of the chain + mov x16, #256 + str x16, [x13] // be quick to reset the counter so we don't get a bunch of contending threads + orr x11, x11, #PROMOTE_CHAIN_FLAG // set PROMOTE_CHAIN_FLAG LOCAL_LABEL(Fail): - b ResolveWorkerAsmStub // call the ResolveWorkerAsmStub method to transition into the VM + b ResolveWorkerAsmStub // call the ResolveWorkerAsmStub method to transition into the VM - NESTED_END ResolveWorkerChainLookupAsmStub, _TEXT +NESTED_END ResolveWorkerChainLookupAsmStub, _TEXT // ------------------------------------------------------------------ // void ResolveWorkerAsmStub(args in regs x0-x7 & stack and possibly retbuf arg in x8, x11:IndirectionCellAndFlags, x12:DispatchToken) // // The stub dispatch thunk which transfers control to VSD_ResolveWorker. - NESTED_ENTRY ResolveWorkerAsmStub, _TEXT, NoHandler +NESTED_ENTRY ResolveWorkerAsmStub, _TEXT, NoHandler - PROLOG_WITH_TRANSITION_BLOCK + PROLOG_WITH_TRANSITION_BLOCK - add x0, sp, #__PWTB_TransitionBlock // pTransitionBlock - and x1, x11, #-4 // Indirection cell - mov x2, x12 // DispatchToken - and x3, x11, #3 // flag - bl VSD_ResolveWorker - mov x9, x0 + add x0, sp, #__PWTB_TransitionBlock // pTransitionBlock + and x1, x11, #-4 // Indirection cell + mov x2, x12 // DispatchToken + and x3, x11, #3 // flag + bl VSD_ResolveWorker + mov x9, x0 - EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + EPILOG_WITH_TRANSITION_BLOCK_TAILCALL - EPILOG_BRANCH_REG x9 + EPILOG_BRANCH_REG x9 - NESTED_END ResolveWorkerAsmStub, _TEXT +NESTED_END ResolveWorkerAsmStub, _TEXT #ifdef FEATURE_READYTORUN @@ -1144,27 +1144,27 @@ NESTED_END DelayLoad_MethodCall_FakeProlog, _TEXT .macro DynamicHelper frameFlags, suffix - NESTED_ENTRY DelayLoad_Helper\suffix\()_FakeProlog, _TEXT, NoHandler +NESTED_ENTRY DelayLoad_Helper\suffix\()_FakeProlog, _TEXT, NoHandler DelayLoad_Helper\suffix: - .global DelayLoad_Helper\suffix - - PROLOG_WITH_TRANSITION_BLOCK - - add x0, sp, #__PWTB_TransitionBlock // pTransitionBlock - mov x1, x11 // Indirection cell - mov x2, x9 // sectionIndex - mov x3, x10 // Module* - mov x4, \frameFlags - bl DynamicHelperWorker - cbnz x0, LOCAL_LABEL(FakeProlog\suffix\()_0) - ldr x0, [sp, #__PWTB_ArgumentRegisters] - EPILOG_WITH_TRANSITION_BLOCK_RETURN + .global DelayLoad_Helper\suffix + + PROLOG_WITH_TRANSITION_BLOCK + + add x0, sp, #__PWTB_TransitionBlock // pTransitionBlock + mov x1, x11 // Indirection cell + mov x2, x9 // sectionIndex + mov x3, x10 // Module* + mov x4, \frameFlags + bl DynamicHelperWorker + cbnz x0, LOCAL_LABEL(FakeProlog\suffix\()_0) + ldr x0, [sp, #__PWTB_ArgumentRegisters] + EPILOG_WITH_TRANSITION_BLOCK_RETURN LOCAL_LABEL(FakeProlog\suffix\()_0): - mov x12, x0 - EPILOG_WITH_TRANSITION_BLOCK_TAILCALL - EPILOG_BRANCH_REG x12 + mov x12, x0 + EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + EPILOG_BRANCH_REG x12 - NESTED_END DelayLoad_Helper\suffix\()_FakeProlog, _TEXT +NESTED_END DelayLoad_Helper\suffix\()_FakeProlog, _TEXT .endm DynamicHelper DynamicHelperFrameFlags_Default