2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
6 /*============================================================
8 ** Header: AppDomain.cpp
12 ** Purpose: Implements AppDomain (loader domain) architecture
15 ===========================================================*/
19 #ifndef CLR_STANDALONE_BINDER
20 #include "eventtrace.h"
21 #include "assembly.hpp"
22 #include "clsload.hpp"
27 #include "arraylist.h"
28 #include "comreflectioncache.hpp"
29 #include "comutilnative.h"
30 #include "domainfile.h"
31 #include "objectlist.h"
32 #include "fptrstubs.h"
33 #include "ilstubcache.h"
34 #include "testhookmgr.h"
35 #ifdef FEATURE_VERSIONING
36 #include "../binder/inc/applicationcontext.hpp"
37 #endif // FEATURE_VERSIONING
40 #ifdef FEATURE_MULTICOREJIT
41 #include "multicorejit.h"
44 #ifdef FEATURE_COMINTEROP
45 #include "clrprivbinderwinrt.h"
46 #ifndef FEATURE_CORECLR
47 #include "clrprivbinderreflectiononlywinrt.h"
48 #include "clrprivtypecachereflectiononlywinrt.h"
50 #include "..\md\winmd\inc\adapter.h"
51 #include "winrttypenameconverter.h"
52 #endif // FEATURE_COMINTEROP
54 #else // CLR_STANDALONE_BINDER
59 typedef DPTR(OBJECTREF) PTR_OBJECTREF;
60 typedef DPTR(DomainFile) PTR_DomainFile;
61 typedef DPTR(IdDispenser) PTR_IdDispenser;
62 #include "..\md\winmd\inc\adapter.h"
63 #endif // CLR_STANDALONE_BINDER
71 class CompilationDomain;
74 class EEMarshalingData;
76 class GlobalStringLiteralMap;
77 class StringLiteralMap;
78 struct SecurityContext;
79 class MngStdInterfacesInfo;
82 struct InteropMethodTableData;
83 class LoadLevelLimiter;
84 class UMEntryThunkCache;
85 class TypeEquivalenceHashTable;
86 class IApplicationSecurityDescriptor;
87 class StringArrayList;
89 typedef VPTR(IApplicationSecurityDescriptor) PTR_IApplicationSecurityDescriptor;
91 extern INT64 g_PauseTime; // Total time in millisecond the CLR has been paused
93 #ifdef FEATURE_COMINTEROP
94 class ComCallWrapperCache;
95 struct SimpleComCallWrapper;
99 // This enum is used to specify whether user want COM or remoting
100 enum COMorRemotingFlag {
101 COMorRemoting_NotInitialized = 0,
102 COMorRemoting_COM = 1, // COM will be used both cross-domain and cross-runtime
103 COMorRemoting_Remoting = 2, // Remoting will be used cross-domain; cross-runtime will use Remoting only if it looks like it's expected (default)
104 COMorRemoting_LegacyMode = 3 // Remoting will be used both cross-domain and cross-runtime
107 #endif // FEATURE_COMINTEROP
110 #pragma warning(push)
111 #pragma warning(disable : 4200) // Disable zero-sized array warning
115 GPTR_DECL(IdDispenser, g_pModuleIndexDispenser);
117 // This enum is aligned to System.ExceptionCatcherType.
118 enum ExceptionCatcher {
119 ExceptionCatcher_ManagedCode = 0,
120 ExceptionCatcher_AppDomainTransition = 1,
121 ExceptionCatcher_COMInterop = 2,
124 // We would like *ALLOCATECLASS_FLAG to AV (in order to catch errors), so don't change it
125 struct ClassInitFlags {
128 INITIALIZED_FLAG_BIT = 0,
129 INITIALIZED_FLAG = 1<<INITIALIZED_FLAG_BIT,
131 ERROR_FLAG = 1<<ERROR_FLAG_BIT,
132 ALLOCATECLASS_FLAG_BIT = 2, // Bit to avoid racing for InstantiateStaticHandles
133 ALLOCATECLASS_FLAG = 1<<ALLOCATECLASS_FLAG_BIT,
134 COLLECTIBLE_FLAG_BIT = 3,
135 COLLECTIBLE_FLAG = 1<<COLLECTIBLE_FLAG_BIT
139 struct DomainLocalModule
141 friend class ClrDataAccess;
142 friend class CheckAsmOffsets;
143 friend struct ThreadLocalModule;
145 // After these macros complete, they may have returned an interior pointer into a gc object. This pointer will have been cast to a byte pointer
146 // It is critically important that no GC is allowed to occur before this pointer is used.
147 #define GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLoaderAllocator, dynamicClassInfoParam, pGCStatics) \
149 DomainLocalModule::PTR_DynamicClassInfo dynamicClassInfo = dac_cast<DomainLocalModule::PTR_DynamicClassInfo>(dynamicClassInfoParam);\
150 DomainLocalModule::PTR_DynamicEntry pDynamicEntry = dac_cast<DomainLocalModule::PTR_DynamicEntry>((DomainLocalModule::DynamicEntry*)dynamicClassInfo->m_pDynamicEntry.Load()); \
151 if ((dynamicClassInfo->m_dwFlags) & ClassInitFlags::COLLECTIBLE_FLAG) \
153 PTRARRAYREF objArray;\
154 objArray = (PTRARRAYREF)pLoaderAllocator->GetHandleValueFastCannotFailType2( \
155 (dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hGCStatics);\
156 *(pGCStatics) = dac_cast<PTR_BYTE>(PTR_READ(PTR_TO_TADDR(OBJECTREFToObject( objArray )) + offsetof(PtrArray, m_Array), objArray->GetNumComponents() * sizeof(void*))) ;\
160 *(pGCStatics) = (dac_cast<DomainLocalModule::PTR_NormalDynamicEntry>(pDynamicEntry))->GetGCStaticsBasePointer();\
164 #define GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLoaderAllocator, dynamicClassInfoParam, pNonGCStatics) \
166 DomainLocalModule::PTR_DynamicClassInfo dynamicClassInfo = dac_cast<DomainLocalModule::PTR_DynamicClassInfo>(dynamicClassInfoParam);\
167 DomainLocalModule::PTR_DynamicEntry pDynamicEntry = dac_cast<DomainLocalModule::PTR_DynamicEntry>((DomainLocalModule::DynamicEntry*)(dynamicClassInfo)->m_pDynamicEntry.Load()); \
168 if (((dynamicClassInfo)->m_dwFlags) & ClassInitFlags::COLLECTIBLE_FLAG) \
170 if ((dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hNonGCStatics != 0) \
172 U1ARRAYREF objArray;\
173 objArray = (U1ARRAYREF)pLoaderAllocator->GetHandleValueFastCannotFailType2( \
174 (dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hNonGCStatics);\
175 *(pNonGCStatics) = dac_cast<PTR_BYTE>(PTR_READ( \
176 PTR_TO_TADDR(OBJECTREFToObject( objArray )) + sizeof(ArrayBase) - DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob(), \
177 objArray->GetNumComponents() * (DWORD)objArray->GetComponentSize() + DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob())); \
178 } else (*pNonGCStatics) = NULL; \
182 *(pNonGCStatics) = dac_cast<DomainLocalModule::PTR_NormalDynamicEntry>(pDynamicEntry)->GetNonGCStaticsBasePointer();\
188 static DWORD GetOffsetOfDataBlob();
190 typedef DPTR(DynamicEntry) PTR_DynamicEntry;
192 struct CollectibleDynamicEntry : public DynamicEntry
194 LOADERHANDLE m_hGCStatics;
195 LOADERHANDLE m_hNonGCStatics;
197 typedef DPTR(CollectibleDynamicEntry) PTR_CollectibleDynamicEntry;
199 struct NormalDynamicEntry : public DynamicEntry
201 PTR_OBJECTREF m_pGCStatics;
202 #ifdef FEATURE_64BIT_ALIGNMENT
203 // Padding to make m_pDataBlob aligned at MAX_PRIMITIVE_FIELD_SIZE
204 // code:MethodTableBuilder::PlaceRegularStaticFields assumes that the start of the data blob is aligned
209 inline PTR_BYTE GetGCStaticsBasePointer()
211 LIMITED_METHOD_CONTRACT;
213 return dac_cast<PTR_BYTE>(m_pGCStatics);
215 inline PTR_BYTE GetNonGCStaticsBasePointer()
217 LIMITED_METHOD_CONTRACT
219 return dac_cast<PTR_BYTE>(this);
222 typedef DPTR(NormalDynamicEntry) PTR_NormalDynamicEntry;
224 struct DynamicClassInfo
226 VolatilePtr<DynamicEntry, PTR_DynamicEntry> m_pDynamicEntry;
227 Volatile<DWORD> m_dwFlags;
229 typedef DPTR(DynamicClassInfo) PTR_DynamicClassInfo;
231 inline UMEntryThunk * GetADThunkTable()
233 LIMITED_METHOD_CONTRACT
234 return m_pADThunkTable;
237 inline void SetADThunkTable(UMEntryThunk* pADThunkTable)
239 LIMITED_METHOD_CONTRACT
240 InterlockedCompareExchangeT(m_pADThunkTable.GetPointer(), pADThunkTable, NULL);
243 // Note the difference between:
245 // GetPrecomputedNonGCStaticsBasePointer() and
246 // GetPrecomputedStaticsClassData()
248 // GetPrecomputedNonGCStaticsBasePointer returns the pointer that should be added to field offsets to retrieve statics
249 // GetPrecomputedStaticsClassData returns a pointer to the first byte of the precomputed statics block
250 inline TADDR GetPrecomputedNonGCStaticsBasePointer()
252 LIMITED_METHOD_CONTRACT
253 return dac_cast<TADDR>(this);
256 inline PTR_BYTE GetPrecomputedStaticsClassData()
258 LIMITED_METHOD_CONTRACT
259 return dac_cast<PTR_BYTE>(this) + offsetof(DomainLocalModule, m_pDataBlob);
262 static SIZE_T GetOffsetOfDataBlob() { return offsetof(DomainLocalModule, m_pDataBlob); }
263 static SIZE_T GetOffsetOfGCStaticPointer() { return offsetof(DomainLocalModule, m_pGCStatics); }
265 inline DomainFile* GetDomainFile()
267 LIMITED_METHOD_CONTRACT
269 return m_pDomainFile;
272 #ifndef DACCESS_COMPILE
273 inline void SetDomainFile(DomainFile* pDomainFile)
275 LIMITED_METHOD_CONTRACT
276 m_pDomainFile = pDomainFile;
280 inline PTR_OBJECTREF GetPrecomputedGCStaticsBasePointer()
282 LIMITED_METHOD_CONTRACT
286 inline PTR_OBJECTREF * GetPrecomputedGCStaticsBasePointerAddress()
288 LIMITED_METHOD_CONTRACT
289 return &m_pGCStatics;
292 #ifndef CLR_STANDALONE_BINDER
293 // Returns bytes so we can add offsets
294 inline PTR_BYTE GetGCStaticsBasePointer(MethodTable * pMT)
299 if (pMT->IsDynamicStatics())
301 _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics());
302 return GetDynamicEntryGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator());
306 return dac_cast<PTR_BYTE>(m_pGCStatics);
310 inline PTR_BYTE GetNonGCStaticsBasePointer(MethodTable * pMT)
315 if (pMT->IsDynamicStatics())
317 _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics());
318 return GetDynamicEntryNonGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator());
322 return dac_cast<PTR_BYTE>(this);
325 #endif // !CLR_STANDALONE_BINDER
327 inline DynamicClassInfo* GetDynamicClassInfo(DWORD n)
329 LIMITED_METHOD_CONTRACT
331 _ASSERTE(m_pDynamicClassTable.Load() && m_aDynamicEntries > n);
332 dac_cast<PTR_DynamicEntry>(m_pDynamicClassTable[n].m_pDynamicEntry.Load());
334 return &m_pDynamicClassTable[n];
337 #ifndef CLR_STANDALONE_BINDER
338 // These helpers can now return null, as the debugger may do queries on a type
339 // before the calls to PopulateClass happen
340 inline PTR_BYTE GetDynamicEntryGCStaticsBasePointer(DWORD n, PTR_LoaderAllocator pLoaderAllocator)
353 if (n >= m_aDynamicEntries)
358 DynamicClassInfo* pClassInfo = GetDynamicClassInfo(n);
359 if (!pClassInfo->m_pDynamicEntry)
364 PTR_BYTE retval = NULL;
366 GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLoaderAllocator, pClassInfo, &retval);
371 inline PTR_BYTE GetDynamicEntryNonGCStaticsBasePointer(DWORD n, PTR_LoaderAllocator pLoaderAllocator)
384 if (n >= m_aDynamicEntries)
389 DynamicClassInfo* pClassInfo = GetDynamicClassInfo(n);
390 if (!pClassInfo->m_pDynamicEntry)
395 PTR_BYTE retval = NULL;
397 GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLoaderAllocator, pClassInfo, &retval);
401 #endif // CLR_STANDALONE_BINDER
403 FORCEINLINE PTR_DynamicClassInfo GetDynamicClassInfoIfInitialized(DWORD n)
407 // m_aDynamicEntries is set last, it needs to be checked first
408 if (n >= m_aDynamicEntries)
413 _ASSERTE(m_pDynamicClassTable.Load() != NULL);
414 PTR_DynamicClassInfo pDynamicClassInfo = (PTR_DynamicClassInfo)(m_pDynamicClassTable.Load() + n);
416 // INITIALIZED_FLAG is set last, it needs to be checked first
417 if ((pDynamicClassInfo->m_dwFlags & ClassInitFlags::INITIALIZED_FLAG) == 0)
422 PREFIX_ASSUME(pDynamicClassInfo != NULL);
423 return pDynamicClassInfo;
426 // iClassIndex is slightly expensive to compute, so if we already know
427 // it, we can use this helper
428 inline BOOL IsClassInitialized(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
431 return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::INITIALIZED_FLAG) != 0;
434 inline BOOL IsPrecomputedClassInitialized(DWORD classID)
436 return GetPrecomputedStaticsClassData()[classID] & ClassInitFlags::INITIALIZED_FLAG;
439 inline BOOL IsClassAllocated(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
442 return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::ALLOCATECLASS_FLAG) != 0;
445 BOOL IsClassInitError(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
448 return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::ERROR_FLAG) != 0;
451 void SetClassInitialized(MethodTable* pMT);
452 void SetClassInitError(MethodTable* pMT);
454 void EnsureDynamicClassIndex(DWORD dwID);
456 void AllocateDynamicClass(MethodTable *pMT);
458 void PopulateClass(MethodTable *pMT);
460 #ifdef DACCESS_COMPILE
461 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
464 static DWORD OffsetOfDataBlob()
466 LIMITED_METHOD_CONTRACT;
467 return offsetof(DomainLocalModule, m_pDataBlob);
470 #ifndef CLR_STANDALONE_BINDER
471 FORCEINLINE MethodTable * GetMethodTableFromClassDomainID(DWORD dwClassDomainID)
473 DWORD rid = (DWORD)(dwClassDomainID) + 1;
474 TypeHandle th = GetDomainFile()->GetModule()->LookupTypeDef(TokenFromRid(rid, mdtTypeDef));
475 _ASSERTE(!th.IsNull());
476 MethodTable * pMT = th.AsMethodTable();
477 PREFIX_ASSUME(pMT != NULL);
480 #endif // CLR_STANDALONE_BINDER
483 friend void EmitFastGetSharedStaticBase(CPUSTUBLINKER *psl, CodeLabel *init, bool bCCtorCheck);
485 void SetClassFlags(MethodTable* pMT, DWORD dwFlags);
486 DWORD GetClassFlags(MethodTable* pMT, DWORD iClassIndex);
488 PTR_DomainFile m_pDomainFile;
489 VolatilePtr<DynamicClassInfo, PTR_DynamicClassInfo> m_pDynamicClassTable; // used for generics and reflection.emit in memory
490 Volatile<SIZE_T> m_aDynamicEntries; // number of entries in dynamic table
491 VolatilePtr<UMEntryThunk> m_pADThunkTable;
492 PTR_OBJECTREF m_pGCStatics; // Handle to GC statics of the module
494 // In addition to storing the ModuleIndex in the Module class, we also
495 // keep a copy of the ModuleIndex in the DomainLocalModule class. This
496 // allows the thread static JIT helpers to quickly convert a pointer to
497 // a DomainLocalModule into a ModuleIndex.
498 ModuleIndex m_ModuleIndex;
500 // Note that the static offset calculation in code:Module::BuildStaticsOffsets takes the offset m_pDataBlob
501 // into consideration for alignment so we do not need any padding to ensure that the start of the data blob is aligned
503 BYTE m_pDataBlob[0]; // First byte of the statics blob
505 // Layout of m_pDataBlob is:
506 // ClassInit bytes (hold flags for cctor run, cctor error, etc)
511 // The Module class need to be able to initialized ModuleIndex,
512 // so for now I will make it a friend..
515 FORCEINLINE ModuleIndex GetModuleIndex()
517 LIMITED_METHOD_DAC_CONTRACT;
518 return m_ModuleIndex;
521 }; // struct DomainLocalModule
524 #ifndef CLR_STANDALONE_BINDER
526 typedef DPTR(class DomainLocalBlock) PTR_DomainLocalBlock;
527 class DomainLocalBlock
529 friend class ClrDataAccess;
530 friend class CheckAsmOffsets;
533 PTR_AppDomain m_pDomain;
534 DPTR(PTR_DomainLocalModule) m_pModuleSlots;
535 SIZE_T m_aModuleIndices; // Module entries the shared block has allocated
537 public: // used by code generators
538 static SIZE_T GetOffsetOfModuleSlotsPointer() { return offsetof(DomainLocalBlock, m_pModuleSlots);}
542 #ifndef DACCESS_COMPILE
544 : m_pDomain(NULL), m_pModuleSlots(NULL), m_aModuleIndices(0) {}
546 void EnsureModuleIndex(ModuleIndex index);
548 void Init(AppDomain *pDomain) { LIMITED_METHOD_CONTRACT; m_pDomain = pDomain; }
551 void SetModuleSlot(ModuleIndex index, PTR_DomainLocalModule pLocalModule);
553 FORCEINLINE PTR_DomainLocalModule GetModuleSlot(ModuleIndex index)
557 _ASSERTE(index.m_dwIndex < m_aModuleIndices);
558 return m_pModuleSlots[index.m_dwIndex];
561 inline PTR_DomainLocalModule GetModuleSlot(MethodTable* pMT)
564 return GetModuleSlot(pMT->GetModuleForStatics()->GetModuleIndex());
567 DomainFile* TryGetDomainFile(ModuleIndex index)
572 // the publishing of m_aModuleIndices and m_pModuleSlots is dependent
573 // on the order of accesses; we must ensure that we read from m_aModuleIndices
574 // before m_pModuleSlots.
575 if (index.m_dwIndex < m_aModuleIndices)
578 if (m_pModuleSlots[index.m_dwIndex])
580 return m_pModuleSlots[index.m_dwIndex]->GetDomainFile();
587 DomainFile* GetDomainFile(SIZE_T ModuleID)
590 ModuleIndex index = Module::IDToIndex(ModuleID);
591 _ASSERTE(index.m_dwIndex < m_aModuleIndices);
592 return m_pModuleSlots[index.m_dwIndex]->GetDomainFile();
595 #ifndef DACCESS_COMPILE
596 void SetDomainFile(ModuleIndex index, DomainFile* pDomainFile)
599 _ASSERTE(index.m_dwIndex < m_aModuleIndices);
600 m_pModuleSlots[index.m_dwIndex]->SetDomainFile(pDomainFile);
604 #ifdef DACCESS_COMPILE
605 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
612 // Low level routines to get & set class entries
622 // The large heap handle bucket class is used to contain handles allocated
623 // from an array contained in the large heap.
624 class LargeHeapHandleBucket
627 // Constructor and desctructor.
628 LargeHeapHandleBucket(LargeHeapHandleBucket *pNext, DWORD Size, BaseDomain *pDomain, BOOL bCrossAD = FALSE);
629 ~LargeHeapHandleBucket();
631 // This returns the next bucket.
632 LargeHeapHandleBucket *GetNext()
634 LIMITED_METHOD_CONTRACT;
639 // This returns the number of remaining handle slots.
640 DWORD GetNumRemainingHandles()
642 LIMITED_METHOD_CONTRACT;
644 return m_ArraySize - m_CurrentPos;
647 void ConsumeRemaining()
649 LIMITED_METHOD_CONTRACT;
651 m_CurrentPos = m_ArraySize;
654 OBJECTREF *TryAllocateEmbeddedFreeHandle();
656 // Allocate handles from the bucket.
657 OBJECTREF* AllocateHandles(DWORD nRequested);
658 OBJECTREF* CurrentPos()
660 LIMITED_METHOD_CONTRACT;
661 return m_pArrayDataPtr + m_CurrentPos;
665 LargeHeapHandleBucket *m_pNext;
668 int m_CurrentEmbeddedFreePos;
669 OBJECTHANDLE m_hndHandleArray;
670 OBJECTREF *m_pArrayDataPtr;
675 // The large heap handle table is used to allocate handles that are pointers
676 // to objects stored in an array in the large object heap.
677 class LargeHeapHandleTable
680 // Constructor and desctructor.
681 LargeHeapHandleTable(BaseDomain *pDomain, DWORD InitialBucketSize);
682 ~LargeHeapHandleTable();
684 // Allocate handles from the large heap handle table.
685 OBJECTREF* AllocateHandles(DWORD nRequested, BOOL bCrossAD = FALSE);
687 // Release object handles allocated using AllocateHandles().
688 void ReleaseHandles(OBJECTREF *pObjRef, DWORD nReleased);
691 // The buckets of object handles.
692 LargeHeapHandleBucket *m_pHead;
694 // We need to know the containing domain so we know where to allocate handles
695 BaseDomain *m_pDomain;
697 // The size of the LargeHeapHandleBuckets.
698 DWORD m_NextBucketSize;
700 // for finding and re-using embedded free items in the list
701 LargeHeapHandleBucket *m_pFreeSearchHint;
702 DWORD m_cEmbeddedFree;
706 // these functions are present to enforce that there is a locking mechanism in place
707 // for each LargeHeapHandleTable even though the code itself does not do the locking
708 // you must tell the table which lock you intend to use and it will verify that it has
709 // in fact been taken before performing any operations
712 void RegisterCrstDebug(CrstBase *pCrst)
714 LIMITED_METHOD_CONTRACT;
716 // this function must be called exactly once
717 _ASSERTE(pCrst != NULL);
718 _ASSERTE(m_pCrstDebug == NULL);
719 m_pCrstDebug = pCrst;
723 // we will assert that this Crst is held before using the object
724 CrstBase *m_pCrstDebug;
730 class LargeHeapHandleBlockHolder;
731 void LargeHeapHandleBlockHolder__StaticFree(LargeHeapHandleBlockHolder*);
734 class LargeHeapHandleBlockHolder:public Holder<LargeHeapHandleBlockHolder*,DoNothing,LargeHeapHandleBlockHolder__StaticFree>
737 LargeHeapHandleTable* m_pTable;
741 FORCEINLINE LargeHeapHandleBlockHolder(LargeHeapHandleTable* pOwner, DWORD nCount)
744 m_Data = pOwner->AllocateHandles(nCount);
749 FORCEINLINE void FreeData()
752 for (DWORD i=0;i< m_Count;i++)
753 ClearObjectReference(m_Data+i);
754 m_pTable->ReleaseHandles(m_Data, m_Count);
756 FORCEINLINE OBJECTREF* operator[] (DWORD idx)
758 LIMITED_METHOD_CONTRACT;
759 _ASSERTE(idx<m_Count);
760 return &(m_Data[idx]);
764 FORCEINLINE void LargeHeapHandleBlockHolder__StaticFree(LargeHeapHandleBlockHolder* pHolder)
774 // The large heap handle bucket class is used to contain handles allocated
775 // from an array contained in the large heap.
776 class ThreadStaticHandleBucket
779 // Constructor and desctructor.
780 ThreadStaticHandleBucket(ThreadStaticHandleBucket *pNext, DWORD Size, BaseDomain *pDomain);
781 ~ThreadStaticHandleBucket();
783 // This returns the next bucket.
784 ThreadStaticHandleBucket *GetNext()
786 LIMITED_METHOD_CONTRACT;
791 // Allocate handles from the bucket.
792 OBJECTHANDLE GetHandles();
795 ThreadStaticHandleBucket *m_pNext;
797 OBJECTHANDLE m_hndHandleArray;
801 // The large heap handle table is used to allocate handles that are pointers
802 // to objects stored in an array in the large object heap.
803 class ThreadStaticHandleTable
806 // Constructor and desctructor.
807 ThreadStaticHandleTable(BaseDomain *pDomain);
808 ~ThreadStaticHandleTable();
810 // Allocate handles from the large heap handle table.
811 OBJECTHANDLE AllocateHandles(DWORD nRequested);
814 // The buckets of object handles.
815 ThreadStaticHandleBucket *m_pHead;
817 // We need to know the containing domain so we know where to allocate handles
818 BaseDomain *m_pDomain;
824 //--------------------------------------------------------------------------------------
825 // Base class for domains. It provides an abstract way of finding the first assembly and
826 // for creating assemblies in the the domain. The system domain only has one assembly, it
827 // contains the classes that are logically shared between domains. All other domains can
828 // have multiple assemblies. Iteration is done be getting the first assembly and then
829 // calling the Next() method on the assembly.
831 // The system domain should be as small as possible, it includes object, exceptions, etc.
832 // which are the basic classes required to load other assemblies. All other classes
833 // should be loaded into the domain. Of coarse there is a trade off between loading the
834 // same classes multiple times, requiring all domains to load certain assemblies (working
835 // set) and being able to specify specific versions.
838 #define LOW_FREQUENCY_HEAP_RESERVE_SIZE (3 * PAGE_SIZE)
839 #define LOW_FREQUENCY_HEAP_COMMIT_SIZE (1 * PAGE_SIZE)
841 #define HIGH_FREQUENCY_HEAP_RESERVE_SIZE (10 * PAGE_SIZE)
842 #define HIGH_FREQUENCY_HEAP_COMMIT_SIZE (1 * PAGE_SIZE)
844 #define STUB_HEAP_RESERVE_SIZE (3 * PAGE_SIZE)
845 #define STUB_HEAP_COMMIT_SIZE (1 * PAGE_SIZE)
847 // --------------------------------------------------------------------------------
848 // PE File List lock - for creating list locks on PE files
849 // --------------------------------------------------------------------------------
851 class PEFileListLock : public ListLock
854 #ifndef DACCESS_COMPILE
855 ListLockEntry *FindFileLock(PEFile *pFile)
857 STATIC_CONTRACT_NOTHROW;
858 STATIC_CONTRACT_GC_NOTRIGGER;
859 STATIC_CONTRACT_FORBID_FAULT;
861 PRECONDITION(HasLock());
863 ListLockEntry *pEntry;
865 for (pEntry = m_pHead;
867 pEntry = pEntry->m_pNext)
869 if (((PEFile *)pEntry->m_pData)->Equals(pFile))
877 #endif // DACCESS_COMPILE
879 DEBUG_NOINLINE static void HolderEnter(PEFileListLock *pThis) PUB
882 ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
887 DEBUG_NOINLINE static void HolderLeave(PEFileListLock *pThis) PUB
890 ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
895 typedef Wrapper<PEFileListLock*, PEFileListLock::HolderEnter, PEFileListLock::HolderLeave> Holder;
898 typedef PEFileListLock::Holder PEFileListLockHolder;
900 // Loading infrastructure:
902 // a DomainFile is a file being loaded. Files are loaded in layers to enable loading in the
903 // presence of dependency loops.
905 // FileLoadLevel describes the various levels available. These are implemented slightly
906 // differently for assemblies and modules, but the basic structure is the same.
908 // LoadLock and FileLoadLock form the ListLock data structures for files. The FileLoadLock
909 // is specialized in that it allows taking a lock at a particular level. Basicall any
910 // thread may obtain the lock at a level at which the file has previously been loaded to, but
911 // only one thread may obtain the lock at its current level.
913 // The PendingLoadQueue is a per thread data structure which serves two purposes. First, it
914 // holds a "load limit" which automatically restricts the level of recursive loads to be
915 // one less than the current load which is preceding. This, together with the AppDomain
916 // LoadLock level behavior, will prevent any deadlocks from occuring due to circular
917 // dependencies. (Note that it is important that the loading logic understands this restriction,
918 // and any given level of loading must deal with the fact that any recursive loads will be partially
919 // unfulfilled in a specific way.)
921 // The second function is to queue up any unfulfilled load requests for the thread. These
922 // are then delivered immediately after the current load request is dealt with.
924 class FileLoadLock : public ListLockEntry
927 FileLoadLevel m_level;
928 DomainFile *m_pDomainFile;
933 static FileLoadLock *Create(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile);
936 DomainFile *GetDomainFile();
937 ADID GetAppDomainId();
938 FileLoadLevel GetLoadLevel();
940 // CanAcquire will return FALSE if Acquire will definitely not take the lock due
941 // to levels or deadlock.
942 // (Note that there is a race exiting from the function, where Acquire may end
943 // up not taking the lock anyway if another thread did work in the meantime.)
944 BOOL CanAcquire(FileLoadLevel targetLevel);
946 // Acquire will return FALSE and not take the lock if the file
947 // has already been loaded to the target level. Otherwise,
948 // it will return TRUE and take the lock.
950 // Note that the taker must release the lock via IncrementLoadLevel.
951 BOOL Acquire(FileLoadLevel targetLevel);
953 // CompleteLoadLevel can be called after Acquire returns true
954 // returns TRUE if it updated load level, FALSE if the level was set already
955 BOOL CompleteLoadLevel(FileLoadLevel level, BOOL success);
957 void SetError(Exception *ex);
960 UINT32 Release() DAC_EMPTY_RET(0);
964 FileLoadLock(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile);
966 static void HolderLeave(FileLoadLock *pThis);
969 typedef Wrapper<FileLoadLock *, DoNothing, FileLoadLock::HolderLeave> Holder;
973 typedef FileLoadLock::Holder FileLoadLockHolder;
975 #ifndef DACCESS_COMPILE
976 typedef ReleaseHolder<FileLoadLock> FileLoadLockRefHolder;
977 #endif // DACCESS_COMPILE
981 #pragma warning(push)
982 #pragma warning (disable: 4324) //sometimes 64bit compilers complain about alignment
984 class LoadLevelLimiter
986 FileLoadLevel m_currentLevel;
987 LoadLevelLimiter* m_previousLimit;
993 : m_currentLevel(FILE_ACTIVE),
994 m_previousLimit(NULL),
997 LIMITED_METHOD_CONTRACT;
1002 WRAPPER_NO_CONTRACT;
1003 m_previousLimit=GetThread()->GetLoadLevelLimiter();
1005 m_currentLevel=m_previousLimit->GetLoadLevel();
1006 GetThread()->SetLoadLevelLimiter(this);
1012 WRAPPER_NO_CONTRACT;
1015 GetThread()->SetLoadLevelLimiter(m_previousLimit);
1022 WRAPPER_NO_CONTRACT;
1024 // PendingLoadQueues are allocated on the stack during a load, and
1025 // shared with all nested loads on the same thread.
1027 // Make sure the thread pointer gets reset after the
1028 // top level queue goes out of scope.
1035 FileLoadLevel GetLoadLevel()
1037 LIMITED_METHOD_CONTRACT;
1038 return m_currentLevel;
1041 void SetLoadLevel(FileLoadLevel level)
1043 LIMITED_METHOD_CONTRACT;
1044 m_currentLevel = level;
1048 #pragma warning (pop) //4324
1051 #define OVERRIDE_LOAD_LEVEL_LIMIT(newLimit) \
1052 LoadLevelLimiter __newLimit; \
1053 __newLimit.Activate(); \
1054 __newLimit.SetLoadLevel(newLimit);
1056 // A BaseDomain much basic information in a code:AppDomain including
1058 // * code:#AppdomainHeaps - Heaps for any data structures that will be freed on appdomain unload
1062 friend class Assembly;
1063 friend class AssemblySpec;
1064 friend class AppDomain;
1065 friend class AppDomainNative;
1067 VPTR_BASE_VTABLE_CLASS(BaseDomain)
1068 VPTR_UNIQUE(VPTR_UNIQUE_BaseDomain)
1071 // These 2 variables are only used on the AppDomain, but by placing them here
1072 // we reduce the cost of keeping the asmconstants file up to date.
1074 // The creation sequence number of this app domain (starting from 1)
1075 // This ID is generated by the code:SystemDomain::GetNewAppDomainId routine
1076 // The ID are recycled.
1078 // see also code:ADID
1081 DomainLocalBlock m_sDomainLocalBlock;
1085 class AssemblyIterator;
1086 friend class AssemblyIterator;
1088 // Static initialization.
1089 static void Attach();
1091 //****************************************************************************************
1093 // Initialization/shutdown routines for every instance of an BaseDomain.
1100 // ID to uniquely identify this AppDomain - used by the AppDomain publishing
1101 // service (to publish the list of all appdomains present in the process),
1102 // which in turn is used by, for eg., the debugger (to decide which App-
1103 // Domain(s) to attach to).
1104 // This is also used by Remoting for routing cross-appDomain calls.
1107 LIMITED_METHOD_DAC_CONTRACT;
1108 STATIC_CONTRACT_SO_TOLERANT;
1112 virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return FALSE; }
1113 virtual BOOL IsSharedDomain() { LIMITED_METHOD_DAC_CONTRACT; return FALSE; }
1115 inline BOOL IsDefaultDomain(); // defined later in this file
1116 virtual PTR_LoaderAllocator GetLoaderAllocator() = 0;
1117 virtual PTR_AppDomain AsAppDomain()
1119 LIMITED_METHOD_CONTRACT;
1120 STATIC_CONTRACT_SO_TOLERANT;
1121 _ASSERTE(!"Not an AppDomain");
1126 // If one domain is the SharedDomain and one is an AppDomain then
1127 // return the AppDomain, i.e. return the domain with the shorter lifetime
1128 // of the two given domains.
1129 static PTR_BaseDomain ComputeBaseDomain(
1130 BaseDomain *pGenericDefinitionDomain, // the domain that owns the generic type or method
1131 Instantiation classInst, // the type arguments to the type (if any)
1132 Instantiation methodInst = Instantiation()); // the type arguments to the method (if any)
1134 static PTR_BaseDomain ComputeBaseDomain(TypeKey * pTypeKey);
1136 #ifdef FEATURE_COMINTEROP
1137 //****************************************************************************************
1139 // This will look up interop data for a method table
1142 #ifndef DACCESS_COMPILE
1143 // Returns the data pointer if present, NULL otherwise
1144 InteropMethodTableData *LookupComInteropData(MethodTable *pMT)
1147 CrstHolder holder(&m_InteropDataCrst);
1150 InteropMethodTableData *pData = (InteropMethodTableData*) m_interopDataHash.LookupValue((UPTR) pMT, (LPVOID) NULL);
1153 if (pData == (InteropMethodTableData*) INVALIDENTRY)
1160 // Returns TRUE if successfully inserted, FALSE if this would be a duplicate entry
1161 BOOL InsertComInteropData(MethodTable* pMT, InteropMethodTableData *pData)
1163 // We don't keep track of this kind of information for interfaces
1164 _ASSERTE(!pMT->IsInterface());
1167 CrstHolder holder(&m_InteropDataCrst);
1169 // Check to see that it's not already in there
1170 InteropMethodTableData *pDupData = (InteropMethodTableData*) m_interopDataHash.LookupValue((UPTR) pMT, (LPVOID) NULL);
1171 if (pDupData != (InteropMethodTableData*) INVALIDENTRY)
1174 // Not in there, so insert
1175 m_interopDataHash.InsertValue((UPTR) pMT, (LPVOID) pData);
1180 #endif // DACCESS_COMPILE
1181 #endif // FEATURE_COMINTEROP
1183 void SetDisableInterfaceCache()
1185 m_fDisableInterfaceCache = TRUE;
1187 BOOL GetDisableInterfaceCache()
1189 return m_fDisableInterfaceCache;
1192 #ifdef FEATURE_COMINTEROP
1193 MngStdInterfacesInfo * GetMngStdInterfacesInfo()
1195 LIMITED_METHOD_CONTRACT;
1197 return m_pMngStdInterfacesInfo;
1200 PTR_CLRPrivBinderWinRT GetWinRtBinder()
1202 return m_pWinRtBinder;
1204 #endif // FEATURE_COMINTEROP
1206 //****************************************************************************************
1207 // This method returns marshaling data that the EE uses that is stored on a per app domain
1209 EEMarshalingData *GetMarshalingData();
1211 // Deletes marshaling data at shutdown (which contains cached factories that needs to be released)
1212 void DeleteMarshalingData();
1215 BOOL OwnDomainLocalBlockLock()
1217 WRAPPER_NO_CONTRACT;
1219 return m_DomainLocalBlockCrst.OwnedByCurrentThread();
1223 //****************************************************************************************
1226 virtual IApplicationSecurityDescriptor* GetSecurityDescriptor() { LIMITED_METHOD_CONTRACT; return NULL; }
1229 //****************************************************************************************
1230 // Get the class init lock. The method is limited to friends because inappropriate use
1231 // will cause deadlocks in the system
1232 ListLock* GetClassInitLock()
1234 LIMITED_METHOD_CONTRACT;
1236 return &m_ClassInitLock;
1239 ListLock* GetJitLock()
1241 LIMITED_METHOD_CONTRACT;
1245 ListLock* GetILStubGenLock()
1247 LIMITED_METHOD_CONTRACT;
1248 return &m_ILStubGenLock;
1251 STRINGREF *IsStringInterned(STRINGREF *pString);
1252 STRINGREF *GetOrInternString(STRINGREF *pString);
1254 virtual BOOL CanUnload() { LIMITED_METHOD_CONTRACT; return FALSE; } // can never unload BaseDomain
1256 // Returns an array of OBJECTREF* that can be used to store domain specific data.
1257 // Statics and reflection info (Types, MemberInfo,..) are stored this way
1258 // If ppLazyAllocate != 0, allocation will only take place if *ppLazyAllocate != 0 (and the allocation
1259 // will be properly serialized)
1260 OBJECTREF *AllocateObjRefPtrsInLargeTable(int nRequested, OBJECTREF** ppLazyAllocate = NULL, BOOL bCrossAD = FALSE);
1262 #ifdef FEATURE_PREJIT
1263 // Ensures that the file for logging profile data is open (we only open it once)
1264 // return false on failure
1265 static BOOL EnsureNGenLogFileOpen();
1268 //****************************************************************************************
1271 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) // needs GetCurrentThreadHomeHeapNumber
1272 OBJECTHANDLE CreateTypedHandle(OBJECTREF object, int type)
1274 WRAPPER_NO_CONTRACT;
1275 return ::CreateTypedHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object, type);
1278 OBJECTHANDLE CreateHandle(OBJECTREF object)
1280 WRAPPER_NO_CONTRACT;
1281 CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL)
1282 return ::CreateHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1285 OBJECTHANDLE CreateWeakHandle(OBJECTREF object)
1287 WRAPPER_NO_CONTRACT;
1288 return ::CreateWeakHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1291 OBJECTHANDLE CreateShortWeakHandle(OBJECTREF object)
1293 WRAPPER_NO_CONTRACT;
1294 return ::CreateShortWeakHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1297 OBJECTHANDLE CreateLongWeakHandle(OBJECTREF object)
1299 WRAPPER_NO_CONTRACT;
1300 CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL)
1301 return ::CreateLongWeakHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1304 OBJECTHANDLE CreateStrongHandle(OBJECTREF object)
1306 WRAPPER_NO_CONTRACT;
1307 return ::CreateStrongHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1310 OBJECTHANDLE CreatePinningHandle(OBJECTREF object)
1312 WRAPPER_NO_CONTRACT;
1313 #if CHECK_APP_DOMAIN_LEAKS
1315 object->TryAssignAppDomain((AppDomain*)this,TRUE);
1317 return ::CreatePinningHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1320 OBJECTHANDLE CreateSizedRefHandle(OBJECTREF object)
1322 WRAPPER_NO_CONTRACT;
1323 OBJECTHANDLE h = ::CreateSizedRefHandle(
1324 m_hHandleTableBucket->pTable[GCHeap::IsServerHeap() ? (m_dwSizedRefHandles % m_iNumberOfProcessors) : GetCurrentThreadHomeHeapNumber()],
1326 InterlockedIncrement((LONG*)&m_dwSizedRefHandles);
1330 #ifdef FEATURE_COMINTEROP
1331 OBJECTHANDLE CreateRefcountedHandle(OBJECTREF object)
1333 WRAPPER_NO_CONTRACT;
1334 return ::CreateRefcountedHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1337 OBJECTHANDLE CreateWinRTWeakHandle(OBJECTREF object, IWeakReference* pWinRTWeakReference)
1347 return ::CreateWinRTWeakHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object, pWinRTWeakReference);
1349 #endif // FEATURE_COMINTEROP
1351 OBJECTHANDLE CreateVariableHandle(OBJECTREF object, UINT type)
1353 WRAPPER_NO_CONTRACT;
1354 return ::CreateVariableHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object, type);
1357 OBJECTHANDLE CreateDependentHandle(OBJECTREF primary, OBJECTREF secondary)
1359 WRAPPER_NO_CONTRACT;
1360 return ::CreateDependentHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], primary, secondary);
1362 #endif // DACCESS_COMPILE && !CROSSGEN_COMPILE
1364 BOOL ContainsOBJECTHANDLE(OBJECTHANDLE handle);
1366 #ifdef FEATURE_FUSION
1367 IApplicationContext *GetFusionContext() {LIMITED_METHOD_CONTRACT; return m_pFusionContext; }
1369 IUnknown *GetFusionContext() {LIMITED_METHOD_CONTRACT; return m_pFusionContext; }
1371 #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
1372 CLRPrivBinderCoreCLR *GetTPABinderContext() {LIMITED_METHOD_CONTRACT; return m_pTPABinderContext; }
1373 #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
1377 CrstExplicitInit * GetLoaderAllocatorReferencesLock()
1379 LIMITED_METHOD_CONTRACT;
1380 return &m_crstLoaderAllocatorReferences;
1385 //****************************************************************************************
1386 // Helper method to initialize the large heap handle table.
1387 void InitLargeHeapHandleTable();
1389 //****************************************************************************************
1390 // Adds an assembly to the domain.
1391 void AddAssemblyNoLock(Assembly* assem);
1393 //****************************************************************************************
1395 // Hash table that maps a MethodTable to COM Interop compatibility data.
1396 PtrHashMap m_interopDataHash;
1398 // Critical sections & locks
1399 PEFileListLock m_FileLoadLock; // Protects the list of assemblies in the domain
1400 CrstExplicitInit m_DomainCrst; // General Protection for the Domain
1401 CrstExplicitInit m_DomainCacheCrst; // Protects the Assembly and Unmanaged caches
1402 CrstExplicitInit m_DomainLocalBlockCrst;
1403 CrstExplicitInit m_InteropDataCrst; // Used for COM Interop compatiblilty
1404 // Used to protect the reference lists in the collectible loader allocators attached to this appdomain
1405 CrstExplicitInit m_crstLoaderAllocatorReferences;
1406 CrstExplicitInit m_WinRTFactoryCacheCrst; // For WinRT factory cache
1409 // Used to protect the assembly list. Taken also by GC or debugger thread, therefore we have to avoid
1410 // triggering GC while holding this lock (by switching the thread to GC_NOTRIGGER while it is held).
1411 CrstExplicitInit m_crstAssemblyList;
1412 BOOL m_fDisableInterfaceCache; // RCW COM interface cache
1413 ListLock m_ClassInitLock;
1415 ListLock m_ILStubGenLock;
1417 // Fusion context, used for adding assemblies to the is domain. It defines
1418 // fusion properties for finding assemblyies such as SharedBinPath,
1419 // PrivateBinPath, Application Directory, etc.
1420 #ifdef FEATURE_FUSION
1421 IApplicationContext* m_pFusionContext; // Binding context for the domain
1423 IUnknown *m_pFusionContext; // Current binding context for the domain
1425 #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
1426 CLRPrivBinderCoreCLR *m_pTPABinderContext; // Reference to the binding context that holds TPA list details
1427 #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
1431 HandleTableBucket *m_hHandleTableBucket;
1433 // The large heap handle table.
1434 LargeHeapHandleTable *m_pLargeHeapHandleTable;
1436 // The large heap handle table critical section.
1437 CrstExplicitInit m_LargeHeapHandleTableCrst;
1439 EEMarshalingData *m_pMarshalingData;
1441 #ifdef FEATURE_COMINTEROP
1442 // Information regarding the managed standard interfaces.
1443 MngStdInterfacesInfo *m_pMngStdInterfacesInfo;
1445 // WinRT binder (only in classic = non-AppX; AppX has the WinRT binder inside code:CLRPrivBinderAppX)
1446 PTR_CLRPrivBinderWinRT m_pWinRtBinder;
1447 #endif // FEATURE_COMINTEROP
1449 // Number of allocated slots for context local statics of this domain
1450 DWORD m_dwContextStatics;
1452 // Protects allocation of slot IDs for thread and context statics
1453 static CrstStatic m_SpecialStaticsCrst;
1456 // Lazily allocate offset for context static
1457 DWORD AllocateContextStaticsOffset(DWORD* pOffsetSlot);
1460 // Only call this routine when you can guarantee there are no
1461 // loads in progress.
1462 void ClearFusionContext();
1466 //****************************************************************************************
1467 // Synchronization holders.
1469 class LockHolder : public CrstHolder
1472 LockHolder(BaseDomain *pD)
1473 : CrstHolder(&pD->m_DomainCrst)
1475 WRAPPER_NO_CONTRACT;
1478 friend class LockHolder;
1480 class CacheLockHolder : public CrstHolder
1483 CacheLockHolder(BaseDomain *pD)
1484 : CrstHolder(&pD->m_DomainCacheCrst)
1486 WRAPPER_NO_CONTRACT;
1489 friend class CacheLockHolder;
1491 class DomainLocalBlockLockHolder : public CrstHolder
1494 DomainLocalBlockLockHolder(BaseDomain *pD)
1495 : CrstHolder(&pD->m_DomainLocalBlockCrst)
1497 WRAPPER_NO_CONTRACT;
1500 friend class DomainLocalBlockLockHolder;
1502 class LoadLockHolder : public PEFileListLockHolder
1505 LoadLockHolder(BaseDomain *pD, BOOL Take = TRUE)
1506 : PEFileListLockHolder(&pD->m_FileLoadLock, Take)
1518 friend class LoadLockHolder;
1519 class WinRTFactoryCacheLockHolder : public CrstHolder
1522 WinRTFactoryCacheLockHolder(BaseDomain *pD)
1523 : CrstHolder(&pD->m_WinRTFactoryCacheCrst)
1525 WRAPPER_NO_CONTRACT;
1528 friend class WinRTFactoryCacheLockHolder;
1532 RangeList *GetCollectibleVSDRanges() { return &m_collVSDRanges; }
1535 TypeIDMap m_typeIDMap;
1536 // Range list for collectible types. Maps VSD PCODEs back to the VirtualCallStubManager they belong to
1537 LockedRangeList m_collVSDRanges;
1540 UINT32 GetTypeID(PTR_MethodTable pMT);
1541 UINT32 LookupTypeID(PTR_MethodTable pMT);
1542 PTR_MethodTable LookupType(UINT32 id);
1545 // I have yet to figure out an efficent way to get the number of handles
1546 // of a particular type that's currently used by the process without
1547 // spending more time looking at the handle table code. We know that
1548 // our only customer (asp.net) in Dev10 is not going to create many of
1549 // these handles so I am taking a shortcut for now and keep the sizedref
1550 // handle count on the AD itself.
1551 DWORD m_dwSizedRefHandles;
1553 static int m_iNumberOfProcessors;
1556 // Called by DestroySizedRefHandle
1557 void DecNumSizedRefHandles()
1559 WRAPPER_NO_CONTRACT;
1561 result = InterlockedDecrement((LONG*)&m_dwSizedRefHandles);
1562 _ASSERTE(result >= 0);
1565 DWORD GetNumSizedRefHandles()
1567 return m_dwSizedRefHandles;
1572 ReJitManager m_reJitMgr;
1575 ReJitManager * GetReJitManager() { return &m_reJitMgr; }
1577 #ifdef DACCESS_COMPILE
1579 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
1583 #ifdef FEATURE_CORECLR
1585 enum AppDomainCompatMode
1587 APPDOMAINCOMPAT_NONE
1588 #ifdef FEATURE_LEGACYNETCF
1589 , APPDOMAINCOMPAT_APP_EARLIER_THAN_WP8 // for "AppDomainCompatSwitch" == "WindowsPhone_3.7.0.0" or "AppDomainCompatSwitch" == "WindowsPhone_3.8.0.0"
1592 void SetAppDomainCompatMode(AppDomainCompatMode compatMode);
1593 AppDomainCompatMode GetAppDomainCompatMode();
1596 AppDomainCompatMode m_CompatMode;
1597 #endif // FEATURE_CORECLR
1599 }; // class BaseDomain
1603 ATTACH_ASSEMBLY_LOAD = 0x1,
1604 ATTACH_MODULE_LOAD = 0x2,
1605 ATTACH_CLASS_LOAD = 0x4,
1615 CLREvent m_UnloadCompleteEvent;
1616 HRESULT m_UnloadResult;
1617 Volatile<LONG> m_cRef;
1620 void ReportUnloadResult (HRESULT hr, OBJECTREF* pException);
1621 void WaitUnloadCompletion();
1622 HRESULT GetUnloadResult() {LIMITED_METHOD_CONTRACT; return m_UnloadResult;};
1629 FORCEINLINE void ADUnloadSink__Release(ADUnloadSink* pADSink)
1631 WRAPPER_NO_CONTRACT;
1637 typedef Wrapper <ADUnloadSink*,DoNothing,ADUnloadSink__Release,NULL> ADUnloadSinkHolder;
1639 // This filters the output of IterateAssemblies. This ought to be declared more locally
1640 // but it would result in really verbose callsites.
1642 // Assemblies can be categorized by their load status (loaded, loading, or loaded just
1643 // enough that they would be made available to profilers)
1644 // Independently, they can also be categorized as execution or introspection.
1646 // An assembly will be included in the results of IterateAssemblies only if
1647 // the appropriate bit is set for *both* characterizations.
1649 // The flags can be combined so if you want all loaded assemblies, you must specify:
1651 /// kIncludeLoaded|kIncludeExecution|kIncludeIntrospection
1653 enum AssemblyIterationFlags
1655 // load status flags
1656 kIncludeLoaded = 0x00000001, // include assemblies that are already loaded
1657 // (m_level >= code:FILE_LOAD_DELIVER_EVENTS)
1658 kIncludeLoading = 0x00000002, // include assemblies that are still in the process of loading
1659 // (all m_level values)
1660 kIncludeAvailableToProfilers
1661 = 0x00000020, // include assemblies available to profilers
1662 // See comment at code:DomainFile::IsAvailableToProfilers
1664 // Execution / introspection flags
1665 kIncludeExecution = 0x00000004, // include assemblies that are loaded for execution only
1666 kIncludeIntrospection = 0x00000008, // include assemblies that are loaded for introspection only
1668 kIncludeFailedToLoad = 0x00000010, // include assemblies that failed to load
1670 // Collectible assemblies flags
1671 kExcludeCollectible = 0x00000040, // Exclude all collectible assemblies
1672 kIncludeCollected = 0x00000080,
1673 // Include assemblies which were collected and cannot be referenced anymore. Such assemblies are not
1674 // AddRef-ed. Any manipulation with them should be protected by code:GetAssemblyListLock.
1675 // Should be used only by code:LoaderAllocator::GCLoaderAllocators.
1677 }; // enum AssemblyIterationFlags
1679 //---------------------------------------------------------------------------------------
1681 // Base class for holder code:CollectibleAssemblyHolder (see code:HolderBase).
1682 // Manages AddRef/Release for collectible assemblies. It is no-op for 'normal' non-collectible assemblies.
1684 // Each type of type parameter needs 2 methods implemented:
1685 // code:CollectibleAssemblyHolderBase::GetLoaderAllocator
1686 // code:CollectibleAssemblyHolderBase::IsCollectible
1688 template<typename _Type>
1689 class CollectibleAssemblyHolderBase
1694 CollectibleAssemblyHolderBase(const _Type & value = NULL)
1696 LIMITED_METHOD_CONTRACT;
1709 // We don't need to keep the assembly alive in DAC - see code:#CAH_DAC
1710 #ifndef DACCESS_COMPILE
1711 if (this->IsCollectible(m_value))
1713 LoaderAllocator * pLoaderAllocator = GetLoaderAllocator(m_value);
1714 pLoaderAllocator->AddReference();
1716 #endif //!DACCESS_COMPILE
1728 #ifndef DACCESS_COMPILE
1729 if (this->IsCollectible(m_value))
1731 LoaderAllocator * pLoaderAllocator = GetLoaderAllocator(m_value);
1732 pLoaderAllocator->Release();
1734 #endif //!DACCESS_COMPILE
1738 LoaderAllocator * GetLoaderAllocator(DomainAssembly * pDomainAssembly)
1740 WRAPPER_NO_CONTRACT;
1741 return pDomainAssembly->GetLoaderAllocator();
1743 BOOL IsCollectible(DomainAssembly * pDomainAssembly)
1745 WRAPPER_NO_CONTRACT;
1746 return pDomainAssembly->IsCollectible();
1748 LoaderAllocator * GetLoaderAllocator(Assembly * pAssembly)
1750 WRAPPER_NO_CONTRACT;
1751 return pAssembly->GetLoaderAllocator();
1753 BOOL IsCollectible(Assembly * pAssembly)
1755 WRAPPER_NO_CONTRACT;
1756 return pAssembly->IsCollectible();
1758 }; // class CollectibleAssemblyHolderBase<>
1760 //---------------------------------------------------------------------------------------
1762 // Holder of assembly reference which keeps collectible assembly alive while the holder is valid.
1764 // Collectible assembly can be collected at any point when GC happens. Almost instantly all native data
1765 // structures of the assembly (e.g. code:DomainAssembly, code:Assembly) could be deallocated.
1766 // Therefore any usage of (collectible) assembly data structures from native world, has to prevent the
1767 // deallocation by increasing ref-count on the assembly / associated loader allocator.
1770 // In DAC we don't AddRef/Release as the assembly doesn't have to be kept alive: The process is stopped when
1771 // DAC is used and therefore the assembly cannot just disappear.
1773 template<typename _Type>
1774 class CollectibleAssemblyHolder : public BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >
1778 CollectibleAssemblyHolder(const _Type & value = NULL, BOOL fTake = TRUE)
1779 : BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >(value, fTake)
1781 STATIC_CONTRACT_WRAPPER;
1785 CollectibleAssemblyHolder &
1786 operator=(const _Type & value)
1788 STATIC_CONTRACT_WRAPPER;
1789 BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >::operator=(value);
1793 // Operator & is overloaded in parent, therefore we have to get to 'this' pointer explicitly.
1795 CollectibleAssemblyHolder<_Type> *
1798 LIMITED_METHOD_CONTRACT;
1801 }; // class CollectibleAssemblyHolder<>
1803 //---------------------------------------------------------------------------------------
1805 #ifdef FEATURE_LOADER_OPTIMIZATION
1806 class SharedAssemblyLocator
1815 DWORD GetType() {LIMITED_METHOD_CONTRACT; return m_type;};
1816 #ifndef DACCESS_COMPILE
1817 DomainAssembly* GetDomainAssembly() {LIMITED_METHOD_CONTRACT; _ASSERTE(m_type==DOMAINASSEMBLY); return (DomainAssembly*)m_value;};
1818 PEAssembly* GetPEAssembly() {LIMITED_METHOD_CONTRACT; _ASSERTE(m_type==PEASSEMBLY||m_type==PEASSEMBLYEXACT); return (PEAssembly*)m_value;};
1819 SharedAssemblyLocator(DomainAssembly* pAssembly)
1821 LIMITED_METHOD_CONTRACT;
1822 m_type=DOMAINASSEMBLY;
1825 SharedAssemblyLocator(PEAssembly* pFile, DWORD type = PEASSEMBLY)
1827 LIMITED_METHOD_CONTRACT;
1831 #endif // DACCESS_COMPILE
1837 #if FEATURE_VERSIONING
1838 ULONG m_uIdentityHash;
1841 #endif // FEATURE_LOADER_OPTIMIZATION
1844 // Stores binding information about failed assembly loads for DAC
1846 struct FailedAssembly {
1847 SString displayName;
1849 #ifdef FEATURE_FUSION
1850 LOADCTX_TYPE context;
1854 void Initialize(AssemblySpec *pSpec, Exception *ex)
1864 displayName.SetASCII(pSpec->GetName());
1865 location.Set(pSpec->GetCodeBase());
1866 error = ex->GetHR();
1869 // Determine the binding context assembly would have been in.
1870 // If the parent has been set, use its binding context.
1871 // If the parent hasn't been set but the code base has, use LoadFrom.
1872 // Otherwise, use the default.
1874 #ifdef FEATURE_FUSION
1875 context = pSpec->GetParentIAssembly() ? pSpec->GetParentIAssembly()->GetFusionLoadContext() : LOADCTX_TYPE_LOADFROM;
1876 #endif // FEATURE_FUSION
1880 #ifdef FEATURE_COMINTEROP
1882 // Cache used by COM Interop
1883 struct NameToTypeMapEntry
1885 // Host space representation of the key
1888 LPCWSTR m_wzName; // The type name or registry string representation of the GUID "{<guid>}"
1889 SIZE_T m_cchName; // wcslen(m_wzName) for faster hashtable lookup
1893 PTR_CWSTR m_wzName; // The type name or registry string representation of the GUID "{<guid>}"
1894 SIZE_T m_cchName; // wcslen(m_wzName) for faster hashtable lookup
1896 TypeHandle m_typeHandle; // Using TypeHandle instead of MethodTable* to avoid losing information when sharing method tables.
1897 UINT m_nEpoch; // tracks creation Epoch. This is incremented each time an external reader enumerate the cache
1901 typedef DPTR(NameToTypeMapEntry) PTR_NameToTypeMapEntry;
1903 class NameToTypeMapTraits : public NoRemoveSHashTraits< DefaultSHashTraits<NameToTypeMapEntry> >
1906 typedef NameToTypeMapEntry::Key key_t;
1908 static const NameToTypeMapEntry Null() { NameToTypeMapEntry e; e.m_key.m_wzName = NULL; e.m_key.m_cchName = 0; return e; }
1909 static bool IsNull(const NameToTypeMapEntry &e) { return e.m_key.m_wzName == NULL; }
1910 static const key_t GetKey(const NameToTypeMapEntry &e)
1913 key.m_wzName = (LPCWSTR)(e.m_key.m_wzName); // this cast brings the string over to the host, in a DAC build
1914 key.m_cchName = e.m_key.m_cchName;
1918 static count_t Hash(const key_t &key) { WRAPPER_NO_CONTRACT; return HashStringN(key.m_wzName, key.m_cchName); }
1920 static BOOL Equals(const key_t &lhs, const key_t &rhs)
1922 WRAPPER_NO_CONTRACT;
1923 return (lhs.m_cchName == rhs.m_cchName) && memcmp(lhs.m_wzName, rhs.m_wzName, lhs.m_cchName * sizeof(WCHAR)) == 0;
1926 void OnDestructPerEntryCleanupAction(const NameToTypeMapEntry& e)
1928 WRAPPER_NO_CONTRACT;
1929 _ASSERTE(e.m_key.m_cchName == wcslen(e.m_key.m_wzName));
1930 #ifndef DACCESS_COMPILE
1931 delete [] e.m_key.m_wzName;
1932 #endif // DACCESS_COMPILE
1934 static const bool s_DestructPerEntryCleanupAction = true;
1937 typedef SHash<NameToTypeMapTraits> NameToTypeMapTable;
1939 typedef DPTR(NameToTypeMapTable) PTR_NameToTypeMapTable;
1941 struct WinRTFactoryCacheEntry
1943 typedef MethodTable *Key;
1944 Key key; // Type as KEY
1946 CtxEntry *m_pCtxEntry; // Context entry - used to verify whether the cache is a match
1947 OBJECTHANDLE m_ohFactoryObject; // Handle to factory object
1950 class WinRTFactoryCacheTraits : public DefaultSHashTraits<WinRTFactoryCacheEntry>
1953 typedef WinRTFactoryCacheEntry::Key key_t;
1954 static const WinRTFactoryCacheEntry Null() { WinRTFactoryCacheEntry e; e.key = NULL; return e; }
1955 static bool IsNull(const WinRTFactoryCacheEntry &e) { return e.key == NULL; }
1956 static const WinRTFactoryCacheEntry::Key GetKey(const WinRTFactoryCacheEntry& e) { return e.key; }
1957 static count_t Hash(WinRTFactoryCacheEntry::Key key) { return (count_t)((size_t)key); }
1958 static BOOL Equals(WinRTFactoryCacheEntry::Key lhs, WinRTFactoryCacheEntry::Key rhs)
1959 { return lhs == rhs; }
1960 static const WinRTFactoryCacheEntry Deleted() { WinRTFactoryCacheEntry e; e.key = (MethodTable *)-1; return e; }
1961 static bool IsDeleted(const WinRTFactoryCacheEntry &e) { return e.key == (MethodTable *)-1; }
1963 static void OnDestructPerEntryCleanupAction(const WinRTFactoryCacheEntry& e);
1964 static const bool s_DestructPerEntryCleanupAction = true;
1967 typedef SHash<WinRTFactoryCacheTraits> WinRTFactoryCache;
1969 #endif // FEATURE_COMINTEROP
1971 class AppDomainIterator;
1973 const DWORD DefaultADID = 1;
1975 template <class AppDomainType> class AppDomainCreationHolder;
1977 // An Appdomain is the managed equivalent of a process. It is an isolation unit (conceptually you don't
1978 // have pointers directly from one appdomain to another, but rather go through remoting proxies). It is
1979 // also a unit of unloading.
1981 // Threads are always running in the context of a particular AppDomain. See
1982 // file:threads.h#RuntimeThreadLocals for more details.
1984 // see code:BaseDomain for much of the meat of a AppDomain (heaps locks, etc)
1985 // * code:AppDomain.m_Assemblies - is a list of code:Assembly in the appdomain
1987 class AppDomain : public BaseDomain
1989 friend class ADUnloadSink;
1990 friend class SystemDomain;
1991 friend class AssemblySink;
1992 friend class AppDomainNative;
1993 friend class AssemblyNative;
1994 friend class AssemblySpec;
1995 friend class ClassLoader;
1996 friend class ThreadNative;
1997 friend class RCWCache;
1998 friend class ClrDataAccess;
1999 friend class CheckAsmOffsets;
2000 friend class AppDomainFromIDHolder;
2002 VPTR_VTABLE_CLASS(AppDomain, BaseDomain)
2005 #ifndef DACCESS_COMPILE
2007 virtual ~AppDomain();
2009 static void DoADUnloadWork();
2010 DomainAssembly* FindDomainAssembly(Assembly*);
2011 void EnterContext(Thread* pThread, Context* pCtx,ContextTransitionFrame *pFrame);
2013 #ifndef DACCESS_COMPILE
2014 //-----------------------------------------------------------------------------------------------------------------
2015 // Convenience wrapper for ::GetAppDomain to provide better encapsulation.
2016 static AppDomain * GetCurrentDomain()
2017 { return ::GetAppDomain(); }
2018 #endif //!DACCESS_COMPILE
2020 //-----------------------------------------------------------------------------------------------------------------
2021 // Initializes an AppDomain. (this functions is not called from the SystemDomain)
2024 // creates only unamaged part
2025 static void CreateUnmanagedObject(AppDomainCreationHolder<AppDomain>& result);
2026 inline void SetAppDomainManagerInfo(LPCWSTR szAssemblyName, LPCWSTR szTypeName, EInitializeNewDomainFlags dwInitializeDomainFlags);
2027 inline BOOL HasAppDomainManagerInfo();
2028 inline LPCWSTR GetAppDomainManagerAsm();
2029 inline LPCWSTR GetAppDomainManagerType();
2030 inline EInitializeNewDomainFlags GetAppDomainManagerInitializeNewDomainFlags();
2032 #ifndef FEATURE_CORECLR
2033 inline BOOL AppDomainManagerSetFromConfig();
2034 Assembly *GetAppDomainManagerEntryAssembly();
2035 #endif // FEATURE_CORECLR
2037 #if defined(FEATURE_CORECLR) && defined(FEATURE_COMINTEROP)
2038 HRESULT SetWinrtApplicationContext(SString &appLocalWinMD);
2039 #endif // FEATURE_CORECLR && FEATURE_COMINTEROP
2041 BOOL CanReversePInvokeEnter();
2042 void SetReversePInvokeCannotEnter();
2043 bool MustForceTrivialWaitOperations();
2044 void SetForceTrivialWaitOperations();
2046 //****************************************************************************************
2048 // Stop deletes all the assemblies but does not remove other resources like
2049 // the critical sections
2052 // Gets rid of resources
2055 #ifdef FEATURE_PREJIT
2056 //assembly cleanup that requires suspended runtime
2057 void DeleteNativeCodeRanges();
2060 // final assembly cleanup
2061 void ShutdownAssemblies();
2062 void ShutdownFreeLoaderAllocators(BOOL bFromManagedCode);
2064 void ReleaseDomainBoundInfo();
2065 void ReleaseFiles();
2068 // Remove the Appdomain for the system and cleans up. This call should not be
2069 // called from shut down code.
2072 virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; }
2073 virtual PTR_AppDomain AsAppDomain() { LIMITED_METHOD_CONTRACT; return dac_cast<PTR_AppDomain>(this); }
2075 #ifndef FEATURE_CORECLR
2076 void InitializeSorting(OBJECTREF* ppAppdomainSetup);
2077 void InitializeHashing(OBJECTREF* ppAppdomainSetup);
2080 OBJECTREF DoSetup(OBJECTREF* setupInfo);
2082 OBJECTREF GetExposedObject();
2083 OBJECTREF GetRawExposedObject() {
2092 if (m_ExposedObject) {
2093 return ObjectFromHandle(m_ExposedObject);
2100 OBJECTHANDLE GetRawExposedObjectHandleForDebugger() { LIMITED_METHOD_DAC_CONTRACT; return m_ExposedObject; }
2102 #ifdef FEATURE_COMINTEROP
2103 HRESULT GetComIPForExposedObject(IUnknown **pComIP);
2105 MethodTable *GetRedirectedType(WinMDAdapter::RedirectedTypeIndex index);
2106 bool FindRedirectedAssembly(Assembly* pAssembly, WinMDAdapter::FrameworkAssemblyIndex* pIndex);
2107 #endif // FEATURE_COMINTEROP
2110 //****************************************************************************************
2113 // Multi-thread safe access to the list of assemblies
2114 class DomainAssemblyList
2119 AppDomain * dbg_m_pAppDomain;
2121 void Debug_SetAppDomain(AppDomain * pAppDomain)
2123 dbg_m_pAppDomain = pAppDomain;
2135 // This function can be reliably called without taking the lock, because the first assembly
2136 // added to the arraylist is non-collectible, and the ArrayList itself allows lockless read access
2137 return (m_array.GetCount() == 0);
2139 void Clear(AppDomain * pAppDomain)
2143 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2147 _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2149 CrstHolder ch(pAppDomain->GetAssemblyListLock());
2153 DWORD GetCount(AppDomain * pAppDomain)
2157 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2161 _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2163 CrstHolder ch(pAppDomain->GetAssemblyListLock());
2164 return GetCount_Unlocked();
2166 DWORD GetCount_Unlocked()
2174 #ifndef DACCESS_COMPILE
2175 _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2177 // code:Append_Unlock guarantees that we do not have more than MAXDWORD items
2178 return m_array.GetCount();
2181 void Get(AppDomain * pAppDomain, DWORD index, CollectibleAssemblyHolder<DomainAssembly *> * pAssemblyHolder)
2185 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2189 _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2191 CrstHolder ch(pAppDomain->GetAssemblyListLock());
2192 Get_Unlocked(index, pAssemblyHolder);
2194 void Get_Unlocked(DWORD index, CollectibleAssemblyHolder<DomainAssembly *> * pAssemblyHolder)
2202 _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2203 *pAssemblyHolder = dac_cast<PTR_DomainAssembly>(m_array.Get(index));
2205 // Doesn't lock the assembly list (caller has to hold the lock already).
2206 // Doesn't AddRef the returned assembly (if collectible).
2207 DomainAssembly * Get_UnlockedNoReference(DWORD index)
2216 #ifndef DACCESS_COMPILE
2217 _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2219 return dac_cast<PTR_DomainAssembly>(m_array.Get(index));
2222 #ifndef DACCESS_COMPILE
2223 void Set(AppDomain * pAppDomain, DWORD index, DomainAssembly * pAssembly)
2227 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2231 _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2233 CrstHolder ch(pAppDomain->GetAssemblyListLock());
2234 return Set_Unlocked(index, pAssembly);
2236 void Set_Unlocked(DWORD index, DomainAssembly * pAssembly)
2244 _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2245 m_array.Set(index, pAssembly);
2248 HRESULT Append_Unlocked(DomainAssembly * pAssembly)
2256 _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2257 return m_array.Append(pAssembly);
2259 #else //DACCESS_COMPILE
2261 EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2265 m_array.EnumMemoryRegions(flags);
2267 #endif // DACCESS_COMPILE
2269 // Should be used only by code:AssemblyIterator::Create
2270 ArrayList::Iterator GetArrayListIterator()
2272 return m_array.Iterate();
2274 }; // class DomainAssemblyList
2276 // Conceptually a list of code:Assembly structures, protected by lock code:GetAssemblyListLock
2277 DomainAssemblyList m_Assemblies;
2280 // Note that this lock switches thread into GC_NOTRIGGER region as GC can take it too.
2281 CrstExplicitInit * GetAssemblyListLock()
2283 LIMITED_METHOD_CONTRACT;
2284 return &m_crstAssemblyList;
2288 class AssemblyIterator
2290 // AppDomain context with the assembly list
2291 AppDomain * m_pAppDomain;
2292 ArrayList::Iterator m_Iterator;
2293 AssemblyIterationFlags m_assemblyIterationFlags;
2296 BOOL Next(CollectibleAssemblyHolder<DomainAssembly *> * pDomainAssemblyHolder);
2297 // Note: Does not lock the assembly list, but AddRefs collectible assemblies.
2298 BOOL Next_Unlocked(CollectibleAssemblyHolder<DomainAssembly *> * pDomainAssemblyHolder);
2299 #ifndef DACCESS_COMPILE
2301 // Can be called only from AppDomain shutdown code:AppDomain::ShutdownAssemblies.
2302 // Note: Does not lock the assembly list and does not AddRefs collectible assemblies.
2303 BOOL Next_UnsafeNoAddRef(DomainAssembly ** ppDomainAssembly);
2307 inline DWORD GetIndex()
2309 LIMITED_METHOD_CONTRACT;
2310 return m_Iterator.GetIndex();
2314 friend class AppDomain;
2315 // Cannot have constructor so this iterator can be used inside a union
2316 static AssemblyIterator Create(AppDomain * pAppDomain, AssemblyIterationFlags assemblyIterationFlags)
2318 LIMITED_METHOD_CONTRACT;
2321 i.m_pAppDomain = pAppDomain;
2322 i.m_Iterator = pAppDomain->m_Assemblies.GetArrayListIterator();
2323 i.m_assemblyIterationFlags = assemblyIterationFlags;
2326 }; // class AssemblyIterator
2328 AssemblyIterator IterateAssembliesEx(AssemblyIterationFlags assemblyIterationFlags)
2330 LIMITED_METHOD_CONTRACT;
2331 return AssemblyIterator::Create(this, assemblyIterationFlags);
2334 #ifdef FEATURE_CORECLR
2336 struct NativeImageDependenciesEntry
2338 BaseAssemblySpec m_AssemblySpec;
2342 class NativeImageDependenciesTraits : public NoRemoveSHashTraits<DefaultSHashTraits<NativeImageDependenciesEntry *> >
2345 typedef BaseAssemblySpec *key_t;
2346 static key_t GetKey(NativeImageDependenciesEntry * e) { return &(e->m_AssemblySpec); }
2348 static count_t Hash(key_t k)
2353 static BOOL Equals(key_t lhs, key_t rhs)
2355 return lhs->CompareEx(rhs);
2359 SHash<NativeImageDependenciesTraits> m_NativeImageDependencies;
2362 void CheckForMismatchedNativeImages(AssemblySpec * pSpec, const GUID * pGuid);
2367 friend class AppDomain;
2369 ArrayList::Iterator m_i;
2374 WRAPPER_NO_CONTRACT;
2380 WRAPPER_NO_CONTRACT;
2381 return dac_cast<PTR_SString>(m_i.GetElement());
2384 BOOL BindingByManifestFile();
2386 PathIterator IterateNativeDllSearchDirectories();
2387 void SetNativeDllSearchDirectories(LPCWSTR paths);
2388 BOOL HasNativeDllSearchDirectories();
2389 void ShutdownNativeDllSearchDirectories();
2390 #endif // FEATURE_CORECLR
2393 SIZE_T GetAssemblyCount()
2395 WRAPPER_NO_CONTRACT;
2396 return m_Assemblies.GetCount(this);
2399 CHECK CheckCanLoadTypes(Assembly *pAssembly);
2400 CHECK CheckCanExecuteManagedCode(MethodDesc* pMD);
2401 CHECK CheckLoading(DomainFile *pFile, FileLoadLevel level);
2403 FileLoadLevel GetDomainFileLoadLevel(DomainFile *pFile);
2404 BOOL IsLoading(DomainFile *pFile, FileLoadLevel level);
2405 static FileLoadLevel GetThreadFileLoadLevel();
2407 void LoadDomainFile(DomainFile *pFile,
2408 FileLoadLevel targetLevel);
2410 enum FindAssemblyOptions
2412 FindAssemblyOptions_None = 0x0,
2413 FindAssemblyOptions_IncludeFailedToLoad = 0x1
2416 DomainAssembly * FindAssembly(PEAssembly * pFile, FindAssemblyOptions options = FindAssemblyOptions_None) DAC_EMPTY_RET(NULL);
2418 #ifdef FEATURE_MIXEDMODE
2419 // Finds only loaded modules, elevates level if needed
2420 Module* GetIJWModule(HMODULE hMod) DAC_EMPTY_RET(NULL);
2421 // Finds loading modules
2422 DomainFile* FindIJWDomainFile(HMODULE hMod, const SString &path) DAC_EMPTY_RET(NULL);
2423 #endif // FEATURE_MIXEDMODE
2425 Assembly *LoadAssembly(AssemblySpec* pIdentity,
2427 FileLoadLevel targetLevel,
2428 AssemblyLoadSecurity *pLoadSecurity = NULL);
2430 // this function does not provide caching, you must use LoadDomainAssembly
2431 // unless the call is guaranteed to succeed or you don't need the caching
2432 // (e.g. if you will FailFast or tear down the AppDomain anyway)
2433 // The main point that you should not bypass caching if you might try to load the same file again,
2434 // resulting in multiple DomainAssembly objects that share the same PEAssembly for ngen image
2435 //which is violating our internal assumptions
2436 DomainAssembly *LoadDomainAssemblyInternal( AssemblySpec* pIdentity,
2438 FileLoadLevel targetLevel,
2439 AssemblyLoadSecurity *pLoadSecurity = NULL);
2441 DomainAssembly *LoadDomainAssembly( AssemblySpec* pIdentity,
2443 FileLoadLevel targetLevel,
2444 AssemblyLoadSecurity *pLoadSecurity = NULL);
2446 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
2447 DomainModule *LoadDomainModule(DomainAssembly *pAssembly,
2449 FileLoadLevel targetLevel);
2452 CHECK CheckValidModule(Module *pModule);
2453 #ifdef FEATURE_LOADER_OPTIMIZATION
2454 DomainFile *LoadDomainNeutralModuleDependency(Module *pModule, FileLoadLevel targetLevel);
2457 #ifdef FEATURE_FUSION
2458 PEAssembly *BindExplicitAssembly(HMODULE hMod, BOOL bindable);
2459 Assembly *LoadExplicitAssembly(HMODULE hMod, BOOL bindable);
2460 void GetFileFromFusion(IAssembly *pIAssembly, LPCWSTR wszModuleName,
2464 void LoadSystemAssemblies();
2466 DomainFile *LoadDomainFile(FileLoadLock *pLock,
2467 FileLoadLevel targetLevel);
2469 void TryIncrementalLoad(DomainFile *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder);
2471 Assembly *LoadAssemblyHelper(LPCWSTR wszAssembly,
2472 LPCWSTR wszCodeBase);
2474 #ifndef DACCESS_COMPILE // needs AssemblySpec
2475 //****************************************************************************************
2476 // Returns and Inserts assemblies into a lookup cache based on the binding information
2477 // in the AssemblySpec. There can be many AssemblySpecs to a single assembly.
2478 DomainAssembly* FindCachedAssembly(AssemblySpec* pSpec, BOOL fThrow=TRUE)
2480 WRAPPER_NO_CONTRACT;
2481 return m_AssemblyCache.LookupAssembly(pSpec, fThrow);
2484 PEAssembly* FindCachedFile(AssemblySpec* pSpec, BOOL fThrow = TRUE);
2485 BOOL IsCached(AssemblySpec *pSpec);
2486 #endif // DACCESS_COMPILE
2487 void CacheStringsForDAC();
2489 BOOL AddFileToCache(AssemblySpec* pSpec, PEAssembly *pFile, BOOL fAllowFailure = FALSE);
2490 BOOL AddAssemblyToCache(AssemblySpec* pSpec, DomainAssembly *pAssembly);
2491 BOOL AddExceptionToCache(AssemblySpec* pSpec, Exception *ex);
2492 void AddUnmanagedImageToCache(LPCWSTR libraryName, HMODULE hMod);
2493 HMODULE FindUnmanagedImageInCache(LPCWSTR libraryName);
2494 //****************************************************************************************
2496 // Adds an assembly to the domain.
2497 void AddAssembly(DomainAssembly * assem);
2498 void RemoveAssembly_Unlocked(DomainAssembly * pAsm);
2500 BOOL ContainsAssembly(Assembly * assem);
2502 #ifdef FEATURE_LOADER_OPTIMIZATION
2505 // Attributes to control when to use domain neutral assemblies
2506 SHARE_POLICY_UNSPECIFIED, // Use the current default policy (LoaderOptimization.NotSpecified)
2507 SHARE_POLICY_NEVER, // Do not share anything, except the system assembly (LoaderOptimization.SingleDomain)
2508 SHARE_POLICY_ALWAYS, // Share everything possible (LoaderOptimization.MultiDomain)
2509 SHARE_POLICY_GAC, // Share only GAC-bound assemblies (LoaderOptimization.MultiDomainHost)
2512 SHARE_POLICY_MASK = 0x3,
2514 // NOTE that previously defined was a bit 0x40 which might be set on this value
2515 // in custom attributes.
2516 SHARE_POLICY_DEFAULT = SHARE_POLICY_NEVER,
2519 void SetSharePolicy(SharePolicy policy);
2520 SharePolicy GetSharePolicy();
2521 BOOL ReduceSharePolicyFromAlways();
2523 //****************************************************************************************
2524 // Determines if the image is to be loaded into the shared assembly or an individual
2526 #ifndef FEATURE_CORECLR
2527 BOOL ApplySharePolicy(DomainAssembly *pFile);
2528 BOOL ApplySharePolicyFlag(DomainAssembly *pFile);
2530 #endif // FEATURE_LOADER_OPTIMIZATION
2532 BOOL HasSetSecurityPolicy();
2534 FORCEINLINE IApplicationSecurityDescriptor* GetSecurityDescriptor()
2536 LIMITED_METHOD_CONTRACT;
2537 STATIC_CONTRACT_SO_TOLERANT;
2538 return static_cast<IApplicationSecurityDescriptor*>(m_pSecDesc);
2541 void CreateSecurityDescriptor();
2543 //****************************************************************************************
2545 // Reference count. When an appdomain is first created the reference is bump
2546 // to one when it is added to the list of domains (see SystemDomain). An explicit
2547 // Removal from the list is necessary before it will be deleted.
2549 ULONG Release(void) DAC_EMPTY_RET(0);
2551 //****************************************************************************************
2552 LPCWSTR GetFriendlyName(BOOL fDebuggerCares = TRUE);
2553 LPCWSTR GetFriendlyNameForDebugger();
2554 LPCWSTR GetFriendlyNameForLogging();
2555 #ifdef DACCESS_COMPILE
2556 PVOID GetFriendlyNameNoSet(bool* isUtf8);
2558 void SetFriendlyName(LPCWSTR pwzFriendlyName, BOOL fDebuggerCares = TRUE);
2559 void ResetFriendlyName(BOOL fDebuggerCares = TRUE);
2561 //****************************************************************************************
2563 // This can be used to override the binding behavior of the appdomain. It
2564 // is overridden in the compilation domain. It is important that all
2565 // static binding goes through this path.
2566 virtual PEAssembly * BindAssemblySpec(
2567 AssemblySpec *pSpec,
2568 BOOL fThrowOnFileNotFound,
2569 BOOL fRaisePrebindEvents,
2570 StackCrawlMark *pCallerStackMark = NULL,
2571 AssemblyLoadSecurity *pLoadSecurity = NULL,
2572 BOOL fUseHostBinderIfAvailable = TRUE) DAC_EMPTY_RET(NULL);
2574 #ifdef FEATURE_HOSTED_BINDER
2575 HRESULT BindAssemblySpecForHostedBinder(
2576 AssemblySpec * pSpec,
2577 IAssemblyName * pAssemblyName,
2578 ICLRPrivBinder * pBinder,
2579 PEAssembly ** ppAssembly) DAC_EMPTY_RET(E_FAIL);
2581 HRESULT BindHostedPrivAssembly(
2582 PEAssembly * pParentPEAssembly,
2583 ICLRPrivAssembly * pPrivAssembly,
2584 IAssemblyName * pAssemblyName,
2585 PEAssembly ** ppAssembly,
2586 BOOL fIsIntrospectionOnly = FALSE) DAC_EMPTY_RET(S_OK);
2587 #endif // FEATURE_HOSTED_BINDER
2589 #ifdef FEATURE_REFLECTION_ONLY_LOAD
2590 virtual DomainAssembly *BindAssemblySpecForIntrospectionDependencies(AssemblySpec *pSpec) DAC_EMPTY_RET(NULL);
2593 PEAssembly *TryResolveAssembly(AssemblySpec *pSpec, BOOL fPreBind);
2595 // Store a successful binding into the cache. This will keep the file from
2596 // being physically unmapped, as well as shortcutting future attempts to bind
2597 // the same spec throught the Cached entry point.
2599 // Right now we only cache assembly binds for "probing" type
2600 // binding situations, basically when loading domain neutral assemblies or
2603 // <TODO>@todo: We may want to be more aggressive about this if
2604 // there are other situations where we are repeatedly binding the
2605 // same assembly specs, though.</TODO>
2607 // Returns TRUE if stored
2608 // FALSE if it's a duplicate (caller should clean up args)
2609 BOOL StoreBindAssemblySpecResult(AssemblySpec *pSpec,
2613 BOOL StoreBindAssemblySpecError(AssemblySpec *pSpec,
2615 OBJECTREF *pThrowable,
2618 //****************************************************************************************
2620 #ifdef FEATURE_FUSION
2621 static BOOL SetContextProperty(IApplicationContext* pFusionContext,
2625 //****************************************************************************************
2627 // Uses the first assembly to add an application base to the Context. This is done
2628 // in a lazy fashion so executables do not take the perf hit unless the load other
2630 #ifdef FEATURE_FUSION
2631 LPWSTR GetDynamicDir();
2633 #ifndef DACCESS_COMPILE
2634 void OnAssemblyLoad(Assembly *assem);
2635 void OnAssemblyLoadUnlocked(Assembly *assem);
2636 static BOOL OnUnhandledException(OBJECTREF *pThrowable, BOOL isTerminating = TRUE);
2640 // True iff a debugger is attached to the process (same as CORDebuggerAttached)
2641 BOOL IsDebuggerAttached (void);
2643 #ifdef DEBUGGING_SUPPORTED
2644 // Notify debugger of all assemblies, modules, and possibly classes in this AppDomain
2645 BOOL NotifyDebuggerLoad(int flags, BOOL attaching);
2647 // Send unload notifications to the debugger for all assemblies, modules and classes in this AppDomain
2648 void NotifyDebuggerUnload();
2649 #endif // DEBUGGING_SUPPORTED
2651 void SetSystemAssemblyLoadEventSent (BOOL fFlag);
2652 BOOL WasSystemAssemblyLoadEventSent (void);
2654 #ifndef DACCESS_COMPILE
2655 OBJECTREF* AllocateStaticFieldObjRefPtrs(int nRequested, OBJECTREF** ppLazyAllocate = NULL)
2657 WRAPPER_NO_CONTRACT;
2659 return AllocateObjRefPtrsInLargeTable(nRequested, ppLazyAllocate);
2662 OBJECTREF* AllocateStaticFieldObjRefPtrsCrossDomain(int nRequested, OBJECTREF** ppLazyAllocate = NULL)
2664 WRAPPER_NO_CONTRACT;
2666 return AllocateObjRefPtrsInLargeTable(nRequested, ppLazyAllocate, TRUE);
2668 #endif // DACCESS_COMPILE
2670 void EnumStaticGCRefs(promote_func* fn, ScanContext* sc);
2672 DomainLocalBlock *GetDomainLocalBlock()
2674 LIMITED_METHOD_DAC_CONTRACT;
2676 return &m_sDomainLocalBlock;
2679 static SIZE_T GetOffsetOfModuleSlotsPointer()
2681 WRAPPER_NO_CONTRACT;
2683 return offsetof(AppDomain,m_sDomainLocalBlock) + DomainLocalBlock::GetOffsetOfModuleSlotsPointer();
2686 void SetupSharedStatics();
2688 ADUnloadSink* PrepareForWaitUnloadCompletion();
2690 //****************************************************************************************
2692 // Create a quick lookup for classes loaded into this domain based on their GUID.
2694 void InsertClassForCLSID(MethodTable* pMT, BOOL fForceInsert = FALSE);
2695 void InsertClassForCLSID(MethodTable* pMT, GUID *pGuid);
2697 #ifdef FEATURE_COMINTEROP
2699 void CacheTypeByNameWorker(const SString &ssClassName, const UINT vCacheVersion, TypeHandle typeHandle, BYTE flags, BOOL bReplaceExisting = FALSE);
2700 TypeHandle LookupTypeByNameWorker(const SString &ssClassName, UINT *pvCacheVersion, BYTE *pbFlags);
2702 // Used by COM Interop for mapping WinRT runtime class names to real types.
2703 void CacheTypeByName(const SString &ssClassName, const UINT vCacheVersion, TypeHandle typeHandle, BYTE flags, BOOL bReplaceExisting = FALSE);
2704 TypeHandle LookupTypeByName(const SString &ssClassName, UINT *pvCacheVersion, BYTE *pbFlags);
2705 PTR_MethodTable LookupTypeByGuid(const GUID & guid);
2707 #ifndef DACCESS_COMPILE
2708 inline BOOL CanCacheWinRTTypeByGuid(TypeHandle typeHandle)
2718 // Only allow caching guid/types maps for types loaded during
2719 // "normal" domain operation
2720 if (IsCompilationDomain() || (m_Stage < STAGE_OPEN))
2723 MethodTable *pMT = typeHandle.GetMethodTable();
2726 // Don't cache mscorlib-internal declarations of WinRT types.
2727 if (pMT->GetModule()->IsSystem() && pMT->IsProjectedFromWinRT())
2730 // Don't cache redirected WinRT types.
2731 if (WinRTTypeNameConverter::IsRedirectedWinRTSourceType(pMT))
2737 #endif // !DACCESS_COMPILE
2739 void CacheWinRTTypeByGuid(TypeHandle typeHandle);
2740 void GetCachedWinRTTypes(SArray<PTR_MethodTable> * pTypes, SArray<GUID> * pGuids, UINT minEpoch, UINT * pCurEpoch);
2742 // Used by COM Interop for caching WinRT factory objects.
2743 void CacheWinRTFactoryObject(MethodTable *pClassMT, OBJECTREF *refFactory, LPVOID lpCtxCookie);
2744 OBJECTREF LookupWinRTFactoryObject(MethodTable *pClassMT, LPVOID lpCtxCookie);
2745 void RemoveWinRTFactoryObjects(LPVOID pCtxCookie);
2747 MethodTable *LoadCOMClass(GUID clsid, BOOL bLoadRecord = FALSE, BOOL* pfAssemblyInReg = NULL);
2748 COMorRemotingFlag GetComOrRemotingFlag();
2749 BOOL GetPreferComInsteadOfManagedRemoting();
2750 OBJECTREF GetMissingObject(); // DispatchInfo will call function to retrieve the Missing.Value object.
2751 #endif // FEATURE_COMINTEROP
2753 #ifndef DACCESS_COMPILE
2754 MethodTable* LookupClass(REFIID iid)
2756 WRAPPER_NO_CONTRACT;
2758 MethodTable *pMT = (MethodTable*) m_clsidHash.LookupValue((UPTR) GetKeyFromGUID(&iid), (LPVOID)&iid);
2759 return (pMT == (MethodTable*) INVALIDENTRY
2763 #endif // DACCESS_COMPILE
2765 //<TODO>@todo get a better key</TODO>
2766 ULONG GetKeyFromGUID(const GUID *pguid)
2768 LIMITED_METHOD_CONTRACT;
2770 return *(ULONG *) pguid;
2773 #ifdef FEATURE_COMINTEROP
2774 ComCallWrapperCache* GetComCallWrapperCache();
2775 RCWCache *GetRCWCache()
2777 WRAPPER_NO_CONTRACT;
2781 // By separating the cache creation from the common lookup, we
2782 // can keep the (x86) EH prolog/epilog off the path.
2783 return CreateRCWCache();
2786 RCWCache *CreateRCWCache();
2788 RCWCache *GetRCWCacheNoCreate()
2790 LIMITED_METHOD_CONTRACT;
2794 RCWRefCache *GetRCWRefCache();
2796 void ResetComCallWrapperCache()
2798 LIMITED_METHOD_CONTRACT;
2799 m_pComCallWrapperCache = NULL;
2802 MethodTable* GetLicenseInteropHelperMethodTable();
2803 #endif // FEATURE_COMINTEROP
2805 //****************************************************************************************
2806 // Get the proxy for this app domain
2807 #ifdef FEATURE_REMOTING
2808 OBJECTREF GetAppDomainProxy();
2813 LIMITED_METHOD_CONTRACT;
2819 TPIndex GetTPIndex()
2821 LIMITED_METHOD_CONTRACT;
2825 void InitializeDomainContext(BOOL allowRedirects, LPCWSTR pwszPath, LPCWSTR pwszConfig);
2827 #ifdef FEATURE_FUSION
2828 IApplicationContext *CreateFusionContext();
2829 void SetupLoaderOptimization(DWORD optimization);
2831 #ifdef FEATURE_VERSIONING
2832 IUnknown *CreateFusionContext();
2833 #endif // FEATURE_VERSIONING
2835 #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
2836 void OverrideDefaultContextBinder(IUnknown *pOverrideBinder)
2838 LIMITED_METHOD_CONTRACT;
2840 _ASSERTE(pOverrideBinder != NULL);
2841 pOverrideBinder->AddRef();
2842 m_pFusionContext->Release();
2843 m_pFusionContext = pOverrideBinder;
2846 #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
2848 #ifdef FEATURE_PREJIT
2849 CorCompileConfigFlags GetNativeConfigFlags();
2850 #endif // FEATURE_PREJIT
2852 //****************************************************************************************
2853 // Create a domain context rooted at the fileName. The directory containing the file name
2854 // is the application base and the configuration file is the fileName appended with
2855 // .config. If no name is passed in then no domain is created.
2856 static AppDomain* CreateDomainContext(LPCWSTR fileName);
2858 // Sets up the current domain's fusion context based on the given exe file name
2859 // (app base & config file)
2860 void SetupExecutableFusionContext(LPCWSTR exePath);
2862 //****************************************************************************************
2863 // Manage a pool of asyncrhonous objects used to fetch assemblies. When a sink is released
2864 // it places itself back on the pool list. Only one object is kept in the pool.
2865 #ifdef FEATURE_FUSION
2866 AssemblySink* AllocateAssemblySink(AssemblySpec* pSpec);
2868 void SetIsUserCreatedDomain()
2870 LIMITED_METHOD_CONTRACT;
2872 m_dwFlags |= USER_CREATED_DOMAIN;
2875 BOOL IsUserCreatedDomain()
2877 LIMITED_METHOD_CONTRACT;
2879 return (m_dwFlags & USER_CREATED_DOMAIN);
2882 void SetIgnoreUnhandledExceptions()
2884 LIMITED_METHOD_CONTRACT;
2886 m_dwFlags |= IGNORE_UNHANDLED_EXCEPTIONS;
2889 BOOL IgnoreUnhandledExceptions()
2891 LIMITED_METHOD_CONTRACT;
2893 return (m_dwFlags & IGNORE_UNHANDLED_EXCEPTIONS);
2896 #if defined(FEATURE_CORECLR)
2897 void SetEnablePInvokeAndClassicComInterop()
2899 LIMITED_METHOD_CONTRACT;
2901 m_dwFlags |= ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP;
2904 BOOL EnablePInvokeAndClassicComInterop()
2906 LIMITED_METHOD_CONTRACT;
2908 return (m_dwFlags & ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP);
2911 void SetAllowPlatformSpecificAppAssemblies()
2913 LIMITED_METHOD_CONTRACT;
2915 m_dwFlags |= ENABLE_SKIP_PLAT_CHECKS;
2918 BOOL AllowPlatformSpecificAppAssemblies()
2920 LIMITED_METHOD_CONTRACT;
2921 if(IsCompilationDomain())
2924 return (m_dwFlags & ENABLE_SKIP_PLAT_CHECKS);
2927 void SetAllowLoadFile()
2929 LIMITED_METHOD_CONTRACT;
2931 m_dwFlags |= ENABLE_ASSEMBLY_LOADFILE;
2934 BOOL IsLoadFileAllowed()
2936 LIMITED_METHOD_CONTRACT;
2938 return (m_dwFlags & ENABLE_ASSEMBLY_LOADFILE);
2940 #endif // defined(FEATURE_CORECLR)
2942 void SetPassiveDomain()
2944 LIMITED_METHOD_CONTRACT;
2946 m_dwFlags |= PASSIVE_DOMAIN;
2949 BOOL IsPassiveDomain()
2951 LIMITED_METHOD_CONTRACT;
2953 return (m_dwFlags & PASSIVE_DOMAIN);
2956 void SetVerificationDomain()
2958 LIMITED_METHOD_CONTRACT;
2960 m_dwFlags |= VERIFICATION_DOMAIN;
2963 BOOL IsVerificationDomain()
2965 LIMITED_METHOD_CONTRACT;
2967 return (m_dwFlags & VERIFICATION_DOMAIN);
2970 void SetIllegalVerificationDomain()
2972 LIMITED_METHOD_CONTRACT;
2974 m_dwFlags |= ILLEGAL_VERIFICATION_DOMAIN;
2977 BOOL IsIllegalVerificationDomain()
2979 LIMITED_METHOD_CONTRACT;
2981 return (m_dwFlags & ILLEGAL_VERIFICATION_DOMAIN);
2984 void SetCompilationDomain()
2986 LIMITED_METHOD_CONTRACT;
2988 m_dwFlags |= (PASSIVE_DOMAIN|COMPILATION_DOMAIN);
2991 BOOL IsCompilationDomain();
2993 PTR_CompilationDomain ToCompilationDomain()
2995 LIMITED_METHOD_CONTRACT;
2997 _ASSERTE(IsCompilationDomain());
2998 return dac_cast<PTR_CompilationDomain>(this);
3002 void SetMDILCompilationDomain()
3005 LIMITED_METHOD_CONTRACT;
3007 _ASSERTE(IsCompilationDomain());
3008 m_dwFlags |= MDIL_COMPILATION_DOMAIN;
3011 BOOL IsMDILCompilationDomain()
3014 LIMITED_METHOD_CONTRACT;
3015 return m_dwFlags & MDIL_COMPILATION_DOMAIN;
3018 void SetMinimalMDILCompilationDomain()
3020 LIMITED_METHOD_CONTRACT;
3022 _ASSERTE(IsCompilationDomain());
3023 m_dwFlags |= MINIMAL_MDIL_COMPILATION_DOMAIN;
3026 BOOL IsMinimalMDILCompilationDomain()
3028 LIMITED_METHOD_CONTRACT;
3029 return m_dwFlags & MINIMAL_MDIL_COMPILATION_DOMAIN;
3032 void SetNoMDILCompilationDomain()
3034 LIMITED_METHOD_CONTRACT;
3036 _ASSERTE(IsCompilationDomain());
3037 m_dwFlags |= NO_MDIL_COMPILATION_DOMAIN;
3040 BOOL IsNoMDILCompilationDomain()
3042 LIMITED_METHOD_CONTRACT;
3043 return m_dwFlags & NO_MDIL_COMPILATION_DOMAIN;
3049 LIMITED_METHOD_CONTRACT;
3051 m_dwFlags |= APP_DOMAIN_CAN_BE_UNLOADED;
3056 LIMITED_METHOD_CONTRACT;
3057 STATIC_CONTRACT_SO_TOLERANT;
3058 return m_dwFlags & APP_DOMAIN_CAN_BE_UNLOADED;
3061 void SetRemotingConfigured()
3063 LIMITED_METHOD_CONTRACT;
3064 STATIC_CONTRACT_SO_TOLERANT;
3065 FastInterlockOr((ULONG*)&m_dwFlags, REMOTING_CONFIGURED_FOR_DOMAIN);
3068 BOOL IsRemotingConfigured()
3070 LIMITED_METHOD_CONTRACT;
3071 STATIC_CONTRACT_SO_TOLERANT;
3072 return m_dwFlags & REMOTING_CONFIGURED_FOR_DOMAIN;
3075 void SetOrphanedLocks()
3077 LIMITED_METHOD_CONTRACT;
3078 STATIC_CONTRACT_SO_TOLERANT;
3079 FastInterlockOr((ULONG*)&m_dwFlags, ORPHANED_LOCKS);
3082 BOOL HasOrphanedLocks()
3084 LIMITED_METHOD_CONTRACT;
3085 STATIC_CONTRACT_SO_TOLERANT;
3086 return m_dwFlags & ORPHANED_LOCKS;
3089 // This function is used to relax asserts in the lock accounting.
3090 // It returns true if we are fine with hosed lock accounting in this domain.
3091 BOOL OkToIgnoreOrphanedLocks()
3093 WRAPPER_NO_CONTRACT;
3094 return HasOrphanedLocks() && m_Stage >= STAGE_UNLOAD_REQUESTED;
3097 static void ExceptionUnwind(Frame *pFrame);
3100 void TrackADThreadEnter(Thread *pThread, Frame *pFrame);
3101 void TrackADThreadExit(Thread *pThread, Frame *pFrame);
3102 void DumpADThreadTrack();
3105 #ifndef DACCESS_COMPILE
3106 void ThreadEnter(Thread *pThread, Frame *pFrame)
3108 STATIC_CONTRACT_NOTHROW;
3109 STATIC_CONTRACT_GC_NOTRIGGER;
3112 if (LoggingOn(LF_APPDOMAIN, LL_INFO100))
3113 TrackADThreadEnter(pThread, pFrame);
3117 InterlockedIncrement((LONG*)&m_dwThreadEnterCount);
3118 LOG((LF_APPDOMAIN, LL_INFO1000, "AppDomain::ThreadEnter %p to [%d] (%8.8x) %S count %d\n",
3119 pThread,GetId().m_dwId, this,
3120 GetFriendlyNameForLogging(),GetThreadEnterCount()));
3121 #if _DEBUG_AD_UNLOAD
3122 printf("AppDomain::ThreadEnter %p to [%d] (%8.8x) %S count %d\n",
3123 pThread, GetId().m_dwId, this,
3124 GetFriendlyNameForLogging(), GetThreadEnterCount());
3129 void ThreadExit(Thread *pThread, Frame *pFrame)
3131 STATIC_CONTRACT_NOTHROW;
3132 STATIC_CONTRACT_GC_NOTRIGGER;
3135 if (LoggingOn(LF_APPDOMAIN, LL_INFO100)) {
3136 TrackADThreadExit(pThread, pFrame);
3142 result = InterlockedDecrement((LONG*)&m_dwThreadEnterCount);
3143 _ASSERTE(result >= 0);
3144 LOG((LF_APPDOMAIN, LL_INFO1000, "AppDomain::ThreadExit from [%d] (%8.8x) %S count %d\n",
3145 this, GetId().m_dwId,
3146 GetFriendlyNameForLogging(), GetThreadEnterCount()));
3148 printf("AppDomain::ThreadExit %x from [%d] (%8.8x) %S count %d\n",
3149 pThread->GetThreadId(), this, GetId().m_dwId,
3150 GetFriendlyNameForLogging(), GetThreadEnterCount());
3154 #endif // DACCESS_COMPILE
3156 ULONG GetThreadEnterCount()
3158 LIMITED_METHOD_CONTRACT;
3159 return m_dwThreadEnterCount;
3162 BOOL OnlyOneThreadLeft()
3164 LIMITED_METHOD_CONTRACT;
3165 return m_dwThreadEnterCount==1 || m_dwThreadsStillInAppDomain ==1;
3168 Context *GetDefaultContext()
3170 LIMITED_METHOD_CONTRACT;
3171 return m_pDefaultContext;
3176 LIMITED_METHOD_CONTRACT;
3177 return m_Stage >= STAGE_READYFORMANAGEDCODE && m_Stage < STAGE_CLOSED;
3180 void SetAnonymouslyHostedDynamicMethodsAssembly(DomainAssembly * pDomainAssembly)
3182 LIMITED_METHOD_CONTRACT;
3183 _ASSERTE(pDomainAssembly != NULL);
3184 _ASSERTE(m_anonymouslyHostedDynamicMethodsAssembly == NULL);
3185 m_anonymouslyHostedDynamicMethodsAssembly = pDomainAssembly;
3188 DomainAssembly * GetAnonymouslyHostedDynamicMethodsAssembly()
3190 LIMITED_METHOD_CONTRACT;
3191 return m_anonymouslyHostedDynamicMethodsAssembly;
3194 BOOL HasUnloadStarted()
3196 LIMITED_METHOD_CONTRACT;
3197 return m_Stage>=STAGE_EXITED;
3199 static void RefTakerAcquire(AppDomain* pDomain)
3201 WRAPPER_NO_CONTRACT;
3206 FastInterlockIncrement(&pDomain->m_dwRefTakers);
3210 static void RefTakerRelease(AppDomain* pDomain)
3212 WRAPPER_NO_CONTRACT;
3216 _ASSERTE(pDomain->m_dwRefTakers);
3217 FastInterlockDecrement(&pDomain->m_dwRefTakers);
3224 BOOL IsHeldByIterator()
3226 LIMITED_METHOD_CONTRACT;
3227 return m_dwIterHolders>0;
3230 BOOL IsHeldByRefTaker()
3232 LIMITED_METHOD_CONTRACT;
3233 return m_dwRefTakers>0;
3236 void IteratorRelease()
3238 LIMITED_METHOD_CONTRACT;
3239 _ASSERTE(m_dwIterHolders);
3240 FastInterlockDecrement(&m_dwIterHolders);
3244 void IteratorAcquire()
3246 LIMITED_METHOD_CONTRACT;
3247 FastInterlockIncrement(&m_dwIterHolders);
3253 LIMITED_METHOD_DAC_CONTRACT;
3255 return m_Stage >= STAGE_ACTIVE && m_Stage < STAGE_CLOSED;
3257 // Range for normal execution of code in the appdomain, currently used for
3258 // appdomain resource monitoring since we don't care to update resource usage
3259 // unless it's in these stages (as fields of AppDomain may not be valid if it's
3260 // not within these stages)
3263 LIMITED_METHOD_DAC_CONTRACT;
3265 return m_Stage >= STAGE_ACTIVE && m_Stage <= STAGE_OPEN;
3269 LIMITED_METHOD_DAC_CONTRACT;
3271 #ifdef DACCESS_COMPILE
3272 // We want to see all appdomains in SOS, even the about to be destructed ones.
3273 // There is no risk of races under DAC, so we will pretend to be unconditionally valid.
3276 return m_Stage > STAGE_CREATING && m_Stage < STAGE_CLOSED;
3281 BOOL IsBeingCreated()
3283 LIMITED_METHOD_CONTRACT;
3285 return m_dwCreationHolders > 0;
3288 void IncCreationCount()
3290 LIMITED_METHOD_CONTRACT;
3292 FastInterlockIncrement(&m_dwCreationHolders);
3293 _ASSERTE(m_dwCreationHolders > 0);
3296 void DecCreationCount()
3298 LIMITED_METHOD_CONTRACT;
3300 FastInterlockDecrement(&m_dwCreationHolders);
3301 _ASSERTE(m_dwCreationHolders > -1);
3304 BOOL IsRunningIn(Thread* pThread);
3308 LIMITED_METHOD_CONTRACT;
3311 return m_Stage > STAGE_UNLOAD_REQUESTED;
3314 BOOL NotReadyForManagedCode()
3316 LIMITED_METHOD_CONTRACT;
3318 return m_Stage < STAGE_READYFORMANAGEDCODE;
3323 LIMITED_METHOD_CONTRACT;
3324 SetStage(STAGE_FINALIZED);
3329 LIMITED_METHOD_CONTRACT;
3331 return m_Stage >= STAGE_FINALIZING;
3336 LIMITED_METHOD_CONTRACT;
3338 return m_Stage >= STAGE_FINALIZED;
3341 BOOL NoAccessToHandleTable()
3343 LIMITED_METHOD_CONTRACT;
3346 return m_Stage >= STAGE_HANDLETABLE_NOACCESS;
3349 // Checks whether the given thread can enter the app domain
3350 BOOL CanThreadEnter(Thread *pThread);
3352 // Following two are needed for the Holder
3353 static void SetUnloadInProgress(AppDomain *pThis) PUB;
3354 static void SetUnloadComplete(AppDomain *pThis) PUB;
3355 // Predicates for GC asserts
3356 BOOL ShouldHaveFinalization()
3358 LIMITED_METHOD_CONTRACT;
3360 return ((DWORD) m_Stage) < STAGE_COLLECTED;
3362 BOOL ShouldHaveCode()
3364 LIMITED_METHOD_CONTRACT;
3366 return ((DWORD) m_Stage) < STAGE_COLLECTED;
3368 BOOL ShouldHaveRoots()
3370 LIMITED_METHOD_CONTRACT;
3372 return ((DWORD) m_Stage) < STAGE_CLEARED;
3374 BOOL ShouldHaveInstances()
3376 LIMITED_METHOD_CONTRACT;
3378 return ((DWORD) m_Stage) < STAGE_COLLECTED;
3382 static void RaiseExitProcessEvent();
3383 Assembly* RaiseResourceResolveEvent(DomainAssembly* pAssembly, LPCSTR szName);
3384 DomainAssembly* RaiseTypeResolveEventThrowing(DomainAssembly* pAssembly, LPCSTR szName, ASSEMBLYREF *pResultingAssemblyRef);
3385 Assembly* RaiseAssemblyResolveEvent(AssemblySpec *pSpec, BOOL fIntrospection, BOOL fPreBind);
3388 CrstExplicitInit m_ReflectionCrst;
3389 CrstExplicitInit m_RefClassFactCrst;
3392 EEClassFactoryInfoHashTable *m_pRefClassFactHash; // Hash table that maps a class factory info to a COM comp.
3393 #ifdef FEATURE_COMINTEROP
3394 DispIDCache *m_pRefDispIDCache;
3395 COMorRemotingFlag m_COMorRemotingFlag;
3396 OBJECTHANDLE m_hndMissing; //Handle points to Missing.Value Object which is used for [Optional] arg scenario during IDispatch CCW Call
3398 PTR_DomainAssembly m_pSystemDll; // System.dll loaded into this domain
3399 PTR_DomainAssembly m_pSystemRuntimeWindowsRuntimeDll; // System.Runtime.WindowsRuntime.dll loaded into this domain
3400 PTR_DomainAssembly m_pSystemRuntimeWindowsRuntimeUIXamlDll; // System.Runtime.WindowsRuntime.UI.Xaml.dll loaded into this domain
3401 PTR_DomainAssembly m_pSystemNumericsVectors; // System.Numerics.Vectors.dll loaded into this domain
3403 BOOL FindRedirectedAssemblyFromIndexIfLoaded(WinMDAdapter::FrameworkAssemblyIndex index, Assembly** ppAssembly);
3405 BOOL IsSystemDll(Assembly *pAssembly)
3407 LIMITED_METHOD_CONTRACT;
3408 return (m_pSystemDll != NULL && m_pSystemDll->GetCurrentAssembly() == pAssembly);
3412 MethodTable* m_rpCLRTypes[WinMDAdapter::RedirectedTypeIndex_Count];
3414 MethodTable* LoadRedirectedType(WinMDAdapter::RedirectedTypeIndex index, WinMDAdapter::FrameworkAssemblyIndex assembly);
3415 #endif // FEATURE_COMINTEROP
3419 CrstBase *GetRefClassFactCrst()
3421 LIMITED_METHOD_CONTRACT;
3423 return &m_RefClassFactCrst;
3426 #ifndef DACCESS_COMPILE
3427 EEClassFactoryInfoHashTable* GetClassFactHash()
3429 STATIC_CONTRACT_THROWS;
3430 STATIC_CONTRACT_GC_TRIGGERS;
3431 STATIC_CONTRACT_FAULT;
3433 if (m_pRefClassFactHash != NULL) {
3434 return m_pRefClassFactHash;
3437 return SetupClassFactHash();
3439 #endif // DACCESS_COMPILE
3441 #ifdef FEATURE_COMINTEROP
3442 DispIDCache* GetRefDispIDCache()
3444 STATIC_CONTRACT_THROWS;
3445 STATIC_CONTRACT_GC_TRIGGERS;
3446 STATIC_CONTRACT_FAULT;
3448 if (m_pRefDispIDCache != NULL) {
3449 return m_pRefDispIDCache;
3452 return SetupRefDispIDCache();
3454 #endif // FEATURE_COMINTEROP
3456 PTR_LoaderHeap GetStubHeap();
3457 PTR_LoaderHeap GetLowFrequencyHeap();
3458 PTR_LoaderHeap GetHighFrequencyHeap();
3459 virtual PTR_LoaderAllocator GetLoaderAllocator();
3461 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
3462 #define ARM_ETW_ALLOC_THRESHOLD (4 * 1024 * 1024)
3463 // cache line size in ULONGLONG - 128 bytes which are 16 ULONGLONG's
3464 #define ARM_CACHE_LINE_SIZE_ULL 16
3466 inline ULONGLONG GetAllocBytes()
3468 LIMITED_METHOD_CONTRACT;
3469 ULONGLONG ullTotalAllocBytes = 0;
3471 // Ensure that m_pullAllocBytes is non-null to avoid an AV in a race between GC and AD unload.
3472 // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullAllocBytes, causing the AD unload.
3473 if(NULL != m_pullAllocBytes)
3475 for (DWORD i = 0; i < m_dwNumHeaps; i++)
3477 ullTotalAllocBytes += m_pullAllocBytes[i * ARM_CACHE_LINE_SIZE_ULL];
3480 return ullTotalAllocBytes;
3483 void RecordAllocBytes(size_t allocatedBytes, DWORD dwHeapNumber)
3485 LIMITED_METHOD_CONTRACT;
3486 _ASSERTE(dwHeapNumber < m_dwNumHeaps);
3488 // Ensure that m_pullAllocBytes is non-null to avoid an AV in a race between GC and AD unload.
3489 // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullAllocBytes, causing the AD unload.
3490 if(NULL != m_pullAllocBytes)
3492 m_pullAllocBytes[dwHeapNumber * ARM_CACHE_LINE_SIZE_ULL] += allocatedBytes;
3495 ULONGLONG ullTotalAllocBytes = GetAllocBytes();
3497 if ((ullTotalAllocBytes - m_ullLastEtwAllocBytes) >= ARM_ETW_ALLOC_THRESHOLD)
3499 m_ullLastEtwAllocBytes = ullTotalAllocBytes;
3500 FireEtwAppDomainMemAllocated((ULONGLONG)this, ullTotalAllocBytes, GetClrInstanceId());
3504 inline ULONGLONG GetSurvivedBytes()
3506 LIMITED_METHOD_CONTRACT;
3507 ULONGLONG ullTotalSurvivedBytes = 0;
3509 // Ensure that m_pullSurvivedBytes is non-null to avoid an AV in a race between GC and AD unload.
3510 // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullSurvivedBytes, causing the AD unload.
3511 if(NULL != m_pullSurvivedBytes)
3513 for (DWORD i = 0; i < m_dwNumHeaps; i++)
3515 ullTotalSurvivedBytes += m_pullSurvivedBytes[i * ARM_CACHE_LINE_SIZE_ULL];
3518 return ullTotalSurvivedBytes;
3521 void RecordSurvivedBytes(size_t promotedBytes, DWORD dwHeapNumber)
3523 WRAPPER_NO_CONTRACT;
3524 _ASSERTE(dwHeapNumber < m_dwNumHeaps);
3526 // Ensure that m_pullSurvivedBytes is non-null to avoid an AV in a race between GC and AD unload.
3527 // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullSurvivedBytes, causing the AD unload.
3528 if(NULL != m_pullSurvivedBytes)
3530 m_pullSurvivedBytes[dwHeapNumber * ARM_CACHE_LINE_SIZE_ULL] += promotedBytes;
3534 inline void ResetSurvivedBytes()
3536 LIMITED_METHOD_CONTRACT;
3538 // Ensure that m_pullSurvivedBytes is non-null to avoid an AV in a race between GC and AD unload.
3539 // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullSurvivedBytes, causing the AD unload.
3540 if(NULL != m_pullSurvivedBytes)
3542 for (DWORD i = 0; i < m_dwNumHeaps; i++)
3544 m_pullSurvivedBytes[i * ARM_CACHE_LINE_SIZE_ULL] = 0;
3549 // Return the total processor time (user and kernel) used by threads executing in this AppDomain so far.
3550 // The result is in 100ns units.
3551 ULONGLONG QueryProcessorUsage();
3553 // Add to the current count of processor time used by threads within this AppDomain. This API is called by
3554 // threads transitioning between AppDomains.
3555 void UpdateProcessorUsage(ULONGLONG ullAdditionalUsage);
3556 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
3559 static void RaiseOneExitProcessEvent_Wrapper(AppDomainIterator* pi);
3560 static void RaiseOneExitProcessEvent();
3561 size_t EstimateSize();
3562 EEClassFactoryInfoHashTable* SetupClassFactHash();
3563 #ifdef FEATURE_COMINTEROP
3564 DispIDCache* SetupRefDispIDCache();
3565 COMorRemotingFlag GetPreferComInsteadOfManagedRemotingFromConfigFile();
3566 #endif // FEATURE_COMINTEROP
3568 void InitializeDefaultDomainManager ();
3570 #ifdef FEATURE_CLICKONCE
3571 void InitializeDefaultClickOnceDomain();
3572 #endif // FEATURE_CLICKONCE
3574 void InitializeDefaultDomainSecurity();
3576 #ifdef FEATURE_CLICKONCE
3577 BOOL IsClickOnceAppDomain();
3578 #endif // FEATURE_CLICKONCE
3581 BOOL PostBindResolveAssembly(AssemblySpec *pPrePolicySpec,
3582 AssemblySpec *pPostPolicySpec,
3583 HRESULT hrBindResult,
3584 AssemblySpec **ppFailedSpec);
3586 #ifdef FEATURE_COMINTEROP
3588 void ReleaseRCWs(LPVOID pCtxCookie);
3592 #endif // FEATURE_COMINTEROP
3594 LPWSTR m_pwDynamicDir;
3597 void RaiseLoadingAssemblyEvent(DomainAssembly* pAssembly);
3599 friend class DomainAssembly;
3602 static void ProcessUnloadDomainEventOnFinalizeThread();
3603 static BOOL HasWorkForFinalizerThread()
3605 LIMITED_METHOD_CONTRACT;
3606 return s_pAppDomainToRaiseUnloadEvent != NULL;
3610 static AppDomain* s_pAppDomainToRaiseUnloadEvent;
3611 static BOOL s_fProcessUnloadDomainEvent;
3613 void RaiseUnloadDomainEvent();
3614 static void RaiseUnloadDomainEvent_Wrapper(LPVOID /* AppDomain * */);
3616 BOOL RaiseUnhandledExceptionEvent(OBJECTREF *pSender, OBJECTREF *pThrowable, BOOL isTerminating);
3617 BOOL HasUnhandledExceptionEventHandler();
3618 BOOL RaiseUnhandledExceptionEventNoThrow(OBJECTREF *pSender, OBJECTREF *pThrowable, BOOL isTerminating);
3620 struct RaiseUnhandled_Args
3622 AppDomain *pExceptionDomain;
3623 AppDomain *pTargetDomain;
3625 OBJECTREF *pThrowable;
3629 #ifndef FEATURE_CORECLR
3630 static void RaiseUnhandledExceptionEvent_Wrapper(LPVOID /* RaiseUnhandled_Args * */);
3634 static void AllowThreadEntrance(AppDomain *pApp);
3635 static void RestrictThreadEntrance(AppDomain *pApp);
3637 typedef Holder<AppDomain*,DoNothing<AppDomain*>,AppDomain::AllowThreadEntrance,NULL> RestrictEnterHolder;
3641 STAGE_READYFORMANAGEDCODE,
3644 STAGE_UNLOAD_REQUESTED,
3649 STAGE_HANDLETABLE_NOACCESS,
3654 void SetStage(Stage stage)
3664 STRESS_LOG2(LF_APPDOMAIN, LL_INFO100,"Updating AD stage, ADID=%d, stage=%d\n",GetId().m_dwId,stage);
3665 TESTHOOKCALL(AppDomainStageChanged(GetId().m_dwId,m_Stage,stage));
3666 Stage lastStage=m_Stage;
3667 while (lastStage !=stage)
3668 lastStage = (Stage)FastInterlockCompareExchange((LONG*)&m_Stage,stage,lastStage);
3670 void Exit(BOOL fRunFinalizers, BOOL fAsyncExit);
3672 void ClearGCRoots();
3673 void ClearGCHandles();
3674 void HandleAsyncPinHandles();
3675 void UnwindThreads();
3676 // Return TRUE if EE is stopped
3677 // Return FALSE if more work is needed
3678 BOOL StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnloadRequestThread);
3680 // Use Rude Abort to unload the domain.
3683 Thread *m_pUnloadRequestThread;
3684 ADUnloadSink* m_ADUnloadSink;
3685 BOOL m_bForceGCOnUnload;
3686 BOOL m_bUnloadingFromUnloadEvent;
3687 AppDomainLoaderAllocator m_LoaderAllocator;
3689 // List of unloaded LoaderAllocators, protected by code:GetLoaderAllocatorReferencesLock (for now)
3690 LoaderAllocator * m_pDelayedLoaderAllocatorUnloadList;
3694 // Register the loader allocator for deletion in code:ShutdownFreeLoaderAllocators.
3695 void RegisterLoaderAllocatorForDeletion(LoaderAllocator * pLoaderAllocator);
3697 AppDomain * m_pNextInDelayedUnloadList;
3699 void SetForceGCOnUnload(BOOL bSet)
3701 m_bForceGCOnUnload=bSet;
3704 void SetUnloadingFromUnloadEvent()
3706 m_bUnloadingFromUnloadEvent=TRUE;
3709 BOOL IsUnloadingFromUnloadEvent()
3711 return m_bUnloadingFromUnloadEvent;
3714 void SetRudeUnload()
3716 LIMITED_METHOD_CONTRACT;
3718 m_fRudeUnload = TRUE;
3723 LIMITED_METHOD_CONTRACT;
3725 return m_fRudeUnload;
3728 ADUnloadSink* GetADUnloadSink();
3729 ADUnloadSink* GetADUnloadSinkForUnload();
3730 void SetUnloadRequestThread(Thread *pThread)
3732 LIMITED_METHOD_CONTRACT;
3734 m_pUnloadRequestThread = pThread;
3737 Thread *GetUnloadRequestThread()
3739 LIMITED_METHOD_CONTRACT;
3741 return m_pUnloadRequestThread;
3745 void SetGCRefPoint(int gccounter)
3747 LIMITED_METHOD_CONTRACT;
3748 m_LoaderAllocator.SetGCRefPoint(gccounter);
3752 LIMITED_METHOD_CONTRACT;
3753 return m_LoaderAllocator.GetGCRefPoint();
3756 static USHORT GetOffsetOfId()
3758 LIMITED_METHOD_CONTRACT;
3759 size_t ofs = offsetof(class AppDomain, m_dwId);
3760 _ASSERTE(FitsInI2(ofs));
3765 void AddMemoryPressure();
3766 void RemoveMemoryPressure();
3767 void Unload(BOOL fForceUnload);
3768 static HRESULT UnloadById(ADID Id, BOOL fSync, BOOL fExceptionsPassThrough=FALSE);
3769 static HRESULT UnloadWait(ADID Id, ADUnloadSink* pSink);
3770 #ifdef FEATURE_TESTHOOKS
3771 static HRESULT UnloadWaitNoCatch(ADID Id, ADUnloadSink* pSink);
3773 static void ResetUnloadRequestThread(ADID Id);
3775 void UnlinkClass(MethodTable *pMT);
3777 typedef Holder<AppDomain *, AppDomain::SetUnloadInProgress, AppDomain::SetUnloadComplete> UnloadHolder;
3778 Assembly *GetRootAssembly()
3780 LIMITED_METHOD_CONTRACT;
3781 return m_pRootAssembly;
3784 #ifndef DACCESS_COMPILE
3785 void SetRootAssembly(Assembly *pAssembly)
3787 LIMITED_METHOD_CONTRACT;
3788 m_pRootAssembly = pAssembly;
3793 SString m_friendlyName;
3794 PTR_Assembly m_pRootAssembly;
3796 // General purpose flags.
3799 // When an application domain is created the ref count is artifically incremented
3800 // by one. For it to hit zero an explicit close must have happened.
3801 LONG m_cRef; // Ref count.
3803 PTR_IApplicationSecurityDescriptor m_pSecDesc; // Application Security Descriptor
3805 OBJECTHANDLE m_ExposedObject;
3807 #ifdef FEATURE_LOADER_OPTIMIZATION
3808 // Indicates where assemblies will be loaded for
3809 // this domain. By default all assemblies are loaded into the domain.
3810 // There are two additional settings, all
3811 // assemblies can be loaded into the shared domain or assemblies
3812 // that are strong named are loaded into the shared area.
3813 SharePolicy m_SharePolicy;
3816 IUnknown *m_pComIPForExposedObject;
3818 // Hash table that maps a clsid to a type
3819 PtrHashMap m_clsidHash;
3821 #ifdef FEATURE_COMINTEROP
3822 // Hash table that maps WinRT class names to MethodTables.
3823 PTR_NameToTypeMapTable m_pNameToTypeMap;
3824 UINT m_vNameToTypeMapVersion;
3826 UINT m_nEpoch; // incremented each time m_pNameToTypeMap is enumerated
3828 // Hash table that remembers the last cached WinRT factory object per type per appdomain.
3829 WinRTFactoryCache *m_pWinRTFactoryCache;
3831 // The wrapper cache for this domain - it has its own CCacheLineAllocator on a per domain basis
3832 // to allow the domain to go away and eventually kill the memory when all refs are gone
3833 ComCallWrapperCache *m_pComCallWrapperCache;
3835 // this cache stores the RCWs in this domain
3836 RCWCache *m_pRCWCache;
3838 // this cache stores the RCW -> CCW references in this domain
3839 RCWRefCache *m_pRCWRefCache;
3841 // The method table used for LicenseInteropHelper
3842 MethodTable* m_pLicenseInteropHelperMT;
3843 #endif // FEATURE_COMINTEROP
3845 AssemblySink* m_pAsyncPool; // asynchronous retrival object pool (only one is kept)
3847 // The index of this app domain among existing app domains (starting from 1)
3850 // The thread-pool index of this app domain among existing app domains (starting from 1)
3853 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
3854 ULONGLONG* m_pullAllocBytes;
3855 ULONGLONG* m_pullSurvivedBytes;
3857 ULONGLONG m_ullLastEtwAllocBytes;
3858 // Total processor time (user and kernel) utilized by threads running in this AppDomain so far. May not
3859 // account for threads currently executing in the AppDomain until a call to QueryProcessorUsage() is
3861 Volatile<ULONGLONG> m_ullTotalProcessorUsage;
3862 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
3865 struct ThreadTrackInfo;
3866 typedef CDynArray<ThreadTrackInfo *> ThreadTrackInfoList;
3867 ThreadTrackInfoList *m_pThreadTrackInfoList;
3868 DWORD m_TrackSpinLock;
3872 // IL stub cache with fabricated MethodTable parented by a random module in this AD.
3873 ILStubCache m_ILStubCache;
3875 // U->M thunks created in this domain and not associated with a delegate.
3876 // The cache is keyed by MethodDesc pointers.
3877 UMEntryThunkCache *m_pUMEntryThunkCache;
3879 // The number of times we have entered this AD
3880 ULONG m_dwThreadEnterCount;
3881 // The number of threads that have entered this AD, for ADU only
3882 ULONG m_dwThreadsStillInAppDomain;
3884 Volatile<Stage> m_Stage;
3886 // The default context for this domain
3887 Context *m_pDefaultContext;
3889 SString m_applicationBase;
3890 SString m_privateBinPaths;
3891 SString m_configFile;
3893 ArrayList m_failedAssemblies;
3895 DomainAssembly * m_anonymouslyHostedDynamicMethodsAssembly;
3898 Volatile<LONG> m_dwIterHolders;
3899 Volatile<LONG> m_dwRefTakers;
3900 Volatile<LONG> m_dwCreationHolders;
3904 // DAC iterator for failed assembly loads
3906 class FailedAssemblyIterator
3908 ArrayList::Iterator m_i;
3913 WRAPPER_NO_CONTRACT;
3916 FailedAssembly *GetFailedAssembly()
3918 WRAPPER_NO_CONTRACT;
3919 return dac_cast<PTR_FailedAssembly>(m_i.GetElement());
3923 WRAPPER_NO_CONTRACT;
3924 return m_i.GetIndex();
3928 friend class AppDomain;
3929 // Cannot have constructor so this iterator can be used inside a union
3930 static FailedAssemblyIterator Create(AppDomain *pDomain)
3932 WRAPPER_NO_CONTRACT;
3933 FailedAssemblyIterator i;
3935 i.m_i = pDomain->m_failedAssemblies.Iterate();
3939 friend class FailedAssemblyIterator;
3941 FailedAssemblyIterator IterateFailedAssembliesEx()
3943 WRAPPER_NO_CONTRACT;
3944 return FailedAssemblyIterator::Create(this);
3947 //---------------------------------------------------------
3948 // Stub caches for Method stubs
3949 //---------------------------------------------------------
3951 #ifdef FEATURE_FUSION
3952 void TurnOnBindingRedirects();
3956 #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
3958 Volatile<BOOL> m_fIsBindingModelLocked;
3960 BOOL IsHostAssemblyResolverInUse();
3961 BOOL IsBindingModelLocked();
3962 BOOL LockBindingModel();
3963 #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
3965 UMEntryThunkCache *GetUMEntryThunkCache();
3967 ILStubCache* GetILStubCache()
3969 LIMITED_METHOD_CONTRACT;
3970 return &m_ILStubCache;
3973 static AppDomain* GetDomain(ILStubCache* pILStubCache)
3975 return CONTAINING_RECORD(pILStubCache, AppDomain, m_ILStubCache);
3979 CONTEXT_INITIALIZED = 0x0001,
3980 USER_CREATED_DOMAIN = 0x0002, // created by call to AppDomain.CreateDomain
3981 ALLOCATEDCOM = 0x0008,
3982 LOAD_SYSTEM_ASSEMBLY_EVENT_SENT = 0x0040,
3983 REMOTING_CONFIGURED_FOR_DOMAIN = 0x0100,
3984 COMPILATION_DOMAIN = 0x0400, // Are we ngenning?
3985 APP_DOMAIN_CAN_BE_UNLOADED = 0x0800, // if need extra bits, can derive this at runtime
3986 ORPHANED_LOCKS = 0x1000, // Orphaned locks exist in this appdomain.
3987 PASSIVE_DOMAIN = 0x2000, // Can we execute code in this AppDomain
3988 VERIFICATION_DOMAIN = 0x4000, // This is a verification domain
3989 ILLEGAL_VERIFICATION_DOMAIN = 0x8000, // This can't be a verification domain
3990 IGNORE_UNHANDLED_EXCEPTIONS = 0x10000, // AppDomain was created using the APPDOMAIN_IGNORE_UNHANDLED_EXCEPTIONS flag
3991 ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP = 0x20000, // AppDomain was created using the APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP flag
3993 MDIL_COMPILATION_DOMAIN = 0x040000, // Are we generating MDIL?
3994 MINIMAL_MDIL_COMPILATION_DOMAIN = 0x080000, // Are we generating platform MDIL?
3995 NO_MDIL_COMPILATION_DOMAIN = 0x100000, // Are we generating a file we believe will fail on the Triton code path
3997 #ifdef FEATURE_CORECLR
3998 ENABLE_SKIP_PLAT_CHECKS = 0x200000, // Skip various assembly checks (like platform check)
3999 ENABLE_ASSEMBLY_LOADFILE = 0x400000, // Allow Assembly.LoadFile in CoreCLR
4003 SecurityContext *m_pSecContext;
4005 AssemblySpecBindingCache m_AssemblyCache;
4006 DomainAssemblyCache m_UnmanagedCache;
4007 size_t m_MemoryPressure;
4009 SString m_AppDomainManagerAssembly;
4010 SString m_AppDomainManagerType;
4011 BOOL m_fAppDomainManagerSetInConfig;
4012 EInitializeNewDomainFlags m_dwAppDomainManagerInitializeDomainFlags;
4014 #ifdef FEATURE_CORECLR
4015 ArrayList m_NativeDllSearchDirectories;
4017 BOOL m_ReversePInvokeCanEnter;
4018 bool m_ForceTrivialWaitOperations;
4019 // Section to support AD unload due to escalation
4021 static void CreateADUnloadWorker();
4023 static void CreateADUnloadStartEvent();
4025 static DWORD WINAPI ADUnloadThreadStart(void *args);
4027 // Default is safe unload with test hook
4028 void EnableADUnloadWorker();
4030 // If called to handle stack overflow, we can not set event, since the thread has limit stack.
4031 void EnableADUnloadWorker(EEPolicy::AppDomainUnloadTypes type, BOOL fHasStack = TRUE);
4033 static void EnableADUnloadWorkerForThreadAbort();
4034 static void EnableADUnloadWorkerForFinalizer();
4035 static void EnableADUnloadWorkerForCollectedADCleanup();
4037 BOOL IsUnloadRequested()
4039 LIMITED_METHOD_CONTRACT;
4041 return (m_Stage == STAGE_UNLOAD_REQUESTED);
4044 #ifdef FEATURE_CORECLR
4045 BOOL IsImageFromTrustedPath(PEImage* pImage);
4046 BOOL IsImageFullyTrusted(PEImage* pImage);
4049 #ifdef FEATURE_TYPEEQUIVALENCE
4051 VolatilePtr<TypeEquivalenceHashTable> m_pTypeEquivalenceTable;
4052 CrstExplicitInit m_TypeEquivalenceCrst;
4054 TypeEquivalenceHashTable * GetTypeEquivalenceCache();
4058 static void ADUnloadWorkerHelper(AppDomain *pDomain);
4059 static CLREvent * g_pUnloadStartEvent;
4061 #ifdef DACCESS_COMPILE
4063 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
4067 #ifdef FEATURE_MULTICOREJIT
4070 MulticoreJitManager m_MulticoreJitManager;
4073 MulticoreJitManager & GetMulticoreJitManager()
4075 LIMITED_METHOD_CONTRACT;
4077 return m_MulticoreJitManager;
4082 #ifdef FEATURE_COMINTEROP
4085 #ifdef FEATURE_REFLECTION_ONLY_LOAD
4086 // ReflectionOnly WinRT binder and its TypeCache (only in classic = non-AppX; the scenario is not supported in AppX)
4087 CLRPrivBinderReflectionOnlyWinRT * m_pReflectionOnlyWinRtBinder;
4088 CLRPrivTypeCacheReflectionOnlyWinRT * m_pReflectionOnlyWinRtTypeCache;
4089 #endif // FEATURE_REFLECTION_ONLY_LOAD
4091 #endif //FEATURE_COMINTEROP
4094 #ifndef FEATURE_CORECLR
4095 BOOL m_bUseOsSorting;
4096 DWORD m_sortVersion;
4097 COMNlsCustomSortLibrary *m_pCustomSortLibrary;
4099 BOOL m_bSortingInitialized;
4101 COMNlsHashProvider *m_pNlsHashProvider;
4102 #endif // !FEATURE_CORECLR
4104 #ifdef FEATURE_HOSTED_BINDER
4106 // This is the root-level default load context root binder. If null, then
4107 // the Fusion binder is used; otherwise this binder is used.
4108 ReleaseHolder<ICLRPrivBinder> m_pLoadContextHostBinder;
4110 // -------------------------
4112 // The shared and designer context binders are ONLY to be used in tool
4113 // scenarios. There are known issues where use of these binders will
4114 // cause application crashes, and interesting behaviors.
4115 // -------------------------
4117 // This is the default designer shared context root binder.
4118 // This is used as the parent binder for ImmersiveDesignerContextBinders
4119 ReleaseHolder<ICLRPrivBinder> m_pSharedContextHostBinder;
4121 // This is the current context root binder.
4122 // Normally, this variable is immutable for appdomain lifetime, but in designer scenarios
4123 // it may be replaced by designer context binders
4124 Volatile<ICLRPrivBinder *> m_pCurrentContextHostBinder;
4127 // Returns the current hosted binder, or null if none available.
4129 ICLRPrivBinder * GetCurrentLoadContextHostBinder() const
4131 LIMITED_METHOD_CONTRACT;
4132 return m_pCurrentContextHostBinder;
4135 // Returns the shared context binder, or null if none available.
4137 ICLRPrivBinder * GetSharedContextHostBinder() const
4139 LIMITED_METHOD_CONTRACT;
4140 return m_pSharedContextHostBinder;
4143 // Returns the load context binder, or null if none available.
4145 ICLRPrivBinder * GetLoadContextHostBinder() const
4147 LIMITED_METHOD_CONTRACT;
4148 return m_pLoadContextHostBinder;
4151 #ifndef DACCESS_COMPILE
4153 // This is only called from the ImmersiveDesignerContext code
4154 // It is protected with a managed monitor lock
4156 void SetSharedContextHostBinder(ICLRPrivBinder * pBinder)
4158 LIMITED_METHOD_CONTRACT;
4160 m_pSharedContextHostBinder = pBinder;
4163 // This is called from CorHost2's implementation of ICLRPrivRuntime::CreateAppDomain.
4164 // Should only be called during AppDomain creation.
4166 void SetLoadContextHostBinder(ICLRPrivBinder * pBinder)
4168 LIMITED_METHOD_CONTRACT;
4170 m_pLoadContextHostBinder = m_pCurrentContextHostBinder = pBinder;
4174 void SetCurrentContextHostBinder(ICLRPrivBinder * pBinder)
4183 LockHolder lh(this);
4185 #ifdef FEATURE_COMINTEROP
4186 if (m_pNameToTypeMap != nullptr)
4188 delete m_pNameToTypeMap;
4189 m_pNameToTypeMap = nullptr;
4192 m_vNameToTypeMapVersion++;
4195 m_pCurrentContextHostBinder = pBinder;
4198 #endif // DACCESS_COMPILE
4200 // Indicates that a hosted binder is present.
4202 bool HasLoadContextHostBinder()
4204 LIMITED_METHOD_CONTRACT;
4205 return m_pLoadContextHostBinder != nullptr;
4208 class ComInterfaceReleaseList
4210 SArray<IUnknown *> m_objects;
4212 ~ComInterfaceReleaseList()
4214 WRAPPER_NO_CONTRACT;
4216 for (COUNT_T i = 0; i < m_objects.GetCount(); i++)
4218 IUnknown *pItf = *(m_objects.GetElements() + i);
4219 if (pItf != nullptr)
4224 // Append to the list of object to free. Only use under the AppDomain "LockHolder(pAppDomain)"
4225 void Append(IUnknown *pInterfaceToRelease)
4227 WRAPPER_NO_CONTRACT;
4228 m_objects.Append(pInterfaceToRelease);
4230 } AppDomainInterfaceReleaseList;
4233 //-----------------------------------------------------------
4234 // Static ICLRPrivAssembly -> DomainAssembly mapping functions.
4235 // This map does not maintain a reference count to either key or value.
4236 // PEFile maintains a reference count on the ICLRPrivAssembly through its code:PEFile::m_pHostAssembly field.
4237 // It is removed from this hash table by code:DomainAssembly::~DomainAssembly.
4238 struct HostAssemblyHashTraits : public DefaultSHashTraits<PTR_DomainAssembly>
4241 typedef PTR_ICLRPrivAssembly key_t;
4243 static key_t GetKey(element_t const & elem)
4245 STATIC_CONTRACT_WRAPPER;
4246 return elem->GetFile()->GetHostAssembly();
4249 static BOOL Equals(key_t key1, key_t key2)
4251 LIMITED_METHOD_CONTRACT;
4252 return dac_cast<TADDR>(key1) == dac_cast<TADDR>(key2);
4255 static count_t Hash(key_t key)
4257 STATIC_CONTRACT_LIMITED_METHOD;
4258 //return reinterpret_cast<count_t>(dac_cast<TADDR>(key));
4259 return (count_t)(dac_cast<TADDR>(key));
4262 static const element_t Null() { return NULL; }
4263 static const element_t Deleted() { return (element_t)(TADDR)-1; }
4264 static bool IsNull(const element_t & e) { return e == NULL; }
4265 static bool IsDeleted(const element_t & e) { return dac_cast<TADDR>(e) == (TADDR)-1; }
4268 struct OriginalFileHostAssemblyHashTraits : public HostAssemblyHashTraits
4271 static key_t GetKey(element_t const & elem)
4273 STATIC_CONTRACT_WRAPPER;
4274 return elem->GetOriginalFile()->GetHostAssembly();
4278 typedef SHash<HostAssemblyHashTraits> HostAssemblyMap;
4279 typedef SHash<OriginalFileHostAssemblyHashTraits> OriginalFileHostAssemblyMap;
4280 HostAssemblyMap m_hostAssemblyMap;
4281 OriginalFileHostAssemblyMap m_hostAssemblyMapForOrigFile;
4282 CrstExplicitInit m_crstHostAssemblyMap;
4283 // Lock to serialize all Add operations (in addition to the "read-lock" above)
4284 CrstExplicitInit m_crstHostAssemblyMapAdd;
4287 // Returns DomainAssembly.
4288 PTR_DomainAssembly FindAssembly(PTR_ICLRPrivAssembly pHostAssembly);
4290 #ifndef DACCESS_COMPILE
4292 friend void DomainAssembly::Allocate();
4293 friend DomainAssembly::~DomainAssembly();
4295 // Called from DomainAssembly::Begin.
4296 void PublishHostedAssembly(
4297 DomainAssembly* pAssembly);
4299 // Called from DomainAssembly::UpdatePEFile.
4300 void UpdatePublishHostedAssembly(
4301 DomainAssembly* pAssembly,
4304 // Called from DomainAssembly::~DomainAssembly
4305 void UnPublishHostedAssembly(
4306 DomainAssembly* pAssembly);
4307 #endif // DACCESS_COMPILE
4309 #endif //FEATURE_HOSTED_BINDER
4310 #ifdef FEATURE_PREJIT
4311 friend void DomainFile::InsertIntoDomainFileWithNativeImageList();
4312 Volatile<DomainFile *> m_pDomainFileWithNativeImageList;
4314 DomainFile *GetDomainFilesWithNativeImagesList()
4316 LIMITED_METHOD_CONTRACT;
4317 return m_pDomainFileWithNativeImageList;
4320 }; // class AppDomain
4323 // This holder is to be used to take a reference to make sure AppDomain* is still valid
4324 // Please do not use if you are aleady ADU-safe
4325 typedef Wrapper<AppDomain*,AppDomain::RefTakerAcquire,AppDomain::RefTakerRelease,NULL> AppDomainRefTaker;
4327 // Just a ref holder
4328 typedef ReleaseHolder<AppDomain> AppDomainRefHolder;
4330 // This class provides a way to access AppDomain by ID
4331 // without risking the appdomain getting invalid in the process
4332 class AppDomainFromIDHolder
4337 SyncType_GC, // Prevents AD from being unloaded by forbidding GC for the lifetime of the object
4338 SyncType_ADLock // Prevents AD from being unloaded by requiring ownership of DomainLock for the lifetime of the object
4341 AppDomain* m_pDomain;
4348 DEBUG_NOINLINE AppDomainFromIDHolder(ADID adId, BOOL bUnsafePoint, SyncType synctype=SyncType_GC);
4349 DEBUG_NOINLINE AppDomainFromIDHolder(SyncType synctype=SyncType_GC);
4350 DEBUG_NOINLINE ~AppDomainFromIDHolder();
4352 void* GetAddress() { return m_pDomain; } // Used to get an identfier for ETW
4353 void Assign(ADID adId, BOOL bUnsafePoint);
4354 void ThrowIfUnloaded();
4358 LIMITED_METHOD_CONTRACT;
4361 if (m_pDomain==NULL)
4363 // no need to enforce anything
4367 return m_pDomain==NULL;
4369 AppDomain* operator->();
4370 }; // class AppDomainFromIDHolder
4374 typedef VPTR(class SystemDomain) PTR_SystemDomain;
4376 class SystemDomain : public BaseDomain
4378 friend class AppDomainNative;
4379 friend class AppDomainIterator;
4380 friend class UnsafeAppDomainIterator;
4381 friend class ClrDataAccess;
4382 friend class AppDomainFromIDHolder;
4383 friend Frame *Thread::IsRunningIn(AppDomain* pDomain, int *count);
4385 VPTR_VTABLE_CLASS(SystemDomain, BaseDomain)
4386 VPTR_UNIQUE(VPTR_UNIQUE_SystemDomain)
4387 static AppDomain *GetAppDomainAtId(ADID indx);
4390 static PTR_LoaderAllocator GetGlobalLoaderAllocator();
4391 virtual PTR_LoaderAllocator GetLoaderAllocator() { WRAPPER_NO_CONTRACT; return GetGlobalLoaderAllocator(); }
4392 static AppDomain* GetAppDomainFromId(ADID indx,DWORD ADValidityKind)
4402 if (indx.m_dwId==DefaultADID)
4403 pRetVal= SystemDomain::System()->DefaultDomain();
4405 pRetVal= GetAppDomainAtId(indx);
4407 // Only call CheckADValidity in DEBUG builds for non-NULL return values
4408 if (pRetVal != NULL)
4409 CheckADValidity(pRetVal, ADValidityKind);
4413 //****************************************************************************************
4415 // To be run during the initial start up of the EE. This must be
4416 // performed prior to any class operations.
4417 static void Attach();
4419 //****************************************************************************************
4421 // To be run during shutdown. This must be done after all operations
4422 // that require the use of system classes (i.e., exceptions).
4423 // DetachBegin stops all domains, while DetachEnd deallocates domain resources.
4424 static void DetachBegin();
4426 //****************************************************************************************
4428 // To be run during shutdown. This must be done after all operations
4429 // that require the use of system classes (i.e., exceptions).
4430 // DetachBegin stops release resources held by systemdomain and the default domain.
4431 static void DetachEnd();
4433 //****************************************************************************************
4435 // Initializes and shutdowns the single instance of the SystemDomain
4437 #ifndef DACCESS_COMPILE
4438 void *operator new(size_t size, void *pInPlace);
4439 void operator delete(void *pMem);
4444 static void LazyInitGlobalStringLiteralMap();
4446 //****************************************************************************************
4448 // Load the base system classes, these classes are required before
4449 // any other classes are loaded
4450 void LoadBaseSystemClasses();
4452 AppDomain* DefaultDomain()
4454 LIMITED_METHOD_DAC_CONTRACT;
4456 return m_pDefaultDomain;
4459 // Notification when an assembly is loaded into the system domain
4460 void OnAssemblyLoad(Assembly *assem);
4462 //****************************************************************************************
4464 // Global Static to get the one and only system domain
4465 static SystemDomain * System()
4467 LIMITED_METHOD_DAC_CONTRACT;
4469 return m_pSystemDomain;
4472 static PEAssembly* SystemFile()
4474 WRAPPER_NO_CONTRACT;
4476 _ASSERTE(m_pSystemDomain);
4477 return System()->m_pSystemFile;
4480 static Assembly* SystemAssembly()
4482 WRAPPER_NO_CONTRACT;
4484 return System()->m_pSystemAssembly;
4487 static Module* SystemModule()
4489 WRAPPER_NO_CONTRACT;
4491 return SystemAssembly()->GetManifestModule();
4494 static BOOL IsSystemLoaded()
4496 WRAPPER_NO_CONTRACT;
4498 return System()->m_pSystemAssembly != NULL;
4501 #ifndef DACCESS_COMPILE
4502 static GlobalStringLiteralMap *GetGlobalStringLiteralMap()
4504 WRAPPER_NO_CONTRACT;
4506 if (m_pGlobalStringLiteralMap == NULL)
4508 SystemDomain::LazyInitGlobalStringLiteralMap();
4510 _ASSERTE(m_pGlobalStringLiteralMap);
4511 return m_pGlobalStringLiteralMap;
4513 static GlobalStringLiteralMap *GetGlobalStringLiteralMapNoCreate()
4515 LIMITED_METHOD_CONTRACT;
4517 _ASSERTE(m_pGlobalStringLiteralMap);
4518 return m_pGlobalStringLiteralMap;
4520 #endif // DACCESS_COMPILE
4522 #ifndef FEATURE_CORECLR
4523 static void ExecuteMainMethod(HMODULE hMod, __in_opt LPWSTR path = NULL);
4525 static void ActivateApplication(int *pReturnValue);
4527 static void InitializeDefaultDomain(
4529 #ifdef FEATURE_HOSTED_BINDER
4530 , ICLRPrivBinder * pBinder = NULL
4533 static void SetupDefaultDomain();
4534 static HRESULT SetupDefaultDomainNoThrow();
4536 #if defined(FEATURE_COMINTEROP_APARTMENT_SUPPORT) && !defined(CROSSGEN_COMPILE)
4537 static Thread::ApartmentState GetEntryPointThreadAptState(IMDInternalImport* pScope, mdMethodDef mdMethod);
4538 static void SetThreadAptState(IMDInternalImport* pScope, Thread::ApartmentState state);
4540 static BOOL SetGlobalSharePolicyUsingAttribute(IMDInternalImport* pScope, mdMethodDef mdMethod);
4542 #ifdef FEATURE_MIXEDMODE
4543 static HRESULT RunDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved);
4544 #endif // FEATURE_MIXEDMODE
4546 //****************************************************************************************
4548 // Use an already exising & inited Application Domain (e.g. a subclass).
4549 static void LoadDomain(AppDomain *pDomain);
4551 #ifndef DACCESS_COMPILE
4552 static void MakeUnloadable(AppDomain* pApp)
4554 WRAPPER_NO_CONTRACT;
4555 System()->AddDomain(pApp);
4556 pApp->SetCanUnload();
4558 #endif // DACCESS_COMPILE
4560 //****************************************************************************************
4561 // Methods used to get the callers module and hence assembly and app domain.
4562 __declspec(deprecated("This method is deprecated, use the version that takes a StackCrawlMark instead"))
4563 static Module* GetCallersModule(int skip);
4564 static MethodDesc* GetCallersMethod(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
4565 static MethodTable* GetCallersType(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
4566 static Module* GetCallersModule(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
4567 static Assembly* GetCallersAssembly(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
4569 static bool IsReflectionInvocationMethod(MethodDesc* pMeth);
4571 #ifndef DACCESS_COMPILE
4572 //****************************************************************************************
4573 // Returns the domain associated with the current context. (this can only be a child domain)
4574 static inline AppDomain * GetCurrentDomain()
4576 WRAPPER_NO_CONTRACT;
4577 return ::GetAppDomain();
4579 #endif //!DACCESS_COMPILE
4581 #ifdef DEBUGGING_SUPPORTED
4582 //****************************************************************************************
4583 // Debugger/Publisher helper function to indicate creation of new app domain to debugger
4584 // and publishing it in the IPC block
4585 static void PublishAppDomainAndInformDebugger (AppDomain *pDomain);
4586 #endif // DEBUGGING_SUPPORTED
4588 //****************************************************************************************
4589 // Helper function to remove a domain from the system
4590 BOOL RemoveDomain(AppDomain* pDomain); // Does not decrement the reference
4592 #ifdef PROFILING_SUPPORTED
4593 //****************************************************************************************
4594 // Tell profiler about system created domains which are created before the profiler is
4595 // actually activated.
4596 static void NotifyProfilerStartup();
4598 //****************************************************************************************
4599 // Tell profiler at shutdown that system created domains are going away. They are not
4600 // torn down using the normal sequence.
4601 static HRESULT NotifyProfilerShutdown();
4602 #endif // PROFILING_SUPPORTED
4604 IApplicationSecurityDescriptor* GetSecurityDescriptor()
4606 LIMITED_METHOD_CONTRACT;
4611 //****************************************************************************************
4612 // return the dev path
4613 #ifdef FEATURE_FUSION
4614 void GetDevpathW(__out_ecount_opt(1) LPWSTR* pPath, DWORD* pSize);
4617 #ifndef DACCESS_COMPILE
4618 void IncrementNumAppDomains ()
4620 LIMITED_METHOD_CONTRACT;
4625 void DecrementNumAppDomains ()
4627 LIMITED_METHOD_CONTRACT;
4632 ULONG GetNumAppDomains ()
4634 LIMITED_METHOD_CONTRACT;
4636 return s_dNumAppDomains;
4638 #endif // DACCESS_COMPILE
4641 // AppDomains currently have both an index and an ID. The
4642 // index is "densely" assigned; indices are reused as domains
4643 // are unloaded. The Id's on the other hand, are not reclaimed
4644 // so may be sparse.
4646 // Another important difference - it's OK to call GetAppDomainAtId for
4647 // an unloaded domain (it will return NULL), while GetAppDomainAtIndex
4648 // will assert if the domain is unloaded.
4651 // I'm not really happy with this situation, but
4652 // (a) we need an ID for a domain which will last the process lifetime for the
4654 // (b) we need a dense ID, for the handle table index.
4655 // So for now, I'm leaving both, but hopefully in the future we can come up
4656 // with something better.
4659 static ADIndex GetNewAppDomainIndex(AppDomain * pAppDomain);
4660 static void ReleaseAppDomainIndex(ADIndex indx);
4661 static PTR_AppDomain GetAppDomainAtIndex(ADIndex indx);
4662 static PTR_AppDomain TestGetAppDomainAtIndex(ADIndex indx);
4663 static DWORD GetCurrentAppDomainMaxIndex()
4665 WRAPPER_NO_CONTRACT;
4667 ArrayListStatic* list = (ArrayListStatic *)&m_appDomainIndexList;
4668 PREFIX_ASSUME(list!=NULL);
4669 return list->GetCount();
4672 static ADID GetNewAppDomainId(AppDomain *pAppDomain);
4673 static void ReleaseAppDomainId(ADID indx);
4675 #ifndef DACCESS_COMPILE
4676 static ADID GetCurrentAppDomainMaxId() { ADID id; id.m_dwId=m_appDomainIdList.GetCount(); return id;}
4677 #endif // DACCESS_COMPILE
4680 #ifndef DACCESS_COMPILE
4681 DWORD RequireAppDomainCleanup()
4683 LIMITED_METHOD_CONTRACT;
4684 return m_pDelayedUnloadList != 0 || m_pDelayedUnloadListOfLoaderAllocators != 0;
4687 void AddToDelayedUnloadList(AppDomain* pDomain, BOOL bAsync)
4696 m_UnloadIsAsync = bAsync;
4698 CrstHolder lh(&m_DelayedUnloadCrst);
4699 pDomain->m_pNextInDelayedUnloadList=m_pDelayedUnloadList;
4700 m_pDelayedUnloadList=pDomain;
4701 if (m_UnloadIsAsync)
4704 int iGCRefPoint=GCHeap::GetGCHeap()->CollectionCount(GCHeap::GetGCHeap()->GetMaxGeneration());
4705 if (GCHeap::GetGCHeap()->IsGCInProgress())
4707 pDomain->SetGCRefPoint(iGCRefPoint);
4711 void AddToDelayedUnloadList(LoaderAllocator * pAllocator)
4721 CrstHolder lh(&m_DelayedUnloadCrst);
4722 pAllocator->m_pLoaderAllocatorDestroyNext=m_pDelayedUnloadListOfLoaderAllocators;
4723 m_pDelayedUnloadListOfLoaderAllocators=pAllocator;
4725 int iGCRefPoint=GCHeap::GetGCHeap()->CollectionCount(GCHeap::GetGCHeap()->GetMaxGeneration());
4726 if (GCHeap::GetGCHeap()->IsGCInProgress())
4728 pAllocator->SetGCRefPoint(iGCRefPoint);
4731 void ClearCollectedDomains();
4732 void ProcessClearingDomains();
4733 void ProcessDelayedUnloadDomains();
4735 static void SetUnloadInProgress(AppDomain *pDomain)
4737 WRAPPER_NO_CONTRACT;
4739 _ASSERTE(m_pAppDomainBeingUnloaded == NULL);
4740 m_pAppDomainBeingUnloaded = pDomain;
4741 m_dwIndexOfAppDomainBeingUnloaded = pDomain->GetIndex();
4744 static void SetUnloadDomainCleared()
4746 LIMITED_METHOD_CONTRACT;
4748 // about to delete, so clear this pointer so nobody uses it
4749 m_pAppDomainBeingUnloaded = NULL;
4751 static void SetUnloadComplete()
4753 LIMITED_METHOD_CONTRACT;
4755 // should have already cleared the AppDomain* prior to delete
4756 // either we succesfully unloaded and cleared or we failed and restored the ID
4757 _ASSERTE(m_pAppDomainBeingUnloaded == NULL && m_dwIndexOfAppDomainBeingUnloaded.m_dwIndex != 0
4758 || m_pAppDomainBeingUnloaded && SystemDomain::GetAppDomainAtId(m_pAppDomainBeingUnloaded->GetId()) != NULL);
4759 m_pAppDomainBeingUnloaded = NULL;
4760 m_pAppDomainUnloadingThread = NULL;
4763 static AppDomain *AppDomainBeingUnloaded()
4765 LIMITED_METHOD_CONTRACT;
4766 return m_pAppDomainBeingUnloaded;
4769 static ADIndex IndexOfAppDomainBeingUnloaded()
4771 LIMITED_METHOD_CONTRACT;
4772 return m_dwIndexOfAppDomainBeingUnloaded;
4775 static void SetUnloadRequestingThread(Thread *pRequestingThread)
4777 LIMITED_METHOD_CONTRACT;
4778 m_pAppDomainUnloadRequestingThread = pRequestingThread;
4781 static Thread *GetUnloadRequestingThread()
4783 LIMITED_METHOD_CONTRACT;
4784 return m_pAppDomainUnloadRequestingThread;
4787 static void SetUnloadingThread(Thread *pUnloadingThread)
4789 LIMITED_METHOD_CONTRACT;
4790 m_pAppDomainUnloadingThread = pUnloadingThread;
4793 static Thread *GetUnloadingThread()
4795 LIMITED_METHOD_CONTRACT;
4796 return m_pAppDomainUnloadingThread;
4799 static void EnumAllStaticGCRefs(promote_func* fn, ScanContext* sc);
4801 #endif // DACCESS_COMPILE
4803 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
4804 // The *AD* methods are what we got from tracing through EE roots.
4805 // RecordTotalSurvivedBytes is the total promoted from a GC.
4806 static void ResetADSurvivedBytes();
4807 static ULONGLONG GetADSurvivedBytes();
4808 static void RecordTotalSurvivedBytes(size_t totalSurvivedBytes);
4809 static ULONGLONG GetTotalSurvivedBytes()
4811 LIMITED_METHOD_CONTRACT;
4812 return m_totalSurvivedBytes;
4814 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
4816 //****************************************************************************************
4817 // Routines to deal with the base library (currently mscorlib.dll)
4818 LPCWSTR BaseLibrary()
4820 WRAPPER_NO_CONTRACT;
4822 return m_BaseLibrary;
4825 #ifndef DACCESS_COMPILE
4826 BOOL IsBaseLibrary(SString &path)
4828 WRAPPER_NO_CONTRACT;
4830 // See if it is the installation path to mscorlib
4831 if (path.EqualsCaseInsensitive(m_BaseLibrary, PEImage::GetFileSystemLocale()))
4834 // Or, it might be the GAC location of mscorlib
4835 if (System()->SystemAssembly() != NULL
4836 && path.EqualsCaseInsensitive(System()->SystemAssembly()->GetManifestFile()->GetPath(),
4837 PEImage::GetFileSystemLocale()))
4843 BOOL IsBaseLibrarySatellite(SString &path)
4845 WRAPPER_NO_CONTRACT;
4847 // See if it is the installation path to mscorlib.resources
4848 SString s(SString::Ascii,g_psBaseLibrarySatelliteAssemblyName);
4849 if (path.EqualsCaseInsensitive(s, PEImage::GetFileSystemLocale()))
4852 // workaround! Must implement some code to do this string comparison for
4853 // mscorlib.resources in a culture-specific directory in the GAC.
4856 // Or, it might be the GAC location of mscorlib.resources
4857 if (System()->SystemAssembly() != NULL
4858 && path.EqualsCaseInsensitive(System()->SystemAssembly()->GetManifestFile()->GetPath(),
4859 PEImage::GetFileSystemLocale()))
4865 #endif // DACCESS_COMPILE
4867 // Return the system directory
4868 LPCWSTR SystemDirectory()
4870 WRAPPER_NO_CONTRACT;
4872 return m_SystemDirectory;
4877 //****************************************************************************************
4878 // Helper function to create the single COM domain
4879 void CreateDefaultDomain();
4881 //****************************************************************************************
4882 // Helper function to add a domain to the global list
4883 void AddDomain(AppDomain* pDomain);
4885 void CreatePreallocatedExceptions();
4887 void PreallocateSpecialObjects();
4889 //****************************************************************************************
4891 static StackWalkAction CallersMethodCallback(CrawlFrame* pCrawlFrame, VOID* pClientData);
4892 static StackWalkAction CallersMethodCallbackWithStackMark(CrawlFrame* pCrawlFrame, VOID* pClientData);
4894 #ifndef DACCESS_COMPILE
4895 // This class is not to be created through normal allocation.
4898 STANDARD_VM_CONTRACT;
4900 m_pDefaultDomain = NULL;
4901 m_pDelayedUnloadList=NULL;
4902 m_pDelayedUnloadListOfLoaderAllocators=NULL;
4903 m_UnloadIsAsync = FALSE;
4905 m_GlobalAllocator.Init(this);
4909 PTR_PEAssembly m_pSystemFile; // Single assembly (here for quicker reference);
4910 PTR_Assembly m_pSystemAssembly; // Single assembly (here for quicker reference);
4911 PTR_AppDomain m_pDefaultDomain; // Default domain for COM+ classes exposed through IClassFactory.
4913 GlobalLoaderAllocator m_GlobalAllocator;
4916 InlineSString<100> m_BaseLibrary;
4918 #ifdef FEATURE_VERSIONING
4920 InlineSString<100> m_SystemDirectory;
4924 LPCWSTR m_SystemDirectory;
4930 BOOL m_fDevpath; // have we searched the environment
4932 // <TODO>@TODO: CTS, we can keep the com modules in a single assembly or in different assemblies.
4933 // We are currently using different assemblies but this is potentitially to slow...</TODO>
4935 // Global domain that every one uses
4936 SPTR_DECL(SystemDomain, m_pSystemDomain);
4938 AppDomain* m_pDelayedUnloadList;
4939 BOOL m_UnloadIsAsync;
4941 LoaderAllocator * m_pDelayedUnloadListOfLoaderAllocators;
4943 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
4944 // This is what gets promoted for the whole GC heap.
4945 static size_t m_totalSurvivedBytes;
4946 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
4948 SVAL_DECL(ArrayListStatic, m_appDomainIndexList);
4949 #ifndef DACCESS_COMPILE
4950 static CrstStatic m_DelayedUnloadCrst;
4951 static CrstStatic m_SystemDomainCrst;
4954 static ArrayListStatic m_appDomainIdList;
4956 // only one ad can be unloaded at a time
4957 static AppDomain* m_pAppDomainBeingUnloaded;
4958 // need this so can determine AD being unloaded after it has been deleted
4959 static ADIndex m_dwIndexOfAppDomainBeingUnloaded;
4961 // if had to spin off a separate thread to do the unload, this is the original thread.
4962 // allows us to delay aborting it until it's the last one so that it can receive
4963 // notification of an unload failure
4964 static Thread *m_pAppDomainUnloadRequestingThread;
4966 // this is the thread doing the actual unload. He's allowed to enter the domain
4967 // even if have started unloading.
4968 static Thread *m_pAppDomainUnloadingThread;
4970 static GlobalStringLiteralMap *m_pGlobalStringLiteralMap;
4972 static ULONG s_dNumAppDomains; // Maintain a count of children app domains.
4974 static DWORD m_dwLowestFreeIndex;
4975 #endif // DACCESS_COMPILE
4979 // These flags let the correct native image of mscorlib to be loaded.
4980 // This is important for hardbinding to it
4982 SVAL_DECL(BOOL, s_fForceDebug);
4983 SVAL_DECL(BOOL, s_fForceProfiling);
4984 SVAL_DECL(BOOL, s_fForceInstrument);
4987 static void SetCompilationOverrides(BOOL fForceDebug,
4988 BOOL fForceProfiling,
4989 BOOL fForceInstrument);
4991 static void GetCompilationOverrides(BOOL * fForceDebug,
4992 BOOL * fForceProfiling,
4993 BOOL * fForceInstrument);
4995 //****************************************************************************************
4998 #ifndef DACCESS_COMPILE
5000 inline static BOOL IsUnderDomainLock() { LIMITED_METHOD_CONTRACT; return m_SystemDomainCrst.OwnedByCurrentThread();};
5003 // This lock controls adding and removing domains from the system domain
5004 class LockHolder : public CrstHolder
5008 : CrstHolder(&m_SystemDomainCrst)
5010 WRAPPER_NO_CONTRACT;
5013 #endif // DACCESS_COMPILE
5016 DWORD GetTotalNumSizedRefHandles();
5018 #ifdef DACCESS_COMPILE
5020 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
5024 }; // class SystemDomain
5028 // an UnsafeAppDomainIterator is used to iterate over all existing domains
5030 // The iteration is guaranteed to include all domains that exist at the
5031 // start & end of the iteration. This iterator is considered unsafe because it does not
5032 // reference count the various appdomains, and can only be used when the runtime is stopped,
5033 // or external synchronization is used. (and therefore no other thread may cause the appdomain list to change.)
5035 class UnsafeAppDomainIterator
5037 friend class SystemDomain;
5039 UnsafeAppDomainIterator(BOOL bOnlyActive)
5041 m_bOnlyActive = bOnlyActive;
5046 LIMITED_METHOD_CONTRACT;
5047 SystemDomain* sysDomain = SystemDomain::System();
5050 ArrayListStatic* list = &sysDomain->m_appDomainIndexList;
5051 PREFIX_ASSUME(list != NULL);
5052 m_i = list->Iterate();
5064 WRAPPER_NO_CONTRACT;
5068 m_pCurrent = dac_cast<PTR_AppDomain>(m_i.GetElement());
5069 if (m_pCurrent != NULL &&
5071 m_pCurrent->IsActive() : m_pCurrent->IsValid()))
5081 AppDomain * GetDomain()
5083 LIMITED_METHOD_DAC_CONTRACT;
5090 ArrayList::Iterator m_i;
5091 AppDomain * m_pCurrent;
5093 }; // class UnsafeAppDomainIterator
5096 // an AppDomainIterator is used to iterate over all existing domains.
5098 // The iteration is guaranteed to include all domains that exist at the
5099 // start & end of the iteration. Any domains added or deleted during
5100 // iteration may or may not be included. The iterator also guarantees
5101 // that the current iterated appdomain (GetDomain()) will not be deleted.
5104 class AppDomainIterator : public UnsafeAppDomainIterator
5106 friend class SystemDomain;
5109 AppDomainIterator(BOOL bOnlyActive) : UnsafeAppDomainIterator(bOnlyActive)
5111 WRAPPER_NO_CONTRACT;
5115 ~AppDomainIterator()
5117 WRAPPER_NO_CONTRACT;
5119 #ifndef DACCESS_COMPILE
5120 if (GetDomain() != NULL)
5123 GetDomain()->IteratorRelease();
5125 GetDomain()->Release();
5132 WRAPPER_NO_CONTRACT;
5134 #ifndef DACCESS_COMPILE
5135 if (GetDomain() != NULL)
5138 GetDomain()->IteratorRelease();
5140 GetDomain()->Release();
5143 SystemDomain::LockHolder lh;
5146 if (UnsafeAppDomainIterator::Next())
5148 #ifndef DACCESS_COMPILE
5149 GetDomain()->AddRef();
5151 GetDomain()->IteratorAcquire();
5159 }; // class AppDomainIterator
5161 typedef VPTR(class SharedDomain) PTR_SharedDomain;
5163 class SharedDomain : public BaseDomain
5165 VPTR_VTABLE_CLASS_AND_CTOR(SharedDomain, BaseDomain)
5169 static void Attach();
5170 static void Detach();
5172 virtual BOOL IsSharedDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; }
5173 virtual PTR_LoaderAllocator GetLoaderAllocator() { WRAPPER_NO_CONTRACT; return SystemDomain::GetGlobalLoaderAllocator(); }
5175 virtual PTR_AppDomain AsAppDomain()
5177 LIMITED_METHOD_CONTRACT;
5178 STATIC_CONTRACT_SO_TOLERANT;
5179 _ASSERTE(!"Not an AppDomain");
5183 static SharedDomain * GetDomain();
5188 // This will also set the tenured bit if and only if the add was successful,
5189 // and will make sure that the bit appears atomically set to all readers that
5190 // might be accessing the hash on another thread.
5191 MethodTable * FindIndexClass(SIZE_T index);
5193 #ifdef FEATURE_LOADER_OPTIMIZATION
5194 void AddShareableAssembly(Assembly * pAssembly);
5196 class SharedAssemblyIterator
5198 PtrHashMap::PtrIterator i;
5199 Assembly * m_pAssembly;
5202 SharedAssemblyIterator() :
5203 i(GetDomain() ? GetDomain()->m_assemblyMap.firstBucket() : NULL)
5204 { LIMITED_METHOD_DAC_CONTRACT; }
5208 WRAPPER_NO_CONTRACT;
5214 m_pAssembly = PTR_Assembly(dac_cast<TADDR>(i.GetValue()));
5219 Assembly * GetAssembly()
5221 LIMITED_METHOD_DAC_CONTRACT;
5227 friend class SharedDomain;
5230 Assembly * FindShareableAssembly(SharedAssemblyLocator * pLocator);
5231 SIZE_T GetShareableAssemblyCount();
5232 #endif //FEATURE_LOADER_OPTIMIZATION
5235 friend class SharedAssemblyIterator;
5236 friend class SharedFileLockHolder;
5237 friend class ClrDataAccess;
5239 #ifndef DACCESS_COMPILE
5240 void *operator new(size_t size, void *pInPlace);
5241 void operator delete(void *pMem);
5244 SPTR_DECL(SharedDomain, m_pSharedDomain);
5246 #ifdef FEATURE_LOADER_OPTIMIZATION
5247 PEFileListLock m_FileCreateLock;
5248 SIZE_T m_nextClassIndex;
5249 PtrHashMap m_assemblyMap;
5253 #ifdef DACCESS_COMPILE
5254 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
5258 #ifdef FEATURE_LOADER_OPTIMIZATION
5259 // Hash map comparison function`
5260 static BOOL CompareSharedAssembly(UPTR u1, UPTR u2);
5264 #ifdef FEATURE_LOADER_OPTIMIZATION
5265 class SharedFileLockHolderBase : protected HolderBase<PEFile *>
5268 PEFileListLock *m_pLock;
5269 ListLockEntry *m_pLockElement;
5271 SharedFileLockHolderBase(PEFile *value)
5272 : HolderBase<PEFile *>(value)
5274 LIMITED_METHOD_CONTRACT;
5277 m_pLockElement = NULL;
5280 #ifndef DACCESS_COMPILE
5283 STATIC_CONTRACT_THROWS;
5284 STATIC_CONTRACT_GC_TRIGGERS;
5285 STATIC_CONTRACT_FAULT;
5287 PEFileListLockHolder lockHolder(m_pLock);
5289 m_pLockElement = m_pLock->FindFileLock(m_value);
5290 if (m_pLockElement == NULL)
5292 m_pLockElement = new ListLockEntry(m_pLock, m_value);
5293 m_pLock->AddElement(m_pLockElement);
5296 m_pLockElement->AddRef();
5298 lockHolder.Release();
5300 m_pLockElement->Enter();
5305 STATIC_CONTRACT_NOTHROW;
5306 STATIC_CONTRACT_GC_TRIGGERS;
5307 STATIC_CONTRACT_FORBID_FAULT;
5309 m_pLockElement->Leave();
5310 m_pLockElement->Release();
5311 m_pLockElement = NULL;
5313 #endif // DACCESS_COMPILE
5316 class SharedFileLockHolder : public BaseHolder<PEFile *, SharedFileLockHolderBase>
5319 DEBUG_NOINLINE SharedFileLockHolder(SharedDomain *pDomain, PEFile *pFile, BOOL Take = TRUE)
5320 : BaseHolder<PEFile *, SharedFileLockHolderBase>(pFile, FALSE)
5322 STATIC_CONTRACT_THROWS;
5323 STATIC_CONTRACT_GC_TRIGGERS;
5324 STATIC_CONTRACT_FAULT;
5325 ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
5327 m_pLock = &pDomain->m_FileCreateLock;
5332 #endif // FEATURE_LOADER_OPTIMIZATION
5334 inline BOOL BaseDomain::IsDefaultDomain()
5336 LIMITED_METHOD_DAC_CONTRACT;
5337 return (SystemDomain::System()->DefaultDomain() == this);
5340 #include "comreflectioncache.inl"
5342 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
5343 // holds an extra reference so needs special Extract() and should not have SuppressRelease()
5344 // Holders/Wrappers have nonvirtual methods so cannot use them as the base class
5345 template <class AppDomainType>
5346 class AppDomainCreationHolder
5349 // disable the copy ctor
5350 AppDomainCreationHolder(const AppDomainCreationHolder<AppDomainType>&) {}
5353 AppDomainType* m_pDomain;
5355 void ReleaseAppDomainDuringCreation()
5360 WRAPPER(GC_TRIGGERS);
5361 PRECONDITION(m_bAcquired);
5362 PRECONDITION(CheckPointer(m_pDomain));
5366 if (m_pDomain->NotReadyForManagedCode())
5368 m_pDomain->Release();
5372 STRESS_LOG2 (LF_APPDOMAIN, LL_INFO100, "Unload domain during creation [%d] %p\n", m_pDomain->GetId().m_dwId, m_pDomain);
5373 SystemDomain::MakeUnloadable(m_pDomain);
5375 DWORD hostTestADUnload = g_pConfig->GetHostTestADUnload();
5376 m_pDomain->EnableADUnloadWorker(hostTestADUnload != 2?EEPolicy::ADU_Safe:EEPolicy::ADU_Rude);
5378 m_pDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
5384 AppDomainCreationHolder()
5389 ~AppDomainCreationHolder()
5396 void Assign(AppDomainType* pDomain)
5403 AppDomain::RefTakerAcquire(m_pDomain);
5405 m_pDomain->IncCreationCount();
5413 _ASSERTE(m_bAcquired);
5417 m_pDomain->DecCreationCount();
5419 if(!m_pDomain->IsDefaultDomain())
5420 ReleaseAppDomainDuringCreation();
5421 AppDomain::RefTakerRelease(m_pDomain);
5426 AppDomainType* Extract()
5428 _ASSERTE(m_bAcquired);
5432 m_pDomain->DecCreationCount();
5434 AppDomain::RefTakerRelease(m_pDomain);
5440 AppDomainType* operator ->()
5442 _ASSERTE(m_bAcquired);
5446 operator AppDomainType*()
5448 _ASSERTE(m_bAcquired);
5457 #endif // !DACCESS_COMPILE && !CROSSGEN_COMPILE
5460 #endif // !CLR_STANDALONE_BINDER