diff options
author | Fadi Hanna <fadim@microsoft.com> | 2016-06-21 11:51:05 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-06-21 11:51:05 -0700 |
commit | b9f5ae88cc49836c8d31f07db7800707165cdb06 (patch) | |
tree | c5d6246379b51c19e9c79489364da1e2a6fe79f5 /src/vm/jithelpers.cpp | |
parent | fb79613c44df5ad80831dba1460ffb14dd6497a3 (diff) | |
download | coreclr-b9f5ae88cc49836c8d31f07db7800707165cdb06.tar.gz coreclr-b9f5ae88cc49836c8d31f07db7800707165cdb06.tar.bz2 coreclr-b9f5ae88cc49836c8d31f07db7800707165cdb06.zip |
Generic dictionary minor performance improvement and simplification for R2R (#5690)
A set of refactoring changes to slighly improve the performance of generic dictionary access on R2R images, and simplifying the codebase:
1) Removing dependency on CEEInfo::ComputeRuntimeLookupForSharedGenericTokenStatic (and deleting the API).
2) Stop parsing the generic type/method signatures when generating the R2R dictionary lookup assembly stub.
3) Avoid re-encoding the generic type/method signatures in a new in-memory blob using a SigBuilder (signatures used directly from the R2R image)
4) Moved the parsing/loading of type/method signatures to Dictionary::PopulateEntry()
5) Dictionary index and slot number are now encoded in the generated assembly stub instead of the signature (stub takes a pointer to a data blob, which contains the signature, the dictionary index and slot, and the module pointer)
Diffstat (limited to 'src/vm/jithelpers.cpp')
-rw-r--r-- | src/vm/jithelpers.cpp | 105 |
1 files changed, 79 insertions, 26 deletions
diff --git a/src/vm/jithelpers.cpp b/src/vm/jithelpers.cpp index fffc6ceece..1626810758 100644 --- a/src/vm/jithelpers.cpp +++ b/src/vm/jithelpers.cpp @@ -3994,11 +3994,7 @@ void ClearJitGenericHandleCache(AppDomain *pDomain) // Factored out most of the body of JIT_GenericHandle so it could be called easily from the CER reliability code to pre-populate the // cache. -CORINFO_GENERIC_HANDLE -JIT_GenericHandleWorker( - MethodDesc * pMD, - MethodTable * pMT, - LPVOID signature) +CORINFO_GENERIC_HANDLE JIT_GenericHandleWorker(MethodDesc * pMD, MethodTable * pMT, LPVOID signature, DWORD dictionaryIndexAndSlot, Module* pModule) { CONTRACTL { THROWS; @@ -4009,20 +4005,34 @@ JIT_GenericHandleWorker( if (pMT != NULL) { - SigPointer ptr((PCCOR_SIGNATURE)signature); + ULONG dictionaryIndex = 0; - ULONG kind; // DictionaryEntryKind - IfFailThrow(ptr.GetData(&kind)); + if (pModule != NULL) + { +#ifdef _DEBUG + // Only in R2R mode are the module, dictionary index and dictionary slot provided as an input + _ASSERTE(dictionaryIndexAndSlot != -1); + _ASSERT(ExecutionManager::FindReadyToRunModule(dac_cast<TADDR>(signature)) == pModule); +#endif + dictionaryIndex = (dictionaryIndexAndSlot >> 16); + } + else + { + SigPointer ptr((PCCOR_SIGNATURE)signature); - // We need to normalize the class passed in (if any) for reliability purposes. That's because preparation of a code region that - // contains these handle lookups depends on being able to predict exactly which lookups are required (so we can pre-cache the - // answers and remove any possibility of failure at runtime). This is hard to do if the lookup (in this case the lookup of the - // dictionary overflow cache) is keyed off the somewhat arbitrary type of the instance on which the call is made (we'd need to - // prepare for every possible derived type of the type containing the method). So instead we have to locate the exactly - // instantiated (non-shared) super-type of the class passed in. + ULONG kind; // DictionaryEntryKind + IfFailThrow(ptr.GetData(&kind)); - ULONG dictionaryIndex = 0; - IfFailThrow(ptr.GetData(&dictionaryIndex)); + // We need to normalize the class passed in (if any) for reliability purposes. That's because preparation of a code region that + // contains these handle lookups depends on being able to predict exactly which lookups are required (so we can pre-cache the + // answers and remove any possibility of failure at runtime). This is hard to do if the lookup (in this case the lookup of the + // dictionary overflow cache) is keyed off the somewhat arbitrary type of the instance on which the call is made (we'd need to + // prepare for every possible derived type of the type containing the method). So instead we have to locate the exactly + // instantiated (non-shared) super-type of the class passed in. + + _ASSERTE(dictionaryIndexAndSlot == -1); + IfFailThrow(ptr.GetData(&dictionaryIndex)); + } pDeclaringMT = pMT; for (;;) @@ -4049,7 +4059,7 @@ JIT_GenericHandleWorker( } DictionaryEntry * pSlot; - CORINFO_GENERIC_HANDLE result = (CORINFO_GENERIC_HANDLE)Dictionary::PopulateEntry(pMD, pDeclaringMT, signature, FALSE, &pSlot); + CORINFO_GENERIC_HANDLE result = (CORINFO_GENERIC_HANDLE)Dictionary::PopulateEntry(pMD, pDeclaringMT, signature, FALSE, &pSlot, dictionaryIndexAndSlot, pModule); if (pSlot == NULL) { @@ -4076,10 +4086,12 @@ JIT_GenericHandleWorker( /*********************************************************************/ // slow helper to tail call from the fast one -NOINLINE HCIMPL3(CORINFO_GENERIC_HANDLE, JIT_GenericHandle_Framed, - CORINFO_CLASS_HANDLE classHnd, - CORINFO_METHOD_HANDLE methodHnd, - LPVOID signature) +NOINLINE HCIMPL5(CORINFO_GENERIC_HANDLE, JIT_GenericHandle_Framed, + CORINFO_CLASS_HANDLE classHnd, + CORINFO_METHOD_HANDLE methodHnd, + LPVOID signature, + DWORD dictionaryIndexAndSlot, + CORINFO_MODULE_HANDLE moduleHnd) { CONTRACTL { FCALL_CHECK; @@ -4092,11 +4104,12 @@ NOINLINE HCIMPL3(CORINFO_GENERIC_HANDLE, JIT_GenericHandle_Framed, MethodDesc * pMD = GetMethod(methodHnd); MethodTable * pMT = TypeHandle(classHnd).AsMethodTable(); + Module * pModule = GetModule(moduleHnd); // Set up a frame HELPER_METHOD_FRAME_BEGIN_RET_0(); - result = JIT_GenericHandleWorker(pMD, pMT, signature); + result = JIT_GenericHandleWorker(pMD, pMT, signature, dictionaryIndexAndSlot, pModule); HELPER_METHOD_FRAME_END(); @@ -4125,7 +4138,27 @@ HCIMPL2(CORINFO_GENERIC_HANDLE, JIT_GenericHandleMethod, CORINFO_METHOD_HANDLE // Tailcall to the slow helper ENDFORBIDGC(); - return HCCALL3(JIT_GenericHandle_Framed, NULL, methodHnd, signature); + return HCCALL5(JIT_GenericHandle_Framed, NULL, methodHnd, signature, -1, NULL); +} +HCIMPLEND + +HCIMPL2(CORINFO_GENERIC_HANDLE, JIT_GenericHandleMethodWithSlotAndModule, CORINFO_METHOD_HANDLE methodHnd, GenericHandleArgs * pArgs) +{ + CONTRACTL{ + FCALL_CHECK; + PRECONDITION(CheckPointer(methodHnd)); + PRECONDITION(GetMethod(methodHnd)->IsRestored()); + PRECONDITION(CheckPointer(pArgs)); + } CONTRACTL_END; + + JitGenericHandleCacheKey key(NULL, methodHnd, pArgs->signature); + HashDatum res; + if (g_pJitGenericHandleCache->GetValueSpeculative(&key, &res)) + return (CORINFO_GENERIC_HANDLE)(DictionaryEntry)res; + + // Tailcall to the slow helper + ENDFORBIDGC(); + return HCCALL5(JIT_GenericHandle_Framed, NULL, methodHnd, pArgs->signature, pArgs->dictionaryIndexAndSlot, pArgs->module); } HCIMPLEND #include <optdefault.h> @@ -4149,7 +4182,7 @@ HCIMPL2(CORINFO_GENERIC_HANDLE, JIT_GenericHandleMethodLogging, CORINFO_METHOD_H // Tailcall to the slow helper ENDFORBIDGC(); - return HCCALL3(JIT_GenericHandle_Framed, NULL, methodHnd, signature); + return HCCALL5(JIT_GenericHandle_Framed, NULL, methodHnd, signature, -1, NULL); } HCIMPLEND @@ -4171,7 +4204,27 @@ HCIMPL2(CORINFO_GENERIC_HANDLE, JIT_GenericHandleClass, CORINFO_CLASS_HANDLE cla // Tailcall to the slow helper ENDFORBIDGC(); - return HCCALL3(JIT_GenericHandle_Framed, classHnd, NULL, signature); + return HCCALL5(JIT_GenericHandle_Framed, classHnd, NULL, signature, -1, NULL); +} +HCIMPLEND + +HCIMPL2(CORINFO_GENERIC_HANDLE, JIT_GenericHandleClassWithSlotAndModule, CORINFO_CLASS_HANDLE classHnd, GenericHandleArgs * pArgs) +{ + CONTRACTL{ + FCALL_CHECK; + PRECONDITION(CheckPointer(classHnd)); + PRECONDITION(TypeHandle(classHnd).IsRestored()); + PRECONDITION(CheckPointer(pArgs)); + } CONTRACTL_END; + + JitGenericHandleCacheKey key(classHnd, NULL, pArgs->signature); + HashDatum res; + if (g_pJitGenericHandleCache->GetValueSpeculative(&key, &res)) + return (CORINFO_GENERIC_HANDLE)(DictionaryEntry)res; + + // Tailcall to the slow helper + ENDFORBIDGC(); + return HCCALL5(JIT_GenericHandle_Framed, classHnd, NULL, pArgs->signature, pArgs->dictionaryIndexAndSlot, pArgs->module); } HCIMPLEND #include <optdefault.h> @@ -4195,7 +4248,7 @@ HCIMPL2(CORINFO_GENERIC_HANDLE, JIT_GenericHandleClassLogging, CORINFO_CLASS_HAN // Tailcall to the slow helper ENDFORBIDGC(); - return HCCALL3(JIT_GenericHandle_Framed, classHnd, NULL, signature); + return HCCALL5(JIT_GenericHandle_Framed, classHnd, NULL, signature, -1, NULL); } HCIMPLEND |