}
CONTRACTL_END;
- m_fDisableInterfaceCache = FALSE;
-
m_pTPABinderContext = NULL;
// Make sure the container is set to NULL so that it gets loaded when it is used.
}
}
-void AppDomain::ReleaseFiles()
-{
- STANDARD_VM_CONTRACT;
-
- // Shutdown assemblies
- AssemblyIterator i = IterateAssembliesEx((AssemblyIterationFlags)(
- kIncludeLoaded | kIncludeExecution | kIncludeFailedToLoad | kIncludeLoading));
- CollectibleAssemblyHolder<DomainAssembly *> pAsm;
-
- while (i.Next(pAsm.This()))
- {
- if (pAsm->GetCurrentAssembly() == NULL)
- {
- // Might be domain neutral or not, but should have no live objects as it has not been
- // really loaded yet. Just reset it.
- _ASSERTE(FitsIn<DWORD>(i.GetIndex()));
- m_Assemblies.Set(this, static_cast<DWORD>(i.GetIndex()), NULL);
- delete pAsm.Extract();
- }
- else
- {
- pAsm->ReleaseFiles();
- }
- }
-} // AppDomain::ReleaseFiles
-
-
OBJECTREF* BaseDomain::AllocateObjRefPtrsInLargeTable(int nRequested, OBJECTREF** ppLazyAllocate)
{
CONTRACTL
}
}
-void AppDomain::InsertClassForCLSID(MethodTable* pMT, GUID *pGuid)
-{
- CONTRACT_VOID
- {
- NOTHROW;
- PRECONDITION(CheckPointer(pMT));
- PRECONDITION(CheckPointer(pGuid));
- }
- CONTRACT_END;
-
- LPVOID val = (LPVOID)pMT;
- {
- LockHolder lh(this);
-
- CVID* cvid = pGuid;
- if (LookupClass(*cvid) != pMT)
- {
- m_clsidHash.InsertValue(GetKeyFromGUID(pGuid), val);
- }
- }
-
- RETURN;
-}
#endif // DACCESS_COMPILE
#ifdef FEATURE_COMINTEROP
#ifdef _DEBUG
m_dwIterHolders=0;
- m_dwRefTakers=0;
- m_dwCreationHolders=0;
#endif
#ifdef FEATURE_TYPEEQUIVALENCE
#ifndef CROSSGEN_COMPILE
- _ASSERTE(m_dwCreationHolders == 0);
-
// release the TPIndex. note that since TPIndex values are recycled the TPIndex
// can only be released once all threads in the AppDomain have exited.
if (GetTPIndex().m_dwIndex != 0)
return NULL;
}
- void SetDisableInterfaceCache()
- {
- m_fDisableInterfaceCache = TRUE;
- }
- BOOL GetDisableInterfaceCache()
- {
- return m_fDisableInterfaceCache;
- }
-
#ifdef FEATURE_COMINTEROP
MngStdInterfacesInfo * GetMngStdInterfacesInfo()
{
// Used to protect the assembly list. Taken also by GC or debugger thread, therefore we have to avoid
// triggering GC while holding this lock (by switching the thread to GC_NOTRIGGER while it is held).
CrstExplicitInit m_crstAssemblyList;
- BOOL m_fDisableInterfaceCache; // RCW COM interface cache
ListLock m_ClassInitLock;
JitListLock m_JITLock;
ListLock m_ILStubGenLock;
// final assembly cleanup
void ShutdownFreeLoaderAllocators();
- void ReleaseFiles();
-
virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; }
virtual PTR_AppDomain AsAppDomain() { LIMITED_METHOD_CONTRACT; return dac_cast<PTR_AppDomain>(this); }
PEAssembly* FindCachedFile(AssemblySpec* pSpec, BOOL fThrow = TRUE);
BOOL IsCached(AssemblySpec *pSpec);
#endif // DACCESS_COMPILE
- void CacheStringsForDAC();
BOOL AddFileToCache(AssemblySpec* pSpec, PEAssembly *pFile, BOOL fAllowFailure = FALSE);
BOOL RemoveFileFromCache(PEAssembly *pFile);
// Create a quick lookup for classes loaded into this domain based on their GUID.
//
void InsertClassForCLSID(MethodTable* pMT, BOOL fForceInsert = FALSE);
- void InsertClassForCLSID(MethodTable* pMT, GUID *pGuid);
#ifdef FEATURE_COMINTEROP
private:
static void ExceptionUnwind(Frame *pFrame);
- static void RefTakerAcquire(AppDomain* pDomain)
- {
- WRAPPER_NO_CONTRACT;
- if(!pDomain)
- return;
- pDomain->AddRef();
-#ifdef _DEBUG
- FastInterlockIncrement(&pDomain->m_dwRefTakers);
-#endif
- }
-
- static void RefTakerRelease(AppDomain* pDomain)
- {
- WRAPPER_NO_CONTRACT;
- if(!pDomain)
- return;
-#ifdef _DEBUG
- _ASSERTE(pDomain->m_dwRefTakers);
- FastInterlockDecrement(&pDomain->m_dwRefTakers);
-#endif
- pDomain->Release();
- }
-
#ifdef _DEBUG
BOOL IsHeldByIterator()
return m_dwIterHolders>0;
}
- BOOL IsHeldByRefTaker()
- {
- LIMITED_METHOD_CONTRACT;
- return m_dwRefTakers>0;
- }
-
void IteratorRelease()
{
LIMITED_METHOD_CONTRACT;
return m_Stage >= STAGE_ACTIVE;
}
- // Range for normal execution of code in the appdomain, currently used for
- // appdomain resource monitoring since we don't care to update resource usage
- // unless it's in these stages (as fields of AppDomain may not be valid if it's
- // not within these stages)
- BOOL IsUserActive()
- {
- LIMITED_METHOD_DAC_CONTRACT;
- return m_Stage >= STAGE_ACTIVE && m_Stage <= STAGE_OPEN;
- }
BOOL IsValid()
{
LIMITED_METHOD_DAC_CONTRACT;
#endif
}
-#ifdef _DEBUG
- BOOL IsBeingCreated()
- {
- LIMITED_METHOD_CONTRACT;
-
- return m_dwCreationHolders > 0;
- }
-
- void IncCreationCount()
- {
- LIMITED_METHOD_CONTRACT;
-
- FastInterlockIncrement(&m_dwCreationHolders);
- _ASSERTE(m_dwCreationHolders > 0);
- }
-
- void DecCreationCount()
- {
- LIMITED_METHOD_CONTRACT;
-
- FastInterlockDecrement(&m_dwCreationHolders);
- _ASSERTE(m_dwCreationHolders > -1);
- }
-#endif
- BOOL NotReadyForManagedCode()
- {
- LIMITED_METHOD_CONTRACT;
-
- return m_Stage < STAGE_READYFORMANAGEDCODE;
- }
static void RaiseExitProcessEvent();
Assembly* RaiseResourceResolveEvent(DomainAssembly* pAssembly, LPCSTR szName);
#ifdef _DEBUG
Volatile<LONG> m_dwIterHolders;
- Volatile<LONG> m_dwRefTakers;
- Volatile<LONG> m_dwCreationHolders;
#endif
//
#endif
}; // class AppDomain
-
-// This holder is to be used to take a reference to make sure AppDomain* is still valid
-// Please do not use if you are aleady ADU-safe
-typedef Wrapper<AppDomain*,AppDomain::RefTakerAcquire,AppDomain::RefTakerRelease,NULL> AppDomainRefTaker;
-
// Just a ref holder
typedef ReleaseHolder<AppDomain> AppDomainRefHolder;
}
#endif // CROSSGEN_COMPILE
-void Module::ReleaseILData(void)
-{
- WRAPPER_NO_CONTRACT;
-
- ReleaseISymUnmanagedReader();
-}
-
-
-
//---------------------------------------------------------------------------------------
//
// Simple wrapper around calling IsAfContentType_WindowsRuntime() against the flags
CaptureModuleMetaDataToMemory();
}
-void ReflectionModule::ReleaseILData()
-{
- WRAPPER_NO_CONTRACT;
-
- if (m_pISymUnmanagedWriter)
- {
- m_pISymUnmanagedWriter->Release();
- m_pISymUnmanagedWriter = NULL;
- }
-
- Module::ReleaseILData();
-}
#endif // !CROSSGEN_COMPILE
#endif // !DACCESS_COMPILE
// concurrently with other uses of the reader (i.e. not shutdown/unload time)
void ReleaseISymUnmanagedReader(void);
- virtual void ReleaseILData();
-
-
#endif // DACCESS_COMPILE
// IL stub cache
static ReflectionModule *Create(Assembly *pAssembly, PEFile *pFile, AllocMemTracker *pamTracker, LPCWSTR szName, BOOL fIsTransient);
void Initialize(AllocMemTracker *pamTracker, LPCWSTR szName);
void Destruct();
-
- void ReleaseILData();
#endif // !DACCESS_COMPILE && !CROSSGEN_COMPILE
// Overides functions to access sections
#ifndef DACCESS_COMPILE
-void DomainFile::ReleaseFiles()
-{
- WRAPPER_NO_CONTRACT;
- Module* pModule=GetCurrentModule();
- if(pModule)
- pModule->StartUnload();
-
- if (m_pFile)
- m_pFile->ReleaseIL();
- if(m_pOriginalFile)
- m_pOriginalFile->ReleaseIL();
-
- if(pModule)
- pModule->ReleaseILData();
-}
-
-BOOL DomainFile::TryEnsureActive()
-{
- CONTRACT(BOOL)
- {
- INSTANCE_CHECK;
- THROWS;
- GC_TRIGGERS;
- }
- CONTRACT_END;
-
- BOOL success = TRUE;
-
- EX_TRY
- {
- EnsureActive();
- }
- EX_CATCH
- {
- success = FALSE;
- }
- EX_END_CATCH(RethrowTransientExceptions);
-
- RETURN success;
-}
-
// Optimization intended for EnsureLoadLevel only
#include <optsmallperfcritical.h>
void DomainFile::EnsureLoadLevel(FileLoadLevel targetLevel)
}
}
-void DomainAssembly::ReleaseFiles()
-{
- STANDARD_VM_CONTRACT;
-
- if(m_pAssembly)
- m_pAssembly->StartUnload();
- ModuleIterator i = IterateModules(kModIterIncludeLoading);
- while (i.Next())
- {
- if (i.GetDomainFile() != this)
- i.GetDomainFile()->ReleaseFiles();
- }
-
- DomainFile::ReleaseFiles();
-}
-
void DomainAssembly::SetAssembly(Assembly* pAssembly)
{
STANDARD_VM_CONTRACT;
}
#endif
-
- void ReleaseFiles() DAC_EMPTY();
-
virtual BOOL IsAssembly() = 0;
DomainAssembly *GetDomainAssembly();
return EnsureLoadLevel(FILE_LOAD_LOADLIBRARY);
}
- // This wraps EnsureActive, suppressing non-transient exceptions
- BOOL TryEnsureActive();
-
// EnsureLoadLevel is a generic routine used to ensure that the file is not in a delay loaded
// state (unless it needs to be.) This should be used when a particular level of loading
// is required for an operation. Note that deadlocks are tolerated so the level may be one
return m_pLoaderAllocator;
}
-#ifndef DACCESS_COMPILE
- void ReleaseFiles();
-#endif // DACCESS_COMPILE
-
// Finds only loaded hmods
DomainFile *FindIJWModule(HMODULE hMod);
}
}
-#ifndef DACCESS_COMPILE
-void PEFile::ReleaseIL()
-{
- WRAPPER_NO_CONTRACT;
- if (m_openedILimage!=NULL )
- {
- ReleaseMetadataInterfaces(TRUE, TRUE);
- if (m_identity != NULL)
- {
- m_identity->Release();
- m_identity=NULL;
- }
- m_openedILimage->Release();
- m_openedILimage = NULL;
- }
-}
-#endif
-
/* static */
PEFile *PEFile::Open(PEImage *image)
{
}
-#ifndef DACCESS_COMPILE
-void PEAssembly::ReleaseIL()
-{
- CONTRACTL
- {
- INSTANCE_CHECK;
- NOTHROW;
- GC_TRIGGERS;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- GCX_PREEMP();
- if (m_creator != NULL)
- {
- m_creator->Release();
- m_creator=NULL;
- }
-
- PEFile::ReleaseIL();
-}
-#endif
-
/* static */
-
PEAssembly *PEAssembly::OpenSystem(IUnknown * pAppCtx)
{
STANDARD_VM_CONTRACT;
#ifndef DACCESS_COMPILE
PEFile(PEImage *image);
virtual ~PEFile();
-
- virtual void ReleaseIL();
#else
virtual ~PEFile() {}
#endif
ULONG HashIdentity();
-#ifndef DACCESS_COMPILE
- virtual void ReleaseIL();
-#endif
-
// ------------------------------------------------------------
// Descriptive strings
// ------------------------------------------------------------
}
AppDomain * pAppDomain = GetAppDomain();
- if((flags & CF_QueryForIdentity) ||
- (pAppDomain && pAppDomain->GetDisableInterfaceCache()))
+ if(flags & CF_QueryForIdentity)
{
IUnknown *pUnkTemp = NULL;
HRESULT hr = SafeQueryInterfacePreemp(pUnk, IID_IUnknown, &pUnkTemp);
if (pUnk == NULL)
RETURN NULL;
- // See if we should cache the result in the fast inline cache. This cache can only store interface pointers
- // returned from QI's in the same context where we created the RCW.
- bool fAllowCache = true;
bool fAllowOutOfContextCache = true;
-
if (!pMT->IsProjectedFromWinRT() && !pMT->IsWinRTRedirectedInterface(TypeHandle::Interop_ManagedToNative) && !pMT->IsWinRTRedirectedDelegate())
{
- AppDomain *pAppDomain = GetAppDomain();
- if (pAppDomain && pAppDomain->GetDisableInterfaceCache())
- {
- // Caching is disabled in this AD
- fAllowCache = false;
- }
- else
- {
- // This is not a WinRT interface and we could in theory use the out-of-context auxiliary cache,
- // at worst we would just do
- // fAllowOutOfContextCache = !IsURTAggregated()
- // however such a change has some breaking potential (COM proxies would live much longer) and is
- // considered to risky for an in-place release.
+ // This is not a WinRT interface and we could in theory use the out-of-context auxiliary cache,
+ // at worst we would just do
+ // fAllowOutOfContextCache = !IsURTAggregated()
+ // however such a change has some breaking potential (COM proxies would live much longer) and is
+ // considered to risky for an in-place release.
- fAllowOutOfContextCache = false;
- }
+ fAllowOutOfContextCache = false;
}
- // try to cache the interface pointer in the inline cache
+ // try to cache the interface pointer in the inline cache. This cache can only store interface pointers
+ // returned from QI's in the same context where we created the RCW.
bool fInterfaceCached = false;
- if (fAllowCache)
+ if (GetWrapperCtxCookie() == pCtxCookie || IsFreeThreaded())
{
- if (GetWrapperCtxCookie() == pCtxCookie || IsFreeThreaded())
+ for (i = 0; i < INTERFACE_ENTRY_CACHE_SIZE; i++)
{
- for (i = 0; i < INTERFACE_ENTRY_CACHE_SIZE; i++)
+ if (m_aInterfaceEntries[i].IsFree() && m_aInterfaceEntries[i].Init(pMT, pUnk))
{
- if (m_aInterfaceEntries[i].IsFree() && m_aInterfaceEntries[i].Init(pMT, pUnk))
+ // If the component is not aggregated then we need to ref-count
+ if (!IsURTAggregated())
{
- // If the component is not aggregated then we need to ref-count
- if (!IsURTAggregated())
- {
- // Get an extra addref to hold this reference alive in our cache
- cbRef = SafeAddRef(pUnk);
- LogInteropAddRef(pUnk, cbRef, "RCW::GetComIPForMethodTableFromCache: Addref because storing pUnk in InterfaceEntry cache");
-
- // Notify Jupiter we have done a AddRef
- // We should do this *after* we made a AddRef because we should never
- // be in a state where report refs > actual refs
- RCWWalker::AfterInterfaceAddRef(this);
- }
-
- fInterfaceCached = true;
- break;
+ // Get an extra addref to hold this reference alive in our cache
+ cbRef = SafeAddRef(pUnk);
+ LogInteropAddRef(pUnk, cbRef, "RCW::GetComIPForMethodTableFromCache: Addref because storing pUnk in InterfaceEntry cache");
+
+ // Notify Jupiter we have done a AddRef
+ // We should do this *after* we made a AddRef because we should never
+ // be in a state where report refs > actual refs
+ RCWWalker::AfterInterfaceAddRef(this);
}
+
+ fInterfaceCached = true;
+ break;
}
}
+ }
- if (!fInterfaceCached && fAllowOutOfContextCache)
- {
- // We couldn't insert into the inline cache, either because it didn't fit, or because
- // we are in a wrong COM context. We'll use the RCWAuxiliaryData structure.
- GetOrCreateAuxiliaryData()->CacheInterfacePointer(pMT, pUnk, (IsFreeThreaded() ? NULL : pCtxCookie));
-
- // If the component is not aggregated then we need to ref-count
- if (!IsURTAggregated())
- {
- // Get an extra addref to hold this reference alive in our cache
- cbRef = SafeAddRef(pUnk);
- LogInteropAddRef(pUnk, cbRef, "RCW::GetComIPForMethodTableFromCache: Addref because storing pUnk in the auxiliary interface pointer cache");
+ if (!fInterfaceCached && fAllowOutOfContextCache)
+ {
+ // We couldn't insert into the inline cache, either because it didn't fit, or because
+ // we are in a wrong COM context. We'll use the RCWAuxiliaryData structure.
+ GetOrCreateAuxiliaryData()->CacheInterfacePointer(pMT, pUnk, (IsFreeThreaded() ? NULL : pCtxCookie));
- // Notify Jupiter we have done a AddRef
- // We should do this *after* we made a AddRef because we should never
- // be in a state where report refs > actual refs
- RCWWalker::AfterInterfaceAddRef(this);
- }
+ // If the component is not aggregated then we need to ref-count
+ if (!IsURTAggregated())
+ {
+ // Get an extra addref to hold this reference alive in our cache
+ cbRef = SafeAddRef(pUnk);
+ LogInteropAddRef(pUnk, cbRef, "RCW::GetComIPForMethodTableFromCache: Addref because storing pUnk in the auxiliary interface pointer cache");
- fInterfaceCached = true;
+ // Notify Jupiter we have done a AddRef
+ // We should do this *after* we made a AddRef because we should never
+ // be in a state where report refs > actual refs
+ RCWWalker::AfterInterfaceAddRef(this);
}
+
+ fInterfaceCached = true;
}
// Make sure we cache successful QI's for variant interfaces. This is so we can cast an RCW for