1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 /*============================================================
7 ** Header: AppDomain.cpp
11 ** Purpose: Implements AppDomain (loader domain) architecture
14 ===========================================================*/
18 #include "eventtrace.h"
19 #include "assembly.hpp"
20 #include "clsload.hpp"
22 #include "arraylist.h"
23 #include "comreflectioncache.hpp"
24 #include "comutilnative.h"
25 #include "domainfile.h"
26 #include "objectlist.h"
27 #include "fptrstubs.h"
28 #include "ilstubcache.h"
29 #include "testhookmgr.h"
30 #include "gcheaputilities.h"
31 #include "gchandleutilities.h"
32 #include "../binder/inc/applicationcontext.hpp"
35 #ifdef FEATURE_MULTICOREJIT
36 #include "multicorejit.h"
39 #ifdef FEATURE_COMINTEROP
40 #include "clrprivbinderwinrt.h"
41 #include "..\md\winmd\inc\adapter.h"
42 #include "winrttypenameconverter.h"
43 #endif // FEATURE_COMINTEROP
47 #ifdef FEATURE_TIERED_COMPILATION
48 #include "tieredcompilation.h"
49 #include "callcounter.h"
52 #include "codeversion.h"
58 class CompilationDomain;
61 class EEMarshalingData;
63 class GlobalStringLiteralMap;
64 class StringLiteralMap;
65 class MngStdInterfacesInfo;
68 struct InteropMethodTableData;
69 class LoadLevelLimiter;
70 class TypeEquivalenceHashTable;
71 class StringArrayList;
73 extern INT64 g_PauseTime; // Total time in millisecond the CLR has been paused
75 #ifdef FEATURE_COMINTEROP
76 class ComCallWrapperCache;
77 struct SimpleComCallWrapper;
81 // This enum is used to specify whether user want COM or remoting
82 enum COMorRemotingFlag {
83 COMorRemoting_NotInitialized = 0,
84 COMorRemoting_COM = 1, // COM will be used both cross-domain and cross-runtime
85 COMorRemoting_Remoting = 2, // Remoting will be used cross-domain; cross-runtime will use Remoting only if it looks like it's expected (default)
86 COMorRemoting_LegacyMode = 3 // Remoting will be used both cross-domain and cross-runtime
89 #endif // FEATURE_COMINTEROP
93 #pragma warning(disable : 4200) // Disable zero-sized array warning
97 GPTR_DECL(IdDispenser, g_pModuleIndexDispenser);
99 // This enum is aligned to System.ExceptionCatcherType.
100 enum ExceptionCatcher {
101 ExceptionCatcher_ManagedCode = 0,
102 ExceptionCatcher_AppDomainTransition = 1,
103 ExceptionCatcher_COMInterop = 2,
106 // We would like *ALLOCATECLASS_FLAG to AV (in order to catch errors), so don't change it
107 struct ClassInitFlags {
110 INITIALIZED_FLAG_BIT = 0,
111 INITIALIZED_FLAG = 1<<INITIALIZED_FLAG_BIT,
113 ERROR_FLAG = 1<<ERROR_FLAG_BIT,
114 ALLOCATECLASS_FLAG_BIT = 2, // Bit to avoid racing for InstantiateStaticHandles
115 ALLOCATECLASS_FLAG = 1<<ALLOCATECLASS_FLAG_BIT,
116 COLLECTIBLE_FLAG_BIT = 3,
117 COLLECTIBLE_FLAG = 1<<COLLECTIBLE_FLAG_BIT
121 struct DomainLocalModule
123 friend class ClrDataAccess;
124 friend class CheckAsmOffsets;
125 friend struct ThreadLocalModule;
127 // 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
128 // It is critically important that no GC is allowed to occur before this pointer is used.
129 #define GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLoaderAllocator, dynamicClassInfoParam, pGCStatics) \
131 DomainLocalModule::PTR_DynamicClassInfo dynamicClassInfo = dac_cast<DomainLocalModule::PTR_DynamicClassInfo>(dynamicClassInfoParam);\
132 DomainLocalModule::PTR_DynamicEntry pDynamicEntry = dac_cast<DomainLocalModule::PTR_DynamicEntry>((DomainLocalModule::DynamicEntry*)dynamicClassInfo->m_pDynamicEntry.Load()); \
133 if ((dynamicClassInfo->m_dwFlags) & ClassInitFlags::COLLECTIBLE_FLAG) \
135 PTRARRAYREF objArray;\
136 objArray = (PTRARRAYREF)pLoaderAllocator->GetHandleValueFastCannotFailType2( \
137 (dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hGCStatics);\
138 *(pGCStatics) = dac_cast<PTR_BYTE>(PTR_READ(PTR_TO_TADDR(OBJECTREFToObject( objArray )) + offsetof(PtrArray, m_Array), objArray->GetNumComponents() * sizeof(void*))) ;\
142 *(pGCStatics) = (dac_cast<DomainLocalModule::PTR_NormalDynamicEntry>(pDynamicEntry))->GetGCStaticsBasePointer();\
146 #define GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLoaderAllocator, dynamicClassInfoParam, pNonGCStatics) \
148 DomainLocalModule::PTR_DynamicClassInfo dynamicClassInfo = dac_cast<DomainLocalModule::PTR_DynamicClassInfo>(dynamicClassInfoParam);\
149 DomainLocalModule::PTR_DynamicEntry pDynamicEntry = dac_cast<DomainLocalModule::PTR_DynamicEntry>((DomainLocalModule::DynamicEntry*)(dynamicClassInfo)->m_pDynamicEntry.Load()); \
150 if (((dynamicClassInfo)->m_dwFlags) & ClassInitFlags::COLLECTIBLE_FLAG) \
152 if ((dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hNonGCStatics != 0) \
154 U1ARRAYREF objArray;\
155 objArray = (U1ARRAYREF)pLoaderAllocator->GetHandleValueFastCannotFailType2( \
156 (dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hNonGCStatics);\
157 *(pNonGCStatics) = dac_cast<PTR_BYTE>(PTR_READ( \
158 PTR_TO_TADDR(OBJECTREFToObject( objArray )) + sizeof(ArrayBase) - DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob(), \
159 objArray->GetNumComponents() * (DWORD)objArray->GetComponentSize() + DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob())); \
160 } else (*pNonGCStatics) = NULL; \
164 *(pNonGCStatics) = dac_cast<DomainLocalModule::PTR_NormalDynamicEntry>(pDynamicEntry)->GetNonGCStaticsBasePointer();\
170 static DWORD GetOffsetOfDataBlob();
172 typedef DPTR(DynamicEntry) PTR_DynamicEntry;
174 struct CollectibleDynamicEntry : public DynamicEntry
176 LOADERHANDLE m_hGCStatics;
177 LOADERHANDLE m_hNonGCStatics;
179 typedef DPTR(CollectibleDynamicEntry) PTR_CollectibleDynamicEntry;
181 struct NormalDynamicEntry : public DynamicEntry
183 PTR_OBJECTREF m_pGCStatics;
184 #ifdef FEATURE_64BIT_ALIGNMENT
185 // Padding to make m_pDataBlob aligned at MAX_PRIMITIVE_FIELD_SIZE
186 // code:MethodTableBuilder::PlaceRegularStaticFields assumes that the start of the data blob is aligned
191 inline PTR_BYTE GetGCStaticsBasePointer()
193 LIMITED_METHOD_CONTRACT;
195 return dac_cast<PTR_BYTE>(m_pGCStatics);
197 inline PTR_BYTE GetNonGCStaticsBasePointer()
199 LIMITED_METHOD_CONTRACT
201 return dac_cast<PTR_BYTE>(this);
204 typedef DPTR(NormalDynamicEntry) PTR_NormalDynamicEntry;
206 struct DynamicClassInfo
208 VolatilePtr<DynamicEntry, PTR_DynamicEntry> m_pDynamicEntry;
209 Volatile<DWORD> m_dwFlags;
211 typedef DPTR(DynamicClassInfo) PTR_DynamicClassInfo;
213 inline UMEntryThunk * GetADThunkTable()
215 LIMITED_METHOD_CONTRACT
216 return m_pADThunkTable;
219 inline void SetADThunkTable(UMEntryThunk* pADThunkTable)
221 LIMITED_METHOD_CONTRACT
222 InterlockedCompareExchangeT(m_pADThunkTable.GetPointer(), pADThunkTable, NULL);
225 // Note the difference between:
227 // GetPrecomputedNonGCStaticsBasePointer() and
228 // GetPrecomputedStaticsClassData()
230 // GetPrecomputedNonGCStaticsBasePointer returns the pointer that should be added to field offsets to retrieve statics
231 // GetPrecomputedStaticsClassData returns a pointer to the first byte of the precomputed statics block
232 inline TADDR GetPrecomputedNonGCStaticsBasePointer()
234 LIMITED_METHOD_CONTRACT
235 return dac_cast<TADDR>(this);
238 inline PTR_BYTE GetPrecomputedStaticsClassData()
240 LIMITED_METHOD_CONTRACT
241 return dac_cast<PTR_BYTE>(this) + offsetof(DomainLocalModule, m_pDataBlob);
244 static SIZE_T GetOffsetOfDataBlob() { return offsetof(DomainLocalModule, m_pDataBlob); }
245 static SIZE_T GetOffsetOfGCStaticPointer() { return offsetof(DomainLocalModule, m_pGCStatics); }
247 inline DomainFile* GetDomainFile()
249 LIMITED_METHOD_CONTRACT
251 return m_pDomainFile;
254 #ifndef DACCESS_COMPILE
255 inline void SetDomainFile(DomainFile* pDomainFile)
257 LIMITED_METHOD_CONTRACT
258 m_pDomainFile = pDomainFile;
262 inline PTR_OBJECTREF GetPrecomputedGCStaticsBasePointer()
264 LIMITED_METHOD_CONTRACT
268 inline PTR_OBJECTREF * GetPrecomputedGCStaticsBasePointerAddress()
270 LIMITED_METHOD_CONTRACT
271 return &m_pGCStatics;
274 // Returns bytes so we can add offsets
275 inline PTR_BYTE GetGCStaticsBasePointer(MethodTable * pMT)
280 if (pMT->IsDynamicStatics())
282 _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics());
283 return GetDynamicEntryGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator());
287 return dac_cast<PTR_BYTE>(m_pGCStatics);
291 inline PTR_BYTE GetNonGCStaticsBasePointer(MethodTable * pMT)
296 if (pMT->IsDynamicStatics())
298 _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics());
299 return GetDynamicEntryNonGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator());
303 return dac_cast<PTR_BYTE>(this);
307 inline DynamicClassInfo* GetDynamicClassInfo(DWORD n)
309 LIMITED_METHOD_CONTRACT
311 _ASSERTE(m_pDynamicClassTable.Load() && m_aDynamicEntries > n);
312 dac_cast<PTR_DynamicEntry>(m_pDynamicClassTable[n].m_pDynamicEntry.Load());
314 return &m_pDynamicClassTable[n];
317 // These helpers can now return null, as the debugger may do queries on a type
318 // before the calls to PopulateClass happen
319 inline PTR_BYTE GetDynamicEntryGCStaticsBasePointer(DWORD n, PTR_LoaderAllocator pLoaderAllocator)
332 if (n >= m_aDynamicEntries)
337 DynamicClassInfo* pClassInfo = GetDynamicClassInfo(n);
338 if (!pClassInfo->m_pDynamicEntry)
343 PTR_BYTE retval = NULL;
345 GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLoaderAllocator, pClassInfo, &retval);
350 inline PTR_BYTE GetDynamicEntryNonGCStaticsBasePointer(DWORD n, PTR_LoaderAllocator pLoaderAllocator)
363 if (n >= m_aDynamicEntries)
368 DynamicClassInfo* pClassInfo = GetDynamicClassInfo(n);
369 if (!pClassInfo->m_pDynamicEntry)
374 PTR_BYTE retval = NULL;
376 GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLoaderAllocator, pClassInfo, &retval);
381 FORCEINLINE PTR_DynamicClassInfo GetDynamicClassInfoIfInitialized(DWORD n)
385 // m_aDynamicEntries is set last, it needs to be checked first
386 if (n >= m_aDynamicEntries)
391 _ASSERTE(m_pDynamicClassTable.Load() != NULL);
392 PTR_DynamicClassInfo pDynamicClassInfo = (PTR_DynamicClassInfo)(m_pDynamicClassTable.Load() + n);
394 // INITIALIZED_FLAG is set last, it needs to be checked first
395 if ((pDynamicClassInfo->m_dwFlags & ClassInitFlags::INITIALIZED_FLAG) == 0)
400 PREFIX_ASSUME(pDynamicClassInfo != NULL);
401 return pDynamicClassInfo;
404 // iClassIndex is slightly expensive to compute, so if we already know
405 // it, we can use this helper
406 inline BOOL IsClassInitialized(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
409 return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::INITIALIZED_FLAG) != 0;
412 inline BOOL IsPrecomputedClassInitialized(DWORD classID)
414 return GetPrecomputedStaticsClassData()[classID] & ClassInitFlags::INITIALIZED_FLAG;
417 inline BOOL IsClassAllocated(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
420 return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::ALLOCATECLASS_FLAG) != 0;
423 BOOL IsClassInitError(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
426 return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::ERROR_FLAG) != 0;
429 void SetClassInitialized(MethodTable* pMT);
430 void SetClassInitError(MethodTable* pMT);
432 void EnsureDynamicClassIndex(DWORD dwID);
434 void AllocateDynamicClass(MethodTable *pMT);
436 void PopulateClass(MethodTable *pMT);
438 #ifdef DACCESS_COMPILE
439 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
442 static DWORD OffsetOfDataBlob()
444 LIMITED_METHOD_CONTRACT;
445 return offsetof(DomainLocalModule, m_pDataBlob);
448 FORCEINLINE MethodTable * GetMethodTableFromClassDomainID(DWORD dwClassDomainID)
450 DWORD rid = (DWORD)(dwClassDomainID) + 1;
451 TypeHandle th = GetDomainFile()->GetModule()->LookupTypeDef(TokenFromRid(rid, mdtTypeDef));
452 _ASSERTE(!th.IsNull());
453 MethodTable * pMT = th.AsMethodTable();
454 PREFIX_ASSUME(pMT != NULL);
459 friend void EmitFastGetSharedStaticBase(CPUSTUBLINKER *psl, CodeLabel *init, bool bCCtorCheck);
461 void SetClassFlags(MethodTable* pMT, DWORD dwFlags);
462 DWORD GetClassFlags(MethodTable* pMT, DWORD iClassIndex);
464 PTR_DomainFile m_pDomainFile;
465 VolatilePtr<DynamicClassInfo, PTR_DynamicClassInfo> m_pDynamicClassTable; // used for generics and reflection.emit in memory
466 Volatile<SIZE_T> m_aDynamicEntries; // number of entries in dynamic table
467 VolatilePtr<UMEntryThunk> m_pADThunkTable;
468 PTR_OBJECTREF m_pGCStatics; // Handle to GC statics of the module
470 // In addition to storing the ModuleIndex in the Module class, we also
471 // keep a copy of the ModuleIndex in the DomainLocalModule class. This
472 // allows the thread static JIT helpers to quickly convert a pointer to
473 // a DomainLocalModule into a ModuleIndex.
474 ModuleIndex m_ModuleIndex;
476 // Note that the static offset calculation in code:Module::BuildStaticsOffsets takes the offset m_pDataBlob
477 // into consideration for alignment so we do not need any padding to ensure that the start of the data blob is aligned
479 BYTE m_pDataBlob[0]; // First byte of the statics blob
481 // Layout of m_pDataBlob is:
482 // ClassInit bytes (hold flags for cctor run, cctor error, etc)
487 // The Module class need to be able to initialized ModuleIndex,
488 // so for now I will make it a friend..
491 FORCEINLINE ModuleIndex GetModuleIndex()
493 LIMITED_METHOD_DAC_CONTRACT;
494 return m_ModuleIndex;
497 }; // struct DomainLocalModule
499 #define OFFSETOF__DomainLocalModule__m_pDataBlob_ (6 * TARGET_POINTER_SIZE)
500 #ifdef FEATURE_64BIT_ALIGNMENT
501 #define OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob (TARGET_POINTER_SIZE /* m_pGCStatics */ + TARGET_POINTER_SIZE /* m_padding */)
503 #define OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob TARGET_POINTER_SIZE /* m_pGCStatics */
506 typedef DPTR(class DomainLocalBlock) PTR_DomainLocalBlock;
507 class DomainLocalBlock
509 friend class ClrDataAccess;
510 friend class CheckAsmOffsets;
513 PTR_AppDomain m_pDomain;
514 DPTR(PTR_DomainLocalModule) m_pModuleSlots;
515 SIZE_T m_aModuleIndices; // Module entries the shared block has allocated
517 public: // used by code generators
518 static SIZE_T GetOffsetOfModuleSlotsPointer() { return offsetof(DomainLocalBlock, m_pModuleSlots);}
522 #ifndef DACCESS_COMPILE
524 : m_pDomain(NULL), m_pModuleSlots(NULL), m_aModuleIndices(0) {}
526 void EnsureModuleIndex(ModuleIndex index);
528 void Init(AppDomain *pDomain) { LIMITED_METHOD_CONTRACT; m_pDomain = pDomain; }
531 void SetModuleSlot(ModuleIndex index, PTR_DomainLocalModule pLocalModule);
533 FORCEINLINE PTR_DomainLocalModule GetModuleSlot(ModuleIndex index)
537 _ASSERTE(index.m_dwIndex < m_aModuleIndices);
538 return m_pModuleSlots[index.m_dwIndex];
541 inline PTR_DomainLocalModule GetModuleSlot(MethodTable* pMT)
544 return GetModuleSlot(pMT->GetModuleForStatics()->GetModuleIndex());
547 DomainFile* TryGetDomainFile(ModuleIndex index)
552 // the publishing of m_aModuleIndices and m_pModuleSlots is dependent
553 // on the order of accesses; we must ensure that we read from m_aModuleIndices
554 // before m_pModuleSlots.
555 if (index.m_dwIndex < m_aModuleIndices)
558 if (m_pModuleSlots[index.m_dwIndex])
560 return m_pModuleSlots[index.m_dwIndex]->GetDomainFile();
567 DomainFile* GetDomainFile(SIZE_T ModuleID)
570 ModuleIndex index = Module::IDToIndex(ModuleID);
571 _ASSERTE(index.m_dwIndex < m_aModuleIndices);
572 return m_pModuleSlots[index.m_dwIndex]->GetDomainFile();
575 #ifndef DACCESS_COMPILE
576 void SetDomainFile(ModuleIndex index, DomainFile* pDomainFile)
579 _ASSERTE(index.m_dwIndex < m_aModuleIndices);
580 m_pModuleSlots[index.m_dwIndex]->SetDomainFile(pDomainFile);
584 #ifdef DACCESS_COMPILE
585 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
592 // Low level routines to get & set class entries
602 // The large heap handle bucket class is used to contain handles allocated
603 // from an array contained in the large heap.
604 class LargeHeapHandleBucket
607 // Constructor and desctructor.
608 LargeHeapHandleBucket(LargeHeapHandleBucket *pNext, DWORD Size, BaseDomain *pDomain, BOOL bCrossAD = FALSE);
609 ~LargeHeapHandleBucket();
611 // This returns the next bucket.
612 LargeHeapHandleBucket *GetNext()
614 LIMITED_METHOD_CONTRACT;
619 // This returns the number of remaining handle slots.
620 DWORD GetNumRemainingHandles()
622 LIMITED_METHOD_CONTRACT;
624 return m_ArraySize - m_CurrentPos;
627 void ConsumeRemaining()
629 LIMITED_METHOD_CONTRACT;
631 m_CurrentPos = m_ArraySize;
634 OBJECTREF *TryAllocateEmbeddedFreeHandle();
636 // Allocate handles from the bucket.
637 OBJECTREF* AllocateHandles(DWORD nRequested);
638 OBJECTREF* CurrentPos()
640 LIMITED_METHOD_CONTRACT;
641 return m_pArrayDataPtr + m_CurrentPos;
645 LargeHeapHandleBucket *m_pNext;
648 int m_CurrentEmbeddedFreePos;
649 OBJECTHANDLE m_hndHandleArray;
650 OBJECTREF *m_pArrayDataPtr;
655 // The large heap handle table is used to allocate handles that are pointers
656 // to objects stored in an array in the large object heap.
657 class LargeHeapHandleTable
660 // Constructor and desctructor.
661 LargeHeapHandleTable(BaseDomain *pDomain, DWORD InitialBucketSize);
662 ~LargeHeapHandleTable();
664 // Allocate handles from the large heap handle table.
665 OBJECTREF* AllocateHandles(DWORD nRequested, BOOL bCrossAD = FALSE);
667 // Release object handles allocated using AllocateHandles().
668 void ReleaseHandles(OBJECTREF *pObjRef, DWORD nReleased);
671 // The buckets of object handles.
672 LargeHeapHandleBucket *m_pHead;
674 // We need to know the containing domain so we know where to allocate handles
675 BaseDomain *m_pDomain;
677 // The size of the LargeHeapHandleBuckets.
678 DWORD m_NextBucketSize;
680 // for finding and re-using embedded free items in the list
681 LargeHeapHandleBucket *m_pFreeSearchHint;
682 DWORD m_cEmbeddedFree;
686 // these functions are present to enforce that there is a locking mechanism in place
687 // for each LargeHeapHandleTable even though the code itself does not do the locking
688 // you must tell the table which lock you intend to use and it will verify that it has
689 // in fact been taken before performing any operations
692 void RegisterCrstDebug(CrstBase *pCrst)
694 LIMITED_METHOD_CONTRACT;
696 // this function must be called exactly once
697 _ASSERTE(pCrst != NULL);
698 _ASSERTE(m_pCrstDebug == NULL);
699 m_pCrstDebug = pCrst;
703 // we will assert that this Crst is held before using the object
704 CrstBase *m_pCrstDebug;
710 class LargeHeapHandleBlockHolder;
711 void LargeHeapHandleBlockHolder__StaticFree(LargeHeapHandleBlockHolder*);
714 class LargeHeapHandleBlockHolder:public Holder<LargeHeapHandleBlockHolder*,DoNothing,LargeHeapHandleBlockHolder__StaticFree>
717 LargeHeapHandleTable* m_pTable;
721 FORCEINLINE LargeHeapHandleBlockHolder(LargeHeapHandleTable* pOwner, DWORD nCount)
724 m_Data = pOwner->AllocateHandles(nCount);
729 FORCEINLINE void FreeData()
732 for (DWORD i=0;i< m_Count;i++)
733 ClearObjectReference(m_Data+i);
734 m_pTable->ReleaseHandles(m_Data, m_Count);
736 FORCEINLINE OBJECTREF* operator[] (DWORD idx)
738 LIMITED_METHOD_CONTRACT;
739 _ASSERTE(idx<m_Count);
740 return &(m_Data[idx]);
744 FORCEINLINE void LargeHeapHandleBlockHolder__StaticFree(LargeHeapHandleBlockHolder* pHolder)
754 // The large heap handle bucket class is used to contain handles allocated
755 // from an array contained in the large heap.
756 class ThreadStaticHandleBucket
759 // Constructor and desctructor.
760 ThreadStaticHandleBucket(ThreadStaticHandleBucket *pNext, DWORD Size, BaseDomain *pDomain);
761 ~ThreadStaticHandleBucket();
763 // This returns the next bucket.
764 ThreadStaticHandleBucket *GetNext()
766 LIMITED_METHOD_CONTRACT;
771 // Allocate handles from the bucket.
772 OBJECTHANDLE GetHandles();
775 ThreadStaticHandleBucket *m_pNext;
777 OBJECTHANDLE m_hndHandleArray;
781 // The large heap handle table is used to allocate handles that are pointers
782 // to objects stored in an array in the large object heap.
783 class ThreadStaticHandleTable
786 // Constructor and desctructor.
787 ThreadStaticHandleTable(BaseDomain *pDomain);
788 ~ThreadStaticHandleTable();
790 // Allocate handles from the large heap handle table.
791 OBJECTHANDLE AllocateHandles(DWORD nRequested);
794 // The buckets of object handles.
795 ThreadStaticHandleBucket *m_pHead;
797 // We need to know the containing domain so we know where to allocate handles
798 BaseDomain *m_pDomain;
804 //--------------------------------------------------------------------------------------
805 // Base class for domains. It provides an abstract way of finding the first assembly and
806 // for creating assemblies in the the domain. The system domain only has one assembly, it
807 // contains the classes that are logically shared between domains. All other domains can
808 // have multiple assemblies. Iteration is done be getting the first assembly and then
809 // calling the Next() method on the assembly.
811 // The system domain should be as small as possible, it includes object, exceptions, etc.
812 // which are the basic classes required to load other assemblies. All other classes
813 // should be loaded into the domain. Of coarse there is a trade off between loading the
814 // same classes multiple times, requiring all domains to load certain assemblies (working
815 // set) and being able to specify specific versions.
818 #define LOW_FREQUENCY_HEAP_RESERVE_SIZE (3 * GetOsPageSize())
819 #define LOW_FREQUENCY_HEAP_COMMIT_SIZE (1 * GetOsPageSize())
821 #define HIGH_FREQUENCY_HEAP_RESERVE_SIZE (10 * GetOsPageSize())
822 #define HIGH_FREQUENCY_HEAP_COMMIT_SIZE (1 * GetOsPageSize())
824 #define STUB_HEAP_RESERVE_SIZE (3 * GetOsPageSize())
825 #define STUB_HEAP_COMMIT_SIZE (1 * GetOsPageSize())
827 // --------------------------------------------------------------------------------
828 // PE File List lock - for creating list locks on PE files
829 // --------------------------------------------------------------------------------
831 class PEFileListLock : public ListLock
834 #ifndef DACCESS_COMPILE
835 ListLockEntry *FindFileLock(PEFile *pFile)
837 STATIC_CONTRACT_NOTHROW;
838 STATIC_CONTRACT_GC_NOTRIGGER;
839 STATIC_CONTRACT_FORBID_FAULT;
841 PRECONDITION(HasLock());
843 ListLockEntry *pEntry;
845 for (pEntry = m_pHead;
847 pEntry = pEntry->m_pNext)
849 if (((PEFile *)pEntry->m_data)->Equals(pFile))
857 #endif // DACCESS_COMPILE
859 DEBUG_NOINLINE static void HolderEnter(PEFileListLock *pThis) PUB
862 ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
867 DEBUG_NOINLINE static void HolderLeave(PEFileListLock *pThis) PUB
870 ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
875 typedef Wrapper<PEFileListLock*, PEFileListLock::HolderEnter, PEFileListLock::HolderLeave> Holder;
878 typedef PEFileListLock::Holder PEFileListLockHolder;
880 // Loading infrastructure:
882 // a DomainFile is a file being loaded. Files are loaded in layers to enable loading in the
883 // presence of dependency loops.
885 // FileLoadLevel describes the various levels available. These are implemented slightly
886 // differently for assemblies and modules, but the basic structure is the same.
888 // LoadLock and FileLoadLock form the ListLock data structures for files. The FileLoadLock
889 // is specialized in that it allows taking a lock at a particular level. Basicall any
890 // thread may obtain the lock at a level at which the file has previously been loaded to, but
891 // only one thread may obtain the lock at its current level.
893 // The PendingLoadQueue is a per thread data structure which serves two purposes. First, it
894 // holds a "load limit" which automatically restricts the level of recursive loads to be
895 // one less than the current load which is preceding. This, together with the AppDomain
896 // LoadLock level behavior, will prevent any deadlocks from occuring due to circular
897 // dependencies. (Note that it is important that the loading logic understands this restriction,
898 // and any given level of loading must deal with the fact that any recursive loads will be partially
899 // unfulfilled in a specific way.)
901 // The second function is to queue up any unfulfilled load requests for the thread. These
902 // are then delivered immediately after the current load request is dealt with.
904 class FileLoadLock : public ListLockEntry
907 FileLoadLevel m_level;
908 DomainFile *m_pDomainFile;
913 static FileLoadLock *Create(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile);
916 DomainFile *GetDomainFile();
917 ADID GetAppDomainId();
918 FileLoadLevel GetLoadLevel();
920 // CanAcquire will return FALSE if Acquire will definitely not take the lock due
921 // to levels or deadlock.
922 // (Note that there is a race exiting from the function, where Acquire may end
923 // up not taking the lock anyway if another thread did work in the meantime.)
924 BOOL CanAcquire(FileLoadLevel targetLevel);
926 // Acquire will return FALSE and not take the lock if the file
927 // has already been loaded to the target level. Otherwise,
928 // it will return TRUE and take the lock.
930 // Note that the taker must release the lock via IncrementLoadLevel.
931 BOOL Acquire(FileLoadLevel targetLevel);
933 // CompleteLoadLevel can be called after Acquire returns true
934 // returns TRUE if it updated load level, FALSE if the level was set already
935 BOOL CompleteLoadLevel(FileLoadLevel level, BOOL success);
937 void SetError(Exception *ex);
940 UINT32 Release() DAC_EMPTY_RET(0);
944 FileLoadLock(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile);
946 static void HolderLeave(FileLoadLock *pThis);
949 typedef Wrapper<FileLoadLock *, DoNothing, FileLoadLock::HolderLeave> Holder;
953 typedef FileLoadLock::Holder FileLoadLockHolder;
955 #ifndef DACCESS_COMPILE
956 typedef ReleaseHolder<FileLoadLock> FileLoadLockRefHolder;
957 #endif // DACCESS_COMPILE
959 typedef ListLockBase<NativeCodeVersion> JitListLock;
960 typedef ListLockEntryBase<NativeCodeVersion> JitListLockEntry;
964 #pragma warning(push)
965 #pragma warning (disable: 4324) //sometimes 64bit compilers complain about alignment
967 class LoadLevelLimiter
969 FileLoadLevel m_currentLevel;
970 LoadLevelLimiter* m_previousLimit;
976 : m_currentLevel(FILE_ACTIVE),
977 m_previousLimit(NULL),
980 LIMITED_METHOD_CONTRACT;
986 m_previousLimit=GetThread()->GetLoadLevelLimiter();
988 m_currentLevel=m_previousLimit->GetLoadLevel();
989 GetThread()->SetLoadLevelLimiter(this);
998 GetThread()->SetLoadLevelLimiter(m_previousLimit);
1005 WRAPPER_NO_CONTRACT;
1007 // PendingLoadQueues are allocated on the stack during a load, and
1008 // shared with all nested loads on the same thread.
1010 // Make sure the thread pointer gets reset after the
1011 // top level queue goes out of scope.
1018 FileLoadLevel GetLoadLevel()
1020 LIMITED_METHOD_CONTRACT;
1021 return m_currentLevel;
1024 void SetLoadLevel(FileLoadLevel level)
1026 LIMITED_METHOD_CONTRACT;
1027 m_currentLevel = level;
1031 #pragma warning (pop) //4324
1034 #define OVERRIDE_LOAD_LEVEL_LIMIT(newLimit) \
1035 LoadLevelLimiter __newLimit; \
1036 __newLimit.Activate(); \
1037 __newLimit.SetLoadLevel(newLimit);
1039 // A BaseDomain much basic information in a code:AppDomain including
1041 // * code:#AppdomainHeaps - Heaps for any data structures that will be freed on appdomain unload
1045 friend class Assembly;
1046 friend class AssemblySpec;
1047 friend class AppDomain;
1048 friend class AppDomainNative;
1050 VPTR_BASE_VTABLE_CLASS(BaseDomain)
1051 VPTR_UNIQUE(VPTR_UNIQUE_BaseDomain)
1054 // These 2 variables are only used on the AppDomain, but by placing them here
1055 // we reduce the cost of keeping the asmconstants file up to date.
1057 // The creation sequence number of this app domain (starting from 1)
1058 // This ID is generated by the code:SystemDomain::GetNewAppDomainId routine
1059 // The ID are recycled.
1061 // see also code:ADID
1064 DomainLocalBlock m_sDomainLocalBlock;
1068 class AssemblyIterator;
1069 friend class AssemblyIterator;
1071 // Static initialization.
1072 static void Attach();
1074 //****************************************************************************************
1076 // Initialization/shutdown routines for every instance of an BaseDomain.
1079 virtual ~BaseDomain() {}
1084 // ID to uniquely identify this AppDomain - used by the AppDomain publishing
1085 // service (to publish the list of all appdomains present in the process),
1086 // which in turn is used by, for eg., the debugger (to decide which App-
1087 // Domain(s) to attach to).
1088 // This is also used by Remoting for routing cross-appDomain calls.
1091 LIMITED_METHOD_DAC_CONTRACT;
1092 STATIC_CONTRACT_SO_TOLERANT;
1096 virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return FALSE; }
1097 virtual BOOL IsSharedDomain() { LIMITED_METHOD_DAC_CONTRACT; return FALSE; }
1099 inline BOOL IsDefaultDomain(); // defined later in this file
1100 virtual PTR_LoaderAllocator GetLoaderAllocator() = 0;
1101 virtual PTR_AppDomain AsAppDomain()
1103 LIMITED_METHOD_CONTRACT;
1104 STATIC_CONTRACT_SO_TOLERANT;
1105 _ASSERTE(!"Not an AppDomain");
1110 // If one domain is the SharedDomain and one is an AppDomain then
1111 // return the AppDomain, i.e. return the domain with the shorter lifetime
1112 // of the two given domains.
1113 static PTR_BaseDomain ComputeBaseDomain(
1114 BaseDomain *pGenericDefinitionDomain, // the domain that owns the generic type or method
1115 Instantiation classInst, // the type arguments to the type (if any)
1116 Instantiation methodInst = Instantiation()); // the type arguments to the method (if any)
1118 static PTR_BaseDomain ComputeBaseDomain(TypeKey * pTypeKey);
1120 #ifdef FEATURE_COMINTEROP
1121 //****************************************************************************************
1123 // This will look up interop data for a method table
1126 #ifndef DACCESS_COMPILE
1127 // Returns the data pointer if present, NULL otherwise
1128 InteropMethodTableData *LookupComInteropData(MethodTable *pMT)
1131 CrstHolder holder(&m_InteropDataCrst);
1134 InteropMethodTableData *pData = (InteropMethodTableData*) m_interopDataHash.LookupValue((UPTR) pMT, (LPVOID) NULL);
1137 if (pData == (InteropMethodTableData*) INVALIDENTRY)
1144 // Returns TRUE if successfully inserted, FALSE if this would be a duplicate entry
1145 BOOL InsertComInteropData(MethodTable* pMT, InteropMethodTableData *pData)
1147 // We don't keep track of this kind of information for interfaces
1148 _ASSERTE(!pMT->IsInterface());
1151 CrstHolder holder(&m_InteropDataCrst);
1153 // Check to see that it's not already in there
1154 InteropMethodTableData *pDupData = (InteropMethodTableData*) m_interopDataHash.LookupValue((UPTR) pMT, (LPVOID) NULL);
1155 if (pDupData != (InteropMethodTableData*) INVALIDENTRY)
1158 // Not in there, so insert
1159 m_interopDataHash.InsertValue((UPTR) pMT, (LPVOID) pData);
1164 #endif // DACCESS_COMPILE
1165 #endif // FEATURE_COMINTEROP
1167 void SetDisableInterfaceCache()
1169 m_fDisableInterfaceCache = TRUE;
1171 BOOL GetDisableInterfaceCache()
1173 return m_fDisableInterfaceCache;
1176 #ifdef FEATURE_COMINTEROP
1177 MngStdInterfacesInfo * GetMngStdInterfacesInfo()
1179 LIMITED_METHOD_CONTRACT;
1181 return m_pMngStdInterfacesInfo;
1184 PTR_CLRPrivBinderWinRT GetWinRtBinder()
1186 return m_pWinRtBinder;
1188 #endif // FEATURE_COMINTEROP
1190 //****************************************************************************************
1191 // This method returns marshaling data that the EE uses that is stored on a per app domain
1193 EEMarshalingData *GetMarshalingData();
1195 // Deletes marshaling data at shutdown (which contains cached factories that needs to be released)
1196 void DeleteMarshalingData();
1199 BOOL OwnDomainLocalBlockLock()
1201 WRAPPER_NO_CONTRACT;
1203 return m_DomainLocalBlockCrst.OwnedByCurrentThread();
1207 //****************************************************************************************
1208 // Get the class init lock. The method is limited to friends because inappropriate use
1209 // will cause deadlocks in the system
1210 ListLock* GetClassInitLock()
1212 LIMITED_METHOD_CONTRACT;
1214 return &m_ClassInitLock;
1217 JitListLock* GetJitLock()
1219 LIMITED_METHOD_CONTRACT;
1223 ListLock* GetILStubGenLock()
1225 LIMITED_METHOD_CONTRACT;
1226 return &m_ILStubGenLock;
1229 STRINGREF *IsStringInterned(STRINGREF *pString);
1230 STRINGREF *GetOrInternString(STRINGREF *pString);
1232 // Returns an array of OBJECTREF* that can be used to store domain specific data.
1233 // Statics and reflection info (Types, MemberInfo,..) are stored this way
1234 // If ppLazyAllocate != 0, allocation will only take place if *ppLazyAllocate != 0 (and the allocation
1235 // will be properly serialized)
1236 OBJECTREF *AllocateObjRefPtrsInLargeTable(int nRequested, OBJECTREF** ppLazyAllocate = NULL, BOOL bCrossAD = FALSE);
1238 #ifdef FEATURE_PREJIT
1239 // Ensures that the file for logging profile data is open (we only open it once)
1240 // return false on failure
1241 static BOOL EnsureNGenLogFileOpen();
1244 //****************************************************************************************
1247 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
1248 OBJECTHANDLE CreateTypedHandle(OBJECTREF object, HandleType type)
1250 WRAPPER_NO_CONTRACT;
1251 return ::CreateHandleCommon(m_handleStore, object, type);
1254 OBJECTHANDLE CreateHandle(OBJECTREF object)
1256 WRAPPER_NO_CONTRACT;
1257 CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL)
1258 return ::CreateHandle(m_handleStore, object);
1261 OBJECTHANDLE CreateWeakHandle(OBJECTREF object)
1263 WRAPPER_NO_CONTRACT;
1264 return ::CreateWeakHandle(m_handleStore, object);
1267 OBJECTHANDLE CreateShortWeakHandle(OBJECTREF object)
1269 WRAPPER_NO_CONTRACT;
1270 return ::CreateShortWeakHandle(m_handleStore, object);
1273 OBJECTHANDLE CreateLongWeakHandle(OBJECTREF object)
1275 WRAPPER_NO_CONTRACT;
1276 CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL)
1277 return ::CreateLongWeakHandle(m_handleStore, object);
1280 OBJECTHANDLE CreateStrongHandle(OBJECTREF object)
1282 WRAPPER_NO_CONTRACT;
1283 return ::CreateStrongHandle(m_handleStore, object);
1286 OBJECTHANDLE CreatePinningHandle(OBJECTREF object)
1288 WRAPPER_NO_CONTRACT;
1289 return ::CreatePinningHandle(m_handleStore, object);
1292 OBJECTHANDLE CreateSizedRefHandle(OBJECTREF object)
1294 WRAPPER_NO_CONTRACT;
1296 if (GCHeapUtilities::IsServerHeap())
1298 h = ::CreateSizedRefHandle(m_handleStore, object, m_dwSizedRefHandles % m_iNumberOfProcessors);
1302 h = ::CreateSizedRefHandle(m_handleStore, object);
1305 InterlockedIncrement((LONG*)&m_dwSizedRefHandles);
1309 #ifdef FEATURE_COMINTEROP
1310 OBJECTHANDLE CreateRefcountedHandle(OBJECTREF object)
1312 WRAPPER_NO_CONTRACT;
1313 return ::CreateRefcountedHandle(m_handleStore, object);
1316 OBJECTHANDLE CreateWinRTWeakHandle(OBJECTREF object, IWeakReference* pWinRTWeakReference)
1318 WRAPPER_NO_CONTRACT;
1319 return ::CreateWinRTWeakHandle(m_handleStore, object, pWinRTWeakReference);
1321 #endif // FEATURE_COMINTEROP
1323 OBJECTHANDLE CreateVariableHandle(OBJECTREF object, UINT type)
1325 WRAPPER_NO_CONTRACT;
1326 return ::CreateVariableHandle(m_handleStore, object, type);
1329 OBJECTHANDLE CreateDependentHandle(OBJECTREF primary, OBJECTREF secondary)
1331 WRAPPER_NO_CONTRACT;
1332 return ::CreateDependentHandle(m_handleStore, primary, secondary);
1335 #endif // DACCESS_COMPILE && !CROSSGEN_COMPILE
1337 IUnknown *GetFusionContext() {LIMITED_METHOD_CONTRACT; return m_pFusionContext; }
1339 CLRPrivBinderCoreCLR *GetTPABinderContext() {LIMITED_METHOD_CONTRACT; return m_pTPABinderContext; }
1342 CrstExplicitInit * GetLoaderAllocatorReferencesLock()
1344 LIMITED_METHOD_CONTRACT;
1345 return &m_crstLoaderAllocatorReferences;
1350 //****************************************************************************************
1351 // Helper method to initialize the large heap handle table.
1352 void InitLargeHeapHandleTable();
1354 //****************************************************************************************
1355 // Adds an assembly to the domain.
1356 void AddAssemblyNoLock(Assembly* assem);
1358 //****************************************************************************************
1360 // Hash table that maps a MethodTable to COM Interop compatibility data.
1361 PtrHashMap m_interopDataHash;
1363 // Critical sections & locks
1364 PEFileListLock m_FileLoadLock; // Protects the list of assemblies in the domain
1365 CrstExplicitInit m_DomainCrst; // General Protection for the Domain
1366 CrstExplicitInit m_DomainCacheCrst; // Protects the Assembly and Unmanaged caches
1367 CrstExplicitInit m_DomainLocalBlockCrst;
1368 CrstExplicitInit m_InteropDataCrst; // Used for COM Interop compatiblilty
1369 // Used to protect the reference lists in the collectible loader allocators attached to this appdomain
1370 CrstExplicitInit m_crstLoaderAllocatorReferences;
1371 CrstExplicitInit m_WinRTFactoryCacheCrst; // For WinRT factory cache
1374 // Used to protect the assembly list. Taken also by GC or debugger thread, therefore we have to avoid
1375 // triggering GC while holding this lock (by switching the thread to GC_NOTRIGGER while it is held).
1376 CrstExplicitInit m_crstAssemblyList;
1377 BOOL m_fDisableInterfaceCache; // RCW COM interface cache
1378 ListLock m_ClassInitLock;
1379 JitListLock m_JITLock;
1380 ListLock m_ILStubGenLock;
1382 // Fusion context, used for adding assemblies to the is domain. It defines
1383 // fusion properties for finding assemblyies such as SharedBinPath,
1384 // PrivateBinPath, Application Directory, etc.
1385 IUnknown *m_pFusionContext; // Current binding context for the domain
1387 CLRPrivBinderCoreCLR *m_pTPABinderContext; // Reference to the binding context that holds TPA list details
1389 IGCHandleStore* m_handleStore;
1391 // The large heap handle table.
1392 LargeHeapHandleTable *m_pLargeHeapHandleTable;
1394 // The large heap handle table critical section.
1395 CrstExplicitInit m_LargeHeapHandleTableCrst;
1397 EEMarshalingData *m_pMarshalingData;
1399 #ifdef FEATURE_COMINTEROP
1400 // Information regarding the managed standard interfaces.
1401 MngStdInterfacesInfo *m_pMngStdInterfacesInfo;
1404 PTR_CLRPrivBinderWinRT m_pWinRtBinder;
1405 #endif // FEATURE_COMINTEROP
1407 // Protects allocation of slot IDs for thread statics
1408 static CrstStatic m_SpecialStaticsCrst;
1411 // Only call this routine when you can guarantee there are no
1412 // loads in progress.
1413 void ClearFusionContext();
1415 //****************************************************************************************
1416 // Synchronization holders.
1418 class LockHolder : public CrstHolder
1421 LockHolder(BaseDomain *pD)
1422 : CrstHolder(&pD->m_DomainCrst)
1424 WRAPPER_NO_CONTRACT;
1427 friend class LockHolder;
1429 class CacheLockHolder : public CrstHolder
1432 CacheLockHolder(BaseDomain *pD)
1433 : CrstHolder(&pD->m_DomainCacheCrst)
1435 WRAPPER_NO_CONTRACT;
1438 friend class CacheLockHolder;
1440 class DomainLocalBlockLockHolder : public CrstHolder
1443 DomainLocalBlockLockHolder(BaseDomain *pD)
1444 : CrstHolder(&pD->m_DomainLocalBlockCrst)
1446 WRAPPER_NO_CONTRACT;
1449 friend class DomainLocalBlockLockHolder;
1451 class LoadLockHolder : public PEFileListLockHolder
1454 LoadLockHolder(BaseDomain *pD, BOOL Take = TRUE)
1455 : PEFileListLockHolder(&pD->m_FileLoadLock, Take)
1467 friend class LoadLockHolder;
1468 class WinRTFactoryCacheLockHolder : public CrstHolder
1471 WinRTFactoryCacheLockHolder(BaseDomain *pD)
1472 : CrstHolder(&pD->m_WinRTFactoryCacheCrst)
1474 WRAPPER_NO_CONTRACT;
1477 friend class WinRTFactoryCacheLockHolder;
1481 RangeList *GetCollectibleVSDRanges() { return &m_collVSDRanges; }
1484 TypeIDMap m_typeIDMap;
1485 // Range list for collectible types. Maps VSD PCODEs back to the VirtualCallStubManager they belong to
1486 LockedRangeList m_collVSDRanges;
1489 UINT32 GetTypeID(PTR_MethodTable pMT);
1490 UINT32 LookupTypeID(PTR_MethodTable pMT);
1491 PTR_MethodTable LookupType(UINT32 id);
1494 // I have yet to figure out an efficent way to get the number of handles
1495 // of a particular type that's currently used by the process without
1496 // spending more time looking at the handle table code. We know that
1497 // our only customer (asp.net) in Dev10 is not going to create many of
1498 // these handles so I am taking a shortcut for now and keep the sizedref
1499 // handle count on the AD itself.
1500 DWORD m_dwSizedRefHandles;
1502 static int m_iNumberOfProcessors;
1505 // Called by DestroySizedRefHandle
1506 void DecNumSizedRefHandles()
1508 WRAPPER_NO_CONTRACT;
1510 result = InterlockedDecrement((LONG*)&m_dwSizedRefHandles);
1511 _ASSERTE(result >= 0);
1514 DWORD GetNumSizedRefHandles()
1516 return m_dwSizedRefHandles;
1519 #ifdef FEATURE_CODE_VERSIONING
1521 CodeVersionManager m_codeVersionManager;
1524 CodeVersionManager* GetCodeVersionManager() { return &m_codeVersionManager; }
1525 #endif //FEATURE_CODE_VERSIONING
1527 #ifdef FEATURE_TIERED_COMPILATION
1529 CallCounter m_callCounter;
1532 CallCounter* GetCallCounter() { return &m_callCounter; }
1535 #ifdef DACCESS_COMPILE
1537 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
1541 }; // class BaseDomain
1545 ATTACH_ASSEMBLY_LOAD = 0x1,
1546 ATTACH_MODULE_LOAD = 0x2,
1547 ATTACH_CLASS_LOAD = 0x4,
1552 // This filters the output of IterateAssemblies. This ought to be declared more locally
1553 // but it would result in really verbose callsites.
1555 // Assemblies can be categorized by their load status (loaded, loading, or loaded just
1556 // enough that they would be made available to profilers)
1557 // Independently, they can also be categorized as execution or introspection.
1559 // An assembly will be included in the results of IterateAssemblies only if
1560 // the appropriate bit is set for *both* characterizations.
1562 // The flags can be combined so if you want all loaded assemblies, you must specify:
1564 /// kIncludeLoaded|kIncludeExecution
1566 enum AssemblyIterationFlags
1568 // load status flags
1569 kIncludeLoaded = 0x00000001, // include assemblies that are already loaded
1570 // (m_level >= code:FILE_LOAD_DELIVER_EVENTS)
1571 kIncludeLoading = 0x00000002, // include assemblies that are still in the process of loading
1572 // (all m_level values)
1573 kIncludeAvailableToProfilers
1574 = 0x00000020, // include assemblies available to profilers
1575 // See comment at code:DomainFile::IsAvailableToProfilers
1577 // Execution / introspection flags
1578 kIncludeExecution = 0x00000004, // include assemblies that are loaded for execution only
1580 kIncludeFailedToLoad = 0x00000010, // include assemblies that failed to load
1582 // Collectible assemblies flags
1583 kExcludeCollectible = 0x00000040, // Exclude all collectible assemblies
1584 kIncludeCollected = 0x00000080,
1585 // Include assemblies which were collected and cannot be referenced anymore. Such assemblies are not
1586 // AddRef-ed. Any manipulation with them should be protected by code:GetAssemblyListLock.
1587 // Should be used only by code:LoaderAllocator::GCLoaderAllocators.
1589 }; // enum AssemblyIterationFlags
1591 //---------------------------------------------------------------------------------------
1593 // Base class for holder code:CollectibleAssemblyHolder (see code:HolderBase).
1594 // Manages AddRef/Release for collectible assemblies. It is no-op for 'normal' non-collectible assemblies.
1596 // Each type of type parameter needs 2 methods implemented:
1597 // code:CollectibleAssemblyHolderBase::GetLoaderAllocator
1598 // code:CollectibleAssemblyHolderBase::IsCollectible
1600 template<typename _Type>
1601 class CollectibleAssemblyHolderBase
1606 CollectibleAssemblyHolderBase(const _Type & value = NULL)
1608 LIMITED_METHOD_CONTRACT;
1621 // We don't need to keep the assembly alive in DAC - see code:#CAH_DAC
1622 #ifndef DACCESS_COMPILE
1623 if (this->IsCollectible(m_value))
1625 LoaderAllocator * pLoaderAllocator = GetLoaderAllocator(m_value);
1626 pLoaderAllocator->AddReference();
1628 #endif //!DACCESS_COMPILE
1640 #ifndef DACCESS_COMPILE
1641 if (this->IsCollectible(m_value))
1643 LoaderAllocator * pLoaderAllocator = GetLoaderAllocator(m_value);
1644 pLoaderAllocator->Release();
1646 #endif //!DACCESS_COMPILE
1650 LoaderAllocator * GetLoaderAllocator(DomainAssembly * pDomainAssembly)
1652 WRAPPER_NO_CONTRACT;
1653 return pDomainAssembly->GetLoaderAllocator();
1655 BOOL IsCollectible(DomainAssembly * pDomainAssembly)
1657 WRAPPER_NO_CONTRACT;
1658 return pDomainAssembly->IsCollectible();
1660 LoaderAllocator * GetLoaderAllocator(Assembly * pAssembly)
1662 WRAPPER_NO_CONTRACT;
1663 return pAssembly->GetLoaderAllocator();
1665 BOOL IsCollectible(Assembly * pAssembly)
1667 WRAPPER_NO_CONTRACT;
1668 return pAssembly->IsCollectible();
1670 }; // class CollectibleAssemblyHolderBase<>
1672 //---------------------------------------------------------------------------------------
1674 // Holder of assembly reference which keeps collectible assembly alive while the holder is valid.
1676 // Collectible assembly can be collected at any point when GC happens. Almost instantly all native data
1677 // structures of the assembly (e.g. code:DomainAssembly, code:Assembly) could be deallocated.
1678 // Therefore any usage of (collectible) assembly data structures from native world, has to prevent the
1679 // deallocation by increasing ref-count on the assembly / associated loader allocator.
1682 // In DAC we don't AddRef/Release as the assembly doesn't have to be kept alive: The process is stopped when
1683 // DAC is used and therefore the assembly cannot just disappear.
1685 template<typename _Type>
1686 class CollectibleAssemblyHolder : public BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >
1690 CollectibleAssemblyHolder(const _Type & value = NULL, BOOL fTake = TRUE)
1691 : BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >(value, fTake)
1693 STATIC_CONTRACT_WRAPPER;
1697 CollectibleAssemblyHolder &
1698 operator=(const _Type & value)
1700 STATIC_CONTRACT_WRAPPER;
1701 BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >::operator=(value);
1705 // Operator & is overloaded in parent, therefore we have to get to 'this' pointer explicitly.
1707 CollectibleAssemblyHolder<_Type> *
1710 LIMITED_METHOD_CONTRACT;
1713 }; // class CollectibleAssemblyHolder<>
1715 //---------------------------------------------------------------------------------------
1717 #ifdef FEATURE_LOADER_OPTIMIZATION
1718 class SharedAssemblyLocator
1727 DWORD GetType() {LIMITED_METHOD_CONTRACT; return m_type;};
1728 #ifndef DACCESS_COMPILE
1729 DomainAssembly* GetDomainAssembly() {LIMITED_METHOD_CONTRACT; _ASSERTE(m_type==DOMAINASSEMBLY); return (DomainAssembly*)m_value;};
1730 PEAssembly* GetPEAssembly() {LIMITED_METHOD_CONTRACT; _ASSERTE(m_type==PEASSEMBLY||m_type==PEASSEMBLYEXACT); return (PEAssembly*)m_value;};
1731 SharedAssemblyLocator(DomainAssembly* pAssembly)
1733 LIMITED_METHOD_CONTRACT;
1734 m_type=DOMAINASSEMBLY;
1737 SharedAssemblyLocator(PEAssembly* pFile, DWORD type = PEASSEMBLY)
1739 LIMITED_METHOD_CONTRACT;
1743 #endif // DACCESS_COMPILE
1749 ULONG m_uIdentityHash;
1751 #endif // FEATURE_LOADER_OPTIMIZATION
1754 // Stores binding information about failed assembly loads for DAC
1756 struct FailedAssembly {
1757 SString displayName;
1761 void Initialize(AssemblySpec *pSpec, Exception *ex)
1771 displayName.SetASCII(pSpec->GetName());
1772 location.Set(pSpec->GetCodeBase());
1773 error = ex->GetHR();
1776 // Determine the binding context assembly would have been in.
1777 // If the parent has been set, use its binding context.
1778 // If the parent hasn't been set but the code base has, use LoadFrom.
1779 // Otherwise, use the default.
1784 #ifdef FEATURE_COMINTEROP
1786 // Cache used by COM Interop
1787 struct NameToTypeMapEntry
1789 // Host space representation of the key
1792 LPCWSTR m_wzName; // The type name or registry string representation of the GUID "{<guid>}"
1793 SIZE_T m_cchName; // wcslen(m_wzName) for faster hashtable lookup
1797 PTR_CWSTR m_wzName; // The type name or registry string representation of the GUID "{<guid>}"
1798 SIZE_T m_cchName; // wcslen(m_wzName) for faster hashtable lookup
1800 TypeHandle m_typeHandle; // Using TypeHandle instead of MethodTable* to avoid losing information when sharing method tables.
1801 UINT m_nEpoch; // tracks creation Epoch. This is incremented each time an external reader enumerate the cache
1805 typedef DPTR(NameToTypeMapEntry) PTR_NameToTypeMapEntry;
1807 class NameToTypeMapTraits : public NoRemoveSHashTraits< DefaultSHashTraits<NameToTypeMapEntry> >
1810 typedef NameToTypeMapEntry::Key key_t;
1812 static const NameToTypeMapEntry Null() { NameToTypeMapEntry e; e.m_key.m_wzName = NULL; e.m_key.m_cchName = 0; return e; }
1813 static bool IsNull(const NameToTypeMapEntry &e) { return e.m_key.m_wzName == NULL; }
1814 static const key_t GetKey(const NameToTypeMapEntry &e)
1817 key.m_wzName = (LPCWSTR)(e.m_key.m_wzName); // this cast brings the string over to the host, in a DAC build
1818 key.m_cchName = e.m_key.m_cchName;
1822 static count_t Hash(const key_t &key) { WRAPPER_NO_CONTRACT; return HashStringN(key.m_wzName, key.m_cchName); }
1824 static BOOL Equals(const key_t &lhs, const key_t &rhs)
1826 WRAPPER_NO_CONTRACT;
1827 return (lhs.m_cchName == rhs.m_cchName) && memcmp(lhs.m_wzName, rhs.m_wzName, lhs.m_cchName * sizeof(WCHAR)) == 0;
1830 void OnDestructPerEntryCleanupAction(const NameToTypeMapEntry& e)
1832 WRAPPER_NO_CONTRACT;
1833 _ASSERTE(e.m_key.m_cchName == wcslen(e.m_key.m_wzName));
1834 #ifndef DACCESS_COMPILE
1835 delete [] e.m_key.m_wzName;
1836 #endif // DACCESS_COMPILE
1838 static const bool s_DestructPerEntryCleanupAction = true;
1841 typedef SHash<NameToTypeMapTraits> NameToTypeMapTable;
1843 typedef DPTR(NameToTypeMapTable) PTR_NameToTypeMapTable;
1845 struct WinRTFactoryCacheEntry
1847 typedef MethodTable *Key;
1848 Key key; // Type as KEY
1850 CtxEntry *m_pCtxEntry; // Context entry - used to verify whether the cache is a match
1851 OBJECTHANDLE m_ohFactoryObject; // Handle to factory object
1854 class WinRTFactoryCacheTraits : public DefaultSHashTraits<WinRTFactoryCacheEntry>
1857 typedef WinRTFactoryCacheEntry::Key key_t;
1858 static const WinRTFactoryCacheEntry Null() { WinRTFactoryCacheEntry e; e.key = NULL; return e; }
1859 static bool IsNull(const WinRTFactoryCacheEntry &e) { return e.key == NULL; }
1860 static const WinRTFactoryCacheEntry::Key GetKey(const WinRTFactoryCacheEntry& e) { return e.key; }
1861 static count_t Hash(WinRTFactoryCacheEntry::Key key) { return (count_t)((size_t)key); }
1862 static BOOL Equals(WinRTFactoryCacheEntry::Key lhs, WinRTFactoryCacheEntry::Key rhs)
1863 { return lhs == rhs; }
1864 static const WinRTFactoryCacheEntry Deleted() { WinRTFactoryCacheEntry e; e.key = (MethodTable *)-1; return e; }
1865 static bool IsDeleted(const WinRTFactoryCacheEntry &e) { return e.key == (MethodTable *)-1; }
1867 static void OnDestructPerEntryCleanupAction(const WinRTFactoryCacheEntry& e);
1868 static const bool s_DestructPerEntryCleanupAction = true;
1871 typedef SHash<WinRTFactoryCacheTraits> WinRTFactoryCache;
1873 #endif // FEATURE_COMINTEROP
1875 class AppDomainIterator;
1877 const DWORD DefaultADID = 1;
1879 template <class AppDomainType> class AppDomainCreationHolder;
1881 // An Appdomain is the managed equivalent of a process. It is an isolation unit (conceptually you don't
1882 // have pointers directly from one appdomain to another, but rather go through remoting proxies). It is
1883 // also a unit of unloading.
1885 // Threads are always running in the context of a particular AppDomain. See
1886 // file:threads.h#RuntimeThreadLocals for more details.
1888 // see code:BaseDomain for much of the meat of a AppDomain (heaps locks, etc)
1889 // * code:AppDomain.m_Assemblies - is a list of code:Assembly in the appdomain
1891 class AppDomain : public BaseDomain
1893 friend class SystemDomain;
1894 friend class AssemblySink;
1895 friend class AppDomainNative;
1896 friend class AssemblyNative;
1897 friend class AssemblySpec;
1898 friend class ClassLoader;
1899 friend class ThreadNative;
1900 friend class RCWCache;
1901 friend class ClrDataAccess;
1902 friend class CheckAsmOffsets;
1904 VPTR_VTABLE_CLASS(AppDomain, BaseDomain)
1907 #ifndef DACCESS_COMPILE
1909 virtual ~AppDomain();
1911 DomainAssembly* FindDomainAssembly(Assembly*);
1912 void EnterContext(Thread* pThread, Context* pCtx,ContextTransitionFrame *pFrame);
1914 #ifndef DACCESS_COMPILE
1915 //-----------------------------------------------------------------------------------------------------------------
1916 // Convenience wrapper for ::GetAppDomain to provide better encapsulation.
1917 static AppDomain * GetCurrentDomain()
1918 { return ::GetAppDomain(); }
1919 #endif //!DACCESS_COMPILE
1921 //-----------------------------------------------------------------------------------------------------------------
1922 // Initializes an AppDomain. (this functions is not called from the SystemDomain)
1925 #if defined(FEATURE_COMINTEROP)
1926 HRESULT SetWinrtApplicationContext(SString &appLocalWinMD);
1927 #endif // FEATURE_COMINTEROP
1929 BOOL CanReversePInvokeEnter();
1930 void SetReversePInvokeCannotEnter();
1931 bool MustForceTrivialWaitOperations();
1932 void SetForceTrivialWaitOperations();
1934 //****************************************************************************************
1936 // Stop deletes all the assemblies but does not remove other resources like
1937 // the critical sections
1940 // Gets rid of resources
1943 #ifdef FEATURE_PREJIT
1944 //assembly cleanup that requires suspended runtime
1945 void DeleteNativeCodeRanges();
1948 // final assembly cleanup
1949 void ShutdownAssemblies();
1950 void ShutdownFreeLoaderAllocators(BOOL bFromManagedCode);
1952 void ReleaseDomainBoundInfo();
1953 void ReleaseFiles();
1956 // Remove the Appdomain for the system and cleans up. This call should not be
1957 // called from shut down code.
1960 virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; }
1961 virtual PTR_AppDomain AsAppDomain() { LIMITED_METHOD_CONTRACT; return dac_cast<PTR_AppDomain>(this); }
1964 OBJECTREF DoSetup(OBJECTREF* setupInfo);
1966 OBJECTREF GetExposedObject();
1967 OBJECTREF GetRawExposedObject() {
1976 if (m_ExposedObject) {
1977 return ObjectFromHandle(m_ExposedObject);
1984 OBJECTHANDLE GetRawExposedObjectHandleForDebugger() { LIMITED_METHOD_DAC_CONTRACT; return m_ExposedObject; }
1986 #ifdef FEATURE_COMINTEROP
1987 HRESULT GetComIPForExposedObject(IUnknown **pComIP);
1989 MethodTable *GetRedirectedType(WinMDAdapter::RedirectedTypeIndex index);
1990 #endif // FEATURE_COMINTEROP
1993 //****************************************************************************************
1996 // Multi-thread safe access to the list of assemblies
1997 class DomainAssemblyList
2002 AppDomain * dbg_m_pAppDomain;
2004 void Debug_SetAppDomain(AppDomain * pAppDomain)
2006 dbg_m_pAppDomain = pAppDomain;
2018 // This function can be reliably called without taking the lock, because the first assembly
2019 // added to the arraylist is non-collectible, and the ArrayList itself allows lockless read access
2020 return (m_array.GetCount() == 0);
2022 void Clear(AppDomain * pAppDomain)
2026 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2030 _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2032 CrstHolder ch(pAppDomain->GetAssemblyListLock());
2036 DWORD GetCount(AppDomain * pAppDomain)
2040 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2044 _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2046 CrstHolder ch(pAppDomain->GetAssemblyListLock());
2047 return GetCount_Unlocked();
2049 DWORD GetCount_Unlocked()
2057 #ifndef DACCESS_COMPILE
2058 _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2060 // code:Append_Unlock guarantees that we do not have more than MAXDWORD items
2061 return m_array.GetCount();
2064 void Get(AppDomain * pAppDomain, DWORD index, CollectibleAssemblyHolder<DomainAssembly *> * pAssemblyHolder)
2068 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2072 _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2074 CrstHolder ch(pAppDomain->GetAssemblyListLock());
2075 Get_Unlocked(index, pAssemblyHolder);
2077 void Get_Unlocked(DWORD index, CollectibleAssemblyHolder<DomainAssembly *> * pAssemblyHolder)
2085 _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2086 *pAssemblyHolder = dac_cast<PTR_DomainAssembly>(m_array.Get(index));
2088 // Doesn't lock the assembly list (caller has to hold the lock already).
2089 // Doesn't AddRef the returned assembly (if collectible).
2090 DomainAssembly * Get_UnlockedNoReference(DWORD index)
2099 #ifndef DACCESS_COMPILE
2100 _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2102 return dac_cast<PTR_DomainAssembly>(m_array.Get(index));
2105 #ifndef DACCESS_COMPILE
2106 void Set(AppDomain * pAppDomain, DWORD index, DomainAssembly * pAssembly)
2110 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2114 _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2116 CrstHolder ch(pAppDomain->GetAssemblyListLock());
2117 return Set_Unlocked(index, pAssembly);
2119 void Set_Unlocked(DWORD index, DomainAssembly * pAssembly)
2127 _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2128 m_array.Set(index, pAssembly);
2131 HRESULT Append_Unlocked(DomainAssembly * pAssembly)
2139 _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2140 return m_array.Append(pAssembly);
2142 #else //DACCESS_COMPILE
2144 EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2148 m_array.EnumMemoryRegions(flags);
2150 #endif // DACCESS_COMPILE
2152 // Should be used only by code:AssemblyIterator::Create
2153 ArrayList::Iterator GetArrayListIterator()
2155 return m_array.Iterate();
2157 }; // class DomainAssemblyList
2159 // Conceptually a list of code:Assembly structures, protected by lock code:GetAssemblyListLock
2160 DomainAssemblyList m_Assemblies;
2163 // Note that this lock switches thread into GC_NOTRIGGER region as GC can take it too.
2164 CrstExplicitInit * GetAssemblyListLock()
2166 LIMITED_METHOD_CONTRACT;
2167 return &m_crstAssemblyList;
2171 class AssemblyIterator
2173 // AppDomain context with the assembly list
2174 AppDomain * m_pAppDomain;
2175 ArrayList::Iterator m_Iterator;
2176 AssemblyIterationFlags m_assemblyIterationFlags;
2179 BOOL Next(CollectibleAssemblyHolder<DomainAssembly *> * pDomainAssemblyHolder);
2180 // Note: Does not lock the assembly list, but AddRefs collectible assemblies.
2181 BOOL Next_Unlocked(CollectibleAssemblyHolder<DomainAssembly *> * pDomainAssemblyHolder);
2182 #ifndef DACCESS_COMPILE
2184 // Can be called only from AppDomain shutdown code:AppDomain::ShutdownAssemblies.
2185 // Note: Does not lock the assembly list and does not AddRefs collectible assemblies.
2186 BOOL Next_UnsafeNoAddRef(DomainAssembly ** ppDomainAssembly);
2190 inline DWORD GetIndex()
2192 LIMITED_METHOD_CONTRACT;
2193 return m_Iterator.GetIndex();
2197 friend class AppDomain;
2198 // Cannot have constructor so this iterator can be used inside a union
2199 static AssemblyIterator Create(AppDomain * pAppDomain, AssemblyIterationFlags assemblyIterationFlags)
2201 LIMITED_METHOD_CONTRACT;
2204 i.m_pAppDomain = pAppDomain;
2205 i.m_Iterator = pAppDomain->m_Assemblies.GetArrayListIterator();
2206 i.m_assemblyIterationFlags = assemblyIterationFlags;
2209 }; // class AssemblyIterator
2211 AssemblyIterator IterateAssembliesEx(AssemblyIterationFlags assemblyIterationFlags)
2213 LIMITED_METHOD_CONTRACT;
2214 return AssemblyIterator::Create(this, assemblyIterationFlags);
2218 struct NativeImageDependenciesEntry
2220 BaseAssemblySpec m_AssemblySpec;
2224 class NativeImageDependenciesTraits : public DeleteElementsOnDestructSHashTraits<DefaultSHashTraits<NativeImageDependenciesEntry *> >
2227 typedef BaseAssemblySpec *key_t;
2228 static key_t GetKey(NativeImageDependenciesEntry * e) { return &(e->m_AssemblySpec); }
2230 static count_t Hash(key_t k)
2235 static BOOL Equals(key_t lhs, key_t rhs)
2237 return lhs->CompareEx(rhs);
2241 SHash<NativeImageDependenciesTraits> m_NativeImageDependencies;
2244 void CheckForMismatchedNativeImages(AssemblySpec * pSpec, const GUID * pGuid);
2245 BOOL RemoveNativeImageDependency(AssemblySpec* pSpec);
2250 friend class AppDomain;
2252 ArrayList::Iterator m_i;
2257 WRAPPER_NO_CONTRACT;
2263 WRAPPER_NO_CONTRACT;
2264 return dac_cast<PTR_SString>(m_i.GetElement());
2267 BOOL BindingByManifestFile();
2269 PathIterator IterateNativeDllSearchDirectories();
2270 void SetNativeDllSearchDirectories(LPCWSTR paths);
2271 BOOL HasNativeDllSearchDirectories();
2272 void ShutdownNativeDllSearchDirectories();
2275 SIZE_T GetAssemblyCount()
2277 WRAPPER_NO_CONTRACT;
2278 return m_Assemblies.GetCount(this);
2281 CHECK CheckCanLoadTypes(Assembly *pAssembly);
2282 CHECK CheckCanExecuteManagedCode(MethodDesc* pMD);
2283 CHECK CheckLoading(DomainFile *pFile, FileLoadLevel level);
2285 FileLoadLevel GetDomainFileLoadLevel(DomainFile *pFile);
2286 BOOL IsLoading(DomainFile *pFile, FileLoadLevel level);
2287 static FileLoadLevel GetThreadFileLoadLevel();
2289 void LoadDomainFile(DomainFile *pFile,
2290 FileLoadLevel targetLevel);
2292 enum FindAssemblyOptions
2294 FindAssemblyOptions_None = 0x0,
2295 FindAssemblyOptions_IncludeFailedToLoad = 0x1
2298 DomainAssembly * FindAssembly(PEAssembly * pFile, FindAssemblyOptions options = FindAssemblyOptions_None) DAC_EMPTY_RET(NULL);
2301 Assembly *LoadAssembly(AssemblySpec* pIdentity,
2303 FileLoadLevel targetLevel);
2305 // this function does not provide caching, you must use LoadDomainAssembly
2306 // unless the call is guaranteed to succeed or you don't need the caching
2307 // (e.g. if you will FailFast or tear down the AppDomain anyway)
2308 // The main point that you should not bypass caching if you might try to load the same file again,
2309 // resulting in multiple DomainAssembly objects that share the same PEAssembly for ngen image
2310 //which is violating our internal assumptions
2311 DomainAssembly *LoadDomainAssemblyInternal( AssemblySpec* pIdentity,
2313 FileLoadLevel targetLevel);
2315 DomainAssembly *LoadDomainAssembly( AssemblySpec* pIdentity,
2317 FileLoadLevel targetLevel);
2320 CHECK CheckValidModule(Module *pModule);
2321 #ifdef FEATURE_LOADER_OPTIMIZATION
2322 DomainFile *LoadDomainNeutralModuleDependency(Module *pModule, FileLoadLevel targetLevel);
2326 void LoadSystemAssemblies();
2328 DomainFile *LoadDomainFile(FileLoadLock *pLock,
2329 FileLoadLevel targetLevel);
2331 void TryIncrementalLoad(DomainFile *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder);
2333 Assembly *LoadAssemblyHelper(LPCWSTR wszAssembly,
2334 LPCWSTR wszCodeBase);
2336 #ifndef DACCESS_COMPILE // needs AssemblySpec
2338 void GetCacheAssemblyList(SetSHash<PTR_DomainAssembly>& assemblyList);
2340 //****************************************************************************************
2341 // Returns and Inserts assemblies into a lookup cache based on the binding information
2342 // in the AssemblySpec. There can be many AssemblySpecs to a single assembly.
2343 DomainAssembly* FindCachedAssembly(AssemblySpec* pSpec, BOOL fThrow=TRUE)
2345 WRAPPER_NO_CONTRACT;
2346 return m_AssemblyCache.LookupAssembly(pSpec, fThrow);
2349 PEAssembly* FindCachedFile(AssemblySpec* pSpec, BOOL fThrow = TRUE);
2350 BOOL IsCached(AssemblySpec *pSpec);
2351 #endif // DACCESS_COMPILE
2352 void CacheStringsForDAC();
2354 BOOL AddFileToCache(AssemblySpec* pSpec, PEAssembly *pFile, BOOL fAllowFailure = FALSE);
2355 BOOL RemoveFileFromCache(PEAssembly *pFile);
2357 BOOL AddAssemblyToCache(AssemblySpec* pSpec, DomainAssembly *pAssembly);
2358 BOOL RemoveAssemblyFromCache(DomainAssembly* pAssembly);
2360 BOOL AddExceptionToCache(AssemblySpec* pSpec, Exception *ex);
2361 void AddUnmanagedImageToCache(LPCWSTR libraryName, HMODULE hMod);
2362 HMODULE FindUnmanagedImageInCache(LPCWSTR libraryName);
2363 //****************************************************************************************
2365 // Adds or removes an assembly to the domain.
2366 void AddAssembly(DomainAssembly * assem);
2367 void RemoveAssembly(DomainAssembly * pAsm);
2369 BOOL ContainsAssembly(Assembly * assem);
2371 #ifdef FEATURE_LOADER_OPTIMIZATION
2374 // Attributes to control when to use domain neutral assemblies
2375 SHARE_POLICY_UNSPECIFIED, // Use the current default policy (LoaderOptimization.NotSpecified)
2376 SHARE_POLICY_NEVER, // Do not share anything, except the system assembly (LoaderOptimization.SingleDomain)
2377 SHARE_POLICY_ALWAYS, // Share everything possible (LoaderOptimization.MultiDomain)
2378 SHARE_POLICY_GAC, // Share only GAC-bound assemblies (LoaderOptimization.MultiDomainHost)
2381 SHARE_POLICY_MASK = 0x3,
2383 // NOTE that previously defined was a bit 0x40 which might be set on this value
2384 // in custom attributes.
2385 SHARE_POLICY_DEFAULT = SHARE_POLICY_NEVER,
2388 SharePolicy GetSharePolicy();
2389 #endif // FEATURE_LOADER_OPTIMIZATION
2391 //****************************************************************************************
2393 // Reference count. When an appdomain is first created the reference is bump
2394 // to one when it is added to the list of domains (see SystemDomain). An explicit
2395 // Removal from the list is necessary before it will be deleted.
2397 ULONG Release(void) DAC_EMPTY_RET(0);
2399 //****************************************************************************************
2400 LPCWSTR GetFriendlyName(BOOL fDebuggerCares = TRUE);
2401 LPCWSTR GetFriendlyNameForDebugger();
2402 LPCWSTR GetFriendlyNameForLogging();
2403 #ifdef DACCESS_COMPILE
2404 PVOID GetFriendlyNameNoSet(bool* isUtf8);
2406 void SetFriendlyName(LPCWSTR pwzFriendlyName, BOOL fDebuggerCares = TRUE);
2407 void ResetFriendlyName(BOOL fDebuggerCares = TRUE);
2409 //****************************************************************************************
2411 // This can be used to override the binding behavior of the appdomain. It
2412 // is overridden in the compilation domain. It is important that all
2413 // static binding goes through this path.
2414 virtual PEAssembly * BindAssemblySpec(
2415 AssemblySpec *pSpec,
2416 BOOL fThrowOnFileNotFound,
2417 StackCrawlMark *pCallerStackMark = NULL,
2418 BOOL fUseHostBinderIfAvailable = TRUE) DAC_EMPTY_RET(NULL);
2420 HRESULT BindAssemblySpecForHostedBinder(
2421 AssemblySpec * pSpec,
2422 IAssemblyName * pAssemblyName,
2423 ICLRPrivBinder * pBinder,
2424 PEAssembly ** ppAssembly) DAC_EMPTY_RET(E_FAIL);
2426 HRESULT BindHostedPrivAssembly(
2427 PEAssembly * pParentPEAssembly,
2428 ICLRPrivAssembly * pPrivAssembly,
2429 IAssemblyName * pAssemblyName,
2430 PEAssembly ** ppAssembly) DAC_EMPTY_RET(S_OK);
2433 PEAssembly *TryResolveAssembly(AssemblySpec *pSpec, BOOL fPreBind);
2435 // Store a successful binding into the cache. This will keep the file from
2436 // being physically unmapped, as well as shortcutting future attempts to bind
2437 // the same spec throught the Cached entry point.
2439 // Right now we only cache assembly binds for "probing" type
2440 // binding situations, basically when loading domain neutral assemblies or
2443 // <TODO>@todo: We may want to be more aggressive about this if
2444 // there are other situations where we are repeatedly binding the
2445 // same assembly specs, though.</TODO>
2447 // Returns TRUE if stored
2448 // FALSE if it's a duplicate (caller should clean up args)
2449 BOOL StoreBindAssemblySpecResult(AssemblySpec *pSpec,
2453 BOOL StoreBindAssemblySpecError(AssemblySpec *pSpec,
2455 OBJECTREF *pThrowable,
2458 //****************************************************************************************
2460 //****************************************************************************************
2462 // Uses the first assembly to add an application base to the Context. This is done
2463 // in a lazy fashion so executables do not take the perf hit unless the load other
2465 #ifndef DACCESS_COMPILE
2466 void OnAssemblyLoad(Assembly *assem);
2467 void OnAssemblyLoadUnlocked(Assembly *assem);
2468 static BOOL OnUnhandledException(OBJECTREF *pThrowable, BOOL isTerminating = TRUE);
2472 // True iff a debugger is attached to the process (same as CORDebuggerAttached)
2473 BOOL IsDebuggerAttached (void);
2475 #ifdef DEBUGGING_SUPPORTED
2476 // Notify debugger of all assemblies, modules, and possibly classes in this AppDomain
2477 BOOL NotifyDebuggerLoad(int flags, BOOL attaching);
2479 // Send unload notifications to the debugger for all assemblies, modules and classes in this AppDomain
2480 void NotifyDebuggerUnload();
2481 #endif // DEBUGGING_SUPPORTED
2483 void SetSystemAssemblyLoadEventSent (BOOL fFlag);
2484 BOOL WasSystemAssemblyLoadEventSent (void);
2486 #ifndef DACCESS_COMPILE
2487 OBJECTREF* AllocateStaticFieldObjRefPtrs(int nRequested, OBJECTREF** ppLazyAllocate = NULL)
2489 WRAPPER_NO_CONTRACT;
2491 return AllocateObjRefPtrsInLargeTable(nRequested, ppLazyAllocate);
2494 OBJECTREF* AllocateStaticFieldObjRefPtrsCrossDomain(int nRequested, OBJECTREF** ppLazyAllocate = NULL)
2496 WRAPPER_NO_CONTRACT;
2498 return AllocateObjRefPtrsInLargeTable(nRequested, ppLazyAllocate, TRUE);
2500 #endif // DACCESS_COMPILE
2502 void EnumStaticGCRefs(promote_func* fn, ScanContext* sc);
2504 DomainLocalBlock *GetDomainLocalBlock()
2506 LIMITED_METHOD_DAC_CONTRACT;
2508 return &m_sDomainLocalBlock;
2511 static SIZE_T GetOffsetOfModuleSlotsPointer()
2513 WRAPPER_NO_CONTRACT;
2515 return offsetof(AppDomain,m_sDomainLocalBlock) + DomainLocalBlock::GetOffsetOfModuleSlotsPointer();
2518 void SetupSharedStatics();
2520 //****************************************************************************************
2522 // Create a quick lookup for classes loaded into this domain based on their GUID.
2524 void InsertClassForCLSID(MethodTable* pMT, BOOL fForceInsert = FALSE);
2525 void InsertClassForCLSID(MethodTable* pMT, GUID *pGuid);
2527 #ifdef FEATURE_COMINTEROP
2529 void CacheTypeByNameWorker(const SString &ssClassName, const UINT vCacheVersion, TypeHandle typeHandle, BYTE flags, BOOL bReplaceExisting = FALSE);
2530 TypeHandle LookupTypeByNameWorker(const SString &ssClassName, UINT *pvCacheVersion, BYTE *pbFlags);
2532 // Used by COM Interop for mapping WinRT runtime class names to real types.
2533 void CacheTypeByName(const SString &ssClassName, const UINT vCacheVersion, TypeHandle typeHandle, BYTE flags, BOOL bReplaceExisting = FALSE);
2534 TypeHandle LookupTypeByName(const SString &ssClassName, UINT *pvCacheVersion, BYTE *pbFlags);
2535 PTR_MethodTable LookupTypeByGuid(const GUID & guid);
2537 #ifndef DACCESS_COMPILE
2538 inline BOOL CanCacheWinRTTypeByGuid(TypeHandle typeHandle)
2548 // Only allow caching guid/types maps for types loaded during
2549 // "normal" domain operation
2550 if (IsCompilationDomain() || (m_Stage < STAGE_OPEN))
2553 MethodTable *pMT = typeHandle.GetMethodTable();
2556 // Don't cache mscorlib-internal declarations of WinRT types.
2557 if (pMT->GetModule()->IsSystem() && pMT->IsProjectedFromWinRT())
2560 // Don't cache redirected WinRT types.
2561 if (WinRTTypeNameConverter::IsRedirectedWinRTSourceType(pMT))
2567 #endif // !DACCESS_COMPILE
2569 void CacheWinRTTypeByGuid(TypeHandle typeHandle);
2570 void GetCachedWinRTTypes(SArray<PTR_MethodTable> * pTypes, SArray<GUID> * pGuids, UINT minEpoch, UINT * pCurEpoch);
2572 // Used by COM Interop for caching WinRT factory objects.
2573 void CacheWinRTFactoryObject(MethodTable *pClassMT, OBJECTREF *refFactory, LPVOID lpCtxCookie);
2574 OBJECTREF LookupWinRTFactoryObject(MethodTable *pClassMT, LPVOID lpCtxCookie);
2575 void RemoveWinRTFactoryObjects(LPVOID pCtxCookie);
2577 MethodTable *LoadCOMClass(GUID clsid, BOOL bLoadRecord = FALSE, BOOL* pfAssemblyInReg = NULL);
2578 COMorRemotingFlag GetComOrRemotingFlag();
2579 BOOL GetPreferComInsteadOfManagedRemoting();
2580 OBJECTREF GetMissingObject(); // DispatchInfo will call function to retrieve the Missing.Value object.
2581 #endif // FEATURE_COMINTEROP
2583 #ifndef DACCESS_COMPILE
2584 MethodTable* LookupClass(REFIID iid)
2586 WRAPPER_NO_CONTRACT;
2588 MethodTable *pMT = (MethodTable*) m_clsidHash.LookupValue((UPTR) GetKeyFromGUID(&iid), (LPVOID)&iid);
2589 return (pMT == (MethodTable*) INVALIDENTRY
2593 #endif // DACCESS_COMPILE
2595 //<TODO>@todo get a better key</TODO>
2596 ULONG GetKeyFromGUID(const GUID *pguid)
2598 LIMITED_METHOD_CONTRACT;
2600 return *(ULONG *) pguid;
2603 #ifdef FEATURE_COMINTEROP
2604 ComCallWrapperCache* GetComCallWrapperCache();
2605 RCWCache *GetRCWCache()
2607 WRAPPER_NO_CONTRACT;
2611 // By separating the cache creation from the common lookup, we
2612 // can keep the (x86) EH prolog/epilog off the path.
2613 return CreateRCWCache();
2616 RCWCache *CreateRCWCache();
2618 RCWCache *GetRCWCacheNoCreate()
2620 LIMITED_METHOD_CONTRACT;
2624 RCWRefCache *GetRCWRefCache();
2626 void ResetComCallWrapperCache()
2628 LIMITED_METHOD_CONTRACT;
2629 m_pComCallWrapperCache = NULL;
2632 MethodTable* GetLicenseInteropHelperMethodTable();
2633 #endif // FEATURE_COMINTEROP
2635 //****************************************************************************************
2636 // Get the proxy for this app domain
2640 LIMITED_METHOD_CONTRACT;
2646 TPIndex GetTPIndex()
2648 LIMITED_METHOD_CONTRACT;
2652 void InitializeDomainContext(BOOL allowRedirects, LPCWSTR pwszPath, LPCWSTR pwszConfig);
2654 IUnknown *CreateFusionContext();
2656 void OverrideDefaultContextBinder(IUnknown *pOverrideBinder)
2658 LIMITED_METHOD_CONTRACT;
2660 _ASSERTE(pOverrideBinder != NULL);
2661 pOverrideBinder->AddRef();
2662 m_pFusionContext->Release();
2663 m_pFusionContext = pOverrideBinder;
2667 #ifdef FEATURE_PREJIT
2668 CorCompileConfigFlags GetNativeConfigFlags();
2669 #endif // FEATURE_PREJIT
2671 //****************************************************************************************
2672 // Create a domain context rooted at the fileName. The directory containing the file name
2673 // is the application base and the configuration file is the fileName appended with
2674 // .config. If no name is passed in then no domain is created.
2675 static AppDomain* CreateDomainContext(LPCWSTR fileName);
2677 // Sets up the current domain's fusion context based on the given exe file name
2678 // (app base & config file)
2679 void SetupExecutableFusionContext(LPCWSTR exePath);
2681 //****************************************************************************************
2682 // Manage a pool of asyncrhonous objects used to fetch assemblies. When a sink is released
2683 // it places itself back on the pool list. Only one object is kept in the pool.
2684 void SetIsUserCreatedDomain()
2686 LIMITED_METHOD_CONTRACT;
2688 m_dwFlags |= USER_CREATED_DOMAIN;
2691 BOOL IsUserCreatedDomain()
2693 LIMITED_METHOD_CONTRACT;
2695 return (m_dwFlags & USER_CREATED_DOMAIN);
2698 void SetIgnoreUnhandledExceptions()
2700 LIMITED_METHOD_CONTRACT;
2702 m_dwFlags |= IGNORE_UNHANDLED_EXCEPTIONS;
2705 BOOL IgnoreUnhandledExceptions()
2707 LIMITED_METHOD_CONTRACT;
2709 return (m_dwFlags & IGNORE_UNHANDLED_EXCEPTIONS);
2712 void SetPassiveDomain()
2714 LIMITED_METHOD_CONTRACT;
2716 m_dwFlags |= PASSIVE_DOMAIN;
2719 BOOL IsPassiveDomain()
2721 LIMITED_METHOD_CONTRACT;
2723 return (m_dwFlags & PASSIVE_DOMAIN);
2726 void SetVerificationDomain()
2728 LIMITED_METHOD_CONTRACT;
2730 m_dwFlags |= VERIFICATION_DOMAIN;
2733 BOOL IsVerificationDomain()
2735 LIMITED_METHOD_CONTRACT;
2737 return (m_dwFlags & VERIFICATION_DOMAIN);
2740 void SetIllegalVerificationDomain()
2742 LIMITED_METHOD_CONTRACT;
2744 m_dwFlags |= ILLEGAL_VERIFICATION_DOMAIN;
2747 BOOL IsIllegalVerificationDomain()
2749 LIMITED_METHOD_CONTRACT;
2751 return (m_dwFlags & ILLEGAL_VERIFICATION_DOMAIN);
2754 void SetCompilationDomain()
2756 LIMITED_METHOD_CONTRACT;
2758 m_dwFlags |= (PASSIVE_DOMAIN|COMPILATION_DOMAIN);
2761 BOOL IsCompilationDomain();
2763 PTR_CompilationDomain ToCompilationDomain()
2765 LIMITED_METHOD_CONTRACT;
2767 _ASSERTE(IsCompilationDomain());
2768 return dac_cast<PTR_CompilationDomain>(this);
2771 void SetRemotingConfigured()
2773 LIMITED_METHOD_CONTRACT;
2774 STATIC_CONTRACT_SO_TOLERANT;
2775 FastInterlockOr((ULONG*)&m_dwFlags, REMOTING_CONFIGURED_FOR_DOMAIN);
2778 BOOL IsRemotingConfigured()
2780 LIMITED_METHOD_CONTRACT;
2781 STATIC_CONTRACT_SO_TOLERANT;
2782 return m_dwFlags & REMOTING_CONFIGURED_FOR_DOMAIN;
2785 void SetOrphanedLocks()
2787 LIMITED_METHOD_CONTRACT;
2788 STATIC_CONTRACT_SO_TOLERANT;
2789 FastInterlockOr((ULONG*)&m_dwFlags, ORPHANED_LOCKS);
2792 BOOL HasOrphanedLocks()
2794 LIMITED_METHOD_CONTRACT;
2795 STATIC_CONTRACT_SO_TOLERANT;
2796 return m_dwFlags & ORPHANED_LOCKS;
2799 static void ExceptionUnwind(Frame *pFrame);
2802 void TrackADThreadEnter(Thread *pThread, Frame *pFrame);
2803 void TrackADThreadExit(Thread *pThread, Frame *pFrame);
2804 void DumpADThreadTrack();
2807 #ifndef DACCESS_COMPILE
2808 void ThreadEnter(Thread *pThread, Frame *pFrame)
2810 STATIC_CONTRACT_NOTHROW;
2811 STATIC_CONTRACT_GC_NOTRIGGER;
2814 if (LoggingOn(LF_APPDOMAIN, LL_INFO100))
2815 TrackADThreadEnter(pThread, pFrame);
2819 InterlockedIncrement((LONG*)&m_dwThreadEnterCount);
2820 LOG((LF_APPDOMAIN, LL_INFO1000, "AppDomain::ThreadEnter %p to [%d] (%8.8x) %S count %d\n",
2821 pThread,GetId().m_dwId, this,
2822 GetFriendlyNameForLogging(),GetThreadEnterCount()));
2823 #if _DEBUG_AD_UNLOAD
2824 printf("AppDomain::ThreadEnter %p to [%d] (%8.8x) %S count %d\n",
2825 pThread, GetId().m_dwId, this,
2826 GetFriendlyNameForLogging(), GetThreadEnterCount());
2831 void ThreadExit(Thread *pThread, Frame *pFrame)
2833 STATIC_CONTRACT_NOTHROW;
2834 STATIC_CONTRACT_GC_NOTRIGGER;
2837 if (LoggingOn(LF_APPDOMAIN, LL_INFO100)) {
2838 TrackADThreadExit(pThread, pFrame);
2844 result = InterlockedDecrement((LONG*)&m_dwThreadEnterCount);
2845 _ASSERTE(result >= 0);
2846 LOG((LF_APPDOMAIN, LL_INFO1000, "AppDomain::ThreadExit from [%d] (%8.8x) %S count %d\n",
2847 this, GetId().m_dwId,
2848 GetFriendlyNameForLogging(), GetThreadEnterCount()));
2850 printf("AppDomain::ThreadExit %x from [%d] (%8.8x) %S count %d\n",
2851 pThread->GetThreadId(), this, GetId().m_dwId,
2852 GetFriendlyNameForLogging(), GetThreadEnterCount());
2856 #endif // DACCESS_COMPILE
2858 ULONG GetThreadEnterCount()
2860 LIMITED_METHOD_CONTRACT;
2861 return m_dwThreadEnterCount;
2864 BOOL OnlyOneThreadLeft()
2866 LIMITED_METHOD_CONTRACT;
2867 return m_dwThreadEnterCount==1 || m_dwThreadsStillInAppDomain ==1;
2870 Context *GetDefaultContext()
2872 LIMITED_METHOD_CONTRACT;
2873 return m_pDefaultContext;
2878 LIMITED_METHOD_CONTRACT;
2879 return m_Stage >= STAGE_READYFORMANAGEDCODE;
2882 void SetAnonymouslyHostedDynamicMethodsAssembly(DomainAssembly * pDomainAssembly)
2884 LIMITED_METHOD_CONTRACT;
2885 _ASSERTE(pDomainAssembly != NULL);
2886 _ASSERTE(m_anonymouslyHostedDynamicMethodsAssembly == NULL);
2887 m_anonymouslyHostedDynamicMethodsAssembly = pDomainAssembly;
2890 DomainAssembly * GetAnonymouslyHostedDynamicMethodsAssembly()
2892 LIMITED_METHOD_CONTRACT;
2893 return m_anonymouslyHostedDynamicMethodsAssembly;
2896 static void RefTakerAcquire(AppDomain* pDomain)
2898 WRAPPER_NO_CONTRACT;
2903 FastInterlockIncrement(&pDomain->m_dwRefTakers);
2907 static void RefTakerRelease(AppDomain* pDomain)
2909 WRAPPER_NO_CONTRACT;
2913 _ASSERTE(pDomain->m_dwRefTakers);
2914 FastInterlockDecrement(&pDomain->m_dwRefTakers);
2921 BOOL IsHeldByIterator()
2923 LIMITED_METHOD_CONTRACT;
2924 return m_dwIterHolders>0;
2927 BOOL IsHeldByRefTaker()
2929 LIMITED_METHOD_CONTRACT;
2930 return m_dwRefTakers>0;
2933 void IteratorRelease()
2935 LIMITED_METHOD_CONTRACT;
2936 _ASSERTE(m_dwIterHolders);
2937 FastInterlockDecrement(&m_dwIterHolders);
2941 void IteratorAcquire()
2943 LIMITED_METHOD_CONTRACT;
2944 FastInterlockIncrement(&m_dwIterHolders);
2950 LIMITED_METHOD_DAC_CONTRACT;
2952 return m_Stage >= STAGE_ACTIVE;
2954 // Range for normal execution of code in the appdomain, currently used for
2955 // appdomain resource monitoring since we don't care to update resource usage
2956 // unless it's in these stages (as fields of AppDomain may not be valid if it's
2957 // not within these stages)
2960 LIMITED_METHOD_DAC_CONTRACT;
2962 return m_Stage >= STAGE_ACTIVE && m_Stage <= STAGE_OPEN;
2966 LIMITED_METHOD_DAC_CONTRACT;
2968 #ifdef DACCESS_COMPILE
2969 // We want to see all appdomains in SOS, even the about to be destructed ones.
2970 // There is no risk of races under DAC, so we will pretend to be unconditionally valid.
2973 return m_Stage > STAGE_CREATING;
2978 BOOL IsBeingCreated()
2980 LIMITED_METHOD_CONTRACT;
2982 return m_dwCreationHolders > 0;
2985 void IncCreationCount()
2987 LIMITED_METHOD_CONTRACT;
2989 FastInterlockIncrement(&m_dwCreationHolders);
2990 _ASSERTE(m_dwCreationHolders > 0);
2993 void DecCreationCount()
2995 LIMITED_METHOD_CONTRACT;
2997 FastInterlockDecrement(&m_dwCreationHolders);
2998 _ASSERTE(m_dwCreationHolders > -1);
3001 BOOL IsRunningIn(Thread* pThread);
3003 BOOL NotReadyForManagedCode()
3005 LIMITED_METHOD_CONTRACT;
3007 return m_Stage < STAGE_READYFORMANAGEDCODE;
3010 static void RaiseExitProcessEvent();
3011 Assembly* RaiseResourceResolveEvent(DomainAssembly* pAssembly, LPCSTR szName);
3012 DomainAssembly* RaiseTypeResolveEventThrowing(DomainAssembly* pAssembly, LPCSTR szName, ASSEMBLYREF *pResultingAssemblyRef);
3013 Assembly* RaiseAssemblyResolveEvent(AssemblySpec *pSpec, BOOL fPreBind);
3016 CrstExplicitInit m_ReflectionCrst;
3017 CrstExplicitInit m_RefClassFactCrst;
3020 EEClassFactoryInfoHashTable *m_pRefClassFactHash; // Hash table that maps a class factory info to a COM comp.
3021 #ifdef FEATURE_COMINTEROP
3022 DispIDCache *m_pRefDispIDCache;
3023 COMorRemotingFlag m_COMorRemotingFlag;
3024 OBJECTHANDLE m_hndMissing; //Handle points to Missing.Value Object which is used for [Optional] arg scenario during IDispatch CCW Call
3026 MethodTable* m_rpCLRTypes[WinMDAdapter::RedirectedTypeIndex_Count];
3028 MethodTable* LoadRedirectedType(WinMDAdapter::RedirectedTypeIndex index, WinMDAdapter::FrameworkAssemblyIndex assembly);
3029 #endif // FEATURE_COMINTEROP
3033 CrstBase *GetRefClassFactCrst()
3035 LIMITED_METHOD_CONTRACT;
3037 return &m_RefClassFactCrst;
3040 #ifndef DACCESS_COMPILE
3041 EEClassFactoryInfoHashTable* GetClassFactHash()
3043 STATIC_CONTRACT_THROWS;
3044 STATIC_CONTRACT_GC_TRIGGERS;
3045 STATIC_CONTRACT_FAULT;
3047 if (m_pRefClassFactHash != NULL) {
3048 return m_pRefClassFactHash;
3051 return SetupClassFactHash();
3053 #endif // DACCESS_COMPILE
3055 #ifdef FEATURE_COMINTEROP
3056 DispIDCache* GetRefDispIDCache()
3058 STATIC_CONTRACT_THROWS;
3059 STATIC_CONTRACT_GC_TRIGGERS;
3060 STATIC_CONTRACT_FAULT;
3062 if (m_pRefDispIDCache != NULL) {
3063 return m_pRefDispIDCache;
3066 return SetupRefDispIDCache();
3068 #endif // FEATURE_COMINTEROP
3070 PTR_LoaderHeap GetStubHeap();
3071 PTR_LoaderHeap GetLowFrequencyHeap();
3072 PTR_LoaderHeap GetHighFrequencyHeap();
3073 virtual PTR_LoaderAllocator GetLoaderAllocator();
3075 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
3076 #define ARM_ETW_ALLOC_THRESHOLD (4 * 1024 * 1024)
3077 // cache line size in ULONGLONG - 128 bytes which are 16 ULONGLONG's
3078 #define ARM_CACHE_LINE_SIZE_ULL 16
3080 inline ULONGLONG GetAllocBytes()
3082 LIMITED_METHOD_CONTRACT;
3083 ULONGLONG ullTotalAllocBytes = 0;
3085 // Ensure that m_pullAllocBytes is non-null to avoid an AV in a race between GC and AD unload.
3086 // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullAllocBytes, causing the AD unload.
3087 if(NULL != m_pullAllocBytes)
3089 for (DWORD i = 0; i < m_dwNumHeaps; i++)
3091 ullTotalAllocBytes += m_pullAllocBytes[i * ARM_CACHE_LINE_SIZE_ULL];
3094 return ullTotalAllocBytes;
3097 void RecordAllocBytes(size_t allocatedBytes, DWORD dwHeapNumber)
3099 LIMITED_METHOD_CONTRACT;
3100 _ASSERTE(dwHeapNumber < m_dwNumHeaps);
3102 // Ensure that m_pullAllocBytes is non-null to avoid an AV in a race between GC and AD unload.
3103 // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullAllocBytes, causing the AD unload.
3104 if(NULL != m_pullAllocBytes)
3106 m_pullAllocBytes[dwHeapNumber * ARM_CACHE_LINE_SIZE_ULL] += allocatedBytes;
3109 ULONGLONG ullTotalAllocBytes = GetAllocBytes();
3111 if ((ullTotalAllocBytes - m_ullLastEtwAllocBytes) >= ARM_ETW_ALLOC_THRESHOLD)
3113 m_ullLastEtwAllocBytes = ullTotalAllocBytes;
3114 FireEtwAppDomainMemAllocated((ULONGLONG)this, ullTotalAllocBytes, GetClrInstanceId());
3118 inline ULONGLONG GetSurvivedBytes()
3120 LIMITED_METHOD_CONTRACT;
3121 ULONGLONG ullTotalSurvivedBytes = 0;
3123 // Ensure that m_pullSurvivedBytes is non-null to avoid an AV in a race between GC and AD unload.
3124 // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullSurvivedBytes, causing the AD unload.
3125 if(NULL != m_pullSurvivedBytes)
3127 for (DWORD i = 0; i < m_dwNumHeaps; i++)
3129 ullTotalSurvivedBytes += m_pullSurvivedBytes[i * ARM_CACHE_LINE_SIZE_ULL];
3132 return ullTotalSurvivedBytes;
3135 void RecordSurvivedBytes(size_t promotedBytes, DWORD dwHeapNumber)
3137 WRAPPER_NO_CONTRACT;
3138 _ASSERTE(dwHeapNumber < m_dwNumHeaps);
3140 // Ensure that m_pullSurvivedBytes is non-null to avoid an AV in a race between GC and AD unload.
3141 // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullSurvivedBytes, causing the AD unload.
3142 if(NULL != m_pullSurvivedBytes)
3144 m_pullSurvivedBytes[dwHeapNumber * ARM_CACHE_LINE_SIZE_ULL] += promotedBytes;
3148 inline void ResetSurvivedBytes()
3150 LIMITED_METHOD_CONTRACT;
3152 // Ensure that m_pullSurvivedBytes is non-null to avoid an AV in a race between GC and AD unload.
3153 // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullSurvivedBytes, causing the AD unload.
3154 if(NULL != m_pullSurvivedBytes)
3156 for (DWORD i = 0; i < m_dwNumHeaps; i++)
3158 m_pullSurvivedBytes[i * ARM_CACHE_LINE_SIZE_ULL] = 0;
3163 // Return the total processor time (user and kernel) used by threads executing in this AppDomain so far.
3164 // The result is in 100ns units.
3165 ULONGLONG QueryProcessorUsage();
3167 // Add to the current count of processor time used by threads within this AppDomain. This API is called by
3168 // threads transitioning between AppDomains.
3169 void UpdateProcessorUsage(ULONGLONG ullAdditionalUsage);
3170 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
3173 static void RaiseOneExitProcessEvent_Wrapper(AppDomainIterator* pi);
3174 static void RaiseOneExitProcessEvent();
3175 size_t EstimateSize();
3176 EEClassFactoryInfoHashTable* SetupClassFactHash();
3177 #ifdef FEATURE_COMINTEROP
3178 DispIDCache* SetupRefDispIDCache();
3179 COMorRemotingFlag GetPreferComInsteadOfManagedRemotingFromConfigFile();
3180 #endif // FEATURE_COMINTEROP
3182 void InitializeDefaultDomainManager ();
3187 BOOL PostBindResolveAssembly(AssemblySpec *pPrePolicySpec,
3188 AssemblySpec *pPostPolicySpec,
3189 HRESULT hrBindResult,
3190 AssemblySpec **ppFailedSpec);
3192 #ifdef FEATURE_COMINTEROP
3194 void ReleaseRCWs(LPVOID pCtxCookie);
3198 #endif // FEATURE_COMINTEROP
3200 LPWSTR m_pwDynamicDir;
3203 void RaiseLoadingAssemblyEvent(DomainAssembly* pAssembly);
3205 friend class DomainAssembly;
3209 BOOL RaiseUnhandledExceptionEvent(OBJECTREF *pSender, OBJECTREF *pThrowable, BOOL isTerminating);
3210 BOOL HasUnhandledExceptionEventHandler();
3211 BOOL RaiseUnhandledExceptionEventNoThrow(OBJECTREF *pSender, OBJECTREF *pThrowable, BOOL isTerminating);
3213 struct RaiseUnhandled_Args
3215 AppDomain *pExceptionDomain;
3216 AppDomain *pTargetDomain;
3218 OBJECTREF *pThrowable;
3226 STAGE_READYFORMANAGEDCODE,
3229 // Don't delete the following *_DONOTUSE members and in case a new member needs to be added,
3230 // add it at the end. The reason is that debugger stuff has its own copy of this enum and
3231 // it can use the members that are marked as *_DONOTUSE here when debugging older version
3233 STAGE_UNLOAD_REQUESTED_DONOTUSE,
3234 STAGE_EXITING_DONOTUSE,
3235 STAGE_EXITED_DONOTUSE,
3236 STAGE_FINALIZING_DONOTUSE,
3237 STAGE_FINALIZED_DONOTUSE,
3238 STAGE_HANDLETABLE_NOACCESS_DONOTUSE,
3239 STAGE_CLEARED_DONOTUSE,
3240 STAGE_COLLECTED_DONOTUSE,
3241 STAGE_CLOSED_DONOTUSE
3243 void SetStage(Stage stage)
3253 STRESS_LOG2(LF_APPDOMAIN, LL_INFO100,"Updating AD stage, ADID=%d, stage=%d\n",GetId().m_dwId,stage);
3254 TESTHOOKCALL(AppDomainStageChanged(GetId().m_dwId,m_Stage,stage));
3255 Stage lastStage=m_Stage;
3256 while (lastStage !=stage)
3257 lastStage = (Stage)FastInterlockCompareExchange((LONG*)&m_Stage,stage,lastStage);
3259 void ClearGCRoots();
3260 void UnwindThreads();
3261 // Return TRUE if EE is stopped
3262 // Return FALSE if more work is needed
3263 BOOL StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnloadRequestThread);
3265 AppDomainLoaderAllocator m_LoaderAllocator;
3267 // List of unloaded LoaderAllocators, protected by code:GetLoaderAllocatorReferencesLock (for now)
3268 LoaderAllocator * m_pDelayedLoaderAllocatorUnloadList;
3272 // Register the loader allocator for deletion in code:ShutdownFreeLoaderAllocators.
3273 void RegisterLoaderAllocatorForDeletion(LoaderAllocator * pLoaderAllocator);
3276 void SetGCRefPoint(int gccounter)
3278 LIMITED_METHOD_CONTRACT;
3279 m_LoaderAllocator.SetGCRefPoint(gccounter);
3283 LIMITED_METHOD_CONTRACT;
3284 return m_LoaderAllocator.GetGCRefPoint();
3287 static USHORT GetOffsetOfId()
3289 LIMITED_METHOD_CONTRACT;
3290 size_t ofs = offsetof(class AppDomain, m_dwId);
3291 _ASSERTE(FitsInI2(ofs));
3296 void AddMemoryPressure();
3297 void RemoveMemoryPressure();
3299 void UnlinkClass(MethodTable *pMT);
3301 Assembly *GetRootAssembly()
3303 LIMITED_METHOD_CONTRACT;
3304 return m_pRootAssembly;
3307 #ifndef DACCESS_COMPILE
3308 void SetRootAssembly(Assembly *pAssembly)
3310 LIMITED_METHOD_CONTRACT;
3311 m_pRootAssembly = pAssembly;
3316 SString m_friendlyName;
3317 PTR_Assembly m_pRootAssembly;
3319 // General purpose flags.
3322 // When an application domain is created the ref count is artifically incremented
3323 // by one. For it to hit zero an explicit close must have happened.
3324 LONG m_cRef; // Ref count.
3326 OBJECTHANDLE m_ExposedObject;
3328 #ifdef FEATURE_LOADER_OPTIMIZATION
3329 // Indicates where assemblies will be loaded for
3330 // this domain. By default all assemblies are loaded into the domain.
3331 // There are two additional settings, all
3332 // assemblies can be loaded into the shared domain or assemblies
3333 // that are strong named are loaded into the shared area.
3334 SharePolicy m_SharePolicy;
3337 IUnknown *m_pComIPForExposedObject;
3339 // Hash table that maps a clsid to a type
3340 PtrHashMap m_clsidHash;
3342 #ifdef FEATURE_COMINTEROP
3343 // Hash table that maps WinRT class names to MethodTables.
3344 PTR_NameToTypeMapTable m_pNameToTypeMap;
3345 UINT m_vNameToTypeMapVersion;
3347 UINT m_nEpoch; // incremented each time m_pNameToTypeMap is enumerated
3349 // Hash table that remembers the last cached WinRT factory object per type per appdomain.
3350 WinRTFactoryCache *m_pWinRTFactoryCache;
3352 // The wrapper cache for this domain - it has its own CCacheLineAllocator on a per domain basis
3353 // to allow the domain to go away and eventually kill the memory when all refs are gone
3354 ComCallWrapperCache *m_pComCallWrapperCache;
3356 // this cache stores the RCWs in this domain
3357 RCWCache *m_pRCWCache;
3359 // this cache stores the RCW -> CCW references in this domain
3360 RCWRefCache *m_pRCWRefCache;
3362 // The method table used for LicenseInteropHelper
3363 MethodTable* m_pLicenseInteropHelperMT;
3364 #endif // FEATURE_COMINTEROP
3366 AssemblySink* m_pAsyncPool; // asynchronous retrival object pool (only one is kept)
3368 // The index of this app domain among existing app domains (starting from 1)
3371 // The thread-pool index of this app domain among existing app domains (starting from 1)
3374 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
3375 ULONGLONG* m_pullAllocBytes;
3376 ULONGLONG* m_pullSurvivedBytes;
3378 ULONGLONG m_ullLastEtwAllocBytes;
3379 // Total processor time (user and kernel) utilized by threads running in this AppDomain so far. May not
3380 // account for threads currently executing in the AppDomain until a call to QueryProcessorUsage() is
3382 Volatile<ULONGLONG> m_ullTotalProcessorUsage;
3383 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
3386 struct ThreadTrackInfo;
3387 typedef CDynArray<ThreadTrackInfo *> ThreadTrackInfoList;
3388 ThreadTrackInfoList *m_pThreadTrackInfoList;
3389 DWORD m_TrackSpinLock;
3393 // IL stub cache with fabricated MethodTable parented by a random module in this AD.
3394 ILStubCache m_ILStubCache;
3396 // The number of times we have entered this AD
3397 ULONG m_dwThreadEnterCount;
3398 // The number of threads that have entered this AD, for ADU only
3399 ULONG m_dwThreadsStillInAppDomain;
3401 Volatile<Stage> m_Stage;
3403 // The default context for this domain
3404 Context *m_pDefaultContext;
3406 ArrayList m_failedAssemblies;
3408 DomainAssembly * m_anonymouslyHostedDynamicMethodsAssembly;
3411 Volatile<LONG> m_dwIterHolders;
3412 Volatile<LONG> m_dwRefTakers;
3413 Volatile<LONG> m_dwCreationHolders;
3417 // DAC iterator for failed assembly loads
3419 class FailedAssemblyIterator
3421 ArrayList::Iterator m_i;
3426 WRAPPER_NO_CONTRACT;
3429 FailedAssembly *GetFailedAssembly()
3431 WRAPPER_NO_CONTRACT;
3432 return dac_cast<PTR_FailedAssembly>(m_i.GetElement());
3436 WRAPPER_NO_CONTRACT;
3437 return m_i.GetIndex();
3441 friend class AppDomain;
3442 // Cannot have constructor so this iterator can be used inside a union
3443 static FailedAssemblyIterator Create(AppDomain *pDomain)
3445 WRAPPER_NO_CONTRACT;
3446 FailedAssemblyIterator i;
3448 i.m_i = pDomain->m_failedAssemblies.Iterate();
3452 friend class FailedAssemblyIterator;
3454 FailedAssemblyIterator IterateFailedAssembliesEx()
3456 WRAPPER_NO_CONTRACT;
3457 return FailedAssemblyIterator::Create(this);
3460 //---------------------------------------------------------
3461 // Stub caches for Method stubs
3462 //---------------------------------------------------------
3467 Volatile<BOOL> m_fIsBindingModelLocked;
3469 BOOL IsHostAssemblyResolverInUse();
3470 BOOL IsBindingModelLocked();
3471 BOOL LockBindingModel();
3473 ILStubCache* GetILStubCache()
3475 LIMITED_METHOD_CONTRACT;
3476 return &m_ILStubCache;
3479 static AppDomain* GetDomain(ILStubCache* pILStubCache)
3481 return CONTAINING_RECORD(pILStubCache, AppDomain, m_ILStubCache);
3485 CONTEXT_INITIALIZED = 0x0001,
3486 USER_CREATED_DOMAIN = 0x0002, // created by call to AppDomain.CreateDomain
3487 ALLOCATEDCOM = 0x0008,
3488 LOAD_SYSTEM_ASSEMBLY_EVENT_SENT = 0x0040,
3489 REMOTING_CONFIGURED_FOR_DOMAIN = 0x0100,
3490 COMPILATION_DOMAIN = 0x0400, // Are we ngenning?
3491 ORPHANED_LOCKS = 0x1000, // Orphaned locks exist in this appdomain.
3492 PASSIVE_DOMAIN = 0x2000, // Can we execute code in this AppDomain
3493 VERIFICATION_DOMAIN = 0x4000, // This is a verification domain
3494 ILLEGAL_VERIFICATION_DOMAIN = 0x8000, // This can't be a verification domain
3495 IGNORE_UNHANDLED_EXCEPTIONS = 0x10000, // AppDomain was created using the APPDOMAIN_IGNORE_UNHANDLED_EXCEPTIONS flag
3496 ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP = 0x20000, // AppDomain was created using the APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP flag
3497 ENABLE_SKIP_PLAT_CHECKS = 0x200000, // Skip various assembly checks (like platform check)
3498 ENABLE_ASSEMBLY_LOADFILE = 0x400000, // Allow Assembly.LoadFile in CoreCLR
3499 DISABLE_TRANSPARENCY_ENFORCEMENT= 0x800000, // Disable enforcement of security transparency rules
3502 AssemblySpecBindingCache m_AssemblyCache;
3503 DomainAssemblyCache m_UnmanagedCache;
3504 size_t m_MemoryPressure;
3506 ArrayList m_NativeDllSearchDirectories;
3507 BOOL m_ReversePInvokeCanEnter;
3508 bool m_ForceTrivialWaitOperations;
3512 BOOL IsImageFromTrustedPath(PEImage* pImage);
3514 #ifdef FEATURE_TYPEEQUIVALENCE
3516 VolatilePtr<TypeEquivalenceHashTable> m_pTypeEquivalenceTable;
3517 CrstExplicitInit m_TypeEquivalenceCrst;
3519 TypeEquivalenceHashTable * GetTypeEquivalenceCache();
3524 #ifdef DACCESS_COMPILE
3526 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
3530 #ifdef FEATURE_MULTICOREJIT
3533 MulticoreJitManager m_MulticoreJitManager;
3536 MulticoreJitManager & GetMulticoreJitManager()
3538 LIMITED_METHOD_CONTRACT;
3540 return m_MulticoreJitManager;
3545 #if defined(FEATURE_TIERED_COMPILATION)
3548 TieredCompilationManager * GetTieredCompilationManager()
3550 LIMITED_METHOD_CONTRACT;
3551 return &m_tieredCompilationManager;
3555 TieredCompilationManager m_tieredCompilationManager;
3559 #ifdef FEATURE_COMINTEROP
3563 #endif //FEATURE_COMINTEROP
3568 // This is the root-level default load context root binder. If null, then
3569 // the Fusion binder is used; otherwise this binder is used.
3570 ReleaseHolder<ICLRPrivBinder> m_pLoadContextHostBinder;
3572 // -------------------------
3574 // The shared and designer context binders are ONLY to be used in tool
3575 // scenarios. There are known issues where use of these binders will
3576 // cause application crashes, and interesting behaviors.
3577 // -------------------------
3579 // This is the default designer shared context root binder.
3580 // This is used as the parent binder for ImmersiveDesignerContextBinders
3581 ReleaseHolder<ICLRPrivBinder> m_pSharedContextHostBinder;
3583 // This is the current context root binder.
3584 // Normally, this variable is immutable for appdomain lifetime, but in designer scenarios
3585 // it may be replaced by designer context binders
3586 Volatile<ICLRPrivBinder *> m_pCurrentContextHostBinder;
3589 // Returns the current hosted binder, or null if none available.
3591 ICLRPrivBinder * GetCurrentLoadContextHostBinder() const
3593 LIMITED_METHOD_CONTRACT;
3594 return m_pCurrentContextHostBinder;
3597 // Returns the shared context binder, or null if none available.
3599 ICLRPrivBinder * GetSharedContextHostBinder() const
3601 LIMITED_METHOD_CONTRACT;
3602 return m_pSharedContextHostBinder;
3605 // Returns the load context binder, or null if none available.
3607 ICLRPrivBinder * GetLoadContextHostBinder() const
3609 LIMITED_METHOD_CONTRACT;
3610 return m_pLoadContextHostBinder;
3613 #ifndef DACCESS_COMPILE
3615 // This is only called from the ImmersiveDesignerContext code
3616 // It is protected with a managed monitor lock
3618 void SetSharedContextHostBinder(ICLRPrivBinder * pBinder)
3620 LIMITED_METHOD_CONTRACT;
3622 m_pSharedContextHostBinder = pBinder;
3625 // This is called from CorHost2's implementation of ICLRPrivRuntime::CreateAppDomain.
3626 // Should only be called during AppDomain creation.
3628 void SetLoadContextHostBinder(ICLRPrivBinder * pBinder)
3630 LIMITED_METHOD_CONTRACT;
3632 m_pLoadContextHostBinder = m_pCurrentContextHostBinder = pBinder;
3636 void SetCurrentContextHostBinder(ICLRPrivBinder * pBinder)
3645 LockHolder lh(this);
3647 #ifdef FEATURE_COMINTEROP
3648 if (m_pNameToTypeMap != nullptr)
3650 delete m_pNameToTypeMap;
3651 m_pNameToTypeMap = nullptr;
3654 m_vNameToTypeMapVersion++;
3657 m_pCurrentContextHostBinder = pBinder;
3660 #endif // DACCESS_COMPILE
3662 // Indicates that a hosted binder is present.
3664 bool HasLoadContextHostBinder()
3666 LIMITED_METHOD_CONTRACT;
3667 return m_pLoadContextHostBinder != nullptr;
3670 class ComInterfaceReleaseList
3672 SArray<IUnknown *> m_objects;
3674 ~ComInterfaceReleaseList()
3676 WRAPPER_NO_CONTRACT;
3678 for (COUNT_T i = 0; i < m_objects.GetCount(); i++)
3680 IUnknown *pItf = *(m_objects.GetElements() + i);
3681 if (pItf != nullptr)
3686 // Append to the list of object to free. Only use under the AppDomain "LockHolder(pAppDomain)"
3687 void Append(IUnknown *pInterfaceToRelease)
3689 WRAPPER_NO_CONTRACT;
3690 m_objects.Append(pInterfaceToRelease);
3692 } AppDomainInterfaceReleaseList;
3695 //-----------------------------------------------------------
3696 // Static ICLRPrivAssembly -> DomainAssembly mapping functions.
3697 // This map does not maintain a reference count to either key or value.
3698 // PEFile maintains a reference count on the ICLRPrivAssembly through its code:PEFile::m_pHostAssembly field.
3699 // It is removed from this hash table by code:DomainAssembly::~DomainAssembly.
3700 struct HostAssemblyHashTraits : public DefaultSHashTraits<PTR_DomainAssembly>
3703 typedef PTR_ICLRPrivAssembly key_t;
3705 static key_t GetKey(element_t const & elem)
3707 STATIC_CONTRACT_WRAPPER;
3708 return elem->GetFile()->GetHostAssembly();
3711 static BOOL Equals(key_t key1, key_t key2)
3713 LIMITED_METHOD_CONTRACT;
3714 return dac_cast<TADDR>(key1) == dac_cast<TADDR>(key2);
3717 static count_t Hash(key_t key)
3719 STATIC_CONTRACT_LIMITED_METHOD;
3720 //return reinterpret_cast<count_t>(dac_cast<TADDR>(key));
3721 return (count_t)(dac_cast<TADDR>(key));
3724 static element_t Null() { return NULL; }
3725 static element_t Deleted() { return (element_t)(TADDR)-1; }
3726 static bool IsNull(const element_t & e) { return e == NULL; }
3727 static bool IsDeleted(const element_t & e) { return dac_cast<TADDR>(e) == (TADDR)-1; }
3730 struct OriginalFileHostAssemblyHashTraits : public HostAssemblyHashTraits
3733 static key_t GetKey(element_t const & elem)
3735 STATIC_CONTRACT_WRAPPER;
3736 return elem->GetOriginalFile()->GetHostAssembly();
3740 typedef SHash<HostAssemblyHashTraits> HostAssemblyMap;
3741 typedef SHash<OriginalFileHostAssemblyHashTraits> OriginalFileHostAssemblyMap;
3742 HostAssemblyMap m_hostAssemblyMap;
3743 OriginalFileHostAssemblyMap m_hostAssemblyMapForOrigFile;
3744 CrstExplicitInit m_crstHostAssemblyMap;
3745 // Lock to serialize all Add operations (in addition to the "read-lock" above)
3746 CrstExplicitInit m_crstHostAssemblyMapAdd;
3749 // Returns DomainAssembly.
3750 PTR_DomainAssembly FindAssembly(PTR_ICLRPrivAssembly pHostAssembly);
3752 #ifndef DACCESS_COMPILE
3754 friend void DomainAssembly::Allocate();
3755 friend DomainAssembly::~DomainAssembly();
3757 // Called from DomainAssembly::Begin.
3758 void PublishHostedAssembly(
3759 DomainAssembly* pAssembly);
3761 // Called from DomainAssembly::UpdatePEFile.
3762 void UpdatePublishHostedAssembly(
3763 DomainAssembly* pAssembly,
3766 // Called from DomainAssembly::~DomainAssembly
3767 void UnPublishHostedAssembly(
3768 DomainAssembly* pAssembly);
3769 #endif // DACCESS_COMPILE
3771 #ifdef FEATURE_PREJIT
3772 friend void DomainFile::InsertIntoDomainFileWithNativeImageList();
3773 Volatile<DomainFile *> m_pDomainFileWithNativeImageList;
3775 DomainFile *GetDomainFilesWithNativeImagesList()
3777 LIMITED_METHOD_CONTRACT;
3778 return m_pDomainFileWithNativeImageList;
3781 }; // class AppDomain
3784 // This holder is to be used to take a reference to make sure AppDomain* is still valid
3785 // Please do not use if you are aleady ADU-safe
3786 typedef Wrapper<AppDomain*,AppDomain::RefTakerAcquire,AppDomain::RefTakerRelease,NULL> AppDomainRefTaker;
3788 // Just a ref holder
3789 typedef ReleaseHolder<AppDomain> AppDomainRefHolder;
3791 typedef VPTR(class SystemDomain) PTR_SystemDomain;
3793 class SystemDomain : public BaseDomain
3795 friend class AppDomainNative;
3796 friend class AppDomainIterator;
3797 friend class UnsafeAppDomainIterator;
3798 friend class ClrDataAccess;
3799 friend Frame *Thread::IsRunningIn(AppDomain* pDomain, int *count);
3801 VPTR_VTABLE_CLASS(SystemDomain, BaseDomain)
3802 VPTR_UNIQUE(VPTR_UNIQUE_SystemDomain)
3803 static AppDomain *GetAppDomainAtId(ADID indx);
3806 static PTR_LoaderAllocator GetGlobalLoaderAllocator();
3807 virtual PTR_LoaderAllocator GetLoaderAllocator() { WRAPPER_NO_CONTRACT; return GetGlobalLoaderAllocator(); }
3808 static AppDomain* GetAppDomainFromId(ADID indx,DWORD ADValidityKind)
3818 if (indx.m_dwId==DefaultADID)
3819 pRetVal= SystemDomain::System()->DefaultDomain();
3821 pRetVal= GetAppDomainAtId(indx);
3823 // Only call CheckADValidity in DEBUG builds for non-NULL return values
3824 if (pRetVal != NULL)
3825 CheckADValidity(pRetVal, ADValidityKind);
3829 //****************************************************************************************
3831 // To be run during the initial start up of the EE. This must be
3832 // performed prior to any class operations.
3833 static void Attach();
3835 //****************************************************************************************
3837 // To be run during shutdown. This must be done after all operations
3838 // that require the use of system classes (i.e., exceptions).
3839 // DetachBegin stops all domains, while DetachEnd deallocates domain resources.
3840 static void DetachBegin();
3842 //****************************************************************************************
3844 // To be run during shutdown. This must be done after all operations
3845 // that require the use of system classes (i.e., exceptions).
3846 // DetachBegin stops release resources held by systemdomain and the default domain.
3847 static void DetachEnd();
3849 //****************************************************************************************
3851 // Initializes and shutdowns the single instance of the SystemDomain
3853 #ifndef DACCESS_COMPILE
3854 void *operator new(size_t size, void *pInPlace);
3855 void operator delete(void *pMem);
3860 static void LazyInitGlobalStringLiteralMap();
3862 //****************************************************************************************
3864 // Load the base system classes, these classes are required before
3865 // any other classes are loaded
3866 void LoadBaseSystemClasses();
3868 AppDomain* DefaultDomain()
3870 LIMITED_METHOD_DAC_CONTRACT;
3872 return m_pDefaultDomain;
3875 // Notification when an assembly is loaded into the system domain
3876 void OnAssemblyLoad(Assembly *assem);
3878 //****************************************************************************************
3880 // Global Static to get the one and only system domain
3881 static SystemDomain * System()
3883 LIMITED_METHOD_DAC_CONTRACT;
3885 return m_pSystemDomain;
3888 static PEAssembly* SystemFile()
3890 WRAPPER_NO_CONTRACT;
3892 _ASSERTE(m_pSystemDomain);
3893 return System()->m_pSystemFile;
3896 static Assembly* SystemAssembly()
3898 WRAPPER_NO_CONTRACT;
3900 return System()->m_pSystemAssembly;
3903 static Module* SystemModule()
3905 WRAPPER_NO_CONTRACT;
3907 return SystemAssembly()->GetManifestModule();
3910 static BOOL IsSystemLoaded()
3912 WRAPPER_NO_CONTRACT;
3914 return System()->m_pSystemAssembly != NULL;
3917 #ifndef DACCESS_COMPILE
3918 static GlobalStringLiteralMap *GetGlobalStringLiteralMap()
3920 WRAPPER_NO_CONTRACT;
3922 if (m_pGlobalStringLiteralMap == NULL)
3924 SystemDomain::LazyInitGlobalStringLiteralMap();
3926 _ASSERTE(m_pGlobalStringLiteralMap);
3927 return m_pGlobalStringLiteralMap;
3929 static GlobalStringLiteralMap *GetGlobalStringLiteralMapNoCreate()
3931 LIMITED_METHOD_CONTRACT;
3933 _ASSERTE(m_pGlobalStringLiteralMap);
3934 return m_pGlobalStringLiteralMap;
3936 #endif // DACCESS_COMPILE
3938 static void ActivateApplication(int *pReturnValue);
3940 static void InitializeDefaultDomain(BOOL allowRedirects, ICLRPrivBinder * pBinder = NULL);
3941 static void SetupDefaultDomain();
3942 static HRESULT SetupDefaultDomainNoThrow();
3944 #if defined(FEATURE_COMINTEROP_APARTMENT_SUPPORT) && !defined(CROSSGEN_COMPILE)
3945 static Thread::ApartmentState GetEntryPointThreadAptState(IMDInternalImport* pScope, mdMethodDef mdMethod);
3946 static void SetThreadAptState(Thread::ApartmentState state);
3948 static BOOL SetGlobalSharePolicyUsingAttribute(IMDInternalImport* pScope, mdMethodDef mdMethod);
3951 //****************************************************************************************
3953 // Use an already exising & inited Application Domain (e.g. a subclass).
3954 static void LoadDomain(AppDomain *pDomain);
3956 //****************************************************************************************
3957 // Methods used to get the callers module and hence assembly and app domain.
3958 __declspec(deprecated("This method is deprecated, use the version that takes a StackCrawlMark instead"))
3959 static Module* GetCallersModule(int skip);
3960 static MethodDesc* GetCallersMethod(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
3961 static MethodTable* GetCallersType(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
3962 static Module* GetCallersModule(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
3963 static Assembly* GetCallersAssembly(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
3965 static bool IsReflectionInvocationMethod(MethodDesc* pMeth);
3967 #ifndef DACCESS_COMPILE
3968 //****************************************************************************************
3969 // Returns the domain associated with the current context. (this can only be a child domain)
3970 static inline AppDomain * GetCurrentDomain()
3972 WRAPPER_NO_CONTRACT;
3973 return ::GetAppDomain();
3975 #endif //!DACCESS_COMPILE
3977 #ifdef DEBUGGING_SUPPORTED
3978 //****************************************************************************************
3979 // Debugger/Publisher helper function to indicate creation of new app domain to debugger
3980 // and publishing it in the IPC block
3981 static void PublishAppDomainAndInformDebugger (AppDomain *pDomain);
3982 #endif // DEBUGGING_SUPPORTED
3984 //****************************************************************************************
3985 // Helper function to remove a domain from the system
3986 BOOL RemoveDomain(AppDomain* pDomain); // Does not decrement the reference
3988 #ifdef PROFILING_SUPPORTED
3989 //****************************************************************************************
3990 // Tell profiler about system created domains which are created before the profiler is
3991 // actually activated.
3992 static void NotifyProfilerStartup();
3994 //****************************************************************************************
3995 // Tell profiler at shutdown that system created domains are going away. They are not
3996 // torn down using the normal sequence.
3997 static HRESULT NotifyProfilerShutdown();
3998 #endif // PROFILING_SUPPORTED
4000 //****************************************************************************************
4001 // return the dev path
4003 #ifndef DACCESS_COMPILE
4004 void IncrementNumAppDomains ()
4006 LIMITED_METHOD_CONTRACT;
4011 void DecrementNumAppDomains ()
4013 LIMITED_METHOD_CONTRACT;
4018 ULONG GetNumAppDomains ()
4020 LIMITED_METHOD_CONTRACT;
4022 return s_dNumAppDomains;
4024 #endif // DACCESS_COMPILE
4027 // AppDomains currently have both an index and an ID. The
4028 // index is "densely" assigned; indices are reused as domains
4029 // are unloaded. The Id's on the other hand, are not reclaimed
4030 // so may be sparse.
4032 // Another important difference - it's OK to call GetAppDomainAtId for
4033 // an unloaded domain (it will return NULL), while GetAppDomainAtIndex
4034 // will assert if the domain is unloaded.
4037 // I'm not really happy with this situation, but
4038 // (a) we need an ID for a domain which will last the process lifetime for the
4040 // (b) we need a dense ID, for the handle table index.
4041 // So for now, I'm leaving both, but hopefully in the future we can come up
4042 // with something better.
4045 static ADIndex GetNewAppDomainIndex(AppDomain * pAppDomain);
4046 static void ReleaseAppDomainIndex(ADIndex indx);
4047 static PTR_AppDomain GetAppDomainAtIndex(ADIndex indx);
4048 static PTR_AppDomain TestGetAppDomainAtIndex(ADIndex indx);
4049 static DWORD GetCurrentAppDomainMaxIndex()
4051 WRAPPER_NO_CONTRACT;
4053 ArrayListStatic* list = (ArrayListStatic *)&m_appDomainIndexList;
4054 PREFIX_ASSUME(list!=NULL);
4055 return list->GetCount();
4058 static ADID GetNewAppDomainId(AppDomain *pAppDomain);
4059 static void ReleaseAppDomainId(ADID indx);
4061 #ifndef DACCESS_COMPILE
4062 static ADID GetCurrentAppDomainMaxId() { ADID id; id.m_dwId=m_appDomainIdList.GetCount(); return id;}
4063 #endif // DACCESS_COMPILE
4066 #ifndef DACCESS_COMPILE
4067 DWORD RequireAppDomainCleanup()
4069 LIMITED_METHOD_CONTRACT;
4070 return m_pDelayedUnloadListOfLoaderAllocators != 0;
4073 void AddToDelayedUnloadList(LoaderAllocator * pAllocator)
4083 CrstHolder lh(&m_DelayedUnloadCrst);
4084 pAllocator->m_pLoaderAllocatorDestroyNext=m_pDelayedUnloadListOfLoaderAllocators;
4085 m_pDelayedUnloadListOfLoaderAllocators=pAllocator;
4087 int iGCRefPoint=GCHeapUtilities::GetGCHeap()->CollectionCount(GCHeapUtilities::GetGCHeap()->GetMaxGeneration());
4088 if (GCHeapUtilities::IsGCInProgress())
4090 pAllocator->SetGCRefPoint(iGCRefPoint);
4093 void ProcessDelayedUnloadLoaderAllocators();
4095 static void EnumAllStaticGCRefs(promote_func* fn, ScanContext* sc);
4097 #endif // DACCESS_COMPILE
4099 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
4100 // The *AD* methods are what we got from tracing through EE roots.
4101 // RecordTotalSurvivedBytes is the total promoted from a GC.
4102 static void ResetADSurvivedBytes();
4103 static ULONGLONG GetADSurvivedBytes();
4104 static void RecordTotalSurvivedBytes(size_t totalSurvivedBytes);
4105 static ULONGLONG GetTotalSurvivedBytes()
4107 LIMITED_METHOD_CONTRACT;
4108 return m_totalSurvivedBytes;
4110 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
4112 //****************************************************************************************
4113 // Routines to deal with the base library (currently mscorlib.dll)
4114 LPCWSTR BaseLibrary()
4116 WRAPPER_NO_CONTRACT;
4118 return m_BaseLibrary;
4121 #ifndef DACCESS_COMPILE
4122 BOOL IsBaseLibrary(SString &path)
4124 WRAPPER_NO_CONTRACT;
4126 // See if it is the installation path to mscorlib
4127 if (path.EqualsCaseInsensitive(m_BaseLibrary, PEImage::GetFileSystemLocale()))
4130 // Or, it might be the GAC location of mscorlib
4131 if (System()->SystemAssembly() != NULL
4132 && path.EqualsCaseInsensitive(System()->SystemAssembly()->GetManifestFile()->GetPath(),
4133 PEImage::GetFileSystemLocale()))
4139 BOOL IsBaseLibrarySatellite(SString &path)
4141 WRAPPER_NO_CONTRACT;
4143 // See if it is the installation path to mscorlib.resources
4144 SString s(SString::Ascii,g_psBaseLibrarySatelliteAssemblyName);
4145 if (path.EqualsCaseInsensitive(s, PEImage::GetFileSystemLocale()))
4148 // workaround! Must implement some code to do this string comparison for
4149 // mscorlib.resources in a culture-specific directory in the GAC.
4152 // Or, it might be the GAC location of mscorlib.resources
4153 if (System()->SystemAssembly() != NULL
4154 && path.EqualsCaseInsensitive(System()->SystemAssembly()->GetManifestFile()->GetPath(),
4155 PEImage::GetFileSystemLocale()))
4161 #endif // DACCESS_COMPILE
4163 // Return the system directory
4164 LPCWSTR SystemDirectory()
4166 WRAPPER_NO_CONTRACT;
4168 return m_SystemDirectory;
4173 //****************************************************************************************
4174 // Helper function to create the single COM domain
4175 void CreateDefaultDomain();
4177 //****************************************************************************************
4178 // Helper function to add a domain to the global list
4179 void AddDomain(AppDomain* pDomain);
4181 void CreatePreallocatedExceptions();
4183 void PreallocateSpecialObjects();
4185 //****************************************************************************************
4187 static StackWalkAction CallersMethodCallback(CrawlFrame* pCrawlFrame, VOID* pClientData);
4188 static StackWalkAction CallersMethodCallbackWithStackMark(CrawlFrame* pCrawlFrame, VOID* pClientData);
4190 #ifndef DACCESS_COMPILE
4191 // This class is not to be created through normal allocation.
4194 STANDARD_VM_CONTRACT;
4196 m_pDefaultDomain = NULL;
4197 m_pDelayedUnloadListOfLoaderAllocators=NULL;
4199 m_GlobalAllocator.Init(this);
4203 PTR_PEAssembly m_pSystemFile; // Single assembly (here for quicker reference);
4204 PTR_Assembly m_pSystemAssembly; // Single assembly (here for quicker reference);
4205 PTR_AppDomain m_pDefaultDomain; // Default domain for COM+ classes exposed through IClassFactory.
4207 GlobalLoaderAllocator m_GlobalAllocator;
4210 InlineSString<100> m_BaseLibrary;
4212 InlineSString<100> m_SystemDirectory;
4217 BOOL m_fDevpath; // have we searched the environment
4219 // <TODO>@TODO: CTS, we can keep the com modules in a single assembly or in different assemblies.
4220 // We are currently using different assemblies but this is potentitially to slow...</TODO>
4222 // Global domain that every one uses
4223 SPTR_DECL(SystemDomain, m_pSystemDomain);
4225 LoaderAllocator * m_pDelayedUnloadListOfLoaderAllocators;
4227 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
4228 // This is what gets promoted for the whole GC heap.
4229 static size_t m_totalSurvivedBytes;
4230 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
4232 SVAL_DECL(ArrayListStatic, m_appDomainIndexList);
4233 #ifndef DACCESS_COMPILE
4234 static CrstStatic m_DelayedUnloadCrst;
4235 static CrstStatic m_SystemDomainCrst;
4238 static ArrayListStatic m_appDomainIdList;
4240 static GlobalStringLiteralMap *m_pGlobalStringLiteralMap;
4242 static ULONG s_dNumAppDomains; // Maintain a count of children app domains.
4244 static DWORD m_dwLowestFreeIndex;
4245 #endif // DACCESS_COMPILE
4249 // These flags let the correct native image of mscorlib to be loaded.
4250 // This is important for hardbinding to it
4252 SVAL_DECL(BOOL, s_fForceDebug);
4253 SVAL_DECL(BOOL, s_fForceProfiling);
4254 SVAL_DECL(BOOL, s_fForceInstrument);
4257 static void SetCompilationOverrides(BOOL fForceDebug,
4258 BOOL fForceProfiling,
4259 BOOL fForceInstrument);
4261 static void GetCompilationOverrides(BOOL * fForceDebug,
4262 BOOL * fForceProfiling,
4263 BOOL * fForceInstrument);
4265 //****************************************************************************************
4268 #ifndef DACCESS_COMPILE
4270 inline static BOOL IsUnderDomainLock() { LIMITED_METHOD_CONTRACT; return m_SystemDomainCrst.OwnedByCurrentThread();};
4273 // This lock controls adding and removing domains from the system domain
4274 class LockHolder : public CrstHolder
4278 : CrstHolder(&m_SystemDomainCrst)
4280 WRAPPER_NO_CONTRACT;
4283 #endif // DACCESS_COMPILE
4286 DWORD GetTotalNumSizedRefHandles();
4288 #ifdef DACCESS_COMPILE
4290 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
4294 }; // class SystemDomain
4298 // an UnsafeAppDomainIterator is used to iterate over all existing domains
4300 // The iteration is guaranteed to include all domains that exist at the
4301 // start & end of the iteration. This iterator is considered unsafe because it does not
4302 // reference count the various appdomains, and can only be used when the runtime is stopped,
4303 // or external synchronization is used. (and therefore no other thread may cause the appdomain list to change.)
4305 class UnsafeAppDomainIterator
4307 friend class SystemDomain;
4309 UnsafeAppDomainIterator(BOOL bOnlyActive)
4311 m_bOnlyActive = bOnlyActive;
4316 LIMITED_METHOD_CONTRACT;
4317 SystemDomain* sysDomain = SystemDomain::System();
4320 ArrayListStatic* list = &sysDomain->m_appDomainIndexList;
4321 PREFIX_ASSUME(list != NULL);
4322 m_i = list->Iterate();
4334 WRAPPER_NO_CONTRACT;
4338 m_pCurrent = dac_cast<PTR_AppDomain>(m_i.GetElement());
4339 if (m_pCurrent != NULL &&
4341 m_pCurrent->IsActive() : m_pCurrent->IsValid()))
4351 AppDomain * GetDomain()
4353 LIMITED_METHOD_DAC_CONTRACT;
4360 ArrayList::Iterator m_i;
4361 AppDomain * m_pCurrent;
4363 }; // class UnsafeAppDomainIterator
4366 // an AppDomainIterator is used to iterate over all existing domains.
4368 // The iteration is guaranteed to include all domains that exist at the
4369 // start & end of the iteration. Any domains added or deleted during
4370 // iteration may or may not be included. The iterator also guarantees
4371 // that the current iterated appdomain (GetDomain()) will not be deleted.
4374 class AppDomainIterator : public UnsafeAppDomainIterator
4376 friend class SystemDomain;
4379 AppDomainIterator(BOOL bOnlyActive) : UnsafeAppDomainIterator(bOnlyActive)
4381 WRAPPER_NO_CONTRACT;
4385 ~AppDomainIterator()
4387 WRAPPER_NO_CONTRACT;
4389 #ifndef DACCESS_COMPILE
4390 if (GetDomain() != NULL)
4393 GetDomain()->IteratorRelease();
4395 GetDomain()->Release();
4402 WRAPPER_NO_CONTRACT;
4404 #ifndef DACCESS_COMPILE
4405 if (GetDomain() != NULL)
4408 GetDomain()->IteratorRelease();
4410 GetDomain()->Release();
4413 SystemDomain::LockHolder lh;
4416 if (UnsafeAppDomainIterator::Next())
4418 #ifndef DACCESS_COMPILE
4419 GetDomain()->AddRef();
4421 GetDomain()->IteratorAcquire();
4429 }; // class AppDomainIterator
4431 typedef VPTR(class SharedDomain) PTR_SharedDomain;
4433 class SharedDomain : public BaseDomain
4435 VPTR_VTABLE_CLASS_AND_CTOR(SharedDomain, BaseDomain)
4439 static void Attach();
4440 static void Detach();
4442 virtual BOOL IsSharedDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; }
4443 virtual PTR_LoaderAllocator GetLoaderAllocator() { WRAPPER_NO_CONTRACT; return SystemDomain::GetGlobalLoaderAllocator(); }
4445 virtual PTR_AppDomain AsAppDomain()
4447 LIMITED_METHOD_CONTRACT;
4448 STATIC_CONTRACT_SO_TOLERANT;
4449 _ASSERTE(!"Not an AppDomain");
4453 static SharedDomain * GetDomain();
4458 // This will also set the tenured bit if and only if the add was successful,
4459 // and will make sure that the bit appears atomically set to all readers that
4460 // might be accessing the hash on another thread.
4461 MethodTable * FindIndexClass(SIZE_T index);
4463 #ifdef FEATURE_LOADER_OPTIMIZATION
4464 void AddShareableAssembly(Assembly * pAssembly);
4466 class SharedAssemblyIterator
4468 PtrHashMap::PtrIterator i;
4469 Assembly * m_pAssembly;
4472 SharedAssemblyIterator() :
4473 i(GetDomain() ? GetDomain()->m_assemblyMap.firstBucket() : NULL)
4474 { LIMITED_METHOD_DAC_CONTRACT; }
4478 WRAPPER_NO_CONTRACT;
4484 m_pAssembly = PTR_Assembly(dac_cast<TADDR>(i.GetValue()));
4489 Assembly * GetAssembly()
4491 LIMITED_METHOD_DAC_CONTRACT;
4497 friend class SharedDomain;
4500 Assembly * FindShareableAssembly(SharedAssemblyLocator * pLocator);
4501 SIZE_T GetShareableAssemblyCount();
4502 #endif //FEATURE_LOADER_OPTIMIZATION
4505 friend class SharedAssemblyIterator;
4506 friend class SharedFileLockHolder;
4507 friend class ClrDataAccess;
4509 #ifndef DACCESS_COMPILE
4510 void *operator new(size_t size, void *pInPlace);
4511 void operator delete(void *pMem);
4514 SPTR_DECL(SharedDomain, m_pSharedDomain);
4516 #ifdef FEATURE_LOADER_OPTIMIZATION
4517 PEFileListLock m_FileCreateLock;
4518 SIZE_T m_nextClassIndex;
4519 PtrHashMap m_assemblyMap;
4523 #ifdef DACCESS_COMPILE
4524 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
4528 #ifdef FEATURE_LOADER_OPTIMIZATION
4529 // Hash map comparison function`
4530 static BOOL CompareSharedAssembly(UPTR u1, UPTR u2);
4534 #ifdef FEATURE_LOADER_OPTIMIZATION
4535 class SharedFileLockHolderBase : protected HolderBase<PEFile *>
4538 PEFileListLock *m_pLock;
4539 ListLockEntry *m_pLockElement;
4541 SharedFileLockHolderBase(PEFile *value)
4542 : HolderBase<PEFile *>(value)
4544 LIMITED_METHOD_CONTRACT;
4547 m_pLockElement = NULL;
4550 #ifndef DACCESS_COMPILE
4553 STATIC_CONTRACT_THROWS;
4554 STATIC_CONTRACT_GC_TRIGGERS;
4555 STATIC_CONTRACT_FAULT;
4557 PEFileListLockHolder lockHolder(m_pLock);
4559 m_pLockElement = m_pLock->FindFileLock(m_value);
4560 if (m_pLockElement == NULL)
4562 m_pLockElement = new ListLockEntry(m_pLock, m_value);
4563 m_pLock->AddElement(m_pLockElement);
4566 m_pLockElement->AddRef();
4568 lockHolder.Release();
4570 m_pLockElement->Enter();
4575 STATIC_CONTRACT_NOTHROW;
4576 STATIC_CONTRACT_GC_TRIGGERS;
4577 STATIC_CONTRACT_FORBID_FAULT;
4579 m_pLockElement->Leave();
4580 m_pLockElement->Release();
4581 m_pLockElement = NULL;
4583 #endif // DACCESS_COMPILE
4586 class SharedFileLockHolder : public BaseHolder<PEFile *, SharedFileLockHolderBase>
4589 DEBUG_NOINLINE SharedFileLockHolder(SharedDomain *pDomain, PEFile *pFile, BOOL Take = TRUE)
4590 : BaseHolder<PEFile *, SharedFileLockHolderBase>(pFile, FALSE)
4592 STATIC_CONTRACT_THROWS;
4593 STATIC_CONTRACT_GC_TRIGGERS;
4594 STATIC_CONTRACT_FAULT;
4595 ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
4597 m_pLock = &pDomain->m_FileCreateLock;
4602 #endif // FEATURE_LOADER_OPTIMIZATION
4604 inline BOOL BaseDomain::IsDefaultDomain()
4606 LIMITED_METHOD_DAC_CONTRACT;
4607 return (SystemDomain::System()->DefaultDomain() == this);
4610 #include "comreflectioncache.inl"
4612 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
4613 // holds an extra reference so needs special Extract() and should not have SuppressRelease()
4614 // Holders/Wrappers have nonvirtual methods so cannot use them as the base class
4615 template <class AppDomainType>
4616 class AppDomainCreationHolder
4619 // disable the copy ctor
4620 AppDomainCreationHolder(const AppDomainCreationHolder<AppDomainType>&) {}
4623 AppDomainType* m_pDomain;
4625 void ReleaseAppDomainDuringCreation()
4630 WRAPPER(GC_TRIGGERS);
4631 PRECONDITION(m_bAcquired);
4632 PRECONDITION(CheckPointer(m_pDomain));
4636 if (m_pDomain->NotReadyForManagedCode())
4638 m_pDomain->Release();
4643 AppDomainCreationHolder()
4648 ~AppDomainCreationHolder()
4655 void Assign(AppDomainType* pDomain)
4662 AppDomain::RefTakerAcquire(m_pDomain);
4664 m_pDomain->IncCreationCount();
4672 _ASSERTE(m_bAcquired);
4676 m_pDomain->DecCreationCount();
4678 if(!m_pDomain->IsDefaultDomain())
4679 ReleaseAppDomainDuringCreation();
4680 AppDomain::RefTakerRelease(m_pDomain);
4685 AppDomainType* Extract()
4687 _ASSERTE(m_bAcquired);
4691 m_pDomain->DecCreationCount();
4693 AppDomain::RefTakerRelease(m_pDomain);
4699 AppDomainType* operator ->()
4701 _ASSERTE(m_bAcquired);
4705 operator AppDomainType*()
4707 _ASSERTE(m_bAcquired);
4716 #endif // !DACCESS_COMPILE && !CROSSGEN_COMPILE
4718 #define INVALID_APPDOMAIN_ID ((DWORD)-1)
4719 #define CURRENT_APPDOMAIN_ID ((ADID)(DWORD)0)