diff options
Diffstat (limited to 'src/vm/arm/asmhelpers.asm')
-rw-r--r-- | src/vm/arm/asmhelpers.asm | 524 |
1 files changed, 4 insertions, 520 deletions
diff --git a/src/vm/arm/asmhelpers.asm b/src/vm/arm/asmhelpers.asm index 796c1d14c5..542bdc65cc 100644 --- a/src/vm/arm/asmhelpers.asm +++ b/src/vm/arm/asmhelpers.asm @@ -40,12 +40,6 @@ #endif // WRITE_BARRIER_CHECK -#ifdef FEATURE_REMOTING - IMPORT $CTPMethodTable__s_pThunkTable - IMPORT VSD_GetTargetForTPWorker - IMPORT VSD_GetTargetForTPWorkerQuick - IMPORT TransparentProxyStubWorker -#endif #ifdef FEATURE_COMINTEROP IMPORT CLRToCOMWorker IMPORT ComPreStubWorker @@ -64,11 +58,6 @@ IMPORT GetCurrentSavedRedirectContext -#ifdef FEATURE_MIXEDMODE - SETALIAS IJWNOADThunk__FindThunkTarget, ?FindThunkTarget@IJWNOADThunk@@QAAPBXXZ - IMPORT $IJWNOADThunk__FindThunkTarget -#endif - ;; Imports to support virtual import fixup for ngen images IMPORT VirtualMethodFixupWorker ;; Import to support cross-moodule external method invocation in ngen images @@ -562,41 +551,6 @@ UM2MThunk_WrapperHelper_ArgumentsSetup NESTED_END -; ------------------------------------------------------------------ -; -; IJWNOADThunk::MakeCall -; -; On entry: -; r12 : IJWNOADThunk * -; -; On exit: -; Tail calls to real managed target -; - -#ifdef FEATURE_MIXEDMODE - NESTED_ENTRY IJWNOADThunk__MakeCall - - ; Can't pass C++ mangled names to NESTED_ENTRY and my attempts to use EQU to define an alternate name - ; for a symbol didn't work. Just define a label for the decorated name of the method and export it - ; manually. -|?MakeCall@IJWNOADThunk@@KAXXZ| - EXPORT |?MakeCall@IJWNOADThunk@@KAXXZ| - - PROLOG_PUSH {r0-r4,lr} - PROLOG_VPUSH {d0-d7} - - CHECK_STACK_ALIGNMENT - - mov r0, r12 ; IJWNOADThunk * is this pointer for IJWNOADThunk::FindThunkTarget - bl $IJWNOADThunk__FindThunkTarget - mov r12, r0 ; Returns real jump target in r0, save this in r12 - - EPILOG_VPOP {d0-d7} - EPILOG_POP {r0-r4,lr} - EPILOG_BRANCH_REG r12 - - NESTED_END -#endif ; ------------------------------------------------------------------ @@ -704,7 +658,7 @@ ThePreStubPatchLabel NESTED_END -#if defined(FEATURE_REMOTING) || defined(FEATURE_COMINTEROP) +#if defined(FEATURE_COMINTEROP) ; ------------------------------------------------------------------ ; setStubReturnValue @@ -753,372 +707,10 @@ NoFloatingPointRetVal LEAF_END -#endif // FEATURE_REMOTING || FEATURE_COMINTEROP - -#ifdef FEATURE_REMOTING - -; ------------------------------------------------------------------ -; Remoting stub used to dispatch a method invocation. This is the choke point for all remoting calls; all -; scenarios where we determine we're not a local or a COM call, regardless of whether the dispatch is -; interface, virtual or direct will wind up here sooner or later. -; -; On entry: -; r0 : transparent proxy -; r12 : target MethodDesc or slot number -; plus user arguments in registers and on the stack -; - NESTED_ENTRY TransparentProxyStub_CrossContext - - PROLOG_WITH_TRANSITION_BLOCK 0x20 - - add r0, sp, #__PWTB_TransitionBlock ; pTransitionBlock - mov r1, r12 ; pMethodDesc - - bl TransparentProxyStubWorker - - ; r0 = fpRetSize - - ; return value is stored before float argument registers - add r1, sp, #(__PWTB_FloatArgumentRegisters - 0x20) - bl setStubReturnValue - - EPILOG_WITH_TRANSITION_BLOCK_RETURN - - NESTED_END - -; ------------------------------------------------------------------ -; This method does nothing. It's just a fixed function for the debugger to put a breakpoint on. - LEAF_ENTRY TransparentProxyStubPatch - add r0, r1, r2 -TransparentProxyStubPatchLabel - EXPORT TransparentProxyStubPatchLabel - bx lr - LEAF_END - -; ------------------------------------------------------------------ -; VSD helper for performing an in-context interface dispatch on a TransparentProxy. This only happens for -; ContextBoundObjects that are invoked in the correct context, never for general remoting. -; -; On entry: -; r0 : transparent proxy -; r12 : interface MethodDesc -; plus user arguments in registers and on the stack -; -; On exit: -; Tail calls to actual target which returns as normal to the caller. -; - NESTED_ENTRY InContextTPQuickDispatchAsmStub - - ; Spill caller's volatile argument registers and some other state we wish to preserve. - PROLOG_PUSH {r0-r3,r12,lr} - PROLOG_VPUSH {d0-d7} - - CHECK_STACK_ALIGNMENT - - ; Set up arguments for VSD_GetTargetForTPWorkerQuick - ; mov r0, r0 ; this - mov r1, r12 ; Interface MethodDesc - - bl VSD_GetTargetForTPWorkerQuick - - ; If we didn't find a target head for the slow path. - cbz r0, CacheMiss - - ; Save target address since we're about to restore the value of r0. Can't place it directly into r12 - ; since that's about to be restored as well. Instead we overwrite the saved version of r12 on the - ; stack (we don't need it any more since the lookup succeeded). - str r0, [sp, #((16 * 4) + (4 * 4))] - - ; Restore caller's argument registers. - EPILOG_VPOP {d0-d7} - EPILOG_POP {r0-r3,r12,lr} - - ; Tail call to the real code using the previously computed target address. - EPILOG_BRANCH_REG r12 - -CacheMiss - ; Restore caller's argument registers. - EPILOG_VPOP {d0-d7} - EPILOG_POP {r0-r3,r12,lr} - - EPILOG_BRANCH InContextTPDispatchAsmStub - - NESTED_END - -; ------------------------------------------------------------------ - - NESTED_ENTRY InContextTPDispatchAsmStub - - PROLOG_WITH_TRANSITION_BLOCK - - add r0, sp, #__PWTB_TransitionBlock ; pTransitionBlock - mov r1, r12 ; pMethodDesc / token - - bl VSD_GetTargetForTPWorker - - mov r12, r0 - - EPILOG_WITH_TRANSITION_BLOCK_TAILCALL - EPILOG_BRANCH_REG r12 - - NESTED_END - -; ------------------------------------------------------------------ -; Macro used to compare a MethodTable with that of __TransparentProxy. Sets the Z condition flag to indicate -; the result (Z=1 for a match, Z=0 for a mismatch). -; - MACRO - TP_TYPE_CHECK $methodTableReg, $scratchReg - - ldr $scratchReg, =$CTPMethodTable__s_pThunkTable - ldr $scratchReg, [$scratchReg] - cmp $scratchReg, $methodTableReg - MEND - -; ------------------------------------------------------------------ -; Macro used to perform a context check. -; -; Calls a user customizable routine that determines whether the current execution context warrants a context -; transition for the call. Regular remoting (as opposed to context transitioning based on ContextBoundObjects) -; always returns a context-mismatch from this call. -; -; On entry: -; r0 : this (TranparentProxy object) -; -; On exit: -; r0 : check result (0 == contexts match, non-zero == contexts mismatch) -; r1-r3,r12,lr: trashed -; - MACRO - TP_CONTEXT_CHECK - - ldr r1, [r0, #TransparentProxyObject___stub] - ldr r0, [r0, #TransparentProxyObject___stubData] - blx r1 - MEND - -; ------------------------------------------------------------------ -; Used by the remoting precode for non-virtual dispatch to instance methods which might be remoted. Performs a -; context and transparent proxy check and if both of these are negative (or the call has been made on a null -; 'this') we simply return and the precode will dispatch the call locally as normal. Otherwise we redirect to -; the remoting system and never return. -; -; On entry: -; r0 : this (may or may not be a TransparentProxy) -; r1 : trashed -; lr : return address into RemotingPrecode (RemotingPrecode* + REMOTING_PRECODE_RET_OFFSET) -; [sp, #0] : caller's saved r1 -; [sp, #4] : caller's saved lr (i.e. return address into caller of RemotingPrecode) -; plus user arguments in registers and on the stack -; - LEAF_ENTRY PrecodeRemotingThunk - - ; Send null 'this' case to local dispatch case (else we'd need to handle an A/V from this stub). - cbz r0, LocalDispatch ; predicted not taken - - ; Load MethodTable* in r12. - ldr r12, [r0] - - ; Compare MethodTable in 'this' with that of __TransparentProxy; if they're not equal we dispatch - ; locally. - TP_TYPE_CHECK r12, r1 ; r1 is a scratch register - beq TransparentProxyDispatch ; predicted not taken - -LocalDispatch - ; Recover target MethodDesc pointer from the RemotingPrecode (we have the address of this + - ; REMOTING_PRECODE_RET_OFFSET in lr). Subtract extra 1 to account for the low-bit being set in LR to - ; indicate thumb mode. - ; We do this here because even the local case needs r12 initialized. - ldr r12, [lr, #(RemotingPrecode__m_pMethodDesc - REMOTING_PRECODE_RET_OFFSET - 1)] - - bx lr - - LEAF_END - -; ------------------------------------------------------------------ -; Handles the atypical path for the remoting precode above (typically the non-local dispatch cases). The -; regular entry point defined by NESTED_ENTRY below is never called directly; it serves only to generate -; prolog unwind data matching the pushes of the caller's r1 and lr done in the remoting precode so we can -; unwind out of this frame. The real entry point is TransparentProxyDispatch called directly from -; PrecodeRemotingThunk. -; - NESTED_ENTRY TransparentProxyDispatch_FakeProlog - - ; Match what the remoting precode has pushed. - PROLOG_PUSH {r1,lr} - - ; This is where execution really starts. -TransparentProxyDispatch - - ; We need some temporary registers and to preserve lr. - PROLOG_PUSH {r0,r2-r5,lr} - - CHECK_STACK_ALIGNMENT - - ; Recover target MethodDesc pointer from the RemotingPrecode (we have the address of this + - ; REMOTING_PRECODE_RET_OFFSET in lr). Subtract extra 1 to account for the low-bit being set in LR to - ; indicate thumb mode. Stash the result in a non-volatile register to preserve it over the call to - ; TP_CONTEXT_CHECK below. - ldr r4, [lr, #(RemotingPrecode__m_pMethodDesc - REMOTING_PRECODE_RET_OFFSET - 1)] - - ; Check whether the TP is already in the correct context. This can happen for ContextBoundObjects - ; only. The following macro will trash volatile registers and lr and return the result in r0 (0 == - ; context match, non-zero for everything else). All other registers are preserved. - TP_CONTEXT_CHECK - - ; Place MethodDesc* in r12 ready for wherever we dispatch to next. - mov r12, r4 - - ; Check the result of TP_CONTEXT_CHECK - cbnz r0, ContextMismatch1 - - ; At this point we know we're being called on a transparent proxy but the source and destination - ; contexts match. This only happens for a ContextBoundObject. For an non-interface dispatch we can - ; just return to the local dispatch case; the precode will eventually redirect to the jitted code - ; which knows how to handle a TP-wrapped ContextBoundObject. For interface calls we need to hand off - ; to VSD so it can resolve to the real target method. The quickest way to determine which of these - ; cases we need is to look at the classification of the method desc. All interface methods for which a - ; remoting precode is used are marked as mcComInterop, which though non-intuitive is generally OK - ; since only COM interop and remoting can dispatch directly on an interface method desc. (Generic - ; interface methods are not classified as mcComInterop but we use a different mechanism to intercept - ; those). - ldrh r0, [r4, #MethodDesc__m_wFlags] - and r0, #MethodDesc__mdcClassification - cmp r0, #MethodDesc__mcComInterop - bne LocalDispatch1 - - ; Local interface dispatch case. Restore argument registers saved here and in the RemotingPrecode, - ; discard return address into the RemotingPrecode (we're not going back there) and restore the real - ; caller's return address to LR before tail calling into the interface dispatch helper. - EPILOG_POP {r0,r2-r5,lr} ; Restore arg registers saved by this routine and RemotingPrecode lr - EPILOG_POP {r1,lr} ; Restore r1 saved by RemotingPrecode and real return address - EPILOG_BRANCH InContextTPQuickDispatchAsmStub - -LocalDispatch1 - - ; Local dispatch case. Restore argument registers saved here and return to the remoting precode. - EPILOG_POP {r0,r2-r5,pc} - -ContextMismatch1 - ; Context-mismatch (remoted) dispatch case. Restore argument registers saved here and in the - ; RemotingPrecode, discard return address into the RemotingPrecode (we're not going back there) and - ; restore the real caller's return address to LR before tail calling into the cross-context helper. - EPILOG_POP {r0,r2-r5,lr} ; Restore arg registers saved by this routine and RemotingPrecode lr - EPILOG_POP {r1,lr} ; Restore r1 saved by RemotingPrecode and real return address - EPILOG_BRANCH TransparentProxyStub_CrossContext - - NESTED_END - -; ------------------------------------------------------------------ -; Used to dispatch an interface call that is possibly be cross-context or remoted. Normally this is handled -; by the remoting precode stub above but there is an edge case for generic interface methods that falls -; through the cracks (it is not easy to cover since the precode stub makes use of it as a quick means -; to differentiate between interface and non-interface calls in the non-cross context case). -; -; On entry: -; r0 : this (TransparentProxy object) -; r12 : interface MethodDesc -; plus user arguments in registers and on the stack -; -; On exit: -; Tail calls to the VSD in-context TP dispatcher or remoting system as appropriate. -; - NESTED_ENTRY CRemotingServices__DispatchInterfaceCall - - PROLOG_PUSH {r0-r3,r12,lr} - - CHECK_STACK_ALIGNMENT - - ; Check whether the TP is already in the correct context. This can happen for ContextBoundObjects - ; only. The following macro will trash volatile registers and lr and return the result in r0 (0 == - ; context match, non-zero for everything else). All other registers are preserved. - TP_CONTEXT_CHECK - cbnz r0, ContextMismatch2 - - ; Local interface dispatch case. Tail call to VSD helper specifically for the in-context TP dispatch - ; scenario. Interface MethodDesc is restored to r12. - EPILOG_POP {r0-r3,r12,lr} - EPILOG_BRANCH InContextTPQuickDispatchAsmStub - -ContextMismatch2 - ; Context-mismatch (remoted) dispatch case. Tail call to the general remoting dispatch code. Interface - ; MethodDesc is restored to r12. - EPILOG_POP {r0-r3,r12,lr} - EPILOG_BRANCH TransparentProxyStub_CrossContext - - NESTED_END - -; ------------------------------------------------------------------ -; Common stub used for vtable dispatch of remoted methods. A small prestub will load the vtable slot index -; into r12 and then jump here. This stub determines whether we're already in the correct context (which can -; only happen for ContextBoundObjects). Depending on the answers we'll either dispatch the call locally or -; re-direct it to the remoting system (via TransparentProxyStub_CrossContext). -; -; On entry: -; r0 : this (TransparentProxy object) -; r12 : virtual method slot number -; plus user arguments in registers and on the stack -; -; On exit: -; Tail calls to the VSD in-context TP dispatcher or remoting system as appropriate. -; - NESTED_ENTRY TransparentProxyStub - - PROLOG_PUSH {r0-r3,r12,lr} - - CHECK_STACK_ALIGNMENT - - ; Check whether the TP is already in the correct context. This can happen for ContextBoundObjects - ; only. The following macro will trash volatile registers and lr and return the result in r0 (0 == - ; context match, non-zero for everything else). All other registers are preserved. - TP_CONTEXT_CHECK - cbnz r0, ContextMismatch3 - - ; We need to perform a local vtable dispatch on the ContextBoundObject. Obviously this needs to be on - ; the real type held in the proxy, not TransparentProxy's MethodTable or we'll just end up back here - ; recursively. - - ; Recover 'this' pointer and slot number. - ldr r0, [sp] - ldr r12, [sp, #0x10] - - ; Extract real type from the TP. - ldr r0, [r0, #TransparentProxyObject___pMT] - - ; Vtables are no longer a linear array. Instead they use a two-level indirection with the first level - ; consisting of fixed sized chunks of function pointer arrays. R12 has our slot number. - - ; Calculate first level chunk index. - lsr r1, r12, #ASM__VTABLE_SLOTS_PER_CHUNK_LOG2 - - ; Load the address of the chunk from the MethodTable (the chunk table immediately follows the - ; MethodTable structure). - add r0, #SIZEOF__MethodTable - ldr r2, [r0, r1, lsl #2] - - ; Calculate the slot index within the chunk. - and r0, r12, #(ASM__VTABLE_SLOTS_PER_CHUNK - 1) - - ; Load the target address into r12 (we no longer need the slot number and we're about to restore the - ; other registers). - ldr r12, [r2, r0, lsl #2] - - ; Restore the stack state and tail call to the local target. - EPILOG_POP {r0-r3} - EPILOG_STACK_FREE 4 ; Skip restore of r12 since we've overwritten it - EPILOG_POP {lr} - EPILOG_BRANCH_REG r12 - -ContextMismatch3 - ; Contexts don't match so we have to dispatch through remoting. Clean up the stack and tail call to - ; the helper. - EPILOG_POP {r0-r3,r12,lr} - EPILOG_BRANCH TransparentProxyStub_CrossContext +#endif // FEATURE_COMINTEROP - NESTED_END -#endif // FEATURE_REMOTING -#if defined(FEATURE_REMOTING) || defined(FEATURE_COMINTEROP) +#if defined(FEATURE_COMINTEROP) ; ------------------------------------------------------------------ ; Function used by remoting/COM interop to get floating point return value (since it's not in the same ; register(s) as non-floating point values). @@ -1168,116 +760,8 @@ LsetFP8 LEAF_END -#endif defined(FEATURE_REMOTING) || defined(FEATURE_COMINTEROP) -#ifdef FEATURE_REMOTING - -; ------------------------------------------------------------------ -; Tail call Object.FieldGetter remotely with the given arguments. -; -; On entry: -; r0 : pMD (MethodDesc * of the Object.FieldGetter method) -; r1 : pThis (the transparent proxy) -; r2 : pFirst -; r3 : pSecond -; [sp, #0] : pThird -; -; On exit: -; Tail calls to the managed method -; - LEAF_ENTRY CRemotingServices__CallFieldGetter - - mov r12, r0 - mov r0, r1 - mov r1, r2 - mov r2, r3 - ldr r3, [sp, #0] - - b TransparentProxyStub_CrossContext - - LEAF_END - -; ------------------------------------------------------------------ -; Tail call Object.FieldSetter remotely with the given arguments. -; -; On entry: -; r0 : pMD (MethodDesc * of the Object.FieldSetter method) -; r1 : pThis (the transparent proxy) -; r2 : pFirst -; r3 : pSecond -; [sp, #0] : pThird -; -; On exit: -; Tail calls to the managed method -; - LEAF_ENTRY CRemotingServices__CallFieldSetter - - mov r12, r0 - mov r0, r1 - mov r1, r2 - mov r2, r3 - ldr r3, [sp, #0] - - b TransparentProxyStub_CrossContext - - LEAF_END - -; ------------------------------------------------------------------ -; General purpose remoting helper used to call given target with two parameters. -; -; On entry: -; r0 : pTarget -; r1 : pFirst -; r2 : pSecond -; -; - NESTED_ENTRY CTPMethodTable__CallTargetHelper2,,CallDescrWorkerUnwindFrameChainHandler - - PROLOG_PUSH {r11, lr} - - mov r12, r0 - mov r0, r1 - mov r1, r2 - - blx r12 - - ; Adding a nop so that unwind does not result in the IP being in epilog. - ; This ensures that the OS unwinder looks up the personality routine for this method. - nop - - EPILOG_POP {r11, pc} - - NESTED_END - -; ------------------------------------------------------------------ -; General purpose remoting helper used to call given target with three parameters. -; -; On entry: -; r0 : pTarget -; r1 : pFirst -; r2 : pSecond -; r3 : pThird -; -; - NESTED_ENTRY CTPMethodTable__CallTargetHelper3,,CallDescrWorkerUnwindFrameChainHandler - - PROLOG_PUSH {r11, lr} - - mov r12, r0 - mov r0, r1 - mov r1, r2 - mov r2, r3 - - blx r12 - - ; Adding a nop so that unwind does not result in the IP being in epilog. - ; This ensures that the OS unwinder looks up the personality routine for this method. - nop - - EPILOG_POP {r11, pc} - - NESTED_END +#endif defined(FEATURE_COMINTEROP) -#endif // FEATURE_REMOTING #ifdef FEATURE_COMINTEROP ; ------------------------------------------------------------------ |