Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/inc/CrstTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -709,3 +709,7 @@ Crst MethodDescBackpatchInfoTracker
AcquiredBefore FuncPtrStubs ThreadStore SystemDomain
AcquiredAfter ReJITGlobalRequest
End

Crst StubMethodInfoCache
AcquiredBefore AppDomainHandleTable LoaderAllocator
End
55 changes: 29 additions & 26 deletions src/inc/crsttypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,32 +144,33 @@ enum CrstType
CrstStrongName = 125,
CrstStubCache = 126,
CrstStubDispatchCache = 127,
CrstStubUnwindInfoHeapSegments = 128,
CrstSyncBlockCache = 129,
CrstSyncHashLock = 130,
CrstSystemBaseDomain = 131,
CrstSystemDomain = 132,
CrstSystemDomainDelayedUnloadList = 133,
CrstThreadIdDispenser = 134,
CrstThreadpoolEventCache = 135,
CrstThreadpoolTimerQueue = 136,
CrstThreadpoolWaitThreads = 137,
CrstThreadpoolWorker = 138,
CrstThreadStaticDataHashTable = 139,
CrstThreadStore = 140,
CrstTieredCompilation = 141,
CrstTPMethodTable = 142,
CrstTypeEquivalenceMap = 143,
CrstTypeIDMap = 144,
CrstUMEntryThunkCache = 145,
CrstUMThunkHash = 146,
CrstUniqueStack = 147,
CrstUnresolvedClassLock = 148,
CrstUnwindInfoTableLock = 149,
CrstVSDIndirectionCellLock = 150,
CrstWinRTFactoryCache = 151,
CrstWrapperTemplate = 152,
kNumberOfCrstTypes = 153
CrstStubMethodInfoCache = 128,
CrstStubUnwindInfoHeapSegments = 129,
CrstSyncBlockCache = 130,
CrstSyncHashLock = 131,
CrstSystemBaseDomain = 132,
CrstSystemDomain = 133,
CrstSystemDomainDelayedUnloadList = 134,
CrstThreadIdDispenser = 135,
CrstThreadpoolEventCache = 136,
CrstThreadpoolTimerQueue = 137,
CrstThreadpoolWaitThreads = 138,
CrstThreadpoolWorker = 139,
CrstThreadStaticDataHashTable = 140,
CrstThreadStore = 141,
CrstTieredCompilation = 142,
CrstTPMethodTable = 143,
CrstTypeEquivalenceMap = 144,
CrstTypeIDMap = 145,
CrstUMEntryThunkCache = 146,
CrstUMThunkHash = 147,
CrstUniqueStack = 148,
CrstUnresolvedClassLock = 149,
CrstUnwindInfoTableLock = 150,
CrstVSDIndirectionCellLock = 151,
CrstWinRTFactoryCache = 152,
CrstWrapperTemplate = 153,
kNumberOfCrstTypes = 154
};

#endif // __CRST_TYPES_INCLUDED
Expand Down Expand Up @@ -308,6 +309,7 @@ int g_rgCrstLevelMap[] =
0, // CrstStrongName
5, // CrstStubCache
0, // CrstStubDispatchCache
15, // CrstStubMethodInfoCache
4, // CrstStubUnwindInfoHeapSegments
3, // CrstSyncBlockCache
0, // CrstSyncHashLock
Expand Down Expand Up @@ -466,6 +468,7 @@ LPCSTR g_rgCrstNameMap[] =
"CrstStrongName",
"CrstStubCache",
"CrstStubDispatchCache",
"CrstStubMethodInfoCache",
"CrstStubUnwindInfoHeapSegments",
"CrstSyncBlockCache",
"CrstSyncHashLock",
Expand Down
43 changes: 43 additions & 0 deletions src/vm/loaderallocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,41 @@ void LoaderAllocator::ActivateManagedTracking()
LOADERALLOCATORREF loaderAllocator = (LOADERALLOCATORREF)ObjectFromHandle(m_hLoaderAllocatorObjectHandle);
loaderAllocator->SetNativeLoaderAllocator(this);
}

REFLECTMETHODREF LoaderAllocator::GetStubMethodInfoForMethodDesc(MethodDesc* pMT)
{
CONTRACTL
{
THROWS;
GC_TRIGGERS;
INJECT_FAULT(COMPlusThrowOM());
MODE_COOPERATIVE;
}
CONTRACTL_END;

CrstHolder holder(&m_stubMethodInfoCacheCrst);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Putting a Crst here adds possible thread contention to an api which was previously effectively lock free.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead, I would do the lookup without the lock, then take the lock, lookup again, and then add. Both the SHash infrastructure and HashMap are supposed to be able to do this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SHash does not support lock-free reads.


UPTR value = m_stubMethodInfoCache.Gethash((UPTR)pMT);

if (value != INVALIDENTRY)
{
return (REFLECTMETHODREF)GetHandleValue((LOADERHANDLE)value);
}

REFLECTMETHODREF retVal;
REFLECTMETHODREF methodRef = (REFLECTMETHODREF)AllocateObject(MscorlibBinder::GetClass(CLASS__STUBMETHODINFO));
GCPROTECT_BEGIN(methodRef);

methodRef->SetMethod(pMT);
if (IsCollectible())
methodRef->SetKeepAlive(GetExposedObject());

m_stubMethodInfoCache.InsertValue((UPTR)pMT, (UPTR)AllocateHandle(methodRef));
retVal = methodRef;
GCPROTECT_END();

return retVal;
}
#endif // !CROSSGEN_COMPILE


Expand All @@ -1061,6 +1096,7 @@ void LoaderAllocator::Init(BaseDomain *pDomain, BYTE *pExecutableHeapMemory)

m_crstLoaderAllocator.Init(CrstLoaderAllocator, (CrstFlags)CRST_UNSAFE_COOPGC);
m_InteropDataCrst.Init(CrstInteropData, CRST_REENTRANCY);
m_stubMethodInfoCacheCrst.Init(CrstStubMethodInfoCache);
#ifdef FEATURE_COMINTEROP
m_ComCallWrapperCrst.Init(CrstCOMCallWrapper);
#endif
Expand Down Expand Up @@ -1219,6 +1255,12 @@ void LoaderAllocator::Init(BaseDomain *pDomain, BYTE *pExecutableHeapMemory)
m_interopDataHash.Init(0, NULL, false, &lock);
}
#endif // FEATURE_COMINTEROP

// Init the StubMethodInfo Cache
{
LockOwner lock = { &m_stubMethodInfoCacheCrst, IsOwnerOfCrst };
m_stubMethodInfoCache.Init(0, (CompareFnPtr)nullptr, false, &lock);
}
}


Expand Down Expand Up @@ -1330,6 +1372,7 @@ void LoaderAllocator::Terminate()
m_ComCallWrapperCrst.Destroy();
m_InteropDataCrst.Destroy();
#endif
m_stubMethodInfoCacheCrst.Destroy();
m_LoaderAllocatorReferences.RemoveAll();

// In collectible types we merge the low frequency and high frequency heaps
Expand Down
6 changes: 6 additions & 0 deletions src/vm/loaderallocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,10 @@ class LoaderAllocator
CrstExplicitInit m_InteropDataCrst;
EEMarshalingData* m_pMarshalingData;

// Used for synchronizing access to m_stubMethodInfoCache.
CrstExplicitInit m_stubMethodInfoCacheCrst;
HashMap m_stubMethodInfoCache;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use HashMap directly for holding pointers. Per the comments on the PtrHashMap implementation, you should never put use a pointer as a key in a HashMap, you should always use a PtrHashMap. Of course, you can't safely store a LOADERHANDLE in a PtrHashMap, as it requires the low bit to be null on values. Instead I recommend you use a MapSHash.


#ifdef FEATURE_TIERED_COMPILATION
CallCounter m_callCounter;
#endif
Expand Down Expand Up @@ -492,6 +496,8 @@ class LoaderAllocator

OBJECTREF GetHandleValue(LOADERHANDLE handle);

REFLECTMETHODREF GetStubMethodInfoForMethodDesc(MethodDesc* pMD);

LoaderAllocator();
virtual ~LoaderAllocator();
BaseDomain *GetDomain() { LIMITED_METHOD_CONTRACT; return m_pDomain; }
Expand Down
23 changes: 2 additions & 21 deletions src/vm/method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5574,28 +5574,9 @@ PTR_LoaderAllocator MethodDesc::GetLoaderAllocator()
#if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
REFLECTMETHODREF MethodDesc::GetStubMethodInfo()
{
CONTRACTL
{
THROWS;
GC_TRIGGERS;
INJECT_FAULT(COMPlusThrowOM());
MODE_COOPERATIVE;
}
CONTRACTL_END;

REFLECTMETHODREF retVal;
REFLECTMETHODREF methodRef = (REFLECTMETHODREF)AllocateObject(MscorlibBinder::GetClass(CLASS__STUBMETHODINFO));
GCPROTECT_BEGIN(methodRef);

methodRef->SetMethod(this);
LoaderAllocator *pLoaderAllocatorOfMethod = this->GetLoaderAllocator();
if (pLoaderAllocatorOfMethod->IsCollectible())
methodRef->SetKeepAlive(pLoaderAllocatorOfMethod->GetExposedObject());

retVal = methodRef;
GCPROTECT_END();
WRAPPER_NO_CONTRACT;

return retVal;
return GetLoaderAllocator()->GetStubMethodInfoForMethodDesc(this);
}
#endif // !DACCESS_COMPILE && CROSSGEN_COMPILE

Expand Down