diff options
author | Fadi Hanna <fadim@microsoft.com> | 2018-11-13 12:44:49 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-13 12:44:49 -0800 |
commit | d2cd0df600cfa697d30cf7ef5a7cf1c3c33b9959 (patch) | |
tree | 5780e415551b7aa0d43cc18d04c977c014a4d3a3 /src/vm/prestub.cpp | |
parent | d8bfe11f24598e6e909e6e49aea8fba3925c91b7 (diff) | |
download | coreclr-d2cd0df600cfa697d30cf7ef5a7cf1c3c33b9959.tar.gz coreclr-d2cd0df600cfa697d30cf7ef5a7cf1c3c33b9959.tar.bz2 coreclr-d2cd0df600cfa697d30cf7ef5a7cf1c3c33b9959.zip |
Optimize vtable calls (#20696)
* Implementation of R2R vtable call thunks. These thunks will fetch the target code pointer from the vtable of the input thisPtr, and jump to that address.
This is especially helpful with generics, since we can avoid a generic dictionary lookup cost for a simple vtable call.
Overall, these thunks cause the CPU to have less branch mispredictions, and give a small performance boost to vtable calls.
These stubs are under VirtualCallStubManager so that the managed debugger can handle stepping through them.
Diffstat (limited to 'src/vm/prestub.cpp')
-rw-r--r-- | src/vm/prestub.cpp | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp index b614e341a2..78e9f22e17 100644 --- a/src/vm/prestub.cpp +++ b/src/vm/prestub.cpp @@ -2286,20 +2286,24 @@ EXTERN_C PCODE STDCALL ExternalMethodFixupWorker(TransitionBlock * pTransitionBl // Get the stub manager for this module VirtualCallStubManager *pMgr = pModule->GetLoaderAllocator()->GetVirtualCallStubManager(); - DispatchToken token; - if (pMT->IsInterface()) - token = pMT->GetLoaderAllocator()->GetDispatchToken(pMT->GetTypeID(), slot); - else - token = DispatchToken::CreateDispatchToken(slot); - OBJECTREF *protectedObj = pEMFrame->GetThisPtr(); _ASSERTE(protectedObj != NULL); if (*protectedObj == NULL) { COMPlusThrow(kNullReferenceException); } - - StubCallSite callSite(pIndirection, pEMFrame->GetReturnAddress()); - pCode = pMgr->ResolveWorker(&callSite, protectedObj, token, VirtualCallStubManager::SK_LOOKUP); + + DispatchToken token; + if (pMT->IsInterface() || MethodTable::VTableIndir_t::isRelative) + { + token = pMT->GetLoaderAllocator()->GetDispatchToken(pMT->GetTypeID(), slot); + StubCallSite callSite(pIndirection, pEMFrame->GetReturnAddress()); + pCode = pMgr->ResolveWorker(&callSite, protectedObj, token, VirtualCallStubManager::SK_LOOKUP); + } + else + { + pCode = pMgr->GetVTableCallStub(slot); + *EnsureWritableExecutablePages((TADDR *)pIndirection) = pCode; + } _ASSERTE(pCode != NULL); } else |