diff options
author | Peter Sollich <petersol@microsoft.com> | 2016-09-01 12:09:10 +0300 |
---|---|---|
committer | Peter Sollich <petersol@microsoft.com> | 2016-09-01 12:09:10 +0300 |
commit | 02080afb110d8c223241721f5571f062ef560c8e (patch) | |
tree | f7d331b563305d7c3f48dfb91dbd8e3c05ec6846 /src/Native/Runtime/RuntimeInstance.cpp | |
parent | 0202afe2f6792f119b13934c23309afd8dbd70ac (diff) |
Change Description:
This is the implementation of generic unification for separate compilation.
When we do not use global analysis, we may end up with multiple instances of generic types and methods in different modules. This causes problems for access to static fields, type casting and reflection, notably GetMethodInfo on delegates.
The implementation proposed has two main components:
- the binder generates "GenericUnificiationDesc" data structures for each generic type and method. It also indirects accesses to generic types and methods through indirection cells. The mechanism is enabled via a new "/separateCompilation" command line switch.
- the runtime enters the generic types and methods into a big hash table. If it finds a duplicate, it declares the existing entry the "winner" and overwrites the indirection cells of the "loser" with those of the winner.
Initial measurements on UnitTests are as follows:
- about 8,000 types and methods are entered into the hash table on startup
- about 2,000 duplicates are found (most are between UnitTests and UnitTests.McgInterop)
- the total number of indirection cells is about 23,000
- the elapsed time to hash the 8000 types and methods is about 3 milliseconds (11 million clock cycles as measured by the rdtsc instruction, see instrumentation in GenericUnification.cpp).
I also added interning of generic composition structures which seems to roughly halve the space taken by them.
[tfs-changeset: 1625336]
Diffstat (limited to 'src/Native/Runtime/RuntimeInstance.cpp')
-rw-r--r-- | src/Native/Runtime/RuntimeInstance.cpp | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/src/Native/Runtime/RuntimeInstance.cpp b/src/Native/Runtime/RuntimeInstance.cpp index 988b9c216..e94c84aa9 100644 --- a/src/Native/Runtime/RuntimeInstance.cpp +++ b/src/Native/Runtime/RuntimeInstance.cpp @@ -26,6 +26,7 @@ #include "eetype.h" #include "varint.h" #include "DebugEventSource.h" +#include "GenericUnification.h" #include "CommonMacros.inl" #include "slist.inl" @@ -273,6 +274,7 @@ RuntimeInstance::RuntimeInstance() : m_pStandaloneExeModule(NULL), m_pStaticGCRefsDescChunkList(NULL), m_pThreadStaticGCRefsDescChunkList(NULL), + m_pGenericUnificationHashtable(NULL), m_conservativeStackReportingEnabled(false) { } @@ -538,12 +540,12 @@ bool RuntimeInstance::CreateGenericAndStaticInfo(EEType * pEEType, assert(pEEType->IsGeneric()); // prepare generic composition - size_t cbGenericCompositionSize = EEType::GenericComposition::GetSize((UInt16)arity, pTemplateType->HasGenericVariance()); + size_t cbGenericCompositionSize = GenericComposition::GetSize((UInt16)arity, pTemplateType->HasGenericVariance()); pGenericCompositionMemory = new (nothrow) UInt8[cbGenericCompositionSize]; if (pGenericCompositionMemory == NULL) return false; - EEType::GenericComposition *pGenericComposition = (EEType::GenericComposition *)(UInt8 *)pGenericCompositionMemory; + GenericComposition *pGenericComposition = (GenericComposition *)(UInt8 *)pGenericCompositionMemory; pGenericComposition->Init((UInt16)arity, pTemplateType->HasGenericVariance()); // fill in variance flags @@ -604,6 +606,18 @@ bool RuntimeInstance::CreateGenericAndStaticInfo(EEType * pEEType, return true; } +bool RuntimeInstance::UnifyGenerics(GenericUnificationDesc *descs, UInt32 descCount, void **pIndirCells, UInt32 indirCellCount) +{ + if (m_pGenericUnificationHashtable == nullptr) + { + m_pGenericUnificationHashtable = new GenericUnificationHashtable(); + if (m_pGenericUnificationHashtable == nullptr) + return false; + } + + return m_pGenericUnificationHashtable->UnifyDescs(descs, descCount, (UIntTarget*)pIndirCells, indirCellCount); +} + COOP_PINVOKE_HELPER(bool, RhCreateGenericInstanceDescForType2, (EEType * pEEType, UInt32 arity, UInt32 nonGcStaticDataSize, @@ -704,6 +718,7 @@ COOP_PINVOKE_HELPER(PTR_VOID, RhGetRuntimeHelperForType, (EEType * pEEType, int case RuntimeHelperKind::CastClass: if (pEEType->IsArray()) return INDIRECTION(RhTypeCast_CheckCastArray); + else if (pEEType->IsInterface()) return INDIRECTION(RhTypeCast_CheckCastInterface); else |