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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
|
; 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 AsmMacros.inc
include AsmConstants.inc
ifdef FEATURE_REMOTING
extern CallDescrWorkerUnwindFrameChainHandler:proc
extern TransparentProxyStubWorker:proc
; Stack frame layout:
;
; (stack parameters)
; ...
; r9
; r8
; rdx
; rcx <- TPSCC_PARAMS_OFFSET
; return address <- TPSCC_STACK_FRAME_SIZE
; r10 <- TPSCC_R10_OFFSET
; xmm3
; xmm2
; xmm1
; xmm0 <- TPSCC_XMM_SAVE_OFFSET
; callee's r9
; callee's r8
; callee's rdx
; callee's rcx
TPSCC_XMM_SAVE_OFFSET = 20h
TPSCC_R10_OFFSET = 60h
TPSCC_STACK_FRAME_SIZE = 68h
TPSCC_PARAMS_OFFSET = 70h
TRANSPARENT_PROXY_STUB_PROLOGUE macro
alloc_stack TPSCC_STACK_FRAME_SIZE
save_reg_postrsp r10, TPSCC_R10_OFFSET
SAVE_ARGUMENT_REGISTERS TPSCC_PARAMS_OFFSET
SAVE_FLOAT_ARGUMENT_REGISTERS TPSCC_XMM_SAVE_OFFSET
END_PROLOGUE
endm
NESTED_ENTRY TransparentProxyStub, _TEXT, CallDescrWorkerUnwindFrameChainHandler
TRANSPARENT_PROXY_STUB_PROLOGUE
;; rcx: this
;; [rsp]: slot number
mov rax, [rcx + TransparentProxyObject___stub]
mov rcx, [rcx + TransparentProxyObject___stubData]
call rax
RESTORE_ARGUMENT_REGISTERS TPSCC_PARAMS_OFFSET
RESTORE_FLOAT_ARGUMENT_REGISTERS TPSCC_XMM_SAVE_OFFSET
mov r10, [rsp + TPSCC_R10_OFFSET]
test rax, rax
jnz CrossContext
mov r11, [rcx + TransparentProxyObject___pMT]
; Convert the slot number (r10) into the code address (in rax)
; See MethodTable.h for details on vtable layout
shr r10, MethodTable_VtableSlotsPerChunkLog2
mov rax, [r11 + r10*8 + METHODTABLE_OFFSET_VTABLE]
mov r10, [rsp + TPSCC_R10_OFFSET] ; Reload the slot
and r10, MethodTable_VtableSlotsPerChunk-1
mov rax, [rax + r10*8]
add rsp, TPSCC_STACK_FRAME_SIZE
TAILJMP_RAX
CrossContext:
add rsp, TPSCC_STACK_FRAME_SIZE
jmp TransparentProxyStub_CrossContext
NESTED_END TransparentProxyStub, _TEXT
NESTED_ENTRY TransparentProxyStub_CrossContext, _TEXT
PROLOG_WITH_TRANSITION_BLOCK 8
;
; Call TransparentProxyStubWorker.
;
lea rcx, [rsp + __PWTB_TransitionBlock] ; pTransitionBlock
mov rdx, r10 ; MethodDesc *
call TransparentProxyStubWorker
; handle FP return values
lea rcx, [rsp + __PWTB_FloatArgumentRegisters - 8]
cmp rax, 4
jne @F
movss xmm0, real4 ptr [rcx]
@@:
cmp rax, 8
jne @F
movsd xmm0, real8 ptr [rcx]
@@:
; load return value
mov rax, [rcx]
EPILOG_WITH_TRANSITION_BLOCK_RETURN
NESTED_END TransparentProxyStub_CrossContext, _TEXT
LEAF_ENTRY TransparentProxyStubPatch, _TEXT
; make sure that the basic block is unique
test eax,12
PATCH_LABEL TransparentProxyStubPatchLabel
ret
LEAF_END TransparentProxyStubPatch, _TEXT
;+----------------------------------------------------------------------------
;
; Method: CRemotingServices::CallFieldGetter private
;
; Synopsis: Calls the field getter function (Object::__FieldGetter) in
; managed code by setting up the stack and calling the target
;
;+----------------------------------------------------------------------------
; extern "C"
;void __stdcall CRemotingServices__CallFieldGetter( MethodDesc *pMD,
; LPVOID pThis,
; LPVOID pFirst,
; LPVOID pSecond,
; LPVOID pThird
; )
LEAF_ENTRY CRemotingServices__CallFieldGetter, _TEXT
; +28 pThird
; +20 scratch area
; +18 scratch area
; +10 scratch area
; + 8 scratch area
; rsp return address
mov METHODDESC_REGISTER, rcx
mov rcx, rdx
mov rdx, r8
mov r8, r9
mov r9, [rsp + 28h]
jmp TransparentProxyStub
LEAF_END CRemotingServices__CallFieldGetter, _TEXT
;+----------------------------------------------------------------------------
;
; Method: CRemotingServices::CallFieldSetter private
;
; Synopsis: Calls the field setter function (Object::__FieldSetter) in
; managed code by setting up the stack and calling the target
;
;+----------------------------------------------------------------------------
; extern "C"
;void __stdcall CRemotingServices__CallFieldSetter( MethodDesc *pMD,
; LPVOID pThis,
; LPVOID pFirst,
; LPVOID pSecond,
; LPVOID pThird
; )
LEAF_ENTRY CRemotingServices__CallFieldSetter, _TEXT
; +28 pThird
; +20 scratch area
; +18 scratch area
; +10 scratch area
; + 8 scratch area
; rsp return address
mov METHODDESC_REGISTER, rcx
mov rcx, rdx
mov rdx, r8
mov r8, r9
mov r9, [rsp + 28h]
jmp TransparentProxyStub
LEAF_END CRemotingServices__CallFieldSetter, _TEXT
;; extern "C" ARG_SLOT __stdcall CTPMethodTable__CallTargetHelper2(const void *pTarget,
;; LPVOID pvFirst,
;; LPVOID pvSecond);
NESTED_ENTRY CTPMethodTable__CallTargetHelper2, _TEXT, CallDescrWorkerUnwindFrameChainHandler
alloc_stack 28h ;; alloc callee scratch and align the stack
END_PROLOGUE
mov rax, rcx ; rax <- call target
mov rcx, rdx ; rcx <- first arg
mov rdx, r8 ; rdx <- second arg
call rax
;; It is important to have an instruction between the previous call and the epilog.
;; If the return address is in epilog, OS won't call personality routine because
;; it thinks personality routine does not help in this case.
nop
; epilog
add rsp, 28h
ret
NESTED_END CTPMethodTable__CallTargetHelper2, _TEXT
;; extern "C" ARG_SLOT __stdcall CTPMethodTable__CallTargetHelper2(const void *pTarget,
;; LPVOID pvFirst,
;; LPVOID pvSecond,
;; LPVOID pvThird);
NESTED_ENTRY CTPMethodTable__CallTargetHelper3, _TEXT, CallDescrWorkerUnwindFrameChainHandler
alloc_stack 28h ;; alloc callee scratch and align the stack
END_PROLOGUE
mov rax, rcx ; rax <- call target
mov rcx, rdx ; rcx <- first arg
mov rdx, r8 ; rdx <- second arg
mov r8, r9 ; r8 <- third arg
call rax
;; It is important to have an instruction between the previous call and the epilog.
;; If the return address is in epilog, OS won't call personality routine because
;; it thinks personality routine does not help in this case.
nop
; epilog
add rsp, 28h
ret
NESTED_END CTPMethodTable__CallTargetHelper3, _TEXT
NESTED_ENTRY CRemotingServices__DispatchInterfaceCall, _TEXT, CallDescrWorkerUnwindFrameChainHandler
TRANSPARENT_PROXY_STUB_PROLOGUE
;
; 'this' is a TransparentProxy. Call to stub to see if need to cross contexts.
;
mov rax, [rcx + TransparentProxyObject___stub]
mov rcx, [rcx + TransparentProxyObject___stubData]
call rax
test rax, rax
jnz CrossContext
extern VSD_GetTargetForTPWorkerQuick:proc
mov rcx, [rsp + TPSCC_PARAMS_OFFSET] ; rcx <- this
mov rdx, [rsp + TPSCC_R10_OFFSET] ; rdx <- Get the MethodDesc* or slot number
call VSD_GetTargetForTPWorkerQuick
RESTORE_ARGUMENT_REGISTERS TPSCC_PARAMS_OFFSET
RESTORE_FLOAT_ARGUMENT_REGISTERS TPSCC_XMM_SAVE_OFFSET
mov r10, [rsp + TPSCC_R10_OFFSET]
test rax, rax ; Did we find a target?
jz SlowDispatch
add rsp, TPSCC_STACK_FRAME_SIZE
TAILJMP_RAX
SlowDispatch:
add rsp, TPSCC_STACK_FRAME_SIZE
jmp InContextTPDispatchAsmStub
CrossContext:
RESTORE_ARGUMENT_REGISTERS TPSCC_PARAMS_OFFSET
RESTORE_FLOAT_ARGUMENT_REGISTERS TPSCC_XMM_SAVE_OFFSET
mov r10, [rsp + TPSCC_R10_OFFSET]
add rsp, TPSCC_STACK_FRAME_SIZE
jmp TransparentProxyStub_CrossContext
NESTED_END CRemotingServices__DispatchInterfaceCall, _TEXT
NESTED_ENTRY InContextTPDispatchAsmStub, _TEXT
PROLOG_WITH_TRANSITION_BLOCK
extern VSD_GetTargetForTPWorker:proc
lea rcx, [rsp + __PWTB_TransitionBlock] ; pTransitionBlock
mov rdx, r10 ; token
call VSD_GetTargetForTPWorker
EPILOG_WITH_TRANSITION_BLOCK_TAILCALL
TAILJMP_RAX
NESTED_END InContextTPDispatchAsmStub, _TEXT
endif ; FEATURE_REMOTING
end
|