diff options
Diffstat (limited to 'src/Native/System.Private.TypeLoader.Native/amd64/VTableResolver.asm')
-rw-r--r-- | src/Native/System.Private.TypeLoader.Native/amd64/VTableResolver.asm | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/src/Native/System.Private.TypeLoader.Native/amd64/VTableResolver.asm b/src/Native/System.Private.TypeLoader.Native/amd64/VTableResolver.asm new file mode 100644 index 000000000..8f540bdcc --- /dev/null +++ b/src/Native/System.Private.TypeLoader.Native/amd64/VTableResolver.asm @@ -0,0 +1,221 @@ +;; 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. + +LEAF_ENTRY macro Name, Section + Section segment para 'CODE' + align 16 + public Name + Name proc +endm + +LEAF_END macro Name, Section + Name endp + Section ends +endm + +.data + +g_vtableResolveCallback qword 0 ; The vtableresolve method +g_universalTransition qword 0 ; The address of Redhawk's UniversalTransition thunk + +.code + +; - TAILCALL_RAX: ("jmp rax") should be used for tailcalls, this emits an instruction +; sequence which is recognized by the unwinder as a valid epilogue terminator +TAILJMP_RAX TEXTEQU <DB 048h, 0FFh, 0E0h> + +;; +;; When an EEType is created its vTable entries will be initially filled with calls to the vTableThunk for the appropriate +;; slot number. When the thunk is invoked it'll check to see if the slot has already been resolved. If so then just call +;; the universal thunk, otherwise call to do the resolution which will also update the vtable slot and then call +;; the universal thunk +;; + +VTableThunkSize equ 30h +;; TODO - do something similar to Redhawk's asmoffsets to compute the value at compile time +EETypeVTableOffset equ 18h +PointerSize equ 8 + +;; +;; __jmpstub__VTableResolver_CommonCallingStub(?) +;; Used when we dynamically need a VTableResolver not pre-generated +;; +;; r10 contains a pointer to a VTableResolverStruct +;; struct VTableResolverStruct +;; { +;; int offsetFromStartOfEETypePtr; +;; IntPtr VTableThunkAddress; +;; }; +;; +LEAF_ENTRY __jmpstub__VTableResolver_CommonCallingStub, _TEXT + ;; r10 <- stub info + ;; rcx is the this pointer to the call being made + mov rax, [rcx] + ;; rax is the EEType pointer add the VTableOffset + slot_number * pointer size to get the vtable entry + mov r11, [r10] + ;; r11 now has offset from start of EEType to interesting slot + + ;; compare the that value to the address of the thunk being executed and if the values are equal then + ;; call to the resolver otherwise call the method + + mov rax, [rax + r11] + cmp rax, [r10 + 8] + je SLOW_DYNAMIC_STUB + TAILJMP_RAX +SLOW_DYNAMIC_STUB: + mov r10, g_vtableResolveCallback + mov rax, g_universalTransition + TAILJMP_RAX +LEAF_END __jmpstub__VTableResolver_CommonCallingStub, _TEXT + +;; Returns the size of the pre-generated thunks +;; int VTableResolver_Init(IntPtr *__jmpstub__VTableResolverSlot0, +;; IntPtr vtableResolveCallback, +;; IntPtr universalTransition, +;; int *slotCount) +;; +LEAF_ENTRY VTableResolver_Init, _TEXT + lea rax, [__jmpstub__VTableSlot0] + mov [rcx], rax + mov g_vtableResolveCallback, rdx + mov g_universalTransition, r8 + mov rax, 100 ;; 100 Pregenerated Stubs + mov [r9], rax + mov rax, VTableThunkSize ;; Thunk size + ret +LEAF_END VTableResolver_Init, _TEXT + +;; void* VTableResolver_GetCommonCallingStub() +;; - Get the address of the common calling stub +LEAF_ENTRY VTableResolver_GetCommonCallingStub, _TEXT + lea rax, [__jmpstub__VTableResolver_CommonCallingStub] + ret +LEAF_END VTableResolver_GetCommonCallingStub, _TEXT + +VTableThunkDecl macro name, slot_number + +LEAF_ENTRY name, _TEXT +ALIGN 16 ; The alignment here forces the thunks to be the same size which gives all of the macros the same size and allows us to index + ;; rcx is the this pointer to the call being made + mov rax, [rcx] + mov r11, EETypeVTableOffset + slot_number * PointerSize + ;; rax is the EEType pointer add the VTableOffset + slot_number * pointer size to get the vtable entry + ;; compare the that value to the address of the thunk being executed and if the values are equal then + ;; call to the resolver otherwise call the method + mov rax, [rax + r11] + lea r10, name + cmp rax, r10 + je SLOW + TAILJMP_RAX +SLOW: + ;; r11 is already set to the EEType offset + mov r10, g_vtableResolveCallback + mov rax, g_universalTransition + TAILJMP_RAX +LEAF_END name, _TEXT + + endm + +VTableThunkDecl __jmpstub__VTableSlot0,0 +VTableThunkDecl __jmpstub__VTableSlot1,1 +VTableThunkDecl __jmpstub__VTableSlot2,2 +VTableThunkDecl __jmpstub__VTableSlot3,3 +VTableThunkDecl __jmpstub__VTableSlot4,4 +VTableThunkDecl __jmpstub__VTableSlot5,5 +VTableThunkDecl __jmpstub__VTableSlot6,6 +VTableThunkDecl __jmpstub__VTableSlot7,7 +VTableThunkDecl __jmpstub__VTableSlot8,8 +VTableThunkDecl __jmpstub__VTableSlot9,9 +VTableThunkDecl __jmpstub__VTableSlot10,10 +VTableThunkDecl __jmpstub__VTableSlot11,11 +VTableThunkDecl __jmpstub__VTableSlot12,12 +VTableThunkDecl __jmpstub__VTableSlot13,13 +VTableThunkDecl __jmpstub__VTableSlot14,14 +VTableThunkDecl __jmpstub__VTableSlot15,15 +VTableThunkDecl __jmpstub__VTableSlot16,16 +VTableThunkDecl __jmpstub__VTableSlot17,17 +VTableThunkDecl __jmpstub__VTableSlot18,18 +VTableThunkDecl __jmpstub__VTableSlot19,19 +VTableThunkDecl __jmpstub__VTableSlot20,20 +VTableThunkDecl __jmpstub__VTableSlot21,21 +VTableThunkDecl __jmpstub__VTableSlot22,22 +VTableThunkDecl __jmpstub__VTableSlot23,23 +VTableThunkDecl __jmpstub__VTableSlot24,24 +VTableThunkDecl __jmpstub__VTableSlot25,25 +VTableThunkDecl __jmpstub__VTableSlot26,26 +VTableThunkDecl __jmpstub__VTableSlot27,27 +VTableThunkDecl __jmpstub__VTableSlot28,28 +VTableThunkDecl __jmpstub__VTableSlot29,29 +VTableThunkDecl __jmpstub__VTableSlot30,30 +VTableThunkDecl __jmpstub__VTableSlot31,31 +VTableThunkDecl __jmpstub__VTableSlot32,32 +VTableThunkDecl __jmpstub__VTableSlot33,33 +VTableThunkDecl __jmpstub__VTableSlot34,34 +VTableThunkDecl __jmpstub__VTableSlot35,35 +VTableThunkDecl __jmpstub__VTableSlot36,36 +VTableThunkDecl __jmpstub__VTableSlot37,37 +VTableThunkDecl __jmpstub__VTableSlot38,38 +VTableThunkDecl __jmpstub__VTableSlot39,39 +VTableThunkDecl __jmpstub__VTableSlot40,40 +VTableThunkDecl __jmpstub__VTableSlot41,41 +VTableThunkDecl __jmpstub__VTableSlot42,42 +VTableThunkDecl __jmpstub__VTableSlot43,43 +VTableThunkDecl __jmpstub__VTableSlot44,44 +VTableThunkDecl __jmpstub__VTableSlot45,45 +VTableThunkDecl __jmpstub__VTableSlot46,46 +VTableThunkDecl __jmpstub__VTableSlot47,47 +VTableThunkDecl __jmpstub__VTableSlot48,48 +VTableThunkDecl __jmpstub__VTableSlot49,49 +VTableThunkDecl __jmpstub__VTableSlot50,50 +VTableThunkDecl __jmpstub__VTableSlot51,51 +VTableThunkDecl __jmpstub__VTableSlot52,52 +VTableThunkDecl __jmpstub__VTableSlot53,53 +VTableThunkDecl __jmpstub__VTableSlot54,54 +VTableThunkDecl __jmpstub__VTableSlot55,55 +VTableThunkDecl __jmpstub__VTableSlot56,56 +VTableThunkDecl __jmpstub__VTableSlot57,57 +VTableThunkDecl __jmpstub__VTableSlot58,58 +VTableThunkDecl __jmpstub__VTableSlot59,59 +VTableThunkDecl __jmpstub__VTableSlot60,60 +VTableThunkDecl __jmpstub__VTableSlot61,61 +VTableThunkDecl __jmpstub__VTableSlot62,62 +VTableThunkDecl __jmpstub__VTableSlot63,63 +VTableThunkDecl __jmpstub__VTableSlot64,64 +VTableThunkDecl __jmpstub__VTableSlot65,65 +VTableThunkDecl __jmpstub__VTableSlot66,66 +VTableThunkDecl __jmpstub__VTableSlot67,67 +VTableThunkDecl __jmpstub__VTableSlot68,68 +VTableThunkDecl __jmpstub__VTableSlot69,69 +VTableThunkDecl __jmpstub__VTableSlot70,70 +VTableThunkDecl __jmpstub__VTableSlot71,71 +VTableThunkDecl __jmpstub__VTableSlot72,72 +VTableThunkDecl __jmpstub__VTableSlot73,73 +VTableThunkDecl __jmpstub__VTableSlot74,74 +VTableThunkDecl __jmpstub__VTableSlot75,75 +VTableThunkDecl __jmpstub__VTableSlot76,76 +VTableThunkDecl __jmpstub__VTableSlot77,77 +VTableThunkDecl __jmpstub__VTableSlot78,78 +VTableThunkDecl __jmpstub__VTableSlot79,79 +VTableThunkDecl __jmpstub__VTableSlot80,80 +VTableThunkDecl __jmpstub__VTableSlot81,81 +VTableThunkDecl __jmpstub__VTableSlot82,82 +VTableThunkDecl __jmpstub__VTableSlot83,83 +VTableThunkDecl __jmpstub__VTableSlot84,84 +VTableThunkDecl __jmpstub__VTableSlot85,85 +VTableThunkDecl __jmpstub__VTableSlot86,86 +VTableThunkDecl __jmpstub__VTableSlot87,87 +VTableThunkDecl __jmpstub__VTableSlot88,88 +VTableThunkDecl __jmpstub__VTableSlot89,89 +VTableThunkDecl __jmpstub__VTableSlot90,90 +VTableThunkDecl __jmpstub__VTableSlot91,91 +VTableThunkDecl __jmpstub__VTableSlot92,92 +VTableThunkDecl __jmpstub__VTableSlot93,93 +VTableThunkDecl __jmpstub__VTableSlot94,94 +VTableThunkDecl __jmpstub__VTableSlot95,95 +VTableThunkDecl __jmpstub__VTableSlot96,96 +VTableThunkDecl __jmpstub__VTableSlot97,97 +VTableThunkDecl __jmpstub__VTableSlot98,98 +VTableThunkDecl __jmpstub__VTableSlot99,99 + +end |