Welcome to mirror list, hosted at ThFree Co, Russian Federation.

StubDispatch.asm « i386 « Runtime « Native « src - github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 5bfcc00dfeb50d6d68ff6b2301804d01a3bf84b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
;; 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


ifdef FEATURE_CACHED_INTERFACE_DISPATCH

EXTERN RhpCidResolve : PROC
EXTERN _RhpUniversalTransition_DebugStepTailCall@0 : PROC
EXTERN RhpCastableObjectResolve : PROC

EXTERN  _t_TLS_DispatchCell:DWORD
EXTERN  __tls_index:DWORD

GET_TLS_DISPATCH_CELL macro
        ASSUME fs : NOTHING
        mov     eax, [__tls_index]
        add     eax, eax
        add     eax, eax
        add     eax, fs:[__tls_array]
        mov     eax, [eax]
        mov     eax, [eax + SECTIONREL _t_TLS_DispatchCell]
endm

SET_TLS_DISPATCH_CELL macro
        ;; ecx: value to assign to the TLS variable
        ASSUME fs : NOTHING
        push    eax
        mov     eax, [__tls_index]
        add     eax, eax
        add     eax, eax
        add     eax, fs:[__tls_array]
        mov     eax, [eax]
        lea     eax, [eax + SECTIONREL _t_TLS_DispatchCell]
        mov     [eax],ecx
        pop     eax
endm

_RhpCastableObjectDispatch_CommonStub proc public
        ;; There are arbitrary callers passing arguments with arbitrary signatures.
        ;; Custom calling convention:
        ;;      eax: pointer to the current thunk's data block (data contains 2 pointer values: context + target pointers)

        ;; make some scratch regs
        push    ecx

        ;; store dispatch cell address into the TLS variable
        mov     ecx, [eax]
        SET_TLS_DISPATCH_CELL
        
        ;; restore the regs we used
        pop     ecx

        ;; jump to the target
        mov     eax, [eax + 4]                                  ;;   eax <- target slot data
        jmp     eax
_RhpCastableObjectDispatch_CommonStub endp

_RhpTailCallTLSDispatchCell proc public
        ;; Load the dispatch cell out of the TLS variable
        GET_TLS_DISPATCH_CELL

        ;; Tail call to the target of the dispatch cell
        jmp     dword ptr [eax]
_RhpTailCallTLSDispatchCell endp

_RhpCastableObjectDispatchHelper_TailCalled proc public
        push    ebp
        mov     ebp, esp
        ;; Load the dispatch cell out of the TLS variable
        GET_TLS_DISPATCH_CELL
        jmp     _RhpCastableObjectDispatchHelper2
_RhpCastableObjectDispatchHelper_TailCalled endp

_RhpCastableObjectDispatchHelper proc public
        push    ebp
        mov     ebp, esp
        ;; TODO! Implement fast lookup helper to avoid the universal transition each time we
        ;; hit a CastableObject

        ;; If the initial lookup fails, call into managed under the universal thunk
        ;; to run the full lookup routine

        ;; EAX currently contains the cache block. We need to point it to the 
        ;; indirection cell using the back pointer in the cache block
        mov     eax, [eax + OFFSETOF__InterfaceDispatchCache__m_pCell]

ALTERNATE_ENTRY RhpCastableObjectDispatchHelper2       
        ;; indirection cell address is in EAX, it will be passed by
        ;; the universal transition thunk as an argument to RhpCastableObjectResolve
        push    eax
        lea     eax, RhpCastableObjectResolve
        push    eax
        jmp     _RhpUniversalTransition_DebugStepTailCall@0
_RhpCastableObjectDispatchHelper endp


;; Macro that generates code to check a single cache entry.
CHECK_CACHE_ENTRY macro entry
NextLabel textequ @CatStr( Attempt, %entry+1 )
        cmp     ebx, [eax + (OFFSETOF__InterfaceDispatchCache__m_rgEntries + (entry * 8))]
        jne     @F
        pop     ebx
        jmp     dword ptr [eax + (OFFSETOF__InterfaceDispatchCache__m_rgEntries + (entry * 8) + 4)]
@@:
endm


;; Macro that generates a stub consuming a cache with the given number of entries.
DEFINE_INTERFACE_DISPATCH_STUB macro entries

StubName textequ @CatStr( _RhpInterfaceDispatch, entries )

    StubName proc public

        ;; Check the instance here to catch null references. We're going to touch it again below (to cache
        ;; the EEType pointer), but that's after we've pushed ebx below, and taking an A/V there will
        ;; mess up the stack trace for debugging. We also don't have a spare scratch register (eax holds
        ;; the cache pointer and the push of ebx below is precisely so we can access a second register
        ;; to hold the EEType pointer).
        test    ecx, ecx
        je      RhpInterfaceDispatchNullReference

        ;; eax currently contains the indirection cell address. We need to update it to point to the cache
        ;; block instead.
        mov     eax, [eax + OFFSETOF__InterfaceDispatchCell__m_pCache]

        ;; Cache pointer is already loaded in the only scratch register we have so far, eax. We need
        ;; another scratch register to hold the instance type so save the value of ebx and use that.
        push    ebx

        ;; Load the EEType from the object instance in ebx.
        mov     ebx, [ecx]

CurrentEntry = 0
    while CurrentEntry lt entries
        CHECK_CACHE_ENTRY %CurrentEntry
CurrentEntry = CurrentEntry + 1
    endm

        ;; 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     RhpInterfaceDispatchSlow

    StubName endp

    endm ;; DEFINE_INTERFACE_DISPATCH_STUB


;; Define all the stub routines we currently need.
DEFINE_INTERFACE_DISPATCH_STUB 1
DEFINE_INTERFACE_DISPATCH_STUB 2
DEFINE_INTERFACE_DISPATCH_STUB 4
DEFINE_INTERFACE_DISPATCH_STUB 8
DEFINE_INTERFACE_DISPATCH_STUB 16
DEFINE_INTERFACE_DISPATCH_STUB 32
DEFINE_INTERFACE_DISPATCH_STUB 64

;; Shared out of line helper used on cache misses.
RhpInterfaceDispatchSlow proc
;; eax points at InterfaceDispatchCell

        ;; 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
RhpInterfaceDispatchSlow endp

;; Out of line helper used when we try to interface dispatch on a null pointer. Sets up the stack so the
;; debugger gives a reasonable stack trace.
RhpInterfaceDispatchNullReference proc public
        push    ebp
        mov     ebp, esp
        mov     ebx, [ecx]  ;; This should A/V
        int     3
RhpInterfaceDispatchNullReference endp

;; Stub dispatch routine for dispatch to a vtable slot
_RhpVTableOffsetDispatch proc public
        ;; eax currently contains the indirection cell address. We need to update it to point to the vtable offset (which is in the m_pCache field)
        mov     eax, [eax + OFFSETOF__InterfaceDispatchCell__m_pCache]

        ;; add the vtable offset to the EEType pointer 
        add     eax, [ecx]

        ;; Load the target address of the vtable into eax
        mov     eax, [eax]

        ;; tail-jump to the target
        jmp     eax
_RhpVTableOffsetDispatch endp


;; Initial dispatch on an interface when we don't have a cache yet.
_RhpInitialInterfaceDispatch proc public
    ALTERNATE_ENTRY RhpInitialDynamicInterfaceDispatch

        jmp RhpInterfaceDispatchSlow

_RhpInitialInterfaceDispatch endp


endif ;; FEATURE_CACHED_INTERFACE_DISPATCH

end