diff --git a/src/coreclr/vm/genmeth.cpp b/src/coreclr/vm/genmeth.cpp index 64394585c8fc3..af6c53ee9d9bc 100644 --- a/src/coreclr/vm/genmeth.cpp +++ b/src/coreclr/vm/genmeth.cpp @@ -63,6 +63,7 @@ // Helper method that creates a method-desc off a template method desc static MethodDesc* CreateMethodDesc(LoaderAllocator *pAllocator, + Module* pLoaderModule, MethodTable *pMT, MethodDesc *pTemplateMD, DWORD classification, @@ -91,7 +92,8 @@ static MethodDesc* CreateMethodDesc(LoaderAllocator *pAllocator, TRUE /* fNonVtableSlot*/, fNativeCodeSlot, pMT, - pamTracker); + pamTracker, + pLoaderModule); // Now initialize the MDesc at the single method descriptor in // the new chunk @@ -415,6 +417,7 @@ InstantiatedMethodDesc::NewInstantiatedMethodDesc(MethodTable *pExactMT, // used in some of the subsequent setup methods for method descs. // pNewMD = (InstantiatedMethodDesc*) (CreateMethodDesc(pAllocator, + pExactMDLoaderModule, pExactMT, pGenericMDescInRepMT, mcInstantiated, @@ -894,6 +897,7 @@ MethodDesc::FindOrCreateAssociatedMethodDesc(MethodDesc* pDefMD, AllocMemTracker amt; pResultMD = CreateMethodDesc(pAllocator, + pLoaderModule, pRepMT, pMDescInCanonMT, mcInstantiated, @@ -975,6 +979,7 @@ MethodDesc::FindOrCreateAssociatedMethodDesc(MethodDesc* pDefMD, _ASSERTE(pDefMD->GetClassification() == mcInstantiated); pResultMD = CreateMethodDesc(pAllocator, + pLoaderModule, pExactMT, pNonUnboxingStub, mcInstantiated, diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index d8313fdc96516..a6c3326a74feb 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -1506,6 +1506,20 @@ DWORD MethodDesc::GetImplAttrs() return props; } +PTR_Module MethodDescChunk::GetLoaderModule() +{ + LIMITED_METHOD_DAC_CONTRACT; + if (IsLoaderModuleAttachedToChunk()) + { + TADDR ppLoaderModule = dac_cast(this) + SizeOf() - sizeof(PTR_Module); + return *dac_cast(ppLoaderModule); + } + else + { + return GetMethodTable()->GetLoaderModule(); + } +} + //******************************************************************************* Module* MethodDesc::GetLoaderModule() { @@ -1517,17 +1531,24 @@ Module* MethodDesc::GetLoaderModule() } CONTRACTL_END; + Module* pLoaderModule = GetMethodDescChunk()->GetLoaderModule(); + +#ifdef _DEBUG + // Verify that the LoaderModule stored in the MethodDescChunk matches the result achieved by computation if (HasMethodInstantiation() && !IsGenericMethodDefinition()) { - Module *retVal = ClassLoader::ComputeLoaderModule(GetMethodTable(), + Module *computeLoaderModuleAlgorithmResult = ClassLoader::ComputeLoaderModule(GetMethodTable(), GetMemberDef(), GetMethodInstantiation()); - return retVal; + _ASSERTE(computeLoaderModuleAlgorithmResult == pLoaderModule); } else { - return GetMethodTable()->GetLoaderModule(); + _ASSERTE(pLoaderModule == GetMethodTable()->GetLoaderModule()); } +#endif // _DEBUG + + return pLoaderModule; } //******************************************************************************* @@ -1845,7 +1866,7 @@ MethodDesc* MethodDesc::StripMethodInstantiation() //******************************************************************************* MethodDescChunk *MethodDescChunk::CreateChunk(LoaderHeap *pHeap, DWORD methodDescCount, - DWORD classification, BOOL fNonVtableSlot, BOOL fNativeCodeSlot, MethodTable *pInitialMT, AllocMemTracker *pamTracker) + DWORD classification, BOOL fNonVtableSlot, BOOL fNativeCodeSlot, MethodTable *pInitialMT, AllocMemTracker *pamTracker, Module *pLoaderModule) { CONTRACT(MethodDescChunk *) { @@ -1878,18 +1899,28 @@ MethodDescChunk *MethodDescChunk::CreateChunk(LoaderHeap *pHeap, DWORD methodDes MethodDescChunk * pFirstChunk = NULL; + bool needsExplicitLoaderModule = false; + if (pLoaderModule != NULL && pLoaderModule != pInitialMT->GetLoaderModule()) + { + needsExplicitLoaderModule = true; + } + do { DWORD count = min(methodDescCount, maxMethodDescsPerChunk); void * pMem = pamTracker->Track( - pHeap->AllocMem(S_SIZE_T(sizeof(MethodDescChunk) + oneSize * count))); + pHeap->AllocMem(S_SIZE_T(sizeof(MethodDescChunk) + oneSize * count + (needsExplicitLoaderModule ? sizeof(Module *) : 0)))); // Skip pointer to temporary entrypoints MethodDescChunk * pChunk = (MethodDescChunk *)((BYTE*)pMem); pChunk->SetSizeAndCount(oneSize * count, count); pChunk->SetMethodTable(pInitialMT); + if (needsExplicitLoaderModule) + { + pChunk->SetLoaderModuleAttachedToChunk(pLoaderModule); + } MethodDesc * pMD = pChunk->GetFirstMethodDesc(); for (DWORD i = 0; i < count; i++) diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index 628eb39864b7e..10d02201a75ea 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -1001,8 +1001,6 @@ class MethodDesc inline PTR_MethodTable GetMethodTable() const; - inline DPTR(PTR_MethodTable) GetMethodTablePtr() const; - public: inline MethodDescChunk* GetMethodDescChunk() const; inline int GetMethodDescChunkIndex() const; @@ -2214,7 +2212,8 @@ class MethodDescChunk // and for the logic that splits the token to be algorithmically generated based on the // #define enum_flag_DeterminedIsEligibleForTieredCompilation = 0x4000, // Has this chunk had its methods been determined eligible for tiered compilation or not - // unused = 0x8000, + enum_flag_LoaderModuleAttachedToChunk = 0x8000, // Is this chunk associated with a LoaderModule directly? If this flag is set, then the + // LoaderModule pointer is placed at the end of the chunk. }; #ifndef DACCESS_COMPILE @@ -2231,7 +2230,8 @@ class MethodDescChunk BOOL fNonVtableSlot, BOOL fNativeCodeSlot, MethodTable *initialMT, - class AllocMemTracker *pamTracker); + class AllocMemTracker *pamTracker, + Module* pLoaderModule = NULL); bool DeterminedIfMethodsAreEligibleForTieredCompilation() { @@ -2247,10 +2247,13 @@ class MethodDescChunk return m_methodTable; } - inline DPTR(PTR_MethodTable) GetMethodTablePtr() const +public: + PTR_Module GetLoaderModule(); + + inline bool IsLoaderModuleAttachedToChunk() const { LIMITED_METHOD_DAC_CONTRACT; - return dac_cast(PTR_HOST_MEMBER_TADDR(MethodDescChunk, this, m_methodTable)); + return (m_flagsAndTokenRange & enum_flag_LoaderModuleAttachedToChunk) != 0; } #ifndef DACCESS_COMPILE @@ -2280,6 +2283,13 @@ class MethodDescChunk LIMITED_METHOD_CONTRACT; m_next = chunk; } + + void SetLoaderModuleAttachedToChunk(Module* pModule) + { + m_flagsAndTokenRange |= enum_flag_LoaderModuleAttachedToChunk; + TADDR ppLoaderModule = dac_cast(this) + SizeOf() - sizeof(PTR_Module); + *(Module**)ppLoaderModule = pModule; + } #endif // !DACCESS_COMPILE PTR_MethodDescChunk GetNextChunk() @@ -2300,10 +2310,10 @@ class MethodDescChunk return m_flagsAndTokenRange & enum_flag_TokenRangeMask; } - inline SIZE_T SizeOf() + inline SIZE_T SizeOf() const { LIMITED_METHOD_DAC_CONTRACT; - return sizeof(MethodDescChunk) + (m_size + 1) * MethodDesc::ALIGNMENT; + return sizeof(MethodDescChunk) + (m_size + 1) * MethodDesc::ALIGNMENT + (IsLoaderModuleAttachedToChunk() ? sizeof(PTR_Module) : 0); } inline MethodDesc *GetFirstMethodDesc() @@ -3430,15 +3440,6 @@ inline PTR_MethodTable MethodDesc::GetMethodTable() const return pChunk->GetMethodTable(); } -inline DPTR(PTR_MethodTable) MethodDesc::GetMethodTablePtr() const -{ - LIMITED_METHOD_DAC_CONTRACT; - - MethodDescChunk *pChunk = GetMethodDescChunk(); - PREFIX_ASSUME(pChunk != NULL); - return pChunk->GetMethodTablePtr(); -} - inline MethodTable* MethodDesc::GetCanonicalMethodTable() { LIMITED_METHOD_DAC_CONTRACT;