Skip to content

Commit 603dac4

Browse files
authored
Stop using DomainAssemblyCache for unmanaged image cache used by p/invokes (#51704)
1 parent a73dbd2 commit 603dac4

File tree

4 files changed

+45
-234
lines changed

4 files changed

+45
-234
lines changed

src/coreclr/vm/appdomain.cpp

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -679,8 +679,6 @@ void BaseDomain::Init()
679679
m_DomainCacheCrst.Init(CrstAppDomainCache);
680680
m_DomainLocalBlockCrst.Init(CrstDomainLocalBlock);
681681

682-
m_InteropDataCrst.Init(CrstInteropData, CRST_REENTRANCY);
683-
684682
// NOTE: CRST_UNSAFE_COOPGC prevents a GC mode switch to preemptive when entering this crst.
685683
// If you remove this flag, we will switch to preemptive mode when entering
686684
// m_FileLoadLock, which means all functions that enter it will become
@@ -716,12 +714,6 @@ void BaseDomain::Init()
716714
m_pMngStdInterfacesInfo = new MngStdInterfacesInfo();
717715
#endif // FEATURE_COMINTEROP
718716

719-
// Init the COM Interop data hash
720-
{
721-
LockOwner lock = {&m_InteropDataCrst, IsOwnerOfCrst};
722-
m_interopDataHash.Init(0, NULL, false, &lock);
723-
}
724-
725717
m_dwSizedRefHandles = 0;
726718
if (!m_iNumberOfProcessors)
727719
{
@@ -2210,9 +2202,8 @@ void AppDomain::Init()
22102202

22112203
BaseDomain::Init();
22122204

2213-
// Set up the binding caches
2205+
// Set up the binding caches
22142206
m_AssemblyCache.Init(&m_DomainCacheCrst, GetHighFrequencyHeap());
2215-
m_UnmanagedCache.InitializeTable(this, &m_DomainCacheCrst);
22162207

22172208
m_MemoryPressure = 0;
22182209

@@ -3778,39 +3769,50 @@ void AppDomain::AddUnmanagedImageToCache(LPCWSTR libraryName, NATIVE_LIBRARY_HAN
37783769
CONTRACTL
37793770
{
37803771
THROWS;
3781-
GC_TRIGGERS;
3772+
GC_NOTRIGGER;
37823773
MODE_ANY;
37833774
PRECONDITION(CheckPointer(libraryName));
3775+
PRECONDITION(CheckPointer(hMod));
37843776
INJECT_FAULT(COMPlusThrowOM(););
37853777
}
37863778
CONTRACTL_END;
3787-
if (libraryName)
3779+
3780+
CrstHolder lock(&m_DomainCacheCrst);
3781+
3782+
const UnmanagedImageCacheEntry *existingEntry = m_unmanagedCache.LookupPtr(libraryName);
3783+
if (existingEntry != NULL)
37883784
{
3789-
AssemblySpec spec;
3790-
spec.SetCodeBase(libraryName);
3791-
m_UnmanagedCache.InsertEntry(&spec, hMod);
3785+
_ASSERTE(existingEntry->Handle == hMod);
3786+
return;
37923787
}
3793-
return ;
3794-
}
37953788

3789+
size_t len = (wcslen(libraryName) + 1) * sizeof(WCHAR);
3790+
AllocMemHolder<WCHAR> copiedName(GetLowFrequencyHeap()->AllocMem(S_SIZE_T(len)));
3791+
memcpy(copiedName, libraryName, len);
3792+
3793+
m_unmanagedCache.Add(UnmanagedImageCacheEntry{ copiedName, hMod });
3794+
copiedName.SuppressRelease();
3795+
}
37963796

37973797
NATIVE_LIBRARY_HANDLE AppDomain::FindUnmanagedImageInCache(LPCWSTR libraryName)
37983798
{
37993799
CONTRACT(NATIVE_LIBRARY_HANDLE)
38003800
{
38013801
THROWS;
3802-
GC_TRIGGERS;
3802+
GC_NOTRIGGER;
38033803
MODE_ANY;
3804-
PRECONDITION(CheckPointer(libraryName,NULL_OK));
3804+
PRECONDITION(CheckPointer(libraryName));
38053805
POSTCONDITION(CheckPointer(RETVAL,NULL_OK));
38063806
INJECT_FAULT(COMPlusThrowOM(););
38073807
}
38083808
CONTRACT_END;
3809-
if(libraryName == NULL) RETURN NULL;
38103809

3811-
AssemblySpec spec;
3812-
spec.SetCodeBase(libraryName);
3813-
RETURN (NATIVE_LIBRARY_HANDLE) m_UnmanagedCache.LookupEntry(&spec, 0);
3810+
CrstHolder lock(&m_DomainCacheCrst);
3811+
const UnmanagedImageCacheEntry *existingEntry = m_unmanagedCache.LookupPtr(libraryName);
3812+
if (existingEntry == NULL)
3813+
RETURN NULL;
3814+
3815+
RETURN existingEntry->Handle;
38143816
}
38153817

38163818
BOOL AppDomain::RemoveFileFromCache(PEAssembly *pFile)

src/coreclr/vm/appdomain.hpp

Lines changed: 20 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,15 @@ class BaseDomain;
4141
class SystemDomain;
4242
class AppDomain;
4343
class CompilationDomain;
44-
class AppDomainEnum;
45-
class AssemblySink;
46-
class EEMarshalingData;
4744
class GlobalStringLiteralMap;
4845
class StringLiteralMap;
4946
class MngStdInterfacesInfo;
50-
class DomainModule;
5147
class DomainAssembly;
52-
struct InteropMethodTableData;
5348
class LoadLevelLimiter;
5449
class TypeEquivalenceHashTable;
55-
class StringArrayList;
5650

5751
#ifdef FEATURE_COMINTEROP
58-
class ComCallWrapperCache;
59-
struct SimpleComCallWrapper;
52+
class RCWCache;
6053
class RCWRefCache;
6154
#endif // FEATURE_COMINTEROP
6255

@@ -68,13 +61,6 @@ class RCWRefCache;
6861

6962
GPTR_DECL(IdDispenser, g_pModuleIndexDispenser);
7063

71-
// This enum is aligned to System.ExceptionCatcherType.
72-
enum ExceptionCatcher {
73-
ExceptionCatcher_ManagedCode = 0,
74-
ExceptionCatcher_AppDomainTransition = 1,
75-
ExceptionCatcher_COMInterop = 2,
76-
};
77-
7864
// We would like *ALLOCATECLASS_FLAG to AV (in order to catch errors), so don't change it
7965
struct ClassInitFlags {
8066
enum
@@ -1131,17 +1117,11 @@ class BaseDomain
11311117
// Helper method to initialize the large heap handle table.
11321118
void InitPinnedHeapHandleTable();
11331119

1134-
//****************************************************************************************
1135-
//
1136-
// Hash table that maps a MethodTable to COM Interop compatibility data.
1137-
PtrHashMap m_interopDataHash;
1138-
11391120
// Critical sections & locks
11401121
PEFileListLock m_FileLoadLock; // Protects the list of assemblies in the domain
11411122
CrstExplicitInit m_DomainCrst; // General Protection for the Domain
11421123
CrstExplicitInit m_DomainCacheCrst; // Protects the Assembly and Unmanaged caches
11431124
CrstExplicitInit m_DomainLocalBlockCrst;
1144-
CrstExplicitInit m_InteropDataCrst; // Used for COM Interop compatiblilty
11451125
// Used to protect the reference lists in the collectible loader allocators attached to this appdomain
11461126
CrstExplicitInit m_crstLoaderAllocatorReferences;
11471127

@@ -1191,17 +1171,6 @@ class BaseDomain
11911171
};
11921172
friend class LockHolder;
11931173

1194-
class CacheLockHolder : public CrstHolder
1195-
{
1196-
public:
1197-
CacheLockHolder(BaseDomain *pD)
1198-
: CrstHolder(&pD->m_DomainCacheCrst)
1199-
{
1200-
WRAPPER_NO_CONTRACT;
1201-
}
1202-
};
1203-
friend class CacheLockHolder;
1204-
12051174
class DomainLocalBlockLockHolder : public CrstHolder
12061175
{
12071176
public:
@@ -1510,13 +1479,11 @@ const DWORD DefaultADID = 1;
15101479
class AppDomain : public BaseDomain
15111480
{
15121481
friend class SystemDomain;
1513-
friend class AssemblySink;
15141482
friend class AppDomainNative;
15151483
friend class AssemblyNative;
15161484
friend class AssemblySpec;
15171485
friend class ClassLoader;
15181486
friend class ThreadNative;
1519-
friend class RCWCache;
15201487
friend class ClrDataAccess;
15211488
friend class CheckAsmOffsets;
15221489

@@ -1989,9 +1956,7 @@ class AppDomain : public BaseDomain
19891956
#ifdef FEATURE_COMINTEROP
19901957
public:
19911958
OBJECTREF GetMissingObject(); // DispatchInfo will call function to retrieve the Missing.Value object.
1992-
#endif // FEATURE_COMINTEROP
19931959

1994-
#ifdef FEATURE_COMINTEROP
19951960
RCWCache *GetRCWCache()
19961961
{
19971962
WRAPPER_NO_CONTRACT;
@@ -2014,9 +1979,6 @@ class AppDomain : public BaseDomain
20141979
RCWRefCache *GetRCWRefCache();
20151980
#endif // FEATURE_COMINTEROP
20161981

2017-
//****************************************************************************************
2018-
// Get the proxy for this app domain
2019-
20201982
TPIndex GetTPIndex()
20211983
{
20221984
LIMITED_METHOD_CONTRACT;
@@ -2247,8 +2209,6 @@ class AppDomain : public BaseDomain
22472209
void AddMemoryPressure();
22482210
void RemoveMemoryPressure();
22492211

2250-
void UnlinkClass(MethodTable *pMT);
2251-
22522212
Assembly *GetRootAssembly()
22532213
{
22542214
LIMITED_METHOD_CONTRACT;
@@ -2357,13 +2317,30 @@ class AppDomain : public BaseDomain
23572317
};
23582318

23592319
AssemblySpecBindingCache m_AssemblyCache;
2360-
DomainAssemblyCache m_UnmanagedCache;
23612320
size_t m_MemoryPressure;
23622321

23632322
ArrayList m_NativeDllSearchDirectories;
23642323
bool m_ForceTrivialWaitOperations;
23652324

2366-
public:
2325+
private:
2326+
struct UnmanagedImageCacheEntry
2327+
{
2328+
LPCWSTR Name;
2329+
NATIVE_LIBRARY_HANDLE Handle;
2330+
};
2331+
2332+
class UnmanagedImageCacheTraits : public NoRemoveSHashTraits<DefaultSHashTraits<UnmanagedImageCacheEntry>>
2333+
{
2334+
public:
2335+
using key_t = LPCWSTR;
2336+
static const key_t GetKey(_In_ const element_t& e) { return e.Name; }
2337+
static count_t Hash(_In_ key_t key) { return HashString(key); }
2338+
static bool Equals(_In_ key_t lhs, _In_ key_t rhs) { return wcscmp(lhs, rhs) == 0; }
2339+
static bool IsNull(_In_ const element_t& e) { return e.Handle == NULL; }
2340+
static const element_t Null() { return UnmanagedImageCacheEntry(); }
2341+
};
2342+
2343+
SHash<UnmanagedImageCacheTraits> m_unmanagedCache;
23672344

23682345
#ifdef FEATURE_TYPEEQUIVALENCE
23692346
private:
@@ -2410,38 +2387,6 @@ class AppDomain : public BaseDomain
24102387

24112388
#endif
24122389

2413-
#ifdef FEATURE_COMINTEROP
2414-
2415-
private:
2416-
2417-
#endif //FEATURE_COMINTEROP
2418-
2419-
public:
2420-
2421-
class ComInterfaceReleaseList
2422-
{
2423-
SArray<IUnknown *> m_objects;
2424-
public:
2425-
~ComInterfaceReleaseList()
2426-
{
2427-
WRAPPER_NO_CONTRACT;
2428-
2429-
for (COUNT_T i = 0; i < m_objects.GetCount(); i++)
2430-
{
2431-
IUnknown *pItf = *(m_objects.GetElements() + i);
2432-
if (pItf != nullptr)
2433-
pItf->Release();
2434-
}
2435-
}
2436-
2437-
// Append to the list of object to free. Only use under the AppDomain "LockHolder(pAppDomain)"
2438-
void Append(IUnknown *pInterfaceToRelease)
2439-
{
2440-
WRAPPER_NO_CONTRACT;
2441-
m_objects.Append(pInterfaceToRelease);
2442-
}
2443-
} AppDomainInterfaceReleaseList;
2444-
24452390
private:
24462391
//-----------------------------------------------------------
24472392
// Static ICLRPrivAssembly -> DomainAssembly mapping functions.

src/coreclr/vm/assemblyspec.cpp

Lines changed: 0 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,92 +1573,6 @@ BOOL AssemblySpecBindingCache::CompareSpecs(UPTR u1, UPTR u2)
15731573
return a1->CompareEx(a2);
15741574
}
15751575

1576-
/* static */
1577-
BOOL DomainAssemblyCache::CompareBindingSpec(UPTR spec1, UPTR spec2)
1578-
{
1579-
WRAPPER_NO_CONTRACT;
1580-
1581-
AssemblySpec* pSpec1 = (AssemblySpec*) (spec1 << 1);
1582-
AssemblyEntry* pEntry2 = (AssemblyEntry*) spec2;
1583-
1584-
return pSpec1->CompareEx(&pEntry2->spec);
1585-
}
1586-
1587-
DomainAssemblyCache::AssemblyEntry* DomainAssemblyCache::LookupEntry(AssemblySpec* pSpec)
1588-
{
1589-
CONTRACT (DomainAssemblyCache::AssemblyEntry*)
1590-
{
1591-
INSTANCE_CHECK;
1592-
THROWS;
1593-
GC_TRIGGERS;
1594-
MODE_ANY;
1595-
POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
1596-
INJECT_FAULT(COMPlusThrowOM(););
1597-
}
1598-
CONTRACT_END
1599-
1600-
DWORD hashValue = pSpec->Hash();
1601-
1602-
LPVOID pResult = m_Table.LookupValue(hashValue, pSpec);
1603-
if(pResult == (LPVOID) INVALIDENTRY)
1604-
RETURN NULL;
1605-
else
1606-
RETURN (AssemblyEntry*) pResult;
1607-
}
1608-
1609-
VOID DomainAssemblyCache::InsertEntry(AssemblySpec* pSpec, LPVOID pData1, LPVOID pData2/*=NULL*/)
1610-
{
1611-
CONTRACTL
1612-
{
1613-
INSTANCE_CHECK;
1614-
THROWS;
1615-
GC_TRIGGERS;
1616-
MODE_ANY;
1617-
INJECT_FAULT(COMPlusThrowOM(););
1618-
}
1619-
CONTRACTL_END
1620-
1621-
LPVOID ptr = LookupEntry(pSpec);
1622-
if(ptr == NULL) {
1623-
1624-
BaseDomain::CacheLockHolder lh(m_pDomain);
1625-
1626-
ptr = LookupEntry(pSpec);
1627-
if(ptr == NULL) {
1628-
AllocMemTracker amTracker;
1629-
AllocMemTracker *pamTracker = &amTracker;
1630-
1631-
AssemblyEntry* pEntry = (AssemblyEntry*) pamTracker->Track( m_pDomain->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(AssemblyEntry))) );
1632-
new (&pEntry->spec) AssemblySpec ();
1633-
1634-
pEntry->spec.CopyFrom(pSpec);
1635-
pEntry->spec.CloneFieldsToLoaderHeap(AssemblySpec::ALL_OWNED, m_pDomain->GetLowFrequencyHeap(), pamTracker);
1636-
1637-
// Clear the parent assembly, it is not needed for the AssemblySpec in the cache entry and it could contain stale
1638-
// pointer when the parent was a collectible assembly that was collected.
1639-
pEntry->spec.SetParentAssembly(NULL);
1640-
1641-
pEntry->pData[0] = pData1;
1642-
pEntry->pData[1] = pData2;
1643-
DWORD hashValue = pEntry->Hash();
1644-
m_Table.InsertValue(hashValue, pEntry);
1645-
1646-
pamTracker->SuppressRelease();
1647-
}
1648-
// lh goes out of scope here
1649-
}
1650-
#ifdef _DEBUG
1651-
else {
1652-
_ASSERTE(pData1 == ((AssemblyEntry*) ptr)->pData[0]);
1653-
_ASSERTE(pData2 == ((AssemblyEntry*) ptr)->pData[1]);
1654-
}
1655-
#endif
1656-
1657-
}
1658-
1659-
1660-
1661-
16621576
DomainAssembly * AssemblySpec::GetParentAssembly()
16631577
{
16641578
LIMITED_METHOD_CONTRACT;

0 commit comments

Comments
 (0)