diff options
author | David Wrighton <davidwr@microsoft.com> | 2019-04-25 10:57:09 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-25 10:57:09 -0700 |
commit | 713091f4e504b9a194dcb2cfda180baa21572c58 (patch) | |
tree | ec53ab52a5747f018ce7b9832aa4b212fe72d976 /src/vm/classcompat.cpp | |
parent | e3d7d212a4d5350227c1fcc6949e9a379e9162c5 (diff) | |
download | coreclr-713091f4e504b9a194dcb2cfda180baa21572c58.tar.gz coreclr-713091f4e504b9a194dcb2cfda180baa21572c58.tar.bz2 coreclr-713091f4e504b9a194dcb2cfda180baa21572c58.zip |
Improve the performance of the type loader (#24177)
Improve the performance of the type loader
- Disable interface ambiguity checks in Corelib
- Improve StackingAllocator perf
- Increase size of allocation blocks
- Cleanup allocation blocks comletely on gc suspension
- Check for presence of generic parameters to methods in a more efficient manner
- Querying the count of GenericParameter records requires a binary search in the GenericParams table
- Checking the generic flag on the method signature is effectively free
- Skip unnecessary checks in EnumerateClassMethods for corelib
- Use Sanity check flag where appropriate
- Use slightly faster hashtable functions in StringLiteralMap
- Remove pointless string literal entry hash table search
- Change stacking allocator to not be allocated for the lifetime of a thread, but instead its allocated/destroyed around the first frame on the thread that needs the allocator.
- Allocate at most 1 stacking allocator per thread
- The allocation is on the stack via _alloca (as managed by the ACQUIRE_STACKING_ALLOCATOR macro
- This will put an 8KB buffer on the stack, and if there is need for a larger buffer it will allocate off of the heap.
- Stacking allocator initial block is always present, so the allocation routine for the allocator can be somewhat simpler
- More logic has been move the the cpp file, to reduce header bloat, and improve iteration when modifying StackingAllocator code
- Avoid use of alloca for StackingAllocator when less than 512KB of stack is available
Diffstat (limited to 'src/vm/classcompat.cpp')
-rw-r--r-- | src/vm/classcompat.cpp | 77 |
1 files changed, 34 insertions, 43 deletions
diff --git a/src/vm/classcompat.cpp b/src/vm/classcompat.cpp index 775a861bff..473e328200 100644 --- a/src/vm/classcompat.cpp +++ b/src/vm/classcompat.cpp @@ -227,8 +227,6 @@ InteropMethodTableData *MethodTableBuilder::BuildInteropVTable(AllocMemTracker * #endif // _DEBUG //Get Check Point for the thread-based allocator - Thread *pThread = GetThread(); - CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease HRESULT hr = S_OK; Module *pModule = pThisMT->GetModule(); @@ -349,19 +347,19 @@ InteropMethodTableData *MethodTableBuilder::BuildInteropVTable(AllocMemTracker * // The interop data for the VTable for COM Interop backward compatibility // Allocate space to hold on to the MethodDesc for each entry - bmtVT.ppSDVtable = new (&pThread->m_MarshalAlloc) InteropMethodTableSlotData*[bmtVT.dwMaxVtableSize]; + bmtVT.ppSDVtable = new (GetStackingAllocator()) InteropMethodTableSlotData*[bmtVT.dwMaxVtableSize]; ZeroMemory(bmtVT.ppSDVtable, bmtVT.dwMaxVtableSize * sizeof(InteropMethodTableSlotData*)); // Allocate space to hold on to the MethodDesc for each entry - bmtVT.ppSDNonVtable = new (&pThread->m_MarshalAlloc) InteropMethodTableSlotData*[NumDeclaredMethods()]; + bmtVT.ppSDNonVtable = new (GetStackingAllocator()) InteropMethodTableSlotData*[NumDeclaredMethods()]; ZeroMemory(bmtVT.ppSDNonVtable , sizeof(InteropMethodTableSlotData*)*NumDeclaredMethods()); DWORD cMaxEntries = (bmtVT.dwMaxVtableSize * 2) + (NumDeclaredMethods() * 2); - InteropMethodTableSlotData *pInteropData = new (&pThread->m_MarshalAlloc) InteropMethodTableSlotData[cMaxEntries]; + InteropMethodTableSlotData *pInteropData = new (GetStackingAllocator()) InteropMethodTableSlotData[cMaxEntries]; memset(pInteropData, 0, cMaxEntries * sizeof(InteropMethodTableSlotData)); - bmtVT.pInteropData = new (&pThread->m_MarshalAlloc) InteropMethodTableSlotDataMap(pInteropData, cMaxEntries); + bmtVT.pInteropData = new (GetStackingAllocator()) InteropMethodTableSlotDataMap(pInteropData, cMaxEntries); // Initialize the map with parent information if (bmtParent.pParentMethodTable != NULL) @@ -632,7 +630,7 @@ VOID MethodTableBuilder::BuildInteropVTable_InterfaceList( Module *pModule = GetModule(); // Allocate the BuildingInterfaceList table - *ppBuildingInterfaceList = new(&pThread->m_MarshalAlloc) BuildingInterfaceInfo_t[cAllInterfaces]; + *ppBuildingInterfaceList = new(GetStackingAllocator()) BuildingInterfaceInfo_t[cAllInterfaces]; BuildingInterfaceInfo_t *pInterfaceBuildInfo = *ppBuildingInterfaceList; while (pMDImport->EnumNext(&hEnumInterfaceImpl, &ii)) @@ -836,13 +834,10 @@ VOID MethodTableBuilder::BuildInteropVTable_PlaceMembers( slotNum = (WORD) pItfMD->GetSlot(); if (bmtInterface->pppInterfaceImplementingMD[j] == NULL) { - Thread *pThread = GetThread(); - StackingAllocator * pAlloc = &pThread->m_MarshalAlloc; - - bmtInterface->pppInterfaceImplementingMD[j] = new (pAlloc) MethodDesc * [pInterface->GetNumVirtuals()]; + bmtInterface->pppInterfaceImplementingMD[j] = new (GetStackingAllocator()) MethodDesc * [pInterface->GetNumVirtuals()]; memset(bmtInterface->pppInterfaceImplementingMD[j], 0, sizeof(MethodDesc *) * pInterface->GetNumVirtuals()); - bmtInterface->pppInterfaceDeclaringMD[j] = new (pAlloc) MethodDesc * [pInterface->GetNumVirtuals()]; + bmtInterface->pppInterfaceDeclaringMD[j] = new (GetStackingAllocator()) MethodDesc * [pInterface->GetNumVirtuals()]; memset(bmtInterface->pppInterfaceDeclaringMD[j], 0, sizeof(MethodDesc *) * pInterface->GetNumVirtuals()); } @@ -1084,7 +1079,7 @@ VOID MethodTableBuilder::BuildInteropVTable_ResolveInterfaces( } // Create a fully expanded map of all interfaces we implement - bmtInterface->pInterfaceMap = new (&pThread->m_MarshalAlloc) InterfaceInfo_t[bmtInterface->dwMaxExpandedInterfaces]; + bmtInterface->pInterfaceMap = new (GetStackingAllocator()) InterfaceInfo_t[bmtInterface->dwMaxExpandedInterfaces]; // # slots of largest interface bmtInterface->dwLargestInterfaceSize = 0; @@ -1100,9 +1095,9 @@ VOID MethodTableBuilder::BuildInteropVTable_ResolveInterfaces( // This is needed later - for each interface, we get the MethodDesc pointer for each // method. We need to be able to persist at most one interface at a time, so we // need enough memory for the largest interface. - bmtInterface->ppInterfaceMethodDescList = new (&pThread->m_MarshalAlloc) MethodDesc*[bmtInterface->dwLargestInterfaceSize]; + bmtInterface->ppInterfaceMethodDescList = new (GetStackingAllocator()) MethodDesc*[bmtInterface->dwLargestInterfaceSize]; - bmtInterface->ppInterfaceDeclMethodDescList = new (&pThread->m_MarshalAlloc) MethodDesc*[bmtInterface->dwLargestInterfaceSize]; + bmtInterface->ppInterfaceDeclMethodDescList = new (GetStackingAllocator()) MethodDesc*[bmtInterface->dwLargestInterfaceSize]; } EEClass *pParentClass = (IsInterface() || bmtParent->pParentMethodTable == NULL) ? NULL : bmtParent->pParentMethodTable->GetClass(); @@ -1134,10 +1129,10 @@ VOID MethodTableBuilder::BuildInteropVTable_ResolveInterfaces( bmtVT->wCurrentNonVtableSlot = 0; - bmtInterface->pppInterfaceImplementingMD = (MethodDesc ***) pThread->m_MarshalAlloc.Alloc(S_UINT32(sizeof(MethodDesc *)) * S_UINT32(bmtInterface->dwMaxExpandedInterfaces)); + bmtInterface->pppInterfaceImplementingMD = (MethodDesc ***) GetStackingAllocator()->Alloc(S_UINT32(sizeof(MethodDesc *)) * S_UINT32(bmtInterface->dwMaxExpandedInterfaces)); memset(bmtInterface->pppInterfaceImplementingMD, 0, sizeof(MethodDesc *) * bmtInterface->dwMaxExpandedInterfaces); - bmtInterface->pppInterfaceDeclaringMD = (MethodDesc ***) pThread->m_MarshalAlloc.Alloc(S_UINT32(sizeof(MethodDesc *)) * S_UINT32(bmtInterface->dwMaxExpandedInterfaces)); + bmtInterface->pppInterfaceDeclaringMD = (MethodDesc ***) GetStackingAllocator()->Alloc(S_UINT32(sizeof(MethodDesc *)) * S_UINT32(bmtInterface->dwMaxExpandedInterfaces)); memset(bmtInterface->pppInterfaceDeclaringMD, 0, sizeof(MethodDesc *) * bmtInterface->dwMaxExpandedInterfaces); return; @@ -1555,8 +1550,8 @@ VOID MethodTableBuilder::BuildInteropVTable_PlaceMethodImpls( // Allocate some temporary storage. The number of overrides for a single method impl // cannot be greater then the number of vtable slots. - DWORD* slots = (DWORD*) new (&GetThread()->m_MarshalAlloc) DWORD[bmtVT->wCurrentVtableSlot]; - MethodDesc **replaced = new (&GetThread()->m_MarshalAlloc) MethodDesc*[bmtVT->wCurrentVtableSlot]; + DWORD* slots = (DWORD*) new (GetStackingAllocator()) DWORD[bmtVT->wCurrentVtableSlot]; + MethodDesc **replaced = new (GetStackingAllocator()) MethodDesc*[bmtVT->wCurrentVtableSlot]; while(pIndex < bmtMethodImpl->pIndex) { @@ -1761,7 +1756,7 @@ VOID MethodTableBuilder::BuildInteropVTable_PlaceInterfaceDeclaration( if(bmtInterface->pdwOriginalStart == NULL) { Thread *pThread = GetThread(); - bmtInterface->pdwOriginalStart = new (&pThread->m_MarshalAlloc) DWORD[bmtInterface->dwMaxExpandedInterfaces]; + bmtInterface->pdwOriginalStart = new (GetStackingAllocator()) DWORD[bmtInterface->dwMaxExpandedInterfaces]; memset(bmtInterface->pdwOriginalStart, 0, sizeof(DWORD)*bmtInterface->dwMaxExpandedInterfaces); } @@ -2080,7 +2075,7 @@ VOID MethodTableBuilder::EnumerateMethodImpls() // // Allocate the structures to keep track of the token pairs // - bmtMethodImpl->rgMethodImplTokens = new (&GetThread()->m_MarshalAlloc) + bmtMethodImpl->rgMethodImplTokens = new (GetStackingAllocator()) bmtMethodImplInfo::MethodImplTokenPair[bmtMethodImpl->dwNumberMethodImpls]; // Iterate through each MethodImpl declared on this class @@ -2137,8 +2132,8 @@ VOID MethodTableBuilder::EnumerateMethodImpls() // // Allocate the structures to keep track of the impl matches // - bmtMethodImpl->pMethodDeclSubsts = new (&GetThread()->m_MarshalAlloc) Substitution[bmtMethodImpl->dwNumberMethodImpls]; - bmtMethodImpl->rgEntries = new (&GetThread()->m_MarshalAlloc) bmtMethodImplInfo::Entry[bmtMethodImpl->dwNumberMethodImpls]; + bmtMethodImpl->pMethodDeclSubsts = new (GetStackingAllocator()) Substitution[bmtMethodImpl->dwNumberMethodImpls]; + bmtMethodImpl->rgEntries = new (GetStackingAllocator()) bmtMethodImplInfo::Entry[bmtMethodImpl->dwNumberMethodImpls]; // These are used for verification maxRidMD = pMDInternalImport->GetCountWithTokenKind(mdtMethodDef); @@ -2309,7 +2304,6 @@ VOID MethodTableBuilder::EnumerateClassMethods() HRESULT hr = S_OK; DWORD i; - Thread *pThread = GetThread(); IMDInternalImport *pMDInternalImport = bmtType->pMDImport; mdToken tok; DWORD dwMemberAttrs; @@ -2346,16 +2340,16 @@ VOID MethodTableBuilder::EnumerateClassMethods() // Allocate an array to contain the method tokens as well as information about the methods. bmtMethod->cMethAndGaps = bmtMethod->hEnumMethod.EnumGetCount(); - bmtMethod->rgMethodTokens = new (&pThread->m_MarshalAlloc) mdToken[bmtMethod->cMethAndGaps]; - bmtMethod->rgMethodRVA = new (&pThread->m_MarshalAlloc) ULONG[bmtMethod->cMethAndGaps]; - bmtMethod->rgMethodAttrs = new (&pThread->m_MarshalAlloc) DWORD[bmtMethod->cMethAndGaps]; - bmtMethod->rgMethodImplFlags = new (&pThread->m_MarshalAlloc) DWORD[bmtMethod->cMethAndGaps]; - bmtMethod->rgMethodClassifications = new (&pThread->m_MarshalAlloc) DWORD[bmtMethod->cMethAndGaps]; + bmtMethod->rgMethodTokens = new (GetStackingAllocator()) mdToken[bmtMethod->cMethAndGaps]; + bmtMethod->rgMethodRVA = new (GetStackingAllocator()) ULONG[bmtMethod->cMethAndGaps]; + bmtMethod->rgMethodAttrs = new (GetStackingAllocator()) DWORD[bmtMethod->cMethAndGaps]; + bmtMethod->rgMethodImplFlags = new (GetStackingAllocator()) DWORD[bmtMethod->cMethAndGaps]; + bmtMethod->rgMethodClassifications = new (GetStackingAllocator()) DWORD[bmtMethod->cMethAndGaps]; - bmtMethod->rgszMethodName = new (&pThread->m_MarshalAlloc) LPCSTR[bmtMethod->cMethAndGaps]; + bmtMethod->rgszMethodName = new (GetStackingAllocator()) LPCSTR[bmtMethod->cMethAndGaps]; - bmtMethod->rgMethodImpl = new (&pThread->m_MarshalAlloc) BYTE[bmtMethod->cMethAndGaps]; - bmtMethod->rgMethodType = new (&pThread->m_MarshalAlloc) BYTE[bmtMethod->cMethAndGaps]; + bmtMethod->rgMethodImpl = new (GetStackingAllocator()) BYTE[bmtMethod->cMethAndGaps]; + bmtMethod->rgMethodType = new (GetStackingAllocator()) BYTE[bmtMethod->cMethAndGaps]; enum { SeenCtor = 1, SeenInvoke = 2, SeenBeginInvoke = 4, SeenEndInvoke = 8}; unsigned delegateMethodsSeen = 0; @@ -2961,10 +2955,8 @@ VOID MethodTableBuilder::AllocateMethodWorkingMemory() CONTRACTL_END; DWORD i; - Thread *pThread = GetThread(); - // Allocate a MethodDesc* for each method (needed later when doing interfaces), and a FieldDesc* for each field - bmtMethod->ppMethodDescList = new (&pThread->m_MarshalAlloc) MethodDesc*[NumDeclaredMethods()]; + bmtMethod->ppMethodDescList = new (GetStackingAllocator()) MethodDesc*[NumDeclaredMethods()]; ZeroMemory(bmtMethod->ppMethodDescList, NumDeclaredMethods() * sizeof(MethodDesc *)); // Create a temporary function table (we don't know how large the vtable will be until the very end, @@ -2979,7 +2971,7 @@ VOID MethodTableBuilder::AllocateMethodWorkingMemory() if (IsValueClass()) { bmtVT->dwMaxVtableSize += NumDeclaredMethods(); - bmtMethod->ppUnboxMethodDescList = new (&pThread->m_MarshalAlloc) MethodDesc*[NumDeclaredMethods()]; + bmtMethod->ppUnboxMethodDescList = new (GetStackingAllocator()) MethodDesc*[NumDeclaredMethods()]; ZeroMemory(bmtMethod->ppUnboxMethodDescList, NumDeclaredMethods() * sizeof(MethodDesc*)); } @@ -2997,13 +2989,13 @@ VOID MethodTableBuilder::AllocateMethodWorkingMemory() } // Allocate the temporary vtable - bmtVT->pVtable = new (&pThread->m_MarshalAlloc)PCODE [bmtVT->dwMaxVtableSize]; + bmtVT->pVtable = new (GetStackingAllocator())PCODE [bmtVT->dwMaxVtableSize]; ZeroMemory(bmtVT->pVtable, bmtVT->dwMaxVtableSize * sizeof(PCODE)); - bmtVT->pVtableMD = new (&pThread->m_MarshalAlloc) MethodDesc*[bmtVT->dwMaxVtableSize]; + bmtVT->pVtableMD = new (GetStackingAllocator()) MethodDesc*[bmtVT->dwMaxVtableSize]; ZeroMemory(bmtVT->pVtableMD, bmtVT->dwMaxVtableSize * sizeof(MethodDesc*)); // Allocate the temporary non-vtable - bmtVT->pNonVtableMD = new (&pThread->m_MarshalAlloc) MethodDesc*[NumDeclaredMethods()]; + bmtVT->pNonVtableMD = new (GetStackingAllocator()) MethodDesc*[NumDeclaredMethods()]; ZeroMemory(bmtVT->pNonVtableMD, sizeof(MethodDesc*) * NumDeclaredMethods()); if (bmtParent->pParentMethodTable != NULL) @@ -3066,7 +3058,7 @@ VOID MethodTableBuilder::AllocateMethodWorkingMemory() if (NumDeclaredMethods() > 0) { bmtParent->ppParentMethodDescBuf = (MethodDesc **) - pThread->m_MarshalAlloc.Alloc(S_UINT32(2) * S_UINT32(NumDeclaredMethods()) * + GetStackingAllocator()->Alloc(S_UINT32(2) * S_UINT32(NumDeclaredMethods()) * S_UINT32(sizeof(MethodDesc*))); bmtParent->ppParentMethodDescBufPtr = bmtParent->ppParentMethodDescBuf; @@ -3532,10 +3524,9 @@ MethodNameHash *MethodTableBuilder::CreateMethodChainHash(MethodTable *pMT) { STANDARD_VM_CONTRACT; - Thread *pThread = GetThread(); - MethodNameHash *pHash = new (&pThread->m_MarshalAlloc) MethodNameHash(); + MethodNameHash *pHash = new (GetStackingAllocator()) MethodNameHash(); - pHash->Init(pMT->GetNumVirtuals(), &(pThread->m_MarshalAlloc)); + pHash->Init(pMT->GetNumVirtuals(), GetStackingAllocator()); MethodTable::MethodIterator it(pMT); for (;it.IsValid(); it.Next()) |