<data name="NotSupported_CollectibleBoundNonCollectible" xml:space="preserve">
<value>A non-collectible assembly may not reference a collectible assembly.</value>
</data>
- <data name="NotSupported_CollectibleCOM" xml:space="preserve">
- <value>COM Interop is not supported for collectible types.</value>
+ <data name="NotSupported_CollectibleWinRT" xml:space="preserve">
+ <value>WinRT Interop is not supported for collectible types.</value>
</data>
<data name="NotSupported_CreateInstanceWithTypeBuilder" xml:space="preserve">
<value>CreateInstance cannot be used with an object of type TypeBuilder.</value>
Crst TieredCompilation
AcquiredBefore ThreadpoolTimerQueue
End
+
+Crst COMCallWrapper
+End
CrstCLRPrivBinderMaps = 16,
CrstCLRPrivBinderMapsAdd = 17,
CrstCodeFragmentHeap = 18,
- CrstCOMWrapperCache = 19,
- CrstConnectionNameTable = 20,
- CrstContexts = 21,
- CrstCoreCLRBinderLog = 22,
- CrstCrstCLRPrivBinderLocalWinMDPath = 23,
- CrstCSPCache = 24,
- CrstDataTest1 = 25,
- CrstDataTest2 = 26,
- CrstDbgTransport = 27,
- CrstDeadlockDetection = 28,
- CrstDebuggerController = 29,
- CrstDebuggerFavorLock = 30,
- CrstDebuggerHeapExecMemLock = 31,
- CrstDebuggerHeapLock = 32,
- CrstDebuggerJitInfo = 33,
- CrstDebuggerMutex = 34,
- CrstDelegateToFPtrHash = 35,
- CrstDomainLocalBlock = 36,
- CrstDynamicIL = 37,
- CrstDynamicMT = 38,
- CrstDynLinkZapItems = 39,
- CrstEtwTypeLogHash = 40,
- CrstEventPipe = 41,
- CrstEventStore = 42,
- CrstException = 43,
- CrstExecuteManLock = 44,
- CrstExecuteManRangeLock = 45,
- CrstFCall = 46,
- CrstFriendAccessCache = 47,
- CrstFuncPtrStubs = 48,
- CrstFusionAppCtx = 49,
- CrstGCCover = 50,
- CrstGCMemoryPressure = 51,
- CrstGlobalStrLiteralMap = 52,
- CrstHandleTable = 53,
- CrstHostAssemblyMap = 54,
- CrstHostAssemblyMapAdd = 55,
- CrstIbcProfile = 56,
- CrstIJWFixupData = 57,
- CrstIJWHash = 58,
- CrstILStubGen = 59,
- CrstInlineTrackingMap = 60,
- CrstInstMethodHashTable = 61,
- CrstInterfaceVTableMap = 62,
- CrstInterop = 63,
- CrstInteropData = 64,
- CrstIOThreadpoolWorker = 65,
- CrstIsJMCMethod = 66,
- CrstISymUnmanagedReader = 67,
- CrstJit = 68,
- CrstJitGenericHandleCache = 69,
- CrstJitPerf = 70,
- CrstJumpStubCache = 71,
- CrstLeafLock = 72,
- CrstListLock = 73,
- CrstLoaderAllocator = 74,
- CrstLoaderAllocatorReferences = 75,
- CrstLoaderHeap = 76,
- CrstMda = 77,
- CrstMetadataTracker = 78,
- CrstModIntPairList = 79,
- CrstModule = 80,
- CrstModuleFixup = 81,
- CrstModuleLookupTable = 82,
- CrstMulticoreJitHash = 83,
- CrstMulticoreJitManager = 84,
- CrstMUThunkHash = 85,
- CrstNativeBinderInit = 86,
- CrstNativeImageCache = 87,
- CrstNls = 88,
- CrstNotifyGdb = 89,
- CrstObjectList = 90,
- CrstOnEventManager = 91,
- CrstPatchEntryPoint = 92,
- CrstPEImage = 93,
- CrstPEImagePDBStream = 94,
- CrstPendingTypeLoadEntry = 95,
- CrstPinHandle = 96,
- CrstPinnedByrefValidation = 97,
- CrstProfilerGCRefDataFreeList = 98,
- CrstProfilingAPIStatus = 99,
- CrstPublisherCertificate = 100,
- CrstRCWCache = 101,
- CrstRCWCleanupList = 102,
- CrstRCWRefCache = 103,
- CrstReadyToRunEntryPointToMethodDescMap = 104,
- CrstReDacl = 105,
- CrstReflection = 106,
- CrstReJITDomainTable = 107,
- CrstReJITGlobalRequest = 108,
- CrstRemoting = 109,
- CrstRetThunkCache = 110,
- CrstRWLock = 111,
- CrstSavedExceptionInfo = 112,
- CrstSaveModuleProfileData = 113,
- CrstSecurityStackwalkCache = 114,
- CrstSharedAssemblyCreate = 115,
- CrstSigConvert = 116,
- CrstSingleUseLock = 117,
- CrstSpecialStatics = 118,
- CrstSqmManager = 119,
- CrstStackSampler = 120,
- CrstStressLog = 121,
- CrstStrongName = 122,
- CrstStubCache = 123,
- CrstStubDispatchCache = 124,
- CrstStubUnwindInfoHeapSegments = 125,
- CrstSyncBlockCache = 126,
- CrstSyncHashLock = 127,
- CrstSystemBaseDomain = 128,
- CrstSystemDomain = 129,
- CrstSystemDomainDelayedUnloadList = 130,
- CrstThreadIdDispenser = 131,
- CrstThreadpoolEventCache = 132,
- CrstThreadpoolTimerQueue = 133,
- CrstThreadpoolWaitThreads = 134,
- CrstThreadpoolWorker = 135,
- CrstThreadStaticDataHashTable = 136,
- CrstThreadStore = 137,
- CrstTieredCompilation = 138,
- CrstTPMethodTable = 139,
- CrstTypeEquivalenceMap = 140,
- CrstTypeIDMap = 141,
- CrstUMEntryThunkCache = 142,
- CrstUMThunkHash = 143,
- CrstUniqueStack = 144,
- CrstUnresolvedClassLock = 145,
- CrstUnwindInfoTableLock = 146,
- CrstVSDIndirectionCellLock = 147,
- CrstWinRTFactoryCache = 148,
- CrstWrapperTemplate = 149,
- kNumberOfCrstTypes = 150
+ CrstCOMCallWrapper = 19,
+ CrstCOMWrapperCache = 20,
+ CrstConnectionNameTable = 21,
+ CrstContexts = 22,
+ CrstCoreCLRBinderLog = 23,
+ CrstCrstCLRPrivBinderLocalWinMDPath = 24,
+ CrstCSPCache = 25,
+ CrstDataTest1 = 26,
+ CrstDataTest2 = 27,
+ CrstDbgTransport = 28,
+ CrstDeadlockDetection = 29,
+ CrstDebuggerController = 30,
+ CrstDebuggerFavorLock = 31,
+ CrstDebuggerHeapExecMemLock = 32,
+ CrstDebuggerHeapLock = 33,
+ CrstDebuggerJitInfo = 34,
+ CrstDebuggerMutex = 35,
+ CrstDelegateToFPtrHash = 36,
+ CrstDomainLocalBlock = 37,
+ CrstDynamicIL = 38,
+ CrstDynamicMT = 39,
+ CrstDynLinkZapItems = 40,
+ CrstEtwTypeLogHash = 41,
+ CrstEventPipe = 42,
+ CrstEventStore = 43,
+ CrstException = 44,
+ CrstExecuteManLock = 45,
+ CrstExecuteManRangeLock = 46,
+ CrstFCall = 47,
+ CrstFriendAccessCache = 48,
+ CrstFuncPtrStubs = 49,
+ CrstFusionAppCtx = 50,
+ CrstGCCover = 51,
+ CrstGCMemoryPressure = 52,
+ CrstGlobalStrLiteralMap = 53,
+ CrstHandleTable = 54,
+ CrstHostAssemblyMap = 55,
+ CrstHostAssemblyMapAdd = 56,
+ CrstIbcProfile = 57,
+ CrstIJWFixupData = 58,
+ CrstIJWHash = 59,
+ CrstILStubGen = 60,
+ CrstInlineTrackingMap = 61,
+ CrstInstMethodHashTable = 62,
+ CrstInterfaceVTableMap = 63,
+ CrstInterop = 64,
+ CrstInteropData = 65,
+ CrstIOThreadpoolWorker = 66,
+ CrstIsJMCMethod = 67,
+ CrstISymUnmanagedReader = 68,
+ CrstJit = 69,
+ CrstJitGenericHandleCache = 70,
+ CrstJitPerf = 71,
+ CrstJumpStubCache = 72,
+ CrstLeafLock = 73,
+ CrstListLock = 74,
+ CrstLoaderAllocator = 75,
+ CrstLoaderAllocatorReferences = 76,
+ CrstLoaderHeap = 77,
+ CrstMda = 78,
+ CrstMetadataTracker = 79,
+ CrstModIntPairList = 80,
+ CrstModule = 81,
+ CrstModuleFixup = 82,
+ CrstModuleLookupTable = 83,
+ CrstMulticoreJitHash = 84,
+ CrstMulticoreJitManager = 85,
+ CrstMUThunkHash = 86,
+ CrstNativeBinderInit = 87,
+ CrstNativeImageCache = 88,
+ CrstNls = 89,
+ CrstNotifyGdb = 90,
+ CrstObjectList = 91,
+ CrstOnEventManager = 92,
+ CrstPatchEntryPoint = 93,
+ CrstPEImage = 94,
+ CrstPEImagePDBStream = 95,
+ CrstPendingTypeLoadEntry = 96,
+ CrstPinHandle = 97,
+ CrstPinnedByrefValidation = 98,
+ CrstProfilerGCRefDataFreeList = 99,
+ CrstProfilingAPIStatus = 100,
+ CrstPublisherCertificate = 101,
+ CrstRCWCache = 102,
+ CrstRCWCleanupList = 103,
+ CrstRCWRefCache = 104,
+ CrstReadyToRunEntryPointToMethodDescMap = 105,
+ CrstReDacl = 106,
+ CrstReflection = 107,
+ CrstReJITDomainTable = 108,
+ CrstReJITGlobalRequest = 109,
+ CrstRemoting = 110,
+ CrstRetThunkCache = 111,
+ CrstRWLock = 112,
+ CrstSavedExceptionInfo = 113,
+ CrstSaveModuleProfileData = 114,
+ CrstSecurityStackwalkCache = 115,
+ CrstSharedAssemblyCreate = 116,
+ CrstSigConvert = 117,
+ CrstSingleUseLock = 118,
+ CrstSpecialStatics = 119,
+ CrstSqmManager = 120,
+ CrstStackSampler = 121,
+ CrstStressLog = 122,
+ CrstStrongName = 123,
+ CrstStubCache = 124,
+ CrstStubDispatchCache = 125,
+ CrstStubUnwindInfoHeapSegments = 126,
+ CrstSyncBlockCache = 127,
+ CrstSyncHashLock = 128,
+ CrstSystemBaseDomain = 129,
+ CrstSystemDomain = 130,
+ CrstSystemDomainDelayedUnloadList = 131,
+ CrstThreadIdDispenser = 132,
+ CrstThreadpoolEventCache = 133,
+ CrstThreadpoolTimerQueue = 134,
+ CrstThreadpoolWaitThreads = 135,
+ CrstThreadpoolWorker = 136,
+ CrstThreadStaticDataHashTable = 137,
+ CrstThreadStore = 138,
+ CrstTieredCompilation = 139,
+ CrstTPMethodTable = 140,
+ CrstTypeEquivalenceMap = 141,
+ CrstTypeIDMap = 142,
+ CrstUMEntryThunkCache = 143,
+ CrstUMThunkHash = 144,
+ CrstUniqueStack = 145,
+ CrstUnresolvedClassLock = 146,
+ CrstUnwindInfoTableLock = 147,
+ CrstVSDIndirectionCellLock = 148,
+ CrstWinRTFactoryCache = 149,
+ CrstWrapperTemplate = 150,
+ kNumberOfCrstTypes = 151
};
#endif // __CRST_TYPES_INCLUDED
0, // CrstCLRPrivBinderMaps
3, // CrstCLRPrivBinderMapsAdd
6, // CrstCodeFragmentHeap
+ 0, // CrstCOMCallWrapper
4, // CrstCOMWrapperCache
0, // CrstConnectionNameTable
15, // CrstContexts
"CrstCLRPrivBinderMaps",
"CrstCLRPrivBinderMapsAdd",
"CrstCodeFragmentHeap",
+ "CrstCOMCallWrapper",
"CrstCOMWrapperCache",
"CrstConnectionNameTable",
"CrstContexts",
m_dwFlags = 0;
m_pDefaultContext = NULL;
#ifdef FEATURE_COMINTEROP
- m_pComCallWrapperCache = NULL;
m_pRCWCache = NULL;
m_pRCWRefCache = NULL;
m_pLicenseInteropHelperMT = NULL;
delete m_pRCWRefCache;
m_pRCWRefCache = NULL;
}
-
- if (m_pComCallWrapperCache)
- {
- m_pComCallWrapperCache->Neuter();
- m_pComCallWrapperCache->Release();
- }
-
- // if the above released the wrapper cache, then it will call back and reset our
- // m_pComCallWrapperCache to null. If not null, then need to set it's domain pointer to
- // null.
- if (! m_pComCallWrapperCache)
- {
- LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::Terminate ComCallWrapperCache released\n"));
- }
-#ifdef _DEBUG
- else
- {
- m_pComCallWrapperCache = NULL;
- LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::Terminate ComCallWrapperCache not released\n"));
- }
-#endif // _DEBUG
-
#endif // FEATURE_COMINTEROP
#ifdef FEATURE_COMINTEROP
-ComCallWrapperCache *AppDomain::GetComCallWrapperCache()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_ANY;
- INJECT_FAULT(COMPlusThrowOM(););
- }
- CONTRACTL_END;
-
- if (! m_pComCallWrapperCache)
- {
- BaseDomain::LockHolder lh(this);
-
- if (! m_pComCallWrapperCache)
- m_pComCallWrapperCache = ComCallWrapperCache::Create(this);
- }
- _ASSERTE(m_pComCallWrapperCache);
- return m_pComCallWrapperCache;
-}
-
RCWRefCache *AppDomain::GetRCWRefCache()
{
CONTRACT(RCWRefCache*)
// This will look up interop data for a method table
//
-#ifndef DACCESS_COMPILE
- // Returns the data pointer if present, NULL otherwise
- InteropMethodTableData *LookupComInteropData(MethodTable *pMT)
- {
- // Take the lock
- CrstHolder holder(&m_InteropDataCrst);
-
- // Lookup
- InteropMethodTableData *pData = (InteropMethodTableData*) m_interopDataHash.LookupValue((UPTR) pMT, (LPVOID) NULL);
-
- // Not there...
- if (pData == (InteropMethodTableData*) INVALIDENTRY)
- return NULL;
-
- // Found it
- return pData;
- }
-
- // Returns TRUE if successfully inserted, FALSE if this would be a duplicate entry
- BOOL InsertComInteropData(MethodTable* pMT, InteropMethodTableData *pData)
- {
- // We don't keep track of this kind of information for interfaces
- _ASSERTE(!pMT->IsInterface());
-
- // Take the lock
- CrstHolder holder(&m_InteropDataCrst);
-
- // Check to see that it's not already in there
- InteropMethodTableData *pDupData = (InteropMethodTableData*) m_interopDataHash.LookupValue((UPTR) pMT, (LPVOID) NULL);
- if (pDupData != (InteropMethodTableData*) INVALIDENTRY)
- return FALSE;
-
- // Not in there, so insert
- m_interopDataHash.InsertValue((UPTR) pMT, (LPVOID) pData);
-
- // Success
- return TRUE;
- }
-#endif // DACCESS_COMPILE
#endif // FEATURE_COMINTEROP
void SetDisableInterfaceCache()
}
#ifdef FEATURE_COMINTEROP
- ComCallWrapperCache* GetComCallWrapperCache();
RCWCache *GetRCWCache()
{
WRAPPER_NO_CONTRACT;
RCWRefCache *GetRCWRefCache();
- void ResetComCallWrapperCache()
- {
- LIMITED_METHOD_CONTRACT;
- m_pComCallWrapperCache = NULL;
- }
-
MethodTable* GetLicenseInteropHelperMethodTable();
#endif // FEATURE_COMINTEROP
// Hash table that remembers the last cached WinRT factory object per type per appdomain.
WinRTFactoryCache *m_pWinRTFactoryCache;
- // The wrapper cache for this domain - it has its own CCacheLineAllocator on a per domain basis
- // to allow the domain to go away and eventually kill the memory when all refs are gone
- ComCallWrapperCache *m_pComCallWrapperCache;
-
// this cache stores the RCWs in this domain
RCWCache *m_pRCWCache;
}
CONTRACTL_END;
+ // Don't cache WinRT types in collectible modules.
+ if (IsCollectible())
+ {
+ return FALSE;
+ }
+
// Don't cache mscorlib-internal declarations of WinRT types.
if (IsSystem() && pMT->IsProjectedFromWinRT())
return FALSE;
// NULL the context, we shall only use m_dwDomainId from this point on
m_pContext = NULL;
- // NULL the handles of DispatchMemberInfo if the AppDomain host them has been unloaded
- DispatchExInfo *pDispatchExInfo = GetDispatchExInfo();
- if (pDispatchExInfo)
- {
- pDispatchExInfo->DestroyMemberInfoHandles();
- }
-
StackSString ssMessage;
ComCallWrapper *pWrap = m_pWrap;
if (g_pConfig->LogCCWRefCountChangeEnabled())
size_t numInterfaces = pTemplate->GetNumInterfaces();
// we have a template, create a wrapper and initialize from the template
- // alloc wrapper, aligned 32 bytes
- if (pWrapperCache->IsDomainUnloading())
- COMPlusThrow(kAppDomainUnloadedException);
-
+ // alloc wrapper, aligned to cache line
NewCCWHolder pStartWrapper(pWrapperCache);
pStartWrapper = (ComCallWrapper*)pWrapperCache->GetCacheLineAllocator()->
#ifdef _WIN64
ComCallWrapperCache *pWrapperCache = NULL;
TypeHandle thClass = pServer->GetTrueTypeHandle();
- //
- // Collectible types do not support com interop
- //
- if (thClass.GetMethodTable()->Collectible())
- {
- COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleCOM"));
- }
-
- pWrapperCache = pContext->GetDomain()->GetComCallWrapperCache();
+ pWrapperCache = thClass.GetMethodTable()->GetLoaderAllocator()->GetComCallWrapperCache();
{
// check if somebody beat us to it
m_lock(CrstCOMWrapperCache),
m_cbRef(0),
m_pCacheLineAllocator(NULL),
- m_pDomain(NULL)
+ m_pLoaderAllocator(NULL)
{
WRAPPER_NO_CONTRACT;
CONTRACTL
{
NOTHROW;
- GC_TRIGGERS;
+ GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;
- LOG((LF_INTEROP, LL_INFO100, "ComCallWrapperCache::~ComCallWrapperCache %8.8x in domain [%d] %8.8x %S\n",
- this, GetDomain()?GetDomain()->GetId().m_dwId:0,
- GetDomain(), GetDomain() ? GetDomain()->GetFriendlyNameForLogging() : NULL));
+ LOG((LF_INTEROP, LL_INFO100, "ComCallWrapperCache::~ComCallWrapperCache %8.8x in loader allocator [%d] %8.8x\n",
+ this, GetLoaderAllocator() ? GetLoaderAllocator()->GetCreationNumber() : 0, GetLoaderAllocator()));
- if (m_pCacheLineAllocator)
+ if (m_pCacheLineAllocator)
{
delete m_pCacheLineAllocator;
m_pCacheLineAllocator = NULL;
}
- AppDomain *pDomain = GetDomain(); // don't use member directly, need to mask off flags
- if (pDomain)
+ LoaderAllocator *pLoaderAllocator = GetLoaderAllocator(); // don't use member directly, need to mask off flags
+ if (pLoaderAllocator)
{
- // clear hook in AppDomain as we're going away
- pDomain->ResetComCallWrapperCache();
+ // clear hook in LoaderAllocator as we're going away
+ pLoaderAllocator->ResetComCallWrapperCache();
}
}
// ComCallable wrapper manager
// Create/Init method
//-------------------------------------------------------------------
-ComCallWrapperCache *ComCallWrapperCache::Create(AppDomain *pDomain)
+ComCallWrapperCache *ComCallWrapperCache::Create(LoaderAllocator *pLoaderAllocator)
{
CONTRACT (ComCallWrapperCache*)
{
GC_TRIGGERS;
MODE_ANY;
INJECT_FAULT(COMPlusThrowOM());
- PRECONDITION(CheckPointer(pDomain));
+ PRECONDITION(CheckPointer(pLoaderAllocator));
POSTCONDITION(CheckPointer(RETVAL));
}
CONTRACT_END;
NewHolder<ComCallWrapperCache> pWrapperCache = new ComCallWrapperCache();
- LOG((LF_INTEROP, LL_INFO100, "ComCallWrapperCache::Create %8.8x in domain %8.8x %S\n",
- (ComCallWrapperCache *)pWrapperCache, pDomain, pDomain->GetFriendlyName(FALSE)));
+ LOG((LF_INTEROP, LL_INFO100, "ComCallWrapperCache::Create %8.8x in loader allocator [%d] %8.8x\n",
+ (ComCallWrapperCache *)pWrapperCache, pLoaderAllocator ? pLoaderAllocator->GetCreationNumber() : 0, pLoaderAllocator));
NewHolder<CCacheLineAllocator> line = new CCacheLineAllocator;
- pWrapperCache->m_pDomain = pDomain;
+ pWrapperCache->m_pLoaderAllocator = pLoaderAllocator;
pWrapperCache->m_pCacheLineAllocator = line;
pWrapperCache->AddRef();
RETURN pWrapperCache;
}
-
-void ComCallWrapperCache::Neuter()
-{
- WRAPPER_NO_CONTRACT;
-
- LOG((LF_INTEROP, LL_INFO100, "ComCallWrapperCache::Neuter %8.8x in domain [%d] %8.8x %S\n",
- this, GetDomain()?GetDomain()->GetId().m_dwId:0,
- GetDomain(),GetDomain() ? GetDomain()->GetFriendlyNameForLogging() : NULL));
- ClearDomain();
-}
-
-
//-------------------------------------------------------------------
// ComCallable wrapper manager
// LONG AddRef()
COUNTER_ONLY(GetPerfCounters().m_Interop.cCCW++);
LONG i = FastInterlockIncrement(&m_cbRef);
- LOG((LF_INTEROP, LL_INFO100, "ComCallWrapperCache::Addref %8.8x with %d in domain [%d] %8.8x %S\n",
- this, i, GetDomain()?GetDomain()->GetId().m_dwId:0,
- GetDomain(), GetDomain() ? GetDomain()->GetFriendlyNameForLogging() : NULL));
+ LOG((LF_INTEROP, LL_INFO100, "ComCallWrapperCache::Addref %8.8x with %d in loader allocator [%d] %8.8x\n",
+ this, i, GetLoaderAllocator()?GetLoaderAllocator()->GetCreationNumber() : 0, GetLoaderAllocator()));
return i;
}
LONG i = FastInterlockDecrement(&m_cbRef);
_ASSERTE(i >= 0);
- LOG((LF_INTEROP, LL_INFO100, "ComCallWrapperCache::Release %8.8x with %d in domain [%d] %8.8x %S\n",
- this, i, GetDomain()?GetDomain()->GetId().m_dwId:0,
- GetDomain(), GetDomain() ? GetDomain()->GetFriendlyNameForLogging() : NULL));
+ LOG((LF_INTEROP, LL_INFO100, "ComCallWrapperCache::Release %8.8x with %d in loader allocator [%d] %8.8x\n",
+ this, i, GetLoaderAllocator() ? GetLoaderAllocator()->GetCreationNumber() : 0, GetLoaderAllocator()));
if ( i == 0)
delete this;
class ComCallWrapperCache
{
- enum
- {
- AD_IS_UNLOADING = 0x01,
- };
-
public:
// Encapsulate a SpinLockHolder, so that clients of our lock don't have to know
// the details of our implementation.
ComCallWrapperCache();
~ComCallWrapperCache();
- // create a new WrapperCache (one per domain)
- static ComCallWrapperCache* Create(AppDomain *pDomain);
-
- // Called when the domain is going away. We may have outstanding references to this cache,
- // so we keep it around in a neutered state.
- void Neuter();
+ // create a new WrapperCache (one per each LoaderAllocator)
+ static ComCallWrapperCache* Create(LoaderAllocator *pLoaderAllocator);
// refcount
LONG AddRef();
RETURN m_pCacheLineAllocator;
}
- AppDomain* GetDomain()
+ LoaderAllocator* GetLoaderAllocator()
{
- CONTRACT (AppDomain*)
+ CONTRACT (LoaderAllocator*)
{
WRAPPER(THROWS);
WRAPPER(GC_TRIGGERS);
}
CONTRACT_END;
- RETURN ((AppDomain*)((size_t)m_pDomain & ~AD_IS_UNLOADING));
- }
-
- void ClearDomain()
- {
- LIMITED_METHOD_CONTRACT;
-
- m_pDomain = (AppDomain *)AD_IS_UNLOADING;
- }
-
- void SetDomainIsUnloading()
- {
- LIMITED_METHOD_CONTRACT;
-
- m_pDomain = (AppDomain*)((size_t)m_pDomain | AD_IS_UNLOADING);
- }
-
- void ResetDomainIsUnloading()
- {
- LIMITED_METHOD_CONTRACT;
-
- m_pDomain = (AppDomain*)((size_t)m_pDomain & (~AD_IS_UNLOADING));
- }
-
- BOOL IsDomainUnloading()
- {
- LIMITED_METHOD_CONTRACT;
-
- return ((size_t)m_pDomain & AD_IS_UNLOADING) != 0;
+ RETURN m_pLoaderAllocator;
}
private:
LONG m_cbRef;
CCacheLineAllocator* m_pCacheLineAllocator;
- AppDomain* m_pDomain;
+ LoaderAllocator* m_pLoaderAllocator;
// spin lock for fast synchronization
Crst m_lock;
CONTRACTL
{
NOTHROW;
- GC_TRIGGERS;
+ GC_NOTRIGGER;
MODE_ANY;
}
CONTRACTL_END;
if (m_pParamInOnly)
delete [] m_pParamInOnly;
- // Destroy the member info object.
- if (m_hndMemberInfo)
- DestroyHandle(m_hndMemberInfo);
-
// Clear the name of the member.
m_strName.Clear();
}
{
case Method:
{
- pGetParamsMD = DispatchInfo::GetMethodInfoMD(METHOD__METHOD__GET_PARAMETERS, ObjectFromHandle(m_hndMemberInfo)->GetTypeHandle());
+ pGetParamsMD = DispatchInfo::GetMethodInfoMD(METHOD__METHOD__GET_PARAMETERS, GetMemberInfoObject()->GetTypeHandle());
_ASSERTE(pGetParamsMD && "Unable to find method MemberBase::GetParameters");
break;
}
case Property:
{
- pGetParamsMD = DispatchInfo::GetPropertyInfoMD(METHOD__PROPERTY__GET_INDEX_PARAMETERS, ObjectFromHandle(m_hndMemberInfo)->GetTypeHandle());
+ pGetParamsMD = DispatchInfo::GetPropertyInfoMD(METHOD__PROPERTY__GET_INDEX_PARAMETERS, GetMemberInfoObject()->GetTypeHandle());
_ASSERTE(pGetParamsMD && "Unable to find method PropertyInfo::GetIndexParameters");
break;
}
// If the member has parameters then retrieve the array of parameters.
if (pGetParamsMD != NULL)
{
- MethodDescCallSite getParams(pGetParamsMD, m_hndMemberInfo);
+ OBJECTREF memberInfoObject = GetMemberInfoObject();
+ GCPROTECT_BEGIN(memberInfoObject)
+ MethodDescCallSite getParams(pGetParamsMD, &memberInfoObject);
ARG_SLOT GetParamsArgs[] =
{
- ObjToArgSlot(ObjectFromHandle(m_hndMemberInfo))
+ ObjToArgSlot(memberInfoObject)
};
ParamArray = (PTRARRAYREF) getParams.Call_RetOBJECTREF(GetParamsArgs);
+ GCPROTECT_END();
}
return ParamArray;
}
CONTRACTL_END;
- OBJECTREF MemberInfoObj = ObjectFromHandle(m_hndMemberInfo);
+ OBJECTREF MemberInfoObj = GetMemberInfoObject();
// Check to see if the member info is of a type we have already seen.
TypeHandle pMemberInfoClass = MemberInfoObj->GetTypeHandle();
MethodDesc *pGetParamsMD = NULL;
- OBJECTREF MemberInfoObj = ObjectFromHandle(m_hndMemberInfo);
+ OBJECTREF MemberInfoObj = GetMemberInfoObject();
GCPROTECT_BEGIN(MemberInfoObj);
{
// Retrieve the method to use to retrieve the array of parameters.
{
case Method:
{
- pGetParamsMD = DispatchInfo::GetMethodInfoMD(METHOD__METHOD__GET_PARAMETERS, ObjectFromHandle(m_hndMemberInfo)->GetTypeHandle());
+ pGetParamsMD = DispatchInfo::GetMethodInfoMD(METHOD__METHOD__GET_PARAMETERS, GetMemberInfoObject()->GetTypeHandle());
_ASSERTE(pGetParamsMD && "Unable to find method MemberBase::GetParameters");
break;
}
case Property:
{
- pGetParamsMD = DispatchInfo::GetPropertyInfoMD(METHOD__PROPERTY__GET_INDEX_PARAMETERS, ObjectFromHandle(m_hndMemberInfo)->GetTypeHandle());
+ pGetParamsMD = DispatchInfo::GetPropertyInfoMD(METHOD__PROPERTY__GET_INDEX_PARAMETERS, GetMemberInfoObject()->GetTypeHandle());
_ASSERTE(pGetParamsMD && "Unable to find method PropertyInfo::GetIndexParameters");
break;
}
ARG_SLOT GetParamsArgs[] =
{
- ObjToArgSlot(ObjectFromHandle(m_hndMemberInfo))
+ ObjToArgSlot(GetMemberInfoObject())
};
PTRARRAYREF ParamArray = (PTRARRAYREF) getParams.Call_RetOBJECTREF(GetParamsArgs);
MethodTable * pLcIdConvAttrClass = MscorlibBinder::GetClass(CLASS__LCID_CONVERSION_TYPE);
// Check to see if the attribute is set.
- OBJECTREF MemberInfoObj = ObjectFromHandle(m_hndMemberInfo);
+ OBJECTREF MemberInfoObj = GetMemberInfoObject();
GCPROTECT_BEGIN(MemberInfoObj);
{
// Retrieve the method to use to determine if the DispIdAttribute custom attribute is set.
BOOL bSetUpReturnValueOnly = FALSE;
OBJECTREF SetterObj = NULL;
OBJECTREF GetterObj = NULL;
- OBJECTREF MemberInfoObj = ObjectFromHandle(m_hndMemberInfo);
+ OBJECTREF MemberInfoObj = GetMemberInfoObject();
GCPROTECT_BEGIN(SetterObj);
GCPROTECT_BEGIN(GetterObj);
m_pParamInOnly[iParam] = ( Info->IsIn() && !Info->IsOut() );
}
+#ifndef DACCESS_COMPILE
+OBJECTREF DispatchMemberInfo::GetMemberInfoObject()
+{
+ return m_pDispInfo->GetLoaderAllocator()->GetHandleValue(m_hndMemberInfo);
+}
+
+void DispatchMemberInfo::ClearMemberInfoObject()
+{
+ m_pDispInfo->GetLoaderAllocator()->SetHandleValue(m_hndMemberInfo, NULL);
+}
+#endif // DACCESS_COMPILE
+
//--------------------------------------------------------------------------------
// The DispatchInfo class implementation.
DispatchMemberInfo *pCurrMemberInfo = m_pFirstMemberInfo;
while (pCurrMemberInfo)
{
- if (ObjectFromHandle(pCurrMemberInfo->m_hndMemberInfo) != NULL)
+ if (pCurrMemberInfo->GetMemberInfoObject() != NULL)
{
// Compare the 2 strings.
if (bCaseSensitive ?
CONTRACT_END;
DispatchMemberInfo* pInfo = new DispatchMemberInfo(this, DispID, strMemberName, MemberInfoObj);
- pInfo->SetHandle(MemberInfoObj->GetMethodTable()->GetDomain()->CreateHandle(MemberInfoObj));
+ pInfo->SetHandle(GetLoaderAllocator()->AllocateHandle(MemberInfoObj));
RETURN pInfo;
}
}
// Retrieve the member info object and the type of the member.
- pObjs->MemberInfo = ObjectFromHandle(pDispMemberInfo->m_hndMemberInfo);
+ pObjs->MemberInfo = pDispMemberInfo->GetMemberInfoObject();
MemberType = pDispMemberInfo->GetMemberType();
switch (MemberType)
//
DispatchMemberInfo *pDispMemberInfo = FindMember(id);
- if (!pDispMemberInfo || !(*((Object **)pDispMemberInfo->m_hndMemberInfo)))
+ if (!pDispMemberInfo || !pDispMemberInfo->GetMemberInfoObject())
{
pDispMemberInfo = NULL;
}
return hr;
}
-void DispatchInfo::DestroyMemberInfoHandles()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- DispatchMemberInfo* pCurrMember = m_pFirstMemberInfo;
- while (pCurrMember)
- {
- // Destroy the handle
- DestroyHandle(pCurrMember->m_hndMemberInfo);
- pCurrMember->m_hndMemberInfo = NULL;
- // Process the next member.
- pCurrMember = pCurrMember->m_pNext;
- }
-}
-
// Parameter marshaling helpers.
void DispatchInfo::MarshalParamNativeToManaged(DispatchMemberInfo *pMemberInfo, int iParam, VARIANT *pSrcVar, OBJECTREF *pDestObj)
{
while (pCurrMemberInfo)
{
// We can simply compare the OBJECTREF's.
- if (CurrMemberInfoObj == ObjectFromHandle(pCurrMemberInfo->m_hndMemberInfo))
+ if (CurrMemberInfoObj == pCurrMemberInfo->GetMemberInfoObject())
{
// We have found a match.
bMatch = TRUE;
AppDomain* pDomain = SystemDomain::GetAppDomainFromId(m_pSimpleWrapperOwner->GetDomainID(), ADV_CURRENTAD);
- pInfo->SetHandle(pDomain->CreateHandle(MemberInfoObj));
+ pInfo->SetHandle(GetLoaderAllocator()->AllocateHandle(MemberInfoObj));
RETURN pInfo;
}
}
// Now we need to make sure we skip any members that are deleted.
- while ((*ppNextMemberInfo) && !ObjectFromHandle((*ppNextMemberInfo)->m_hndMemberInfo))
+ while ((*ppNextMemberInfo) && !(*ppNextMemberInfo)->GetMemberInfoObject())
ppNextMemberInfo = &((*ppNextMemberInfo)->m_pNext);
RETURN *ppNextMemberInfo;
}
// Now we need to make sure we skip any members that are deleted.
- while ((*ppNextMemberInfo) && !ObjectFromHandle((*ppNextMemberInfo)->m_hndMemberInfo))
+ while ((*ppNextMemberInfo) && !(*ppNextMemberInfo)->GetMemberInfoObject())
ppNextMemberInfo = &((*ppNextMemberInfo)->m_pNext);
RETURN *ppNextMemberInfo;
CrstHolder ch(&m_lock);
// If the member does not exist, it is static or has been deleted then we have nothing more to do.
- if (pDispMemberInfo && (ObjectFromHandle(pDispMemberInfo->m_hndMemberInfo) != NULL))
+ if (pDispMemberInfo && (pDispMemberInfo->GetMemberInfoObject() != NULL))
{
OBJECTREF TargetObj = GetReflectionObject();
GCPROTECT_BEGIN(TargetObj);
MethodDesc *pMD = GetIExpandoMD(METHOD__IEXPANDO__REMOVE_MEMBER);
MethodDescCallSite removeMember(pMD, &TargetObj);
- OBJECTREF MemberInfoObj = ObjectFromHandle(pDispMemberInfo->m_hndMemberInfo);
+ OBJECTREF MemberInfoObj = pDispMemberInfo->GetMemberInfoObject();
// Prepare the arguments that will be passed to RemoveMember.
ARG_SLOT Args[] =
removeMember.Call(Args);
// Set the handle to point to NULL to indicate the member has been removed.
- StoreObjectInHandle(pDispMemberInfo->m_hndMemberInfo, NULL);
+ pDispMemberInfo->ClearMemberInfoObject();
GCPROTECT_END();
}
return m_bLastParamOleVarArg;
}
- void SetHandle(OBJECTHANDLE objhnd)
+ void SetHandle(LOADERHANDLE objhnd)
{
m_hndMemberInfo = objhnd;
}
return m_bRequiresManagedCleanup;
}
+#ifndef DACCESS_COMPILE
+ OBJECTREF GetMemberInfoObject();
+ void ClearMemberInfoObject();
+#endif // DACCESS_COMPILE
+
// Parameter marshaling methods.
void MarshalParamNativeToManaged(int iParam, VARIANT *pSrcVar, OBJECTREF *pDestObj);
void MarshalParamManagedToNativeRef(int iParam, OBJECTREF *pSrcObj, VARIANT *pRefVar);
void SetUpDispParamAttributes(int iParam, MarshalInfo* Info);
public:
DISPID m_DispID;
- OBJECTHANDLE m_hndMemberInfo;
+ LOADERHANDLE m_hndMemberInfo;
DispParamMarshaler** m_apParamMarshaler;
BOOL* m_pParamInOnly;
DispatchMemberInfo* m_pNext;
int* pManagedMethodParamIndexMap,
VARIANT** aByrefArgOleVariant);
- // Method to NULL the handles inside DispatchMemberInfo
- void DestroyMemberInfoHandles();
-
// Methods to retrieve the cached MD's
static MethodDesc* GetFieldInfoMD(BinderMethodID Method, TypeHandle hndFieldInfoType);
static MethodDesc* GetPropertyInfoMD(BinderMethodID Method, TypeHandle hndPropInfoType);
// Returns TRUE if the argument is "Missing"
static BOOL VariantIsMissing(VARIANT *pOle);
+ LoaderAllocator* GetLoaderAllocator()
+ {
+ return m_pMT->GetLoaderAllocator();
+ }
+
protected:
// Parameter marshaling helpers.
void MarshalParamNativeToManaged(DispatchMemberInfo *pMemberInfo, int iParam, VARIANT *pSrcVar, OBJECTREF *pDestObj);
return FALSE;
}
- // If the type is collectible, then it is not visible from COM.
- if (hndType.GetLoaderAllocator()->IsCollectible())
- return FALSE;
-
return SpecialIsGenericTypeVisibleFromCom(hndType);
}
if (pClsFac == NULL)
{
//
- // Collectible types do not support com interop
+ // Collectible types do not support WinRT interop
//
- if (pClassMT->Collectible())
+ if (pClassMT->Collectible() && (pClassMT->IsExportedToWinRT() || pClassMT->IsProjectedFromWinRT()))
{
- COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleCOM"));
+ COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleWinRT"));
}
NewHolder<ClassFactoryBase> pNewFactory;
#ifndef DACCESS_COMPILE
#include "comdelegate.h"
#endif
+#include "comcallablewrapper.h"
//*****************************************************************************
// Used by LoaderAllocator::Init for easier readability.
m_pJumpStubCache = NULL;
m_IsCollectible = false;
+#ifdef FEATURE_COMINTEROP
+ m_pComCallWrapperCache = NULL;
+#endif
+
m_pUMEntryThunkCache = NULL;
m_nLoaderAllocator = InterlockedIncrement64((LONGLONG *)&LoaderAllocator::cLoaderAllocatorsCreated);
// This will probably change for shared code unloading
_ASSERTE(pID->GetType() == LAT_Assembly);
+#ifdef FEATURE_COMINTEROP
+ if (pLoaderAllocator->m_pComCallWrapperCache)
+ {
+ pLoaderAllocator->m_pComCallWrapperCache->Release();
+
+ // if the above released the wrapper cache, then it will call back and reset our
+ // m_pComCallWrapperCache to null.
+ if (!pLoaderAllocator->m_pComCallWrapperCache)
+ {
+ LOG((LF_CLASSLOADER, LL_INFO10, "LoaderAllocator::Destroy ComCallWrapperCache released\n"));
+ }
+ #ifdef _DEBUG
+ else
+ {
+ pLoaderAllocator->m_pComCallWrapperCache = NULL;
+ LOG((LF_CLASSLOADER, LL_INFO10, "LoaderAllocator::Destroy ComCallWrapperCache not released\n"));
+ }
+ #endif // _DEBUG
+ }
+#endif // FEATURE_COMINTEROP
+
DomainAssembly* pDomainAssembly = (DomainAssembly*)(pID->GetDomainAssemblyIterator());
if (pDomainAssembly != NULL)
{
m_pDomain = pDomain;
m_crstLoaderAllocator.Init(CrstLoaderAllocator, (CrstFlags)CRST_UNSAFE_COOPGC);
+#ifdef FEATURE_COMINTEROP
+ m_InteropDataCrst.Init(CrstInteropData, CRST_REENTRANCY);
+ m_ComCallWrapperCrst.Init(CrstCOMCallWrapper);
+#endif
//
// Initialize the heaps
// Set up the IL stub cache
m_ILStubCache.Init(m_pHighFrequencyHeap);
+
+#ifdef FEATURE_COMINTEROP
+ // Init the COM Interop data hash
+ {
+ LockOwner lock = { &m_InteropDataCrst, IsOwnerOfCrst };
+ m_interopDataHash.Init(0, NULL, false, &lock);
+ }
+#endif // FEATURE_COMINTEROP
}
m_pUMEntryThunkCache = NULL;
m_crstLoaderAllocator.Destroy();
+#ifdef FEATURE_COMINTEROP
+ m_ComCallWrapperCrst.Destroy();
+ m_InteropDataCrst.Destroy();
+#endif
m_LoaderAllocatorReferences.RemoveAll();
// In collectible types we merge the low frequency and high frequency heaps
}
}
+#ifdef FEATURE_COMINTEROP
+ComCallWrapperCache * LoaderAllocator::GetComCallWrapperCache()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ INJECT_FAULT(COMPlusThrowOM(););
+ }
+ CONTRACTL_END;
+
+ if (!m_pComCallWrapperCache)
+ {
+ CrstHolder lh(&m_ComCallWrapperCrst);
+
+ if (!m_pComCallWrapperCache)
+ m_pComCallWrapperCache = ComCallWrapperCache::Create(this);
+ }
+ _ASSERTE(m_pComCallWrapperCache);
+ return m_pComCallWrapperCache;
+}
+#endif // FEATURE_COMINTEROP
+
// U->M thunks created in this LoaderAllocator and not associated with a delegate.
UMEntryThunkCache *LoaderAllocator::GetUMEntryThunkCache()
{
#endif // !CROSSGEN_COMPILE
+#ifdef FEATURE_COMINTEROP
+
+// Look up interop data for a method table
+// Returns the data pointer if present, NULL otherwise
+InteropMethodTableData *LoaderAllocator::LookupComInteropData(MethodTable *pMT)
+{
+ // Take the lock
+ CrstHolder holder(&m_InteropDataCrst);
+
+ // Lookup
+ InteropMethodTableData *pData = (InteropMethodTableData*)m_interopDataHash.LookupValue((UPTR)pMT, (LPVOID)NULL);
+
+ // Not there...
+ if (pData == (InteropMethodTableData*)INVALIDENTRY)
+ return NULL;
+
+ // Found it
+ return pData;
+}
+
+// Returns TRUE if successfully inserted, FALSE if this would be a duplicate entry
+BOOL LoaderAllocator::InsertComInteropData(MethodTable* pMT, InteropMethodTableData *pData)
+{
+ // We don't keep track of this kind of information for interfaces
+ _ASSERTE(!pMT->IsInterface());
+
+ // Take the lock
+ CrstHolder holder(&m_InteropDataCrst);
+
+ // Check to see that it's not already in there
+ InteropMethodTableData *pDupData = (InteropMethodTableData*)m_interopDataHash.LookupValue((UPTR)pMT, (LPVOID)NULL);
+ if (pDupData != (InteropMethodTableData*)INVALIDENTRY)
+ return FALSE;
+
+ // Not in there, so insert
+ m_interopDataHash.InsertValue((UPTR)pMT, (LPVOID)pData);
+
+ // Success
+ return TRUE;
+}
+
+#endif // FEATURE_COMINTEROP
+
#endif // !DACCESS_COMPILE
typedef ListLockEntryBase<void*> ListLockEntry;
class UMEntryThunkCache;
+#ifdef FEATURE_COMINTEROP
+class ComCallWrapperCache;
+#endif // FEATURE_COMINTEROP
+
class LoaderAllocator
{
VPTR_BASE_VTABLE_CLASS(LoaderAllocator)
SList<FailedTypeInitCleanupListItem> m_failedTypeInitCleanupList;
SegmentedHandleIndexStack m_freeHandleIndexesStack;
+#ifdef FEATURE_COMINTEROP
+ // The wrapper cache for this loader allocator - it has its own CCacheLineAllocator on a per loader allocator basis
+ // to allow the loader allocator to go away and eventually kill the memory when all refs are gone
+
+ VolatilePtr<ComCallWrapperCache> m_pComCallWrapperCache;
+ // Used for synchronizing creation of the m_pComCallWrapperCache
+ CrstExplicitInit m_ComCallWrapperCrst;
+ // Hash table that maps a MethodTable to COM Interop compatibility data.
+ PtrHashMap m_interopDataHash;
+ // Used for synchronizing access to the m_interopDataHash
+ CrstExplicitInit m_InteropDataCrst;
+#endif
#ifndef DACCESS_COMPILE
void InitVirtualCallStubManager(BaseDomain *pDomain);
void UninitVirtualCallStubManager();
+
#ifndef CROSSGEN_COMPILE
inline VirtualCallStubManager *GetVirtualCallStubManager()
{
LIMITED_METHOD_CONTRACT;
return &m_ILStubCache;
}
+
+#ifdef FEATURE_COMINTEROP
+
+ ComCallWrapperCache * GetComCallWrapperCache();
+
+ void ResetComCallWrapperCache()
+ {
+ LIMITED_METHOD_CONTRACT;
+ m_pComCallWrapperCache = NULL;
+ }
+
+#ifndef DACCESS_COMPILE
+
+ // Look up interop data for a method table
+ // Returns the data pointer if present, NULL otherwise
+ InteropMethodTableData *LookupComInteropData(MethodTable *pMT);
+
+ // Returns TRUE if successfully inserted, FALSE if this would be a duplicate entry
+ BOOL InsertComInteropData(MethodTable* pMT, InteropMethodTableData *pData);
+
+#endif // DACCESS_COMPILE
+
+#endif // FEATURE_COMINTEROP
+
}; // class LoaderAllocator
typedef VPTR(LoaderAllocator) PTR_LoaderAllocator;
InteropMethodTableData *MethodTable::LookupComInteropData()
{
WRAPPER_NO_CONTRACT;
- return GetDomain()->LookupComInteropData(this);
+
+ return GetLoaderAllocator()->LookupComInteropData(this);
}
//==========================================================================================
BOOL MethodTable::InsertComInteropData(InteropMethodTableData *pData)
{
WRAPPER_NO_CONTRACT;
- return GetDomain()->InsertComInteropData(this, pData);
+
+ return GetLoaderAllocator()->InsertComInteropData(this, pData);
}
//==========================================================================================
m_pwszProgID = pwszProgID;
m_pwszServer = pwszServer;
- _ASSERTE(pClassMT == NULL || !pClassMT->Collectible());
m_pClassMT = pClassMT;
}
RETURN result;
}
- //
- // Collectible types do not support com interop
- //
- if (pMT->Collectible())
- {
- COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleCOM"));
- }
-
// returns an AddRef'ed IP
RETURN GetComIPForMethodTableFromCache(pMT);
}
{
pMT->CheckRestore();
pMT->EnsureInstanceActive();
-
- //
- // Collectible types do not support com interop
- //
- if (pMT->Collectible())
- {
- COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleCOM"));
- }
-
pMT->CheckRunClassInitThrowing();
}
DispatchMemberInfo *pDispMemberInfo = pDispExInfo->SynchFindMember(id);
// If the member does not exist then we return DISP_E_MEMBERNOTFOUND.
- if (!pDispMemberInfo || !ObjectFromHandle(pDispMemberInfo->m_hndMemberInfo))
+ if (!pDispMemberInfo || !pDispMemberInfo->GetMemberInfoObject())
{
hr = DISP_E_MEMBERNOTFOUND;
}
DispatchMemberInfo *pDispMemberInfo = pDispExInfo->SynchFindMember(id);
// If the member does not exist then we return DISP_E_MEMBERNOTFOUND.
- if (!pDispMemberInfo || (MemberInfoObj = ObjectFromHandle(pDispMemberInfo->m_hndMemberInfo)) == NULL)
+ if (!pDispMemberInfo || (MemberInfoObj = pDispMemberInfo->GetMemberInfoObject()) == NULL)
{
hr = DISP_E_MEMBERNOTFOUND;
}
<ExcludeList Include="$(XunitTestBinBase)/Interop/COM/NETClients/Primitives/NETClientPrimitives/*">
<Issue>20682</Issue>
</ExcludeList>
+ <ExcludeList Include="$(XunitTestBinBase)/Interop/COM/NETClients/Primitives/NETClientPrimitivesInALC/*">
+ <Issue>20682</Issue>
+ </ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Interop/COM/NativeClients/Primitives/*">
<Issue>20682</Issue>
</ExcludeList>
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Runtime.Loader;
using System.Security;
using System.Text;
using System.Threading;
public static IntPtr HKEY_LOCAL_MACHINE => new IntPtr(unchecked((int)0x80000002));
}
+
+ class TestAssemblyLoadContext : AssemblyLoadContext
+ {
+ public TestAssemblyLoadContext() : base(isCollectible: true)
+ {
+
+ }
+
+ protected override Assembly Load(AssemblyName assemblyName)
+ {
+ return null;
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static int ExecuteAndUnloadInternal(string assemblyPath, string[] args, Action<AssemblyLoadContext> unloadingCallback, out WeakReference alcWeakRef)
+ {
+ TestAssemblyLoadContext alc = new TestAssemblyLoadContext();
+ if (unloadingCallback != null)
+ {
+ alc.Unloading += unloadingCallback;
+ }
+ alcWeakRef = new WeakReference(alc);
+
+ Assembly a = alc.LoadFromAssemblyPath(assemblyPath);
+
+ object[] argsObjArray = (a.EntryPoint.GetParameters().Length != 0) ? new object[] { args } : null;
+ object res = a.EntryPoint.Invoke(null, argsObjArray);
+
+ alc.Unload();
+
+ return (a.EntryPoint.ReturnType == typeof(void)) ? Environment.ExitCode : Convert.ToInt32(res);
+ }
+
+ public static int ExecuteAndUnload(string assemblyPath, string[] args, Action<AssemblyLoadContext> unloadingCallback = null)
+ {
+ WeakReference alcWeakRef;
+ int exitCode;
+
+ exitCode = ExecuteAndUnloadInternal(assemblyPath, args, unloadingCallback, out alcWeakRef);
+
+ for (int i = 0; i < 8 && alcWeakRef.IsAlive; i++)
+ {
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ }
+
+ if (alcWeakRef.IsAlive)
+ {
+ exitCode += 100;
+ Console.WriteLine("Unload failed");
+ }
+ else
+ {
+ Console.WriteLine("Unload succeeded");
+ }
+
+ return exitCode;
+ }
}
}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>NETClientPrimitivesInALC</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{85C57688-DA98-4DE3-AC9B-526E4747434C}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{209912F9-0DA1-4184-9CC1-8D583BAF4A28};{87799F5D-CEBD-499D-BDBA-B2C6105CD766}</ProjectTypeGuids>
+ <ApplicationManifest>App.manifest</ApplicationManifest>
+
+ <!-- Blocked on ILAsm supporting embedding resources. See https://github.com/dotnet/coreclr/issues/20819 -->
+ <IlrtTestKind>BuildOnly</IlrtTestKind>
+
+ <!-- Blocked on CrossGen.exe supporting embedding resources. See https://github.com/dotnet/coreclr/issues/21006 -->
+ <CrossGenTest>false</CrossGenTest>
+
+ <!-- Test unsupported outside of windows -->
+ <TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows>
+ <DisableProjectBuild Condition="'$(TargetsUnix)' == 'true'">true</DisableProjectBuild>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="TestInALC.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="../../NativeServer/CMakeLists.txt" />
+ <ProjectReference Include="../../../../Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
+ <ProjectReference Include="NetClientPrimitives.csproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace TestInALC
+{
+ class Test
+ {
+ static int Main(string[] args)
+ {
+ string currentAssemblyDirectory = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath);
+ string testAssemblyFullPath = Path.Combine(currentAssemblyDirectory, "NETClientPrimitives.exe");
+ return TestLibrary.Utilities.ExecuteAndUnload(testAssemblyFullPath, args);
+ }
+ }
+}
</CodeAnalysisDependentAssemblyPaths>
</ItemGroup>
<ItemGroup>
- <Compile Include="*.cs" />
+ <Compile Include="IUnknownTest.cs" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>IUnknownTestInALC</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+
+ <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+
+ <!-- Test unsupported outside of windows -->
+ <TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows>
+ <DisableProjectBuild Condition="'$(TargetsUnix)' == 'true'">true</DisableProjectBuild>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ </PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="TestInALC.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\Common\CoreCLRTestLibrary\CoreCLRTestLibrary.csproj">
+ <Project>{c8c0dc74-fac4-45b1-81fe-70c4808366e0}</Project>
+ <Name>CoreCLRTestLibrary</Name>
+ </ProjectReference>
+ <ProjectReference Include="IUnknownTest.csproj" />
+ <ProjectReference Include="CMakeLists.txt" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace TestInALC
+{
+ class Test
+ {
+ static int Main(string[] args)
+ {
+ string currentAssemblyDirectory = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath);
+ string testAssemblyFullPath = Path.Combine(currentAssemblyDirectory, "IUnknownTest.exe");
+ return TestLibrary.Utilities.ExecuteAndUnload(testAssemblyFullPath, args);
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>DefaultTestInALC</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{43531C46-AFE2-4254-93C6-7F17E30D750C}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\..\</SolutionDir>
+ <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+ <!-- Test unsupported outside of windows -->
+ <TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows>
+ <DisableProjectBuild Condition="'$(TargetsUnix)' == 'true'">true</DisableProjectBuild>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="TestInALC.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CMakeLists.txt" />
+ <ProjectReference Include="DefaultTest.csproj" />
+ </ItemGroup>
+ <Import Project="../../../Interop.settings.targets" />
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace TestInALC
+{
+ class Test
+ {
+ static int Main(string[] args)
+ {
+ string currentAssemblyDirectory = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath);
+ string testAssemblyFullPath = Path.Combine(currentAssemblyDirectory, "DefaultTest.exe");
+ return TestLibrary.Utilities.ExecuteAndUnload(testAssemblyFullPath, args);
+ }
+ }
+}