summaryrefslogtreecommitdiff
path: root/src/vm/amd64/virtualcallstubamd64.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/amd64/virtualcallstubamd64.S')
-rw-r--r--src/vm/amd64/virtualcallstubamd64.S109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/vm/amd64/virtualcallstubamd64.S b/src/vm/amd64/virtualcallstubamd64.S
new file mode 100644
index 0000000000..59b5b77dba
--- /dev/null
+++ b/src/vm/amd64/virtualcallstubamd64.S
@@ -0,0 +1,109 @@
+// 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.
+
+.intel_syntax noprefix
+#include "unixasmmacros.inc"
+
+// This is the number of times a successful chain lookup will occur before the
+// entry is promoted to the front of the chain. This is declared as extern because
+// the default value (CALL_STUB_CACHE_INITIAL_SUCCESS_COUNT) is defined in the header.
+// extern size_t g_dispatch_cache_chain_success_counter;
+#define CHAIN_SUCCESS_COUNTER g_dispatch_cache_chain_success_counter
+
+// The reason for not using .equ or '=' here is that otherwise the assembler compiles e.g.
+// mov rax, BACKPATCH_FLAG as mov rax, [BACKPATCH_FLAG]
+#define BACKPATCH_FLAG 1 // Also known as SDF_ResolveBackPatch in the EE
+#define PROMOTE_CHAIN_FLAG 2 // Also known as SDF_ResolvePromoteChain in the EE
+#define INITIAL_SUCCESS_COUNT 0x100
+
+// On Input:
+// r11 contains the address of the indirection cell (with the flags in the low bits)
+// [rsp+0] m_Datum: contains the dispatch token (slot number or MethodDesc) for the target
+// or the ResolveCacheElem when r11 has the PROMOTE_CHAIN_FLAG set
+// [rsp+8] m_ReturnAddress: contains the return address of caller to stub
+
+NESTED_ENTRY ResolveWorkerAsmStub, _TEXT, NoHandler
+
+ PROLOG_WITH_TRANSITION_BLOCK 0, 8, rdx, 0, 0
+
+ // token stored in rdx by prolog
+
+ lea rdi, [rsp + __PWTB_TransitionBlock] // pTransitionBlock
+ mov rsi, r11 // indirection cell + flags
+ mov rcx, rsi
+ and rcx, 7 // flags
+ sub rsi, rcx // indirection cell
+
+ call C_FUNC(VSD_ResolveWorker)
+
+ EPILOG_WITH_TRANSITION_BLOCK_TAILCALL
+ TAILJMP_RAX
+
+NESTED_END ResolveWorkerAsmStub, _TEXT
+
+// extern void ResolveWorkerChainLookupAsmStub()
+LEAF_ENTRY ResolveWorkerChainLookupAsmStub, _TEXT
+// This will perform a quick chained lookup of the entry if the initial cache lookup fails
+// On Input:
+// rdx contains our type (MethodTable)
+// r10 contains our contract (DispatchToken)
+// r11 contains the address of the indirection (and the flags in the low two bits)
+// [rsp+0x00] contains the pointer to the ResolveCacheElem
+// [rsp+0x08] contains the saved value of rsi
+// [rsp+0x10] contains the return address of caller to stub
+//
+ mov rax, BACKPATCH_FLAG // First we check if r11 has the BACKPATCH_FLAG set
+ and rax, r11 // Set the flags based on (BACKPATCH_FLAG and r11)
+ pop rax // pop the pointer to the ResolveCacheElem from the top of stack (leaving the flags unchanged)
+ jnz Fail_RWCLAS // If the BACKPATCH_FLAGS is set we will go directly to the ResolveWorkerAsmStub
+
+MainLoop_RWCLAS:
+ mov rax, [rax+18h] // get the next entry in the chain (don't bother checking the first entry again)
+ test rax,rax // test if we hit a terminating NULL
+ jz Fail_RWCLAS
+
+ cmp rdx, [rax+00h] // compare our MT with the one in the ResolveCacheElem
+ jne MainLoop_RWCLAS
+ cmp r10, [rax+08h] // compare our DispatchToken with one in the ResolveCacheElem
+ jne MainLoop_RWCLAS
+Success_RWCLAS:
+ PREPARE_EXTERNAL_VAR CHAIN_SUCCESS_COUNTER, rdx
+ sub qword ptr [rdx],1 // decrement success counter
+ jl Promote_RWCLAS
+ mov rax, [rax+10h] // get the ImplTarget
+ pop rdx
+ jmp rax
+
+Promote_RWCLAS: // Move this entry to head postion of the chain
+ // be quick to reset the counter so we don't get a bunch of contending threads
+ mov qword ptr [rdx], INITIAL_SUCCESS_COUNT
+ or r11, PROMOTE_CHAIN_FLAG
+ mov r10, rax // We pass the ResolveCacheElem to ResolveWorkerAsmStub instead of the DispatchToken
+Fail_RWCLAS:
+ pop rdx // Restore the original saved rdx value
+ push r10 // pass the DispatchToken or ResolveCacheElem to promote to ResolveWorkerAsmStub
+
+ jmp C_FUNC(ResolveWorkerAsmStub)
+
+LEAF_END ResolveWorkerChainLookupAsmStub, _TEXT
+
+#ifdef FEATURE_PREJIT
+NESTED_ENTRY StubDispatchFixupStub, _TEXT, NoHandler
+
+ PROLOG_WITH_TRANSITION_BLOCK 0, 0, 0, 0, 0
+
+ lea rdi, [rsp + __PWTB_TransitionBlock] // pTransitionBlock
+ mov rsi, r11 // indirection cell address
+
+ mov rdx,0 // sectionIndex
+ mov rcx,0 // pModule
+
+ call C_FUNC(StubDispatchFixupWorker)
+
+ EPILOG_WITH_TRANSITION_BLOCK_TAILCALL
+PATCH_LABEL StubDispatchFixupPatchLabel
+ TAILJMP_RAX
+
+NESTED_END StubDispatchFixupStub, _TEXT
+#endif