Skip to content

Commit d228238

Browse files
Change MethodDesc::GetLoaderModule and MethodDesc::GetLoaderAllocator into O(1) operations (#106212)
- Today these are dependent on calling into `ClassLoader::ComputerLoaderModule`, which can be a very complex operation, and always requires walking all of the method's instantiation arguments. - This change makes puts a pointer to the Loader Module onto the `MethodDescChunk` and removes the need for running the potentially complex `ComputeLoaderModule` algorithm.
1 parent ca4000c commit d228238

File tree

3 files changed

+60
-23
lines changed

3 files changed

+60
-23
lines changed

src/coreclr/vm/genmeth.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363

6464
// Helper method that creates a method-desc off a template method desc
6565
static MethodDesc* CreateMethodDesc(LoaderAllocator *pAllocator,
66+
Module* pLoaderModule,
6667
MethodTable *pMT,
6768
MethodDesc *pTemplateMD,
6869
DWORD classification,
@@ -91,7 +92,8 @@ static MethodDesc* CreateMethodDesc(LoaderAllocator *pAllocator,
9192
TRUE /* fNonVtableSlot*/,
9293
fNativeCodeSlot,
9394
pMT,
94-
pamTracker);
95+
pamTracker,
96+
pLoaderModule);
9597

9698
// Now initialize the MDesc at the single method descriptor in
9799
// the new chunk
@@ -415,6 +417,7 @@ InstantiatedMethodDesc::NewInstantiatedMethodDesc(MethodTable *pExactMT,
415417
// used in some of the subsequent setup methods for method descs.
416418
//
417419
pNewMD = (InstantiatedMethodDesc*) (CreateMethodDesc(pAllocator,
420+
pExactMDLoaderModule,
418421
pExactMT,
419422
pGenericMDescInRepMT,
420423
mcInstantiated,
@@ -894,6 +897,7 @@ MethodDesc::FindOrCreateAssociatedMethodDesc(MethodDesc* pDefMD,
894897
AllocMemTracker amt;
895898

896899
pResultMD = CreateMethodDesc(pAllocator,
900+
pLoaderModule,
897901
pRepMT,
898902
pMDescInCanonMT,
899903
mcInstantiated,
@@ -975,6 +979,7 @@ MethodDesc::FindOrCreateAssociatedMethodDesc(MethodDesc* pDefMD,
975979
_ASSERTE(pDefMD->GetClassification() == mcInstantiated);
976980

977981
pResultMD = CreateMethodDesc(pAllocator,
982+
pLoaderModule,
978983
pExactMT,
979984
pNonUnboxingStub,
980985
mcInstantiated,

src/coreclr/vm/method.cpp

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,20 @@ DWORD MethodDesc::GetImplAttrs()
15061506
return props;
15071507
}
15081508

1509+
PTR_Module MethodDescChunk::GetLoaderModule()
1510+
{
1511+
LIMITED_METHOD_DAC_CONTRACT;
1512+
if (IsLoaderModuleAttachedToChunk())
1513+
{
1514+
TADDR ppLoaderModule = dac_cast<TADDR>(this) + SizeOf() - sizeof(PTR_Module);
1515+
return *dac_cast<DPTR(PTR_Module)>(ppLoaderModule);
1516+
}
1517+
else
1518+
{
1519+
return GetMethodTable()->GetLoaderModule();
1520+
}
1521+
}
1522+
15091523
//*******************************************************************************
15101524
Module* MethodDesc::GetLoaderModule()
15111525
{
@@ -1517,17 +1531,24 @@ Module* MethodDesc::GetLoaderModule()
15171531
}
15181532
CONTRACTL_END;
15191533

1534+
Module* pLoaderModule = GetMethodDescChunk()->GetLoaderModule();
1535+
1536+
#ifdef _DEBUG
1537+
// Verify that the LoaderModule stored in the MethodDescChunk matches the result achieved by computation
15201538
if (HasMethodInstantiation() && !IsGenericMethodDefinition())
15211539
{
1522-
Module *retVal = ClassLoader::ComputeLoaderModule(GetMethodTable(),
1540+
Module *computeLoaderModuleAlgorithmResult = ClassLoader::ComputeLoaderModule(GetMethodTable(),
15231541
GetMemberDef(),
15241542
GetMethodInstantiation());
1525-
return retVal;
1543+
_ASSERTE(computeLoaderModuleAlgorithmResult == pLoaderModule);
15261544
}
15271545
else
15281546
{
1529-
return GetMethodTable()->GetLoaderModule();
1547+
_ASSERTE(pLoaderModule == GetMethodTable()->GetLoaderModule());
15301548
}
1549+
#endif // _DEBUG
1550+
1551+
return pLoaderModule;
15311552
}
15321553

15331554
//*******************************************************************************
@@ -1845,7 +1866,7 @@ MethodDesc* MethodDesc::StripMethodInstantiation()
18451866

18461867
//*******************************************************************************
18471868
MethodDescChunk *MethodDescChunk::CreateChunk(LoaderHeap *pHeap, DWORD methodDescCount,
1848-
DWORD classification, BOOL fNonVtableSlot, BOOL fNativeCodeSlot, MethodTable *pInitialMT, AllocMemTracker *pamTracker)
1869+
DWORD classification, BOOL fNonVtableSlot, BOOL fNativeCodeSlot, MethodTable *pInitialMT, AllocMemTracker *pamTracker, Module *pLoaderModule)
18491870
{
18501871
CONTRACT(MethodDescChunk *)
18511872
{
@@ -1878,18 +1899,28 @@ MethodDescChunk *MethodDescChunk::CreateChunk(LoaderHeap *pHeap, DWORD methodDes
18781899

18791900
MethodDescChunk * pFirstChunk = NULL;
18801901

1902+
bool needsExplicitLoaderModule = false;
1903+
if (pLoaderModule != NULL && pLoaderModule != pInitialMT->GetLoaderModule())
1904+
{
1905+
needsExplicitLoaderModule = true;
1906+
}
1907+
18811908
do
18821909
{
18831910
DWORD count = min(methodDescCount, maxMethodDescsPerChunk);
18841911

18851912
void * pMem = pamTracker->Track(
1886-
pHeap->AllocMem(S_SIZE_T(sizeof(MethodDescChunk) + oneSize * count)));
1913+
pHeap->AllocMem(S_SIZE_T(sizeof(MethodDescChunk) + oneSize * count + (needsExplicitLoaderModule ? sizeof(Module *) : 0))));
18871914

18881915
// Skip pointer to temporary entrypoints
18891916
MethodDescChunk * pChunk = (MethodDescChunk *)((BYTE*)pMem);
18901917

18911918
pChunk->SetSizeAndCount(oneSize * count, count);
18921919
pChunk->SetMethodTable(pInitialMT);
1920+
if (needsExplicitLoaderModule)
1921+
{
1922+
pChunk->SetLoaderModuleAttachedToChunk(pLoaderModule);
1923+
}
18931924

18941925
MethodDesc * pMD = pChunk->GetFirstMethodDesc();
18951926
for (DWORD i = 0; i < count; i++)

src/coreclr/vm/method.hpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,8 +1001,6 @@ class MethodDesc
10011001

10021002
inline PTR_MethodTable GetMethodTable() const;
10031003

1004-
inline DPTR(PTR_MethodTable) GetMethodTablePtr() const;
1005-
10061004
public:
10071005
inline MethodDescChunk* GetMethodDescChunk() const;
10081006
inline int GetMethodDescChunkIndex() const;
@@ -2214,7 +2212,8 @@ class MethodDescChunk
22142212
// and for the logic that splits the token to be algorithmically generated based on the
22152213
// #define
22162214
enum_flag_DeterminedIsEligibleForTieredCompilation = 0x4000, // Has this chunk had its methods been determined eligible for tiered compilation or not
2217-
// unused = 0x8000,
2215+
enum_flag_LoaderModuleAttachedToChunk = 0x8000, // Is this chunk associated with a LoaderModule directly? If this flag is set, then the
2216+
// LoaderModule pointer is placed at the end of the chunk.
22182217
};
22192218

22202219
#ifndef DACCESS_COMPILE
@@ -2231,7 +2230,8 @@ class MethodDescChunk
22312230
BOOL fNonVtableSlot,
22322231
BOOL fNativeCodeSlot,
22332232
MethodTable *initialMT,
2234-
class AllocMemTracker *pamTracker);
2233+
class AllocMemTracker *pamTracker,
2234+
Module* pLoaderModule = NULL);
22352235

22362236
bool DeterminedIfMethodsAreEligibleForTieredCompilation()
22372237
{
@@ -2247,10 +2247,13 @@ class MethodDescChunk
22472247
return m_methodTable;
22482248
}
22492249

2250-
inline DPTR(PTR_MethodTable) GetMethodTablePtr() const
2250+
public:
2251+
PTR_Module GetLoaderModule();
2252+
2253+
inline bool IsLoaderModuleAttachedToChunk() const
22512254
{
22522255
LIMITED_METHOD_DAC_CONTRACT;
2253-
return dac_cast<DPTR(PTR_MethodTable)>(PTR_HOST_MEMBER_TADDR(MethodDescChunk, this, m_methodTable));
2256+
return (m_flagsAndTokenRange & enum_flag_LoaderModuleAttachedToChunk) != 0;
22542257
}
22552258

22562259
#ifndef DACCESS_COMPILE
@@ -2280,6 +2283,13 @@ class MethodDescChunk
22802283
LIMITED_METHOD_CONTRACT;
22812284
m_next = chunk;
22822285
}
2286+
2287+
void SetLoaderModuleAttachedToChunk(Module* pModule)
2288+
{
2289+
m_flagsAndTokenRange |= enum_flag_LoaderModuleAttachedToChunk;
2290+
TADDR ppLoaderModule = dac_cast<TADDR>(this) + SizeOf() - sizeof(PTR_Module);
2291+
*(Module**)ppLoaderModule = pModule;
2292+
}
22832293
#endif // !DACCESS_COMPILE
22842294

22852295
PTR_MethodDescChunk GetNextChunk()
@@ -2300,10 +2310,10 @@ class MethodDescChunk
23002310
return m_flagsAndTokenRange & enum_flag_TokenRangeMask;
23012311
}
23022312

2303-
inline SIZE_T SizeOf()
2313+
inline SIZE_T SizeOf() const
23042314
{
23052315
LIMITED_METHOD_DAC_CONTRACT;
2306-
return sizeof(MethodDescChunk) + (m_size + 1) * MethodDesc::ALIGNMENT;
2316+
return sizeof(MethodDescChunk) + (m_size + 1) * MethodDesc::ALIGNMENT + (IsLoaderModuleAttachedToChunk() ? sizeof(PTR_Module) : 0);
23072317
}
23082318

23092319
inline MethodDesc *GetFirstMethodDesc()
@@ -3430,15 +3440,6 @@ inline PTR_MethodTable MethodDesc::GetMethodTable() const
34303440
return pChunk->GetMethodTable();
34313441
}
34323442

3433-
inline DPTR(PTR_MethodTable) MethodDesc::GetMethodTablePtr() const
3434-
{
3435-
LIMITED_METHOD_DAC_CONTRACT;
3436-
3437-
MethodDescChunk *pChunk = GetMethodDescChunk();
3438-
PREFIX_ASSUME(pChunk != NULL);
3439-
return pChunk->GetMethodTablePtr();
3440-
}
3441-
34423443
inline MethodTable* MethodDesc::GetCanonicalMethodTable()
34433444
{
34443445
LIMITED_METHOD_DAC_CONTRACT;

0 commit comments

Comments
 (0)