From: David Wrighton Date: Sat, 25 Jul 2020 18:30:34 +0000 (-0700) Subject: Address slowdowns in type loader performance (#39841) X-Git-Tag: submit/tizen/20210909.063632~6423 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8e0324910669c1e8267b55abc8f814e2c6665a94;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Address slowdowns in type loader performance (#39841) --- diff --git a/src/coreclr/src/debug/daccess/nidump.cpp b/src/coreclr/src/debug/daccess/nidump.cpp index 5a0bbfd..06a6fff 100644 --- a/src/coreclr/src/debug/daccess/nidump.cpp +++ b/src/coreclr/src/debug/daccess/nidump.cpp @@ -7996,7 +7996,7 @@ void NativeImageDumper::DumpMethodDesc( PTR_MethodDesc md, PTR_Module module ) InstantiatedMethodDesc, METHODDESCS ); #ifdef FEATURE_COMINTEROP - if (imd->IMD_HasComPlusCallInfo()) + if (imd->IsGenericComPlusCall()) { PTR_ComPlusCallInfo compluscall = imd->IMD_GetComPlusCallInfo(); DumpComPlusCallInfo( compluscall, METHODDESCS ); diff --git a/src/coreclr/src/vm/class.cpp b/src/coreclr/src/vm/class.cpp index 8e18a47..7a243ca 100644 --- a/src/coreclr/src/vm/class.cpp +++ b/src/coreclr/src/vm/class.cpp @@ -1184,107 +1184,127 @@ void ClassLoader::ValidateMethodsWithCovariantReturnTypes(MethodTable* pMT) return; // Step 1: Validate compatibility of return types on overriding methods - - for (WORD i = 0; i < pParentMT->GetNumVirtuals(); i++) + if (pMT->GetClass()->HasCovariantOverride() && (!pMT->GetModule()->IsReadyToRun() || !pMT->GetModule()->GetReadyToRunInfo()->SkipTypeValidation())) { - MethodDesc* pMD = pMT->GetMethodDescForSlot(i); - MethodDesc* pParentMD = pParentMT->GetMethodDescForSlot(i); + for (WORD i = 0; i < pParentMT->GetNumVirtuals(); i++) + { + if (pMT->GetRestoredSlot(i) == pParentMT->GetRestoredSlot(i)) + { + // The real check is that the MethodDesc's must not match, but a simple VTable check will + // work most of the time, and is far faster than the GetMethodDescForSlot method. + _ASSERTE(pMT->GetMethodDescForSlot(i) == pParentMT->GetMethodDescForSlot(i)); + continue; + } + MethodDesc* pMD = pMT->GetMethodDescForSlot(i); + MethodDesc* pParentMD = pParentMT->GetMethodDescForSlot(i); - if (pMD == pParentMD) - continue; + if (pMD == pParentMD) + continue; - if (!pMD->RequiresCovariantReturnTypeChecking() && !pParentMD->RequiresCovariantReturnTypeChecking()) - continue; + if (!pMD->RequiresCovariantReturnTypeChecking() && !pParentMD->RequiresCovariantReturnTypeChecking()) + continue; - // If the bit is not set on this method, but we reach here because it's been set on the method at the same slot on - // the base type, set the bit for the current method to ensure any future overriding method down the chain gets checked. - if (!pMD->RequiresCovariantReturnTypeChecking()) - pMD->SetRequiresCovariantReturnTypeChecking(); + // If the bit is not set on this method, but we reach here because it's been set on the method at the same slot on + // the base type, set the bit for the current method to ensure any future overriding method down the chain gets checked. + if (!pMD->RequiresCovariantReturnTypeChecking()) + pMD->SetRequiresCovariantReturnTypeChecking(); - // The context used to load the return type of the parent method has to use the generic method arguments - // of the overriding method, otherwise the type comparison below will not work correctly - SigTypeContext context1(pParentMD->GetClassInstantiation(), pMD->GetMethodInstantiation()); - MetaSig methodSig1(pParentMD); - TypeHandle hType1 = methodSig1.GetReturnProps().GetTypeHandleThrowing(pParentMD->GetModule(), &context1, ClassLoader::LoadTypesFlag::LoadTypes, CLASS_LOAD_EXACTPARENTS); + // The context used to load the return type of the parent method has to use the generic method arguments + // of the overriding method, otherwise the type comparison below will not work correctly + SigTypeContext context1(pParentMD->GetClassInstantiation(), pMD->GetMethodInstantiation()); + MetaSig methodSig1(pParentMD); + TypeHandle hType1 = methodSig1.GetReturnProps().GetTypeHandleThrowing(pParentMD->GetModule(), &context1, ClassLoader::LoadTypesFlag::LoadTypes, CLASS_LOAD_EXACTPARENTS); - SigTypeContext context2(pMD); - MetaSig methodSig2(pMD); - TypeHandle hType2 = methodSig2.GetReturnProps().GetTypeHandleThrowing(pMD->GetModule(), &context2, ClassLoader::LoadTypesFlag::LoadTypes, CLASS_LOAD_EXACTPARENTS); + SigTypeContext context2(pMD); + MetaSig methodSig2(pMD); + TypeHandle hType2 = methodSig2.GetReturnProps().GetTypeHandleThrowing(pMD->GetModule(), &context2, ClassLoader::LoadTypesFlag::LoadTypes, CLASS_LOAD_EXACTPARENTS); - if (!IsCompatibleWith(hType1, hType2)) - { - SString strAssemblyName; - pMD->GetAssembly()->GetDisplayName(strAssemblyName); + if (!IsCompatibleWith(hType1, hType2)) + { + SString strAssemblyName; + pMD->GetAssembly()->GetDisplayName(strAssemblyName); - SString strInvalidTypeName; - TypeString::AppendType(strInvalidTypeName, TypeHandle(pMD->GetMethodTable())); + SString strInvalidTypeName; + TypeString::AppendType(strInvalidTypeName, TypeHandle(pMD->GetMethodTable())); - SString strInvalidMethodName; - TypeString::AppendMethod(strInvalidMethodName, pMD, pMD->GetMethodInstantiation()); + SString strInvalidMethodName; + TypeString::AppendMethod(strInvalidMethodName, pMD, pMD->GetMethodInstantiation()); - SString strParentMethodName; - TypeString::AppendMethod(strParentMethodName, pParentMD, pParentMD->GetMethodInstantiation()); + SString strParentMethodName; + TypeString::AppendMethod(strParentMethodName, pParentMD, pParentMD->GetMethodInstantiation()); - COMPlusThrow( - kTypeLoadException, - IDS_CLASSLOAD_MI_BADRETURNTYPE, - strInvalidMethodName, - strInvalidTypeName, - strAssemblyName, - strParentMethodName); + COMPlusThrow( + kTypeLoadException, + IDS_CLASSLOAD_MI_BADRETURNTYPE, + strInvalidMethodName, + strInvalidTypeName, + strAssemblyName, + strParentMethodName); + } } } // Step 2: propate overriding MethodImpls to applicable vtable slots if the declaring method has the attribute - MethodTable::MethodDataWrapper hMTData(MethodTable::GetMethodData(pMT, FALSE)); - - for (WORD i = 0; i < pParentMT->GetNumVirtuals(); i++) + if (pMT->GetClass()->HasVTableMethodImpl()) { - MethodDesc* pMD = pMT->GetMethodDescForSlot(i); - MethodDesc* pParentMD = pParentMT->GetMethodDescForSlot(i); - if (pMD == pParentMD) - continue; - - // The attribute is only applicable to MethodImpls. For anything else, it will be treated as a no-op - if (!pMD->IsMethodImpl()) - continue; + MethodTable::MethodDataWrapper hMTData(MethodTable::GetMethodData(pMT, FALSE)); - // Search if the attribute has been applied on this vtable slot, either by the current MethodImpl, or by a previous - // MethodImpl somewhere in the base type hierarchy. - bool foundAttribute = false; - MethodTable* pCurrentMT = pMT; - while (!foundAttribute && pCurrentMT != NULL && i < pCurrentMT->GetNumVirtuals()) + for (WORD i = 0; i < pParentMT->GetNumVirtuals(); i++) { - MethodDesc* pCurrentMD = pCurrentMT->GetMethodDescForSlot(i); + if (pMT->GetRestoredSlot(i) == pParentMT->GetRestoredSlot(i)) + { + // The real check is that the MethodDesc's must not match, but a simple VTable check will + // work most of the time, and is far faster than the GetMethodDescForSlot method. + _ASSERTE(pMT->GetMethodDescForSlot(i) == pParentMT->GetMethodDescForSlot(i)); + continue; + } + + MethodDesc* pMD = pMT->GetMethodDescForSlot(i); + MethodDesc* pParentMD = pParentMT->GetMethodDescForSlot(i); + if (pMD == pParentMD) + continue; // The attribute is only applicable to MethodImpls. For anything else, it will be treated as a no-op - if (pCurrentMD->IsMethodImpl()) + if (!pMD->IsMethodImpl()) + continue; + + // Search if the attribute has been applied on this vtable slot, either by the current MethodImpl, or by a previous + // MethodImpl somewhere in the base type hierarchy. + bool foundAttribute = false; + MethodTable* pCurrentMT = pMT; + while (!foundAttribute && pCurrentMT != NULL && i < pCurrentMT->GetNumVirtuals()) { - BYTE* pVal = NULL; - ULONG cbVal = 0; - if (pCurrentMD->GetCustomAttribute(WellKnownAttribute::PreserveBaseOverridesAttribute, (const void**)&pVal, &cbVal) == S_OK) - foundAttribute = true; - } + MethodDesc* pCurrentMD = pCurrentMT->GetMethodDescForSlot(i); - pCurrentMT = pCurrentMT->GetParentMethodTable(); - } + // The attribute is only applicable to MethodImpls. For anything else, it will be treated as a no-op + if (pCurrentMD->IsMethodImpl()) + { + BYTE* pVal = NULL; + ULONG cbVal = 0; + if (pCurrentMD->GetCustomAttribute(WellKnownAttribute::PreserveBaseOverridesAttribute, (const void**)&pVal, &cbVal) == S_OK) + foundAttribute = true; + } - if (!foundAttribute) - continue; + pCurrentMT = pCurrentMT->GetParentMethodTable(); + } - // Search for any vtable slot still pointing at the parent method, and update it with the current overriding method - for (WORD j = i; j < pParentMT->GetNumVirtuals(); j++) - { - MethodDesc* pCurrentMD = pMT->GetMethodDescForSlot(j); - if (pCurrentMD == pParentMD) + if (!foundAttribute) + continue; + + // Search for any vtable slot still pointing at the parent method, and update it with the current overriding method + for (WORD j = i; j < pParentMT->GetNumVirtuals(); j++) { - // This is a vtable slot that needs to be updated to the new overriding method because of the - // presence of the attribute. - pMT->SetSlot(j, pMT->GetSlot(i)); - _ASSERT(pMT->GetMethodDescForSlot(j) == pMD); + MethodDesc* pCurrentMD = pMT->GetMethodDescForSlot(j); + if (pCurrentMD == pParentMD) + { + // This is a vtable slot that needs to be updated to the new overriding method because of the + // presence of the attribute. + pMT->SetSlot(j, pMT->GetSlot(i)); + _ASSERT(pMT->GetMethodDescForSlot(j) == pMD); - hMTData->UpdateImplMethodDesc(pMD, j); + hMTData->UpdateImplMethodDesc(pMD, j); + } } } } diff --git a/src/coreclr/src/vm/class.h b/src/coreclr/src/vm/class.h index 98a59db..179a082 100644 --- a/src/coreclr/src/vm/class.h +++ b/src/coreclr/src/vm/class.h @@ -1158,6 +1158,30 @@ public: } #endif // FEATURE_COMINTEROP + inline void SetHasVTableMethodImpl() + { + LIMITED_METHOD_CONTRACT; + m_VMFlags |= VMFLAG_VTABLEMETHODIMPL; + } + + inline BOOL HasVTableMethodImpl() + { + LIMITED_METHOD_CONTRACT; + return (m_VMFlags & VMFLAG_VTABLEMETHODIMPL); + } + + inline void SetHasCovariantOverride() + { + LIMITED_METHOD_CONTRACT; + m_VMFlags |= VMFLAG_COVARIANTOVERRIDE; + } + + inline BOOL HasCovariantOverride() + { + LIMITED_METHOD_CONTRACT; + return (m_VMFlags & VMFLAG_COVARIANTOVERRIDE); + } + #ifdef _DEBUG inline DWORD IsDestroyed() { @@ -1691,8 +1715,8 @@ public: VMFLAG_HASCOCLASSATTRIB = 0x01000000, VMFLAG_COMEVENTITFMASK = 0x02000000, // class is a special COM event interface #endif // FEATURE_COMINTEROP - // unused = 0x04000000, - // unused = 0x08000000, + VMFLAG_VTABLEMETHODIMPL = 0x04000000, // class uses MethodImpl to override virtual function defined on class + VMFLAG_COVARIANTOVERRIDE = 0x08000000, // class has a covariant override // This one indicates that the fields of the valuetype are // not tightly packed and is used to check whether we can diff --git a/src/coreclr/src/vm/method.cpp b/src/coreclr/src/vm/method.cpp index 9c247d6..72d0159 100644 --- a/src/coreclr/src/vm/method.cpp +++ b/src/coreclr/src/vm/method.cpp @@ -83,7 +83,7 @@ static_assert_no_msg((sizeof(DynamicMethodDesc) & MethodDesc::ALIGNMENT_MASK adjustment + sizeof(ComPlusCallMethodDesc), /* mcComInterOp */ \ adjustment + sizeof(DynamicMethodDesc) /* mcDynamic */ -const SIZE_T MethodDesc::s_ClassificationSizeTable[] = { +const BYTE MethodDesc::s_ClassificationSizeTable[] = { // This is the raw METHOD_DESC_SIZES(0), @@ -91,7 +91,24 @@ const SIZE_T MethodDesc::s_ClassificationSizeTable[] = { // We index using optional slot flags into it METHOD_DESC_SIZES(sizeof(NonVtableSlot)), METHOD_DESC_SIZES(sizeof(MethodImpl)), - METHOD_DESC_SIZES(sizeof(NonVtableSlot) + sizeof(MethodImpl)) + METHOD_DESC_SIZES(sizeof(NonVtableSlot) + sizeof(MethodImpl)), + + METHOD_DESC_SIZES(sizeof(NativeCodeSlot)), + METHOD_DESC_SIZES(sizeof(NonVtableSlot) + sizeof(NativeCodeSlot)), + METHOD_DESC_SIZES(sizeof(MethodImpl) + sizeof(NativeCodeSlot)), + METHOD_DESC_SIZES(sizeof(NonVtableSlot) + sizeof(MethodImpl) + sizeof(NativeCodeSlot)), + +#ifdef FEATURE_COMINTEROP + METHOD_DESC_SIZES(sizeof(ComPlusCallInfo)), + METHOD_DESC_SIZES(sizeof(NonVtableSlot) + sizeof(ComPlusCallInfo)), + METHOD_DESC_SIZES(sizeof(MethodImpl) + sizeof(ComPlusCallInfo)), + METHOD_DESC_SIZES(sizeof(NonVtableSlot) + sizeof(MethodImpl) + sizeof(ComPlusCallInfo)), + + METHOD_DESC_SIZES(sizeof(NativeCodeSlot) + sizeof(ComPlusCallInfo)), + METHOD_DESC_SIZES(sizeof(NonVtableSlot) + sizeof(NativeCodeSlot) + sizeof(ComPlusCallInfo)), + METHOD_DESC_SIZES(sizeof(MethodImpl) + sizeof(NativeCodeSlot) + sizeof(ComPlusCallInfo)), + METHOD_DESC_SIZES(sizeof(NonVtableSlot) + sizeof(MethodImpl) + sizeof(NativeCodeSlot) + sizeof(ComPlusCallInfo)) +#endif }; #ifndef FEATURE_COMINTEROP @@ -122,18 +139,22 @@ SIZE_T MethodDesc::SizeOf() { LIMITED_METHOD_DAC_CONTRACT; - SIZE_T size = s_ClassificationSizeTable[m_wFlags & (mdcClassification | mdcHasNonVtableSlot | mdcMethodImpl)]; + SIZE_T size = s_ClassificationSizeTable[m_wFlags & + (mdcClassification + | mdcHasNonVtableSlot + | mdcMethodImpl +#ifdef FEATURE_COMINTEROP + | mdcHasComPlusCallInfo +#endif + | mdcHasNativeCodeSlot)]; +#ifdef FEATURE_PREJIT if (HasNativeCodeSlot()) { - size += (*dac_cast(dac_cast(this) + size) & FIXUP_LIST_MASK) ? - (sizeof(NativeCodeSlot) + sizeof(FixupListSlot)) : sizeof(NativeCodeSlot); + size += (*dac_cast(GetAddrOfNativeCodeSlot()) & FIXUP_LIST_MASK) ? + sizeof(FixupListSlot) : 0; } - -#ifdef FEATURE_COMINTEROP - if (IsGenericComPlusCall()) - size += sizeof(ComPlusCallInfo); -#endif // FEATURE_COMINTEROP +#endif return size; } @@ -3696,11 +3717,11 @@ void MethodDesc::SaveChunk::SaveOneChunk(COUNT_T start, COUNT_T count, ULONG siz if (pMethodInfo->m_fHasNativeCodeSlot) { - pNewMD->m_bFlags2 |= enum_flag2_HasNativeCodeSlot; + pNewMD->m_wFlags |= mdcHasNativeCodeSlot; } else { - pNewMD->m_bFlags2 &= ~enum_flag2_HasNativeCodeSlot; + pNewMD->m_wFlags &= ~mdcHasNativeCodeSlot; } #ifdef FEATURE_COMINTEROP diff --git a/src/coreclr/src/vm/method.hpp b/src/coreclr/src/vm/method.hpp index 4103ec6..c19dcc7 100644 --- a/src/coreclr/src/vm/method.hpp +++ b/src/coreclr/src/vm/method.hpp @@ -139,11 +139,18 @@ enum MethodDescClassification // where the function explicitly implements IInterface.foo() instead of foo(). mdcMethodImpl = 0x0010, - // Method is static - mdcStatic = 0x0020, + // Has slot for native code + mdcHasNativeCodeSlot = 0x0020, +#ifdef FEATURE_COMINTEROP + mdcHasComPlusCallInfo = 0x0040, +#else // unused = 0x0040, - // unused = 0x0080, +#endif + + // Method is static + mdcStatic = 0x0080, + // unused = 0x0100, // unused = 0x0200, @@ -1832,7 +1839,7 @@ protected: enum_flag2_HasPrecode = 0x02, // Precode has been allocated for this method enum_flag2_IsUnboxingStub = 0x04, - enum_flag2_HasNativeCodeSlot = 0x08, // Has slot for native code + // unused = 0x08, enum_flag2_IsJitIntrinsic = 0x10, // Jit may expand method as an intrinsic @@ -1881,13 +1888,13 @@ public: inline BOOL HasNativeCodeSlot() { LIMITED_METHOD_DAC_CONTRACT; - return (m_bFlags2 & enum_flag2_HasNativeCodeSlot) != 0; + return (m_wFlags & mdcHasNativeCodeSlot) != 0; } inline void SetHasNativeCodeSlot() { LIMITED_METHOD_CONTRACT; - m_bFlags2 |= enum_flag2_HasNativeCodeSlot; + m_wFlags |= mdcHasNativeCodeSlot; } inline BOOL IsJitIntrinsic() @@ -1915,7 +1922,7 @@ public: m_bFlags2 |= enum_flag2_RequiresCovariantReturnTypeChecking; } - static const SIZE_T s_ClassificationSizeTable[]; + static const BYTE s_ClassificationSizeTable[]; static SIZE_T GetBaseSize(DWORD classification) { @@ -3537,18 +3544,10 @@ public: } #ifdef FEATURE_COMINTEROP - BOOL IMD_HasComPlusCallInfo() - { - LIMITED_METHOD_CONTRACT; - return ((m_wFlags2 & HasComPlusCallInfo) != 0); - } - void IMD_SetupGenericComPlusCall() { LIMITED_METHOD_CONTRACT; - m_wFlags2 |= InstantiatedMethodDesc::HasComPlusCallInfo; - IMD_GetComPlusCallInfo()->InitStackArgumentSize(); } @@ -3556,14 +3555,16 @@ public: { LIMITED_METHOD_CONTRACT; - _ASSERTE(IMD_HasComPlusCallInfo()); - SIZE_T size = s_ClassificationSizeTable[m_wFlags & (mdcClassification | mdcHasNonVtableSlot | mdcMethodImpl)]; + _ASSERTE(IsGenericComPlusCall()); + SIZE_T size = s_ClassificationSizeTable[m_wFlags & (mdcClassification | mdcHasNonVtableSlot | mdcMethodImpl | mdcHasNativeCodeSlot)]; +#ifdef FEATURE_PREJIT if (HasNativeCodeSlot()) { - size += (*dac_cast(dac_cast(this) + size) & FIXUP_LIST_MASK) ? - (sizeof(NativeCodeSlot) + sizeof(FixupListSlot)) : sizeof(NativeCodeSlot); + size += (*dac_cast(GetAddrOfNativeCodeSlot()) & FIXUP_LIST_MASK) ? + sizeof(FixupListSlot) : 0; } +#endif return dac_cast(dac_cast(this) + size); } diff --git a/src/coreclr/src/vm/method.inl b/src/coreclr/src/vm/method.inl index d0d944d..1175d2b 100644 --- a/src/coreclr/src/vm/method.inl +++ b/src/coreclr/src/vm/method.inl @@ -133,11 +133,14 @@ inline BOOL MethodDesc::IsQCall() FORCEINLINE DWORD MethodDesc::IsGenericComPlusCall() { LIMITED_METHOD_CONTRACT; - return (mcInstantiated == GetClassification() && AsInstantiatedMethodDesc()->IMD_HasComPlusCallInfo()); + return m_wFlags & mdcHasComPlusCallInfo; } + inline void MethodDesc::SetupGenericComPlusCall() { LIMITED_METHOD_CONTRACT; + m_wFlags |= mdcHasComPlusCallInfo; + AsInstantiatedMethodDesc()->IMD_SetupGenericComPlusCall(); } #endif // FEATURE_COMINTEROP diff --git a/src/coreclr/src/vm/methodtablebuilder.cpp b/src/coreclr/src/vm/methodtablebuilder.cpp index 2197632..82a4b50 100644 --- a/src/coreclr/src/vm/methodtablebuilder.cpp +++ b/src/coreclr/src/vm/methodtablebuilder.cpp @@ -2410,6 +2410,7 @@ MethodTableBuilder::EnumerateMethodImpls() compatibleSignatures = TRUE; bmtMetaData->rgMethodImplTokens[i].fRequiresCovariantReturnTypeChecking = true; + bmtMetaData->fHasCovariantOverride = true; } } @@ -5589,6 +5590,19 @@ MethodTableBuilder::ProcessMethodImpls() { STANDARD_VM_CONTRACT; + if (bmtMetaData->fHasCovariantOverride) + { + GetHalfBakedClass()->SetHasCovariantOverride(); + } + if (GetParentMethodTable() != NULL) + { + EEClass* parentClass = GetParentMethodTable()->GetClass(); + if (parentClass->HasCovariantOverride()) + GetHalfBakedClass()->SetHasCovariantOverride(); + if (parentClass->HasVTableMethodImpl()) + GetHalfBakedClass()->SetHasVTableMethodImpl(); + } + if (bmtMethod->dwNumberMethodImpls == 0) return; @@ -5680,6 +5694,7 @@ MethodTableBuilder::ProcessMethodImpls() } Substitution *pDeclSubst = &bmtMetaData->pMethodDeclSubsts[m]; + MethodTable * pDeclMT = NULL; MethodSignature declSig(GetModule(), szName, pSig, cbSig, NULL); @@ -5784,6 +5799,7 @@ MethodTableBuilder::ProcessMethodImpls() } else { + GetHalfBakedClass()->SetHasVTableMethodImpl(); declMethod = FindDeclMethodOnClassInHierarchy(it, pDeclMT, declSig); } diff --git a/src/coreclr/src/vm/methodtablebuilder.h b/src/coreclr/src/vm/methodtablebuilder.h index 34a040c..def6ab9 100644 --- a/src/coreclr/src/vm/methodtablebuilder.h +++ b/src/coreclr/src/vm/methodtablebuilder.h @@ -2006,6 +2006,8 @@ private: MethodImplTokenPair *rgMethodImplTokens; Substitution *pMethodDeclSubsts; // Used to interpret generic variables in the interface of the declaring type + bool fHasCovariantOverride; + //----------------------------------------------------------------------------------------- inline bmtMetaDataInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); } }; // struct bmtMetaDataInfo @@ -2282,10 +2284,11 @@ private: class DeclaredMethodIterator { private: - MethodTableBuilder &m_mtb; - int m_idx; // not SLOT_INDEX? + const int m_numDeclaredMethods; + bmtMDMethod ** const m_declaredMethods; + int m_idx; // not SLOT_INDEX? #ifdef _DEBUG - bmtMDMethod * m_debug_pMethod; + bmtMDMethod * m_debug_pMethod; #endif public: diff --git a/src/coreclr/src/vm/methodtablebuilder.inl b/src/coreclr/src/vm/methodtablebuilder.inl index 2d13e78..78424be 100644 --- a/src/coreclr/src/vm/methodtablebuilder.inl +++ b/src/coreclr/src/vm/methodtablebuilder.inl @@ -15,7 +15,10 @@ //*************************************************************************************** inline MethodTableBuilder::DeclaredMethodIterator::DeclaredMethodIterator( - MethodTableBuilder &mtb) : m_mtb(mtb), m_idx(-1) + MethodTableBuilder &mtb) : + m_numDeclaredMethods((int)mtb.NumDeclaredMethods()), + m_declaredMethods(mtb.bmtMethod->m_rgDeclaredMethods), + m_idx(-1) { LIMITED_METHOD_CONTRACT; } @@ -24,7 +27,7 @@ inline MethodTableBuilder::DeclaredMethodIterator::DeclaredMethodIterator( inline int MethodTableBuilder::DeclaredMethodIterator::CurrentIndex() { LIMITED_METHOD_CONTRACT; - CONSISTENCY_CHECK_MSG(0 <= m_idx && m_idx < (int)m_mtb.NumDeclaredMethods(), + CONSISTENCY_CHECK_MSG(0 <= m_idx && m_idx < m_numDeclaredMethods, "Invalid iterator state."); return m_idx; } @@ -33,7 +36,7 @@ inline int MethodTableBuilder::DeclaredMethodIterator::CurrentIndex() inline BOOL MethodTableBuilder::DeclaredMethodIterator::Next() { LIMITED_METHOD_CONTRACT; - if (m_idx + 1 >= (int)m_mtb.NumDeclaredMethods()) + if (m_idx + 1 >= m_numDeclaredMethods) return FALSE; m_idx++; INDEBUG(m_debug_pMethod = GetMDMethod();) @@ -55,7 +58,7 @@ inline BOOL MethodTableBuilder::DeclaredMethodIterator::Prev() inline void MethodTableBuilder::DeclaredMethodIterator::ResetToEnd() { LIMITED_METHOD_CONTRACT; - m_idx = (int)m_mtb.NumDeclaredMethods(); + m_idx = m_numDeclaredMethods; } //*************************************************************************************** @@ -130,7 +133,7 @@ MethodTableBuilder::DeclaredMethodIterator::GetMDMethod() const { LIMITED_METHOD_CONTRACT; _ASSERTE(FitsIn(m_idx)); // Review: m_idx should probably _be_ a SLOT_INDEX, but that asserts. - return (*m_mtb.bmtMethod)[static_cast(m_idx)]; + return m_declaredMethods[m_idx]; } //******************************************************************************* diff --git a/src/coreclr/src/vm/siginfo.cpp b/src/coreclr/src/vm/siginfo.cpp index ba2906f..61bbbb8 100644 --- a/src/coreclr/src/vm/siginfo.cpp +++ b/src/coreclr/src/vm/siginfo.cpp @@ -1288,7 +1288,7 @@ TypeHandle SigPointer::GetTypeHandleThrowing( pGenericTypeModule = pModule; } - TypeHandle genericType = psig.GetGenericInstType(pModule, fLoadTypes, level, pZapSigContext); + TypeHandle genericType = psig.GetGenericInstType(pModule, fLoadTypes, level < CLASS_LOAD_APPROXPARENTS ? level : CLASS_LOAD_APPROXPARENTS, pZapSigContext); if (genericType.IsNull()) {