[ARM64/Unix] (dotnet/coreclr#9500)
authorSteve MacLean <sdmaclea@qti.qualcomm.com>
Fri, 17 Feb 2017 18:25:37 +0000 (13:25 -0500)
committerJan Vorlicek <janvorli@microsoft.com>
Fri, 17 Feb 2017 18:25:37 +0000 (19:25 +0100)
* [Arm64/Unix] Update arm64 *.S files to match *.asm

* [Arm64/Unix] Fix CONTEXTToNativeContext()

* [Arm64/Unix] ThrowExceptionFromContextInternal

* [Arm64/Unix] Preserve x8 argument register

* [ARM64/Unix] Add CFI directives

Add native unwind info

* [Arm64/Unix] Fix RtlRestoreContext

* [Arm64/Unix] Restore FP from CurrentContextPointers

* [Arm64/Unix] fix pointer math

* [Arm64/Unix] Fix CallDescrWorkerInternal personality

* [Arm64/Unix] More Fp fixups

* [Arm64/Unix] CallEHFunclet machine state

Restore non-volatile machine state in CallEHFunclet

* [Arm64/Unix] CallDescrWorkerInternal

Use empty stack slot to save argument

* [Arm64/Unix] RtlVirtualUnwind update pointers

* [Arm64] LazyMachState fixes

* [Arm64/Unix] disable USE_REDIRECT_FOR_GCSTRESS

When FEATURE_PAL is enableds USE_REDIRECT_FOR_GCSTRESS
is not supported

* [Arm64] ClearRegDisplayArgumentAndScratchRegisters()

* [Arm64] Remove unnecesary copy in TransitionFrame

* [Arm64/Unix] Fix comment per review

* [Arm64/Unix] move constants per review

* [Arm64/Unix] Use ldp per review

Also fix indentation

* [Arm64/Unix] Fix indentation per review

* [Arm64/Unix] Remove m_Unwound per review comments

* [Arm64/Unix] Use PREPARE_EXTERNAL_VAR to access globals

* [Arm64/Unix] Fix more whitespace per earlier review comments

Commit migrated from https://github.com/dotnet/coreclr/commit/9baa44aa334cf6f032e4abeae10dc1b960aaeb57

18 files changed:
src/coreclr/src/debug/ee/arm64/dbghelpers.S
src/coreclr/src/debug/ee/wks/CMakeLists.txt
src/coreclr/src/pal/inc/unixasmmacrosarm64.inc
src/coreclr/src/pal/src/arch/arm64/asmconstants.h [new file with mode: 0644]
src/coreclr/src/pal/src/arch/arm64/context2.S
src/coreclr/src/pal/src/arch/arm64/exceptionhelper.S
src/coreclr/src/pal/src/exception/seh-unwind.cpp
src/coreclr/src/pal/src/include/pal/context.h
src/coreclr/src/pal/src/thread/context.cpp
src/coreclr/src/unwinder/arm64/unwinder_arm64.cpp
src/coreclr/src/vm/arm64/asmhelpers.S
src/coreclr/src/vm/arm64/asmhelpers.asm
src/coreclr/src/vm/arm64/calldescrworkerarm64.S
src/coreclr/src/vm/arm64/cgencpu.h
src/coreclr/src/vm/arm64/gmscpu.h
src/coreclr/src/vm/arm64/pinvokestubs.S
src/coreclr/src/vm/arm64/stubs.cpp
src/coreclr/src/vm/exceptionhandling.cpp

index 07ed04a..64932f3 100644 (file)
@@ -1,25 +1,50 @@
-//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"
 
-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
+//
 
-// NOTE: FuncEvalHijackPersonalityRoutine is dependent on the stack layout so if 
-// you change the prolog you will also need to update the personality routine.
+// @dbgtodo- once we port Funceval, use the ExceptionHijack stub instead of this func-eval stub.
+NESTED_ENTRY FuncEvalHijack, _TEXT, UnhandledExceptionHandlerUnix
 
-// push arg to the stack so our personality routine can find it 
-// push lr to get good stacktrace in debugger    
+    // NOTE: FuncEvalHijackPersonalityRoutine is dependent on the stack layout so if
+    //       you change the prolog you will also need to update the personality routine.
 
-PROLOG_SAVE_REG_PAIR  fp, lr, #-32
+    // 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
+// 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
 
-       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_ENTRY ExceptionHijack,,ExceptionHijackPersonalityRoutine
\ No newline at end of file
index 1088355..4c4c537 100644 (file)
@@ -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()
index 359f27f..ed73748 100644 (file)
@@ -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
@@ -94,14 +108,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 +147,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,74 +155,114 @@ 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 
-
-        PROLOG_SAVE_REG_PAIR_INDEXED   fp, lr, #-160
-        // 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
-       
+        __PWTB_ArgumentRegisters = __PWTB_StackAlloc + 96
+
+        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)]
+       .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
 
 // 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)]
+       .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 
+.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 
+.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
 
+.macro EPILOG_BRANCH Target
+        b \Target
 .endm
 
 .macro EPILOG_BRANCH_REG reg
@@ -216,40 +271,42 @@ C_FUNC(\Name\()_End):
 
 .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   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
 
@@ -273,8 +330,8 @@ __RedirectionFuncName SETS "|?RedirectedHandledJITCaseFor":CC:"$reason":CC:"@Thr
         IMPORT $__RedirectionFuncName
 
         NESTED_ENTRY $__RedirectionStubFuncName
-        PROLOG_SAVE_REG_PAIR    fp, lr, #-16
-        sub sp, sp, #16                          // stack slot for CONTEXT * and padding 
+        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
         //If CONTEXT is not saved at 0 offset from SP it must be changed as well.
diff --git a/src/coreclr/src/pal/src/arch/arm64/asmconstants.h b/src/coreclr/src/pal/src/arch/arm64/asmconstants.h
new file mode 100644 (file)
index 0000000..b2bf744
--- /dev/null
@@ -0,0 +1,95 @@
+// 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_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
+#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
index a64e62c..e62a9ac 100644 (file)
@@ -8,87 +8,7 @@
 //
 
 #include "unixasmmacros.inc"
-
-#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_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
+#include "asmconstants.h"
 
 // Incoming:
 //  x0: Context*
@@ -115,10 +35,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
@@ -224,14 +142,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]
@@ -256,12 +168,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]
@@ -279,12 +186,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
@@ -293,8 +195,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
index 4fdcfc5..480846e 100644 (file)
@@ -3,7 +3,30 @@
 // 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]!
+
+    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)
 LEAF_END ThrowExceptionFromContextInternal, _TEXT
index aeb6fa4..1f20ee0 100644 (file)
@@ -244,6 +244,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
index 6857c13..08fa05d 100644 (file)
@@ -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)
index bee6ddd..98867c9 100644 (file)
@@ -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)
index e13c7b9..36f7de1 100644 (file)
@@ -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)
 
@@ -215,7 +236,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 +316,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
@@ -479,9 +500,9 @@ 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 + (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
@@ -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));
index d92e91c..dd28c3e 100644 (file)
@@ -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.
@@ -120,18 +121,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, 8
+    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 +141,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 +188,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 +267,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)
+    PREPARE_EXTERNAL_VAR g_lowest_address, x12
+    ldr  x12, [x12]
+    sub  x12, x14, x12
+    PREPARE_EXTERNAL_VAR g_GCShadow, x13
+    ldr  x13, [x13]
+    add  x12, x13, x12
+
+    // if (pShadow >= g_GCShadowEnd) goto end
+    PREPARE_EXTERNAL_VAR g_GCShadowEnd, x13
+    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 +369,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, 8
+    SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88
 
     // Refer to ZapImportVirtualThunk::Save
     // for details on this.
@@ -366,8 +388,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 +447,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, 8
+    SAVE_FLOAT_ARGUMENT_REGISTERS sp, 88
 
     mov x0, x12
     bl C_FUNC(TheUMEntryPrestubWorker)
@@ -443,8 +611,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 +625,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 +710,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 +749,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
@@ -601,8 +769,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
@@ -659,13 +827,14 @@ 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)
 
     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
@@ -675,13 +844,13 @@ 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
-    // 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_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]
@@ -692,7 +861,7 @@ NESTED_ENTRY OnHijackTripThread, _TEXT, NoHandler
 
     mov x0, sp
     bl OnHijackWorker
-       
+
     // restore any integral return value(s)
     ldp x0, x1, [sp, #96]
 
@@ -700,12 +869,12 @@ 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   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
 
@@ -732,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
@@ -749,16 +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
-    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
@@ -767,7 +946,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:
     //
@@ -781,7 +960,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
@@ -800,7 +979,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
@@ -838,7 +1017,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:
     //
@@ -850,32 +1029,147 @@ 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):
+    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
+
+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
 
 
 .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
+    .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
+NESTED_END DelayLoad_Helper\suffix\()_FakeProlog, _TEXT
 .endm
 
 DynamicHelper DynamicHelperFrameFlags_Default
 DynamicHelper DynamicHelperFrameFlags_ObjectArg, _Obj
 DynamicHelper DynamicHelperFrameFlags_ObjectArg | DynamicHelperFrameFlags_ObjectArg2, _ObjObj
-
 #endif
 
 #ifdef FEATURE_PREJIT
@@ -891,7 +1185,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 +1194,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
index 2fc6a6a..d760765 100644 (file)
@@ -1311,4 +1311,4 @@ Fail
 #endif
 
 ; Must be at very end of file
-    END
\ No newline at end of file
+    END
index 803b949..2210d70 100644 (file)
 //-----------------------------------------------------------------------------
 //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
+NESTED_ENTRY CallDescrWorkerInternal, _TEXT, NoHandler
+    PROLOG_SAVE_REG_PAIR_INDEXED   fp, lr, -32
+    PROLOG_SAVE_REG    x19, 16
+    PROLOG_SAVE_REG    x0, 24
 
     mov     x19, x0 // save pCallDescrData in x19
 
@@ -44,29 +45,31 @@ 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     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     x19, [fp, 24] // Fixup corrupted X19 caller preserved register
 
     ldr     w3, [x19,#CallDescrData__fpReturnSize]
 
@@ -110,7 +113,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):
 
@@ -122,7 +125,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
index be3e34d..a176028 100644 (file)
@@ -14,7 +14,9 @@
 #define INSTRFMT_K64
 #include <stublink.h>
 
+#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);
index e95ef63..7785daf 100644 (file)
@@ -56,25 +56,34 @@ 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 = &copy->captureX19_X29[0];
-    ULONG64* srcUpperBound = (ULONG64*)((BYTE*)copy + offsetof(MachState, ptrX19_X29));
+    // 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
 
-    for (int i = 0; i<NUM_NONVOLATILE_CONTEXT_POINTERS; i++)
+    PULONG64* pSrc = (PULONG64 *)&copy->ptrX19_X29;
+    PULONG64* pDst = (PULONG64 *)&this->ptrX19_X29;
+
+    const PULONG64 LowerBoundDst = (PULONG64) this;
+    const PULONG64 LowerBoundSrc = (PULONG64) copy;
+
+    const PULONG64 UpperBoundSrc = (PULONG64) ((BYTE*)LowerBoundSrc + sizeof(*copy));
+
+    for (int i = 0; i < NUM_NONVOLATILE_CONTEXT_POINTERS; i++)
     {
-        if (copy->ptrX19_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);
index f6c33ba..c87e800 100644 (file)
 // $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
index e526d9e..f56f6ab 100644 (file)
@@ -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,
@@ -371,6 +377,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 +470,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 +496,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 +522,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];
@@ -489,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
 
@@ -759,23 +810,15 @@ 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 + (sizeof(void*)*i)) = pArgRegs->x[i];
-#else
-        pRD->pCurrentContext->X[i] = pArgRegs->x[i];
-#endif
-
     // copy the callee saved regs
     CalleeSavedRegisters *pCalleeSaved = GetCalleeSavedRegisters();
     UpdateRegDisplayFromCalleeSavedRegisters(pRD, pCalleeSaved);
 
+    ClearRegDisplayArgumentAndScratchRegisters(pRD);
+
     // copy the control registers
     pRD->pCurrentContext->Fp = pCalleeSaved->x29;
     pRD->pCurrentContext->Lr = pCalleeSaved->x30;
@@ -788,6 +831,7 @@ void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
     LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK    TransitionFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP));
 }
 
+
 #endif
 
 #ifndef        CROSSGEN_COMPILE
@@ -832,6 +876,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.
 
@@ -859,20 +905,34 @@ 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<TADDR>(m_pCallSiteSP);
 
-    pRD->IsCallerContextValid = FALSE;
-    pRD->IsCallerSPValid      = FALSE;
+    // reset pContext; it's only valid for active (top-most) frame
+    pRD->pContext = NULL;
+
+    ClearRegDisplayArgumentAndScratchRegisters(pRD);
 
-    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;
 
     LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK    InlinedCallFrame::UpdateRegDisplay(pc:%p, sp:%p)\n", pRD->ControlPC, pRD->SP));
index 05500d4..20929bc 100644 (file)
@@ -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");