diff options
author | Jan Vorlicek <janvorli@microsoft.com> | 2016-08-12 03:47:07 +0300 |
---|---|---|
committer | Jan Vorlicek <janvorli@microsoft.com> | 2016-08-12 03:47:07 +0300 |
commit | be6ba12cce4c4404729c4d4a5b462b458a36b8dc (patch) | |
tree | af8a94986645fbd3098714b5d7d893e620a7a77c /src/Native/Runtime/i386 | |
parent | 91a33c98269c5f06ec980c30ef79fec06fccf3ce (diff) |
This fixes debugger step-in in the interface dispatch changes
[tfs-changeset: 1622102]
Diffstat (limited to 'src/Native/Runtime/i386')
-rw-r--r-- | src/Native/Runtime/i386/AsmMacros.inc | 6 | ||||
-rw-r--r-- | src/Native/Runtime/i386/ManagedCalloutThunk.asm | 64 | ||||
-rw-r--r-- | src/Native/Runtime/i386/StubDispatch.asm | 90 | ||||
-rw-r--r-- | src/Native/Runtime/i386/UniversalTransition.asm | 17 |
4 files changed, 25 insertions, 152 deletions
diff --git a/src/Native/Runtime/i386/AsmMacros.inc b/src/Native/Runtime/i386/AsmMacros.inc index 7c8f4d372..bc8051d2b 100644 --- a/src/Native/Runtime/i386/AsmMacros.inc +++ b/src/Native/Runtime/i386/AsmMacros.inc @@ -139,12 +139,6 @@ PTFF_RAX_IS_GCREF equ 00010000h ;; iff PTFF_SAVE_RAX: set -> eax is Obje PTFF_RAX_IS_BYREF equ 00020000h ;; iff PTFF_SAVE_RAX: set -> eax is ByRef, clear -> eax is Object or scalar ;; -;; Offset from FP (ebp) where the managed callout thunk (ManagedCallout2 and possibly others in the future) -;; store a pointer to a transition frame. -;; -MANAGED_CALLOUT_THUNK_TRANSITION_FRAME_POINTER_OFFSET equ -4 - -;; ;; Rename fields of nested structs ;; OFFSETOF__Thread__m_alloc_context__alloc_ptr equ OFFSETOF__Thread__m_rgbAllocContextBuffer + OFFSETOF__alloc_context__alloc_ptr diff --git a/src/Native/Runtime/i386/ManagedCalloutThunk.asm b/src/Native/Runtime/i386/ManagedCalloutThunk.asm deleted file mode 100644 index 8b0a181e3..000000000 --- a/src/Native/Runtime/i386/ManagedCalloutThunk.asm +++ /dev/null @@ -1,64 +0,0 @@ -;; 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. - - .586 - .model flat - option casemap:none - .code - - -include AsmMacros.inc - -;; -;; Defines a small assembly thunk designed to be used when unmanaged code in the runtime calls out to managed -;; code. In such cases the stack walker needs to be able to bridge the unmanaged gap in the stack between the -;; callout and whatever managed code initially entered the runtime. This thunk makes that goal achievable by -;; (a) exporting a well-known address in the thunk that will be the result of unwinding from the callout (so -;; the stack frame iterator knows when its hit this case) and (b) placing a copy of a pointer to a transition -;; frame saved when the previous managed caller entered the runtime into a well-known location relative to the -;; thunk's frame, enabling the stack frame iterator to recover the transition frame address and use it to -;; re-initialize the stack walk at the previous managed caller. -;; -;; If we end up with more cases of this (currently it's used only for the ICastable extension point for -;; interface dispatch) then we might decide to produce a general routine which can handle an arbitrary number -;; of arguments to the target method. For now we'll just implement the case we need, which takes two regular -;; arguments (that's the 2 in the ManagedCallout2 name). -;; -;; Inputs: -;; ecx : Argument 1 to target method -;; edx : Argument 2 to target method -;; [esp + 4] : Target method address -;; [esp + 8] : Pointer to previous managed method's transition frame into the runtime -;; -FASTCALL_FUNC ManagedCallout2, 16 - - ;; Push an EBP frame. Apart from making it easier to walk the stack the stack frame iterator locates - ;; the transition frame for the previous managed caller relative to the frame pointer to keep the code - ;; architecture independent. - push ebp - mov ebp, esp - - ;; Stash the previous transition frame's address immediately on top of the old ebp value. This - ;; position is important; the stack frame iterator knows about this setup. -.erre MANAGED_CALLOUT_THUNK_TRANSITION_FRAME_POINTER_OFFSET eq -4 - mov eax, [ebp + 0Ch] - push eax - - ;; Grab the target method's address. Since the arguments are already set up in the correct registers - ;; we can just go. The _ReturnFromManagedCallout2 label must immediately follow the call instruction. - mov eax, [ebp + 08h] - call eax -LABELED_RETURN_ADDRESS ReturnFromManagedCallout2 - - ;; Pop the ebp frame and return. - mov esp, ebp - pop ebp - ret 8 - -FASTCALL_ENDFUNC - -PUBLIC _ReturnFromManagedCallout2 - - -END diff --git a/src/Native/Runtime/i386/StubDispatch.asm b/src/Native/Runtime/i386/StubDispatch.asm index accf90891..3e8426311 100644 --- a/src/Native/Runtime/i386/StubDispatch.asm +++ b/src/Native/Runtime/i386/StubDispatch.asm @@ -13,7 +13,8 @@ include AsmMacros.inc ifdef FEATURE_CACHED_INTERFACE_DISPATCH -EXTERN @RhpResolveInterfaceMethodCacheMiss@12 : PROC +EXTERN RhpCidResolve : PROC +EXTERN _RhpUniversalTransition_DebugStepTailCall@0 : PROC ;; Macro that generates code to check a single cache entry. @@ -62,6 +63,7 @@ CurrentEntry = CurrentEntry + 1 ;; eax currently contains the cache block. We need to point it back to the ;; indirection cell using the back pointer in the cache block mov eax, [eax + OFFSETOF__InterfaceDispatchCache__m_pCell] + pop ebx jmp InterfaceDispatchCacheMiss StubName endp @@ -80,81 +82,17 @@ DEFINE_INTERFACE_DISPATCH_STUB 64 ;; Shared out of line helper used on cache misses. InterfaceDispatchCacheMiss proc +;; eax points at InterfaceDispatchCell - ;; Push an ebp frame since it makes some of our later calculations easier. - push ebp - mov ebp, esp - - ;; Save argument registers while we call out to the C++ helper. Note that we depend on these registers - ;; (which may contain GC references) being spilled before we build the PInvokeTransitionFrame below - ;; due to the way we build a stack range to report to the GC conservatively during a collection. - push ecx - push edx - - ;; Build PInvokeTransitionFrame. This is only required if we end up resolving the interface method via - ;; a callout to a managed ICastable method. In that instance we need to be able to cope with garbage - ;; collections which in turn need to be able to walk the stack from the ICastable method, skip the - ;; unmanaged runtime portions and resume walking at our caller. This frame provides both the means to - ;; unwind to that caller and a place to spill callee saved registers in case they contain GC - ;; references from the caller. - - ;; Calculate caller's esp: relative to ebp's current value we've pushed the old ebp, ebx and a return - ;; address. - lea edx, [ebp + (3 * 4)] - push edx - - ;; Push callee saved registers. Note we've already pushed ebx but we need to do it here again so that - ;; it is reported to the GC correctly if necessary. As such it's necessary to pushed the saved version - ;; of ebx and make sure when we restore it we use this copy and discard the version that was initially - ;; pushed (since its value may now be stale). - push edi - push esi - mov edx, [ebp + 04h] ; Old RBX value - push edx - - ;; Push flags. - push PTFF_SAVE_ALL_PRESERVED + PTFF_SAVE_RSP - - ;; Leave space for the Thread* (stackwalker does not use this). - push 0 - - ;; The caller's ebp. - push [ebp] - - ;; The caller's eip. - push [ebp + 08h] - - ;; First argument is the instance we're dispatching on which is already in ecx. - - ;; Second argument is the dispatch data cell. - ;; We still have this in eax - mov edx, eax - - ;; The third argument is the address of the transition frame we build above. Currently it's at the top - ;; of the stack so esp points to it. - push esp - - call @RhpResolveInterfaceMethodCacheMiss@12 - - ;; Recover callee-saved values from the transition frame in case a GC updated them. - mov ebx, [esp + 010h] - mov esi, [esp + 014h] - mov edi, [esp + 018h] - - ;; Restore real argument registers. - mov edx, [ebp - 08h] - mov ecx, [ebp - 04h] - - ;; Remove the transition and ebp frames from the stack. - mov esp, ebp - pop ebp - - ;; Discard the space where ebx was pushed on entry, its value is now potentially stale. - add esp, 4 - - ;; Final target address is in eax. - jmp eax +;; Setup call to Universal Transition thunk + push ebp + mov ebp, esp + push eax ; First argument (Interface Dispatch Cell) + lea eax, [RhpCidResolve] + push eax ; Second argument (RhpCidResolve) +;; Jump to Universal Transition + jmp _RhpUniversalTransition_DebugStepTailCall@0 InterfaceDispatchCacheMiss endp ;; Out of line helper used when we try to interface dispatch on a null pointer. Sets up the stack so the @@ -171,10 +109,6 @@ RhpInterfaceDispatchNullReference endp RhpInitialInterfaceDispatch proc public ALTERNATE_ENTRY RhpInitialDynamicInterfaceDispatch - ;; Mainly we just tail call to the cache miss helper. But this helper expects that ebx has been pushed - ;; on the stack. - push ebx - jmp InterfaceDispatchCacheMiss RhpInitialInterfaceDispatch endp diff --git a/src/Native/Runtime/i386/UniversalTransition.asm b/src/Native/Runtime/i386/UniversalTransition.asm index 3f69d463b..1c16e369d 100644 --- a/src/Native/Runtime/i386/UniversalTransition.asm +++ b/src/Native/Runtime/i386/UniversalTransition.asm @@ -55,13 +55,15 @@ ifdef FEATURE_DYNAMIC_CODE ; everything between the base of the IntArgRegs and the top of the StackPassedArgs. ; -FASTCALL_FUNC RhpUniversalTransition_FAKE_ENTRY, 0 +UNIVERSAL_TRANSITION macro FunctionName + +FASTCALL_FUNC Rhp&FunctionName&_FAKE_ENTRY, 0 ; Set up an ebp frame push ebp mov ebp, esp push eax push eax -ALTERNATE_ENTRY RhpUniversalTransition@0 +ALTERNATE_ENTRY Rhp&FunctionName&@0 push ecx push edx @@ -72,7 +74,7 @@ ALTERNATE_ENTRY RhpUniversalTransition@0 mov edx, [ebp-4] ; Get the extra argument to pass to the callee lea ecx, [ebp-10h] ; Get pointer to edx value pushed above call eax -LABELED_RETURN_ADDRESS ReturnFromUniversalTransition +LABELED_RETURN_ADDRESS ReturnFrom&FunctionName pop edx pop ecx @@ -81,7 +83,14 @@ LABELED_RETURN_ADDRESS ReturnFromUniversalTransition jmp eax FASTCALL_ENDFUNC - + endm + + ; To enable proper step-in behavior in the debugger, we need to have two instances + ; of the thunk. For the first one, the debugger steps into the call in the function, + ; for the other, it steps over it. + UNIVERSAL_TRANSITION UniversalTransition + UNIVERSAL_TRANSITION UniversalTransition_DebugStepTailCall + endif end |