Remove superfluous 'const' qualifier from trivial return types (#20652)
[platform/upstream/coreclr.git] / src / vm / appdomain.hpp
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.
4
5 /*============================================================
6 **
7 ** Header:  AppDomain.cpp
8 ** 
9
10 **
11 ** Purpose: Implements AppDomain (loader domain) architecture
12 **
13 **
14 ===========================================================*/
15 #ifndef _APPDOMAIN_H
16 #define _APPDOMAIN_H
17
18 #include "eventtrace.h"
19 #include "assembly.hpp"
20 #include "clsload.hpp"
21 #include "eehash.h"
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"
33 #include "rejit.h"
34
35 #ifdef FEATURE_MULTICOREJIT
36 #include "multicorejit.h"
37 #endif
38
39 #ifdef FEATURE_COMINTEROP
40 #include "clrprivbinderwinrt.h"
41 #include "..\md\winmd\inc\adapter.h"
42 #include "winrttypenameconverter.h"
43 #endif // FEATURE_COMINTEROP
44
45 #include "appxutil.h"
46
47 #ifdef FEATURE_TIERED_COMPILATION
48 #include "tieredcompilation.h"
49 #include "callcounter.h"
50 #endif
51
52 #include "codeversion.h"
53
54 class BaseDomain;
55 class SystemDomain;
56 class SharedDomain;
57 class AppDomain;
58 class CompilationDomain;
59 class AppDomainEnum;
60 class AssemblySink;
61 class EEMarshalingData;
62 class Context;
63 class GlobalStringLiteralMap;
64 class StringLiteralMap;
65 class MngStdInterfacesInfo;
66 class DomainModule;
67 class DomainAssembly;
68 struct InteropMethodTableData;
69 class LoadLevelLimiter;
70 class TypeEquivalenceHashTable;
71 class StringArrayList;
72
73 extern INT64 g_PauseTime;  // Total time in millisecond the CLR has been paused
74
75 #ifdef FEATURE_COMINTEROP
76 class ComCallWrapperCache;
77 struct SimpleComCallWrapper;
78
79 class RCWRefCache;
80
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
87 };
88
89 #endif // FEATURE_COMINTEROP
90
91 #ifdef _MSC_VER
92 #pragma warning(push)
93 #pragma warning(disable : 4200) // Disable zero-sized array warning
94 #endif
95
96
97 GPTR_DECL(IdDispenser,       g_pModuleIndexDispenser);
98
99 // This enum is aligned to System.ExceptionCatcherType. 
100 enum ExceptionCatcher {
101     ExceptionCatcher_ManagedCode = 0,
102     ExceptionCatcher_AppDomainTransition = 1,
103     ExceptionCatcher_COMInterop = 2,    
104 };
105
106 // We would like *ALLOCATECLASS_FLAG to AV (in order to catch errors), so don't change it
107 struct ClassInitFlags {
108     enum
109     {
110         INITIALIZED_FLAG_BIT    = 0,
111         INITIALIZED_FLAG        = 1<<INITIALIZED_FLAG_BIT,
112         ERROR_FLAG_BIT          = 1,
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
118     };
119 };
120
121 struct DomainLocalModule
122 {
123     friend class ClrDataAccess;
124     friend class CheckAsmOffsets;
125     friend struct ThreadLocalModule;
126
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) \
130     {\
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) \
134         {\
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*))) ;\
139         }\
140         else\
141         {\
142             *(pGCStatics) = (dac_cast<DomainLocalModule::PTR_NormalDynamicEntry>(pDynamicEntry))->GetGCStaticsBasePointer();\
143         }\
144     }\
145
146 #define GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLoaderAllocator, dynamicClassInfoParam, pNonGCStatics) \
147     {\
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) \
151         {\
152             if ((dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hNonGCStatics != 0) \
153             { \
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; \
161         }\
162         else\
163         {\
164             *(pNonGCStatics) = dac_cast<DomainLocalModule::PTR_NormalDynamicEntry>(pDynamicEntry)->GetNonGCStaticsBasePointer();\
165         }\
166     }\
167
168     struct DynamicEntry
169     {
170         static DWORD GetOffsetOfDataBlob();
171     };
172     typedef DPTR(DynamicEntry) PTR_DynamicEntry;
173
174     struct CollectibleDynamicEntry : public DynamicEntry
175     {
176         LOADERHANDLE    m_hGCStatics;
177         LOADERHANDLE    m_hNonGCStatics;
178     };
179     typedef DPTR(CollectibleDynamicEntry) PTR_CollectibleDynamicEntry;
180
181     struct NormalDynamicEntry : public DynamicEntry
182     {
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 
187         SIZE_T          m_padding;
188 #endif
189         BYTE            m_pDataBlob[0];
190
191         inline PTR_BYTE GetGCStaticsBasePointer()
192         {
193             LIMITED_METHOD_CONTRACT;
194             SUPPORTS_DAC;
195             return dac_cast<PTR_BYTE>(m_pGCStatics);
196         }
197         inline PTR_BYTE GetNonGCStaticsBasePointer()
198         {
199             LIMITED_METHOD_CONTRACT
200             SUPPORTS_DAC;
201             return dac_cast<PTR_BYTE>(this);
202         }
203     };
204     typedef DPTR(NormalDynamicEntry) PTR_NormalDynamicEntry;
205
206     struct DynamicClassInfo
207     {
208         VolatilePtr<DynamicEntry, PTR_DynamicEntry>  m_pDynamicEntry;
209         Volatile<DWORD>             m_dwFlags;
210     };
211     typedef DPTR(DynamicClassInfo) PTR_DynamicClassInfo;
212     
213     inline UMEntryThunk * GetADThunkTable()
214     {
215         LIMITED_METHOD_CONTRACT
216         return m_pADThunkTable;
217     }
218
219     inline void SetADThunkTable(UMEntryThunk* pADThunkTable)
220     {
221         LIMITED_METHOD_CONTRACT
222         InterlockedCompareExchangeT(m_pADThunkTable.GetPointer(), pADThunkTable, NULL);
223     }
224
225     // Note the difference between:
226     // 
227     //  GetPrecomputedNonGCStaticsBasePointer() and
228     //  GetPrecomputedStaticsClassData()
229     //
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()
233     {
234         LIMITED_METHOD_CONTRACT
235         return dac_cast<TADDR>(this);
236     }
237
238     inline PTR_BYTE GetPrecomputedStaticsClassData()
239     {
240         LIMITED_METHOD_CONTRACT
241         return dac_cast<PTR_BYTE>(this) + offsetof(DomainLocalModule, m_pDataBlob);
242     }
243
244     static SIZE_T GetOffsetOfDataBlob() { return offsetof(DomainLocalModule, m_pDataBlob); }
245     static SIZE_T GetOffsetOfGCStaticPointer() { return offsetof(DomainLocalModule, m_pGCStatics); }
246
247     inline DomainFile* GetDomainFile()
248     {
249         LIMITED_METHOD_CONTRACT
250         SUPPORTS_DAC;
251         return m_pDomainFile;
252     }
253
254 #ifndef DACCESS_COMPILE
255     inline void        SetDomainFile(DomainFile* pDomainFile)
256     {
257         LIMITED_METHOD_CONTRACT
258         m_pDomainFile = pDomainFile;
259     }
260 #endif
261
262     inline PTR_OBJECTREF  GetPrecomputedGCStaticsBasePointer()
263     {
264         LIMITED_METHOD_CONTRACT        
265         return m_pGCStatics;
266     }
267
268     inline PTR_OBJECTREF * GetPrecomputedGCStaticsBasePointerAddress()
269     {
270         LIMITED_METHOD_CONTRACT        
271         return &m_pGCStatics;
272     }
273
274     // Returns bytes so we can add offsets
275     inline PTR_BYTE GetGCStaticsBasePointer(MethodTable * pMT)
276     {
277         WRAPPER_NO_CONTRACT
278         SUPPORTS_DAC;
279
280         if (pMT->IsDynamicStatics())
281         {
282             _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics());
283             return GetDynamicEntryGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator());
284         }
285         else
286         {
287             return dac_cast<PTR_BYTE>(m_pGCStatics);
288         }
289     }
290
291     inline PTR_BYTE GetNonGCStaticsBasePointer(MethodTable * pMT)
292     {
293         WRAPPER_NO_CONTRACT
294         SUPPORTS_DAC;
295
296         if (pMT->IsDynamicStatics())
297         {
298             _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics());
299             return GetDynamicEntryNonGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator());
300         }
301         else
302         {
303             return dac_cast<PTR_BYTE>(this);
304         }
305     }
306
307     inline DynamicClassInfo* GetDynamicClassInfo(DWORD n)
308     {
309         LIMITED_METHOD_CONTRACT
310         SUPPORTS_DAC;
311         _ASSERTE(m_pDynamicClassTable.Load() && m_aDynamicEntries > n);
312         dac_cast<PTR_DynamicEntry>(m_pDynamicClassTable[n].m_pDynamicEntry.Load());
313
314         return &m_pDynamicClassTable[n];
315     }
316
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)
320     {
321         CONTRACTL
322         {
323             NOTHROW;
324             GC_NOTRIGGER;
325             SO_TOLERANT;
326             MODE_COOPERATIVE;
327             SUPPORTS_DAC;
328         }
329         CONTRACTL_END;
330
331
332         if (n >= m_aDynamicEntries)
333         {
334             return NULL;
335         }
336         
337         DynamicClassInfo* pClassInfo = GetDynamicClassInfo(n);
338         if (!pClassInfo->m_pDynamicEntry)
339         {
340             return NULL;
341         }
342
343         PTR_BYTE retval = NULL;
344
345         GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLoaderAllocator, pClassInfo, &retval);
346
347         return retval;
348     }
349
350     inline PTR_BYTE GetDynamicEntryNonGCStaticsBasePointer(DWORD n, PTR_LoaderAllocator pLoaderAllocator)
351     {
352         CONTRACTL
353         {
354             NOTHROW;
355             GC_NOTRIGGER;
356             SO_TOLERANT;
357             MODE_COOPERATIVE;
358             SUPPORTS_DAC;
359         }
360         CONTRACTL_END;
361
362         
363         if (n >= m_aDynamicEntries)
364         {
365             return NULL;
366         }
367         
368         DynamicClassInfo* pClassInfo = GetDynamicClassInfo(n);
369         if (!pClassInfo->m_pDynamicEntry)
370         {
371             return NULL;
372         }
373
374         PTR_BYTE retval = NULL;
375
376         GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLoaderAllocator, pClassInfo, &retval);
377
378         return retval;
379     }
380
381     FORCEINLINE PTR_DynamicClassInfo GetDynamicClassInfoIfInitialized(DWORD n)
382     {
383         WRAPPER_NO_CONTRACT;
384
385         // m_aDynamicEntries is set last, it needs to be checked first
386         if (n >= m_aDynamicEntries)
387         {
388             return NULL;
389         }
390
391         _ASSERTE(m_pDynamicClassTable.Load() != NULL);
392         PTR_DynamicClassInfo pDynamicClassInfo = (PTR_DynamicClassInfo)(m_pDynamicClassTable.Load() + n);
393
394         // INITIALIZED_FLAG is set last, it needs to be checked first
395         if ((pDynamicClassInfo->m_dwFlags & ClassInitFlags::INITIALIZED_FLAG) == 0)
396         {
397             return NULL;
398         }
399
400         PREFIX_ASSUME(pDynamicClassInfo != NULL);
401         return pDynamicClassInfo;
402     }
403
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)
407     {
408         WRAPPER_NO_CONTRACT;
409         return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::INITIALIZED_FLAG) != 0;
410     }
411
412     inline BOOL IsPrecomputedClassInitialized(DWORD classID)
413     {
414         return GetPrecomputedStaticsClassData()[classID] & ClassInitFlags::INITIALIZED_FLAG;
415     }
416     
417     inline BOOL IsClassAllocated(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
418     {
419         WRAPPER_NO_CONTRACT;
420         return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::ALLOCATECLASS_FLAG) != 0;
421     }
422
423     BOOL IsClassInitError(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
424     {
425         WRAPPER_NO_CONTRACT;
426         return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::ERROR_FLAG) != 0;
427     }
428
429     void    SetClassInitialized(MethodTable* pMT);
430     void    SetClassInitError(MethodTable* pMT);
431
432     void    EnsureDynamicClassIndex(DWORD dwID);
433
434     void    AllocateDynamicClass(MethodTable *pMT);
435
436     void    PopulateClass(MethodTable *pMT);
437
438 #ifdef DACCESS_COMPILE
439     void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
440 #endif
441
442     static DWORD OffsetOfDataBlob()
443     {
444         LIMITED_METHOD_CONTRACT;
445         return offsetof(DomainLocalModule, m_pDataBlob);
446     }
447
448     FORCEINLINE MethodTable * GetMethodTableFromClassDomainID(DWORD dwClassDomainID)
449     {
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);
455         return pMT;
456     }
457
458 private:
459     friend void EmitFastGetSharedStaticBase(CPUSTUBLINKER *psl, CodeLabel *init, bool bCCtorCheck);
460
461     void SetClassFlags(MethodTable* pMT, DWORD dwFlags);
462     DWORD GetClassFlags(MethodTable* pMT, DWORD iClassIndex);
463
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
469
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;
475
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
478
479     BYTE                     m_pDataBlob[0];         // First byte of the statics blob
480
481     // Layout of m_pDataBlob is:
482     //              ClassInit bytes (hold flags for cctor run, cctor error, etc)
483     //              Non GC Statics
484
485 public:
486
487     // The Module class need to be able to initialized ModuleIndex,
488     // so for now I will make it a friend..
489     friend class Module;
490
491     FORCEINLINE ModuleIndex GetModuleIndex()
492     {
493         LIMITED_METHOD_DAC_CONTRACT;
494         return m_ModuleIndex;
495     }
496
497 };  // struct DomainLocalModule
498
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 */)
502 #else
503 #define OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob TARGET_POINTER_SIZE /* m_pGCStatics */
504 #endif
505
506 typedef DPTR(class DomainLocalBlock) PTR_DomainLocalBlock;
507 class DomainLocalBlock
508 {
509     friend class ClrDataAccess;
510     friend class CheckAsmOffsets;
511
512 private:
513     PTR_AppDomain          m_pDomain;
514     DPTR(PTR_DomainLocalModule) m_pModuleSlots;
515     SIZE_T                 m_aModuleIndices;               // Module entries the shared block has allocated
516
517 public: // used by code generators
518     static SIZE_T GetOffsetOfModuleSlotsPointer() { return offsetof(DomainLocalBlock, m_pModuleSlots);}
519
520 public:
521
522 #ifndef DACCESS_COMPILE
523     DomainLocalBlock()
524       : m_pDomain(NULL),  m_pModuleSlots(NULL), m_aModuleIndices(0) {}
525
526     void    EnsureModuleIndex(ModuleIndex index);
527
528     void Init(AppDomain *pDomain) { LIMITED_METHOD_CONTRACT; m_pDomain = pDomain; }
529 #endif
530
531     void SetModuleSlot(ModuleIndex index, PTR_DomainLocalModule pLocalModule);
532
533     FORCEINLINE PTR_DomainLocalModule GetModuleSlot(ModuleIndex index)
534     {
535         WRAPPER_NO_CONTRACT;
536         SUPPORTS_DAC;
537         _ASSERTE(index.m_dwIndex < m_aModuleIndices);
538         return m_pModuleSlots[index.m_dwIndex];
539     }
540
541     inline PTR_DomainLocalModule GetModuleSlot(MethodTable* pMT)
542     {
543         WRAPPER_NO_CONTRACT;
544         return GetModuleSlot(pMT->GetModuleForStatics()->GetModuleIndex());
545     }
546
547     DomainFile* TryGetDomainFile(ModuleIndex index)
548     {
549         WRAPPER_NO_CONTRACT;
550         SUPPORTS_DAC;
551
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)
556         {
557             MemoryBarrier();
558             if (m_pModuleSlots[index.m_dwIndex])
559             {
560                 return m_pModuleSlots[index.m_dwIndex]->GetDomainFile();
561             }
562         }
563
564         return NULL;
565     }
566
567     DomainFile* GetDomainFile(SIZE_T ModuleID)
568     {
569         WRAPPER_NO_CONTRACT;
570         ModuleIndex index = Module::IDToIndex(ModuleID);
571         _ASSERTE(index.m_dwIndex < m_aModuleIndices);
572         return m_pModuleSlots[index.m_dwIndex]->GetDomainFile();
573     }
574
575 #ifndef DACCESS_COMPILE
576     void SetDomainFile(ModuleIndex index, DomainFile* pDomainFile)
577     {
578         WRAPPER_NO_CONTRACT;
579         _ASSERTE(index.m_dwIndex < m_aModuleIndices);
580         m_pModuleSlots[index.m_dwIndex]->SetDomainFile(pDomainFile);
581     }
582 #endif
583
584 #ifdef DACCESS_COMPILE
585     void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
586 #endif
587
588
589 private:
590
591     //
592     // Low level routines to get & set class entries
593     //
594
595 };
596
597 #ifdef _MSC_VER
598 #pragma warning(pop)
599 #endif
600
601
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
605 {
606 public:
607     // Constructor and desctructor.
608     LargeHeapHandleBucket(LargeHeapHandleBucket *pNext, DWORD Size, BaseDomain *pDomain, BOOL bCrossAD = FALSE);
609     ~LargeHeapHandleBucket();
610
611     // This returns the next bucket.
612     LargeHeapHandleBucket *GetNext()
613     {
614         LIMITED_METHOD_CONTRACT;
615
616         return m_pNext;
617     }
618
619     // This returns the number of remaining handle slots.
620     DWORD GetNumRemainingHandles()
621     {
622         LIMITED_METHOD_CONTRACT;
623
624         return m_ArraySize - m_CurrentPos;
625     }
626
627     void ConsumeRemaining()
628     {
629         LIMITED_METHOD_CONTRACT;
630         
631         m_CurrentPos = m_ArraySize;
632     }
633
634     OBJECTREF *TryAllocateEmbeddedFreeHandle();       
635
636     // Allocate handles from the bucket.
637     OBJECTREF* AllocateHandles(DWORD nRequested);
638     OBJECTREF* CurrentPos()
639     {
640         LIMITED_METHOD_CONTRACT;
641         return m_pArrayDataPtr + m_CurrentPos;
642     }
643
644 private:
645     LargeHeapHandleBucket *m_pNext;
646     int m_ArraySize;
647     int m_CurrentPos;
648     int m_CurrentEmbeddedFreePos;
649     OBJECTHANDLE m_hndHandleArray;
650     OBJECTREF *m_pArrayDataPtr;
651 };
652
653
654
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
658 {
659 public:
660     // Constructor and desctructor.
661     LargeHeapHandleTable(BaseDomain *pDomain, DWORD InitialBucketSize);
662     ~LargeHeapHandleTable();
663
664     // Allocate handles from the large heap handle table.
665     OBJECTREF* AllocateHandles(DWORD nRequested, BOOL bCrossAD = FALSE);
666
667     // Release object handles allocated using AllocateHandles().
668     void ReleaseHandles(OBJECTREF *pObjRef, DWORD nReleased);    
669
670 private:
671     // The buckets of object handles.
672     LargeHeapHandleBucket *m_pHead;
673
674     // We need to know the containing domain so we know where to allocate handles
675     BaseDomain *m_pDomain;
676
677     // The size of the LargeHeapHandleBuckets.
678     DWORD m_NextBucketSize;
679
680     // for finding and re-using embedded free items in the list
681     LargeHeapHandleBucket *m_pFreeSearchHint;
682     DWORD m_cEmbeddedFree;   
683
684 #ifdef _DEBUG
685
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
690
691 public:
692     void RegisterCrstDebug(CrstBase *pCrst)
693     {
694         LIMITED_METHOD_CONTRACT;
695
696         // this function must be called exactly once
697         _ASSERTE(pCrst != NULL);
698         _ASSERTE(m_pCrstDebug == NULL);
699         m_pCrstDebug = pCrst;
700     }
701
702 private:
703     // we will assert that this Crst is held before using the object
704     CrstBase *m_pCrstDebug;
705
706 #endif
707     
708 };
709
710 class LargeHeapHandleBlockHolder;
711 void LargeHeapHandleBlockHolder__StaticFree(LargeHeapHandleBlockHolder*);
712
713
714 class LargeHeapHandleBlockHolder:public Holder<LargeHeapHandleBlockHolder*,DoNothing,LargeHeapHandleBlockHolder__StaticFree>
715
716 {
717     LargeHeapHandleTable* m_pTable;
718     DWORD m_Count;
719     OBJECTREF* m_Data;
720 public:
721     FORCEINLINE LargeHeapHandleBlockHolder(LargeHeapHandleTable* pOwner, DWORD nCount)
722     {
723         WRAPPER_NO_CONTRACT;
724         m_Data = pOwner->AllocateHandles(nCount);
725         m_Count=nCount;
726         m_pTable=pOwner;
727     };
728
729     FORCEINLINE void FreeData()
730     {
731         WRAPPER_NO_CONTRACT;
732         for (DWORD i=0;i< m_Count;i++)
733             ClearObjectReference(m_Data+i);
734         m_pTable->ReleaseHandles(m_Data, m_Count);
735     };
736     FORCEINLINE OBJECTREF* operator[] (DWORD idx)
737     {
738         LIMITED_METHOD_CONTRACT;
739         _ASSERTE(idx<m_Count);
740         return &(m_Data[idx]);
741     }
742 };
743
744 FORCEINLINE  void LargeHeapHandleBlockHolder__StaticFree(LargeHeapHandleBlockHolder* pHolder)
745 {
746     WRAPPER_NO_CONTRACT;
747     pHolder->FreeData();
748 };
749
750
751
752
753
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
757 {
758 public:
759     // Constructor and desctructor.
760     ThreadStaticHandleBucket(ThreadStaticHandleBucket *pNext, DWORD Size, BaseDomain *pDomain);
761     ~ThreadStaticHandleBucket();
762
763     // This returns the next bucket.
764     ThreadStaticHandleBucket *GetNext()
765     {
766         LIMITED_METHOD_CONTRACT;
767
768         return m_pNext;
769     }
770
771     // Allocate handles from the bucket.
772     OBJECTHANDLE GetHandles();
773
774 private:
775     ThreadStaticHandleBucket *m_pNext;
776     int m_ArraySize;
777     OBJECTHANDLE m_hndHandleArray;
778 };
779
780
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
784 {
785 public:
786     // Constructor and desctructor.
787     ThreadStaticHandleTable(BaseDomain *pDomain);
788     ~ThreadStaticHandleTable();
789
790     // Allocate handles from the large heap handle table.
791     OBJECTHANDLE AllocateHandles(DWORD nRequested);
792
793 private:
794     // The buckets of object handles.
795     ThreadStaticHandleBucket *m_pHead;
796
797     // We need to know the containing domain so we know where to allocate handles
798     BaseDomain *m_pDomain;
799 };
800
801
802
803
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.
810 //
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.
816 //
817
818 #define LOW_FREQUENCY_HEAP_RESERVE_SIZE        (3 * GetOsPageSize())
819 #define LOW_FREQUENCY_HEAP_COMMIT_SIZE         (1 * GetOsPageSize())
820
821 #define HIGH_FREQUENCY_HEAP_RESERVE_SIZE       (10 * GetOsPageSize())
822 #define HIGH_FREQUENCY_HEAP_COMMIT_SIZE        (1 * GetOsPageSize())
823
824 #define STUB_HEAP_RESERVE_SIZE                 (3 * GetOsPageSize())
825 #define STUB_HEAP_COMMIT_SIZE                  (1 * GetOsPageSize())
826
827 // --------------------------------------------------------------------------------
828 // PE File List lock - for creating list locks on PE files
829 // --------------------------------------------------------------------------------
830
831 class PEFileListLock : public ListLock
832 {
833 public:
834 #ifndef DACCESS_COMPILE
835     ListLockEntry *FindFileLock(PEFile *pFile)
836     {
837         STATIC_CONTRACT_NOTHROW;
838         STATIC_CONTRACT_GC_NOTRIGGER;
839         STATIC_CONTRACT_FORBID_FAULT;
840
841         PRECONDITION(HasLock());
842
843         ListLockEntry *pEntry;
844
845         for (pEntry = m_pHead;
846              pEntry != NULL;
847              pEntry = pEntry->m_pNext)
848         {
849             if (((PEFile *)pEntry->m_data)->Equals(pFile))
850             {
851                 return pEntry;
852             }
853         }
854
855         return NULL;
856     }
857 #endif // DACCESS_COMPILE
858
859     DEBUG_NOINLINE static void HolderEnter(PEFileListLock *pThis) PUB
860     {
861         WRAPPER_NO_CONTRACT;
862         ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
863         
864         pThis->Enter();
865     }
866
867     DEBUG_NOINLINE static void HolderLeave(PEFileListLock *pThis) PUB
868     {
869         WRAPPER_NO_CONTRACT;
870         ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
871
872         pThis->Leave();
873     }
874
875     typedef Wrapper<PEFileListLock*, PEFileListLock::HolderEnter, PEFileListLock::HolderLeave> Holder;
876 };
877
878 typedef PEFileListLock::Holder PEFileListLockHolder;
879
880 // Loading infrastructure:
881 //
882 // a DomainFile is a file being loaded.  Files are loaded in layers to enable loading in the
883 // presence of dependency loops.
884 //
885 // FileLoadLevel describes the various levels available.  These are implemented slightly
886 // differently for assemblies and modules, but the basic structure is the same.
887 //
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.
892 //
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.)
900 //
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.
903
904 class FileLoadLock : public ListLockEntry
905 {
906 private:
907     FileLoadLevel           m_level;
908     DomainFile              *m_pDomainFile;
909     HRESULT                 m_cachedHR;
910     ADID                    m_AppDomainId;
911
912 public:
913     static FileLoadLock *Create(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile);
914
915     ~FileLoadLock();
916     DomainFile *GetDomainFile();
917     ADID GetAppDomainId();
918     FileLoadLevel GetLoadLevel();
919
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);
925
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.
929     //
930     // Note that the taker must release the lock via IncrementLoadLevel.
931     BOOL Acquire(FileLoadLevel targetLevel);
932
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);
936
937     void SetError(Exception *ex);
938
939     void AddRef();
940     UINT32 Release() DAC_EMPTY_RET(0);
941
942 private:
943
944     FileLoadLock(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile);
945
946     static void HolderLeave(FileLoadLock *pThis);
947
948 public:
949     typedef Wrapper<FileLoadLock *, DoNothing, FileLoadLock::HolderLeave> Holder;
950
951 };
952
953 typedef FileLoadLock::Holder FileLoadLockHolder;
954
955 #ifndef DACCESS_COMPILE
956     typedef ReleaseHolder<FileLoadLock> FileLoadLockRefHolder;
957 #endif // DACCESS_COMPILE
958
959     typedef ListLockBase<NativeCodeVersion> JitListLock;
960     typedef ListLockEntryBase<NativeCodeVersion> JitListLockEntry;
961
962
963 #ifdef _MSC_VER
964 #pragma warning(push)
965 #pragma warning (disable: 4324) //sometimes 64bit compilers complain about alignment
966 #endif
967 class LoadLevelLimiter
968 {
969     FileLoadLevel                   m_currentLevel;
970     LoadLevelLimiter* m_previousLimit;
971     BOOL m_bActive;
972
973 public:
974
975     LoadLevelLimiter()
976       : m_currentLevel(FILE_ACTIVE),
977       m_previousLimit(NULL),
978       m_bActive(FALSE)
979     {
980         LIMITED_METHOD_CONTRACT;
981     }
982
983     void Activate()
984     {
985         WRAPPER_NO_CONTRACT;
986         m_previousLimit=GetThread()->GetLoadLevelLimiter();
987         if(m_previousLimit)
988             m_currentLevel=m_previousLimit->GetLoadLevel();
989         GetThread()->SetLoadLevelLimiter(this);       
990         m_bActive=TRUE;
991     }
992
993     void Deactivate()
994     {
995         WRAPPER_NO_CONTRACT;
996         if (m_bActive)
997         {
998             GetThread()->SetLoadLevelLimiter(m_previousLimit);
999             m_bActive=FALSE;
1000         }
1001     }
1002
1003     ~LoadLevelLimiter()
1004     {
1005         WRAPPER_NO_CONTRACT;
1006
1007         // PendingLoadQueues are allocated on the stack during a load, and
1008         // shared with all nested loads on the same thread.
1009
1010         // Make sure the thread pointer gets reset after the
1011         // top level queue goes out of scope.
1012         if(m_bActive)
1013         {
1014             Deactivate();
1015         }
1016     }
1017
1018     FileLoadLevel GetLoadLevel()
1019     {
1020         LIMITED_METHOD_CONTRACT;
1021         return m_currentLevel;
1022     }
1023
1024     void SetLoadLevel(FileLoadLevel level)
1025     {
1026         LIMITED_METHOD_CONTRACT;
1027         m_currentLevel = level;
1028     }
1029 };
1030 #ifdef _MSC_VER
1031 #pragma warning (pop) //4324
1032 #endif
1033
1034 #define OVERRIDE_LOAD_LEVEL_LIMIT(newLimit)                    \
1035     LoadLevelLimiter __newLimit;                                                    \
1036     __newLimit.Activate();                                                              \
1037     __newLimit.SetLoadLevel(newLimit);
1038
1039 // A BaseDomain much basic information in a code:AppDomain including
1040 // 
1041 //    * code:#AppdomainHeaps - Heaps for any data structures that will be freed on appdomain unload
1042 //    
1043 class BaseDomain
1044 {
1045     friend class Assembly;
1046     friend class AssemblySpec;
1047     friend class AppDomain;
1048     friend class AppDomainNative;
1049
1050     VPTR_BASE_VTABLE_CLASS(BaseDomain)
1051     VPTR_UNIQUE(VPTR_UNIQUE_BaseDomain)
1052
1053 protected:
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.
1056
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. 
1060     // 
1061     // see also code:ADID 
1062     ADID m_dwId;
1063
1064     DomainLocalBlock    m_sDomainLocalBlock;
1065
1066 public:
1067
1068     class AssemblyIterator;
1069     friend class AssemblyIterator;
1070
1071     // Static initialization.
1072     static void Attach();
1073
1074     //****************************************************************************************
1075     //
1076     // Initialization/shutdown routines for every instance of an BaseDomain.
1077
1078     BaseDomain();
1079     virtual ~BaseDomain() {}
1080     void Init();
1081     void Stop();
1082     void Terminate();
1083
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.
1089     ADID GetId (void)
1090     {
1091         LIMITED_METHOD_DAC_CONTRACT;
1092         STATIC_CONTRACT_SO_TOLERANT;
1093         return m_dwId;
1094     }
1095     
1096     virtual BOOL IsAppDomain()    { LIMITED_METHOD_DAC_CONTRACT; return FALSE; }
1097     virtual BOOL IsSharedDomain() { LIMITED_METHOD_DAC_CONTRACT; return FALSE; }
1098
1099     inline BOOL IsDefaultDomain();  // defined later in this file
1100     virtual PTR_LoaderAllocator GetLoaderAllocator() = 0;
1101     virtual PTR_AppDomain AsAppDomain()
1102     {
1103         LIMITED_METHOD_CONTRACT;
1104         STATIC_CONTRACT_SO_TOLERANT;
1105         _ASSERTE(!"Not an AppDomain");
1106         return NULL;
1107     }
1108
1109     
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)
1117
1118     static PTR_BaseDomain ComputeBaseDomain(TypeKey * pTypeKey);
1119
1120 #ifdef FEATURE_COMINTEROP
1121     //****************************************************************************************
1122     //
1123     // This will look up interop data for a method table
1124     //
1125
1126 #ifndef DACCESS_COMPILE
1127     // Returns the data pointer if present, NULL otherwise
1128     InteropMethodTableData *LookupComInteropData(MethodTable *pMT)
1129     {
1130         // Take the lock
1131         CrstHolder holder(&m_InteropDataCrst);
1132
1133         // Lookup
1134         InteropMethodTableData *pData = (InteropMethodTableData*) m_interopDataHash.LookupValue((UPTR) pMT, (LPVOID) NULL);
1135
1136         // Not there...
1137         if (pData == (InteropMethodTableData*) INVALIDENTRY)
1138             return NULL;
1139
1140         // Found it
1141         return pData;
1142     }
1143
1144     // Returns TRUE if successfully inserted, FALSE if this would be a duplicate entry
1145     BOOL InsertComInteropData(MethodTable* pMT, InteropMethodTableData *pData)
1146     {
1147         // We don't keep track of this kind of information for interfaces
1148         _ASSERTE(!pMT->IsInterface());
1149
1150         // Take the lock
1151         CrstHolder holder(&m_InteropDataCrst);
1152
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)
1156             return FALSE;
1157
1158         // Not in there, so insert
1159         m_interopDataHash.InsertValue((UPTR) pMT, (LPVOID) pData);
1160
1161         // Success
1162         return TRUE;
1163     }
1164 #endif // DACCESS_COMPILE
1165 #endif // FEATURE_COMINTEROP
1166
1167     void SetDisableInterfaceCache()
1168     {
1169         m_fDisableInterfaceCache = TRUE;
1170     }
1171     BOOL GetDisableInterfaceCache()
1172     {
1173         return m_fDisableInterfaceCache;
1174     }
1175
1176 #ifdef FEATURE_COMINTEROP
1177     MngStdInterfacesInfo * GetMngStdInterfacesInfo()
1178     {
1179         LIMITED_METHOD_CONTRACT;
1180
1181         return m_pMngStdInterfacesInfo;
1182     }
1183     
1184     PTR_CLRPrivBinderWinRT GetWinRtBinder()
1185     {
1186         return m_pWinRtBinder;
1187     }
1188 #endif // FEATURE_COMINTEROP
1189
1190     //****************************************************************************************
1191     // This method returns marshaling data that the EE uses that is stored on a per app domain
1192     // basis.
1193     EEMarshalingData *GetMarshalingData();
1194
1195     // Deletes marshaling data at shutdown (which contains cached factories that needs to be released)
1196     void DeleteMarshalingData();
1197     
1198 #ifdef _DEBUG
1199     BOOL OwnDomainLocalBlockLock()
1200     {
1201         WRAPPER_NO_CONTRACT;
1202
1203         return m_DomainLocalBlockCrst.OwnedByCurrentThread();
1204     }
1205 #endif
1206
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()
1211     {
1212         LIMITED_METHOD_CONTRACT;
1213
1214         return &m_ClassInitLock;
1215     }
1216
1217     JitListLock* GetJitLock()
1218     {
1219         LIMITED_METHOD_CONTRACT;
1220         return &m_JITLock;
1221     }
1222
1223     ListLock* GetILStubGenLock()
1224     {
1225         LIMITED_METHOD_CONTRACT;
1226         return &m_ILStubGenLock;
1227     }
1228
1229     STRINGREF *IsStringInterned(STRINGREF *pString);
1230     STRINGREF *GetOrInternString(STRINGREF *pString);
1231
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);
1237
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();
1242 #endif
1243
1244     //****************************************************************************************
1245     // Handles
1246
1247 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
1248     OBJECTHANDLE CreateTypedHandle(OBJECTREF object, HandleType type)
1249     {
1250         WRAPPER_NO_CONTRACT;
1251         return ::CreateHandleCommon(m_handleStore, object, type);
1252     }
1253
1254     OBJECTHANDLE CreateHandle(OBJECTREF object)
1255     {
1256         WRAPPER_NO_CONTRACT;
1257         CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL)
1258         return ::CreateHandle(m_handleStore, object);
1259     }
1260
1261     OBJECTHANDLE CreateWeakHandle(OBJECTREF object)
1262     {
1263         WRAPPER_NO_CONTRACT;
1264         return ::CreateWeakHandle(m_handleStore, object);
1265     }
1266
1267     OBJECTHANDLE CreateShortWeakHandle(OBJECTREF object)
1268     {
1269         WRAPPER_NO_CONTRACT;
1270         return ::CreateShortWeakHandle(m_handleStore, object);
1271     }
1272
1273     OBJECTHANDLE CreateLongWeakHandle(OBJECTREF object)
1274     {
1275         WRAPPER_NO_CONTRACT;
1276         CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL)
1277         return ::CreateLongWeakHandle(m_handleStore, object);
1278     }
1279
1280     OBJECTHANDLE CreateStrongHandle(OBJECTREF object)
1281     {
1282         WRAPPER_NO_CONTRACT;
1283         return ::CreateStrongHandle(m_handleStore, object);
1284     }
1285
1286     OBJECTHANDLE CreatePinningHandle(OBJECTREF object)
1287     {
1288         WRAPPER_NO_CONTRACT;
1289         return ::CreatePinningHandle(m_handleStore, object);
1290     }
1291
1292     OBJECTHANDLE CreateSizedRefHandle(OBJECTREF object)
1293     {
1294         WRAPPER_NO_CONTRACT;
1295         OBJECTHANDLE h;
1296         if (GCHeapUtilities::IsServerHeap())
1297         {
1298             h = ::CreateSizedRefHandle(m_handleStore, object, m_dwSizedRefHandles % m_iNumberOfProcessors);
1299         }
1300         else
1301         {
1302             h = ::CreateSizedRefHandle(m_handleStore, object);
1303         }
1304
1305         InterlockedIncrement((LONG*)&m_dwSizedRefHandles);
1306         return h;
1307     }
1308
1309 #ifdef FEATURE_COMINTEROP
1310     OBJECTHANDLE CreateRefcountedHandle(OBJECTREF object)
1311     {
1312         WRAPPER_NO_CONTRACT;
1313         return ::CreateRefcountedHandle(m_handleStore, object);
1314     }
1315
1316     OBJECTHANDLE CreateWinRTWeakHandle(OBJECTREF object, IWeakReference* pWinRTWeakReference)
1317     {
1318         WRAPPER_NO_CONTRACT;
1319         return ::CreateWinRTWeakHandle(m_handleStore, object, pWinRTWeakReference);
1320     }
1321 #endif // FEATURE_COMINTEROP
1322
1323     OBJECTHANDLE CreateVariableHandle(OBJECTREF object, UINT type)
1324     {
1325         WRAPPER_NO_CONTRACT;
1326         return ::CreateVariableHandle(m_handleStore, object, type);
1327     }
1328
1329     OBJECTHANDLE CreateDependentHandle(OBJECTREF primary, OBJECTREF secondary)
1330     {
1331         WRAPPER_NO_CONTRACT;
1332         return ::CreateDependentHandle(m_handleStore, primary, secondary);
1333     }
1334
1335 #endif // DACCESS_COMPILE && !CROSSGEN_COMPILE
1336
1337     IUnknown *GetFusionContext() {LIMITED_METHOD_CONTRACT;  return m_pFusionContext; }
1338     
1339     CLRPrivBinderCoreCLR *GetTPABinderContext() {LIMITED_METHOD_CONTRACT;  return m_pTPABinderContext; }
1340
1341
1342     CrstExplicitInit * GetLoaderAllocatorReferencesLock()
1343     {
1344         LIMITED_METHOD_CONTRACT;
1345         return &m_crstLoaderAllocatorReferences;
1346     }
1347     
1348 protected:
1349     
1350     //****************************************************************************************
1351     // Helper method to initialize the large heap handle table.
1352     void InitLargeHeapHandleTable();
1353
1354     //****************************************************************************************
1355     // Adds an assembly to the domain.
1356     void AddAssemblyNoLock(Assembly* assem);
1357
1358     //****************************************************************************************
1359     //
1360     // Hash table that maps a MethodTable to COM Interop compatibility data.
1361     PtrHashMap          m_interopDataHash;
1362
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
1372     
1373     //#AssemblyListLock
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;
1381
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
1386
1387     CLRPrivBinderCoreCLR *m_pTPABinderContext; // Reference to the binding context that holds TPA list details
1388
1389     IGCHandleStore* m_handleStore;
1390
1391     // The large heap handle table.
1392     LargeHeapHandleTable        *m_pLargeHeapHandleTable;
1393
1394     // The large heap handle table critical section.
1395     CrstExplicitInit             m_LargeHeapHandleTableCrst;
1396
1397     EEMarshalingData            *m_pMarshalingData;
1398
1399 #ifdef FEATURE_COMINTEROP
1400     // Information regarding the managed standard interfaces.
1401     MngStdInterfacesInfo        *m_pMngStdInterfacesInfo;
1402     
1403     // WinRT binder
1404     PTR_CLRPrivBinderWinRT m_pWinRtBinder;
1405 #endif // FEATURE_COMINTEROP
1406
1407     // Protects allocation of slot IDs for thread statics
1408     static CrstStatic   m_SpecialStaticsCrst;
1409
1410 public:
1411     // Only call this routine when you can guarantee there are no
1412     // loads in progress.
1413     void ClearFusionContext();
1414
1415     //****************************************************************************************
1416     // Synchronization holders.
1417
1418     class LockHolder : public CrstHolder
1419     {
1420     public:
1421         LockHolder(BaseDomain *pD)
1422             : CrstHolder(&pD->m_DomainCrst)
1423         {
1424             WRAPPER_NO_CONTRACT;
1425         }
1426     };
1427     friend class LockHolder;
1428
1429     class CacheLockHolder : public CrstHolder
1430     {
1431     public:
1432         CacheLockHolder(BaseDomain *pD)
1433             : CrstHolder(&pD->m_DomainCacheCrst)
1434         {
1435             WRAPPER_NO_CONTRACT;
1436         }
1437     };
1438     friend class CacheLockHolder;
1439
1440     class DomainLocalBlockLockHolder : public CrstHolder
1441     {
1442     public:
1443         DomainLocalBlockLockHolder(BaseDomain *pD)
1444             : CrstHolder(&pD->m_DomainLocalBlockCrst)
1445         {
1446             WRAPPER_NO_CONTRACT;
1447         }
1448     };
1449     friend class DomainLocalBlockLockHolder;
1450
1451     class LoadLockHolder :  public PEFileListLockHolder
1452     {
1453     public:
1454         LoadLockHolder(BaseDomain *pD, BOOL Take = TRUE)
1455           : PEFileListLockHolder(&pD->m_FileLoadLock, Take)
1456         {
1457             CONTRACTL
1458             {
1459                 NOTHROW;
1460                 GC_NOTRIGGER;
1461                 MODE_ANY;
1462                 CAN_TAKE_LOCK;
1463             }
1464             CONTRACTL_END;
1465         }
1466     };
1467     friend class LoadLockHolder;
1468     class WinRTFactoryCacheLockHolder : public CrstHolder
1469     {
1470     public:
1471         WinRTFactoryCacheLockHolder(BaseDomain *pD)
1472             : CrstHolder(&pD->m_WinRTFactoryCacheCrst)
1473         {
1474             WRAPPER_NO_CONTRACT;
1475         }
1476     };
1477     friend class WinRTFactoryCacheLockHolder;
1478
1479 public:
1480     void InitVSD();
1481     RangeList *GetCollectibleVSDRanges() { return &m_collVSDRanges; }
1482
1483 private:
1484     TypeIDMap m_typeIDMap;
1485     // Range list for collectible types. Maps VSD PCODEs back to the VirtualCallStubManager they belong to
1486     LockedRangeList m_collVSDRanges;
1487
1488 public:
1489     UINT32 GetTypeID(PTR_MethodTable pMT);
1490     UINT32 LookupTypeID(PTR_MethodTable pMT);
1491     PTR_MethodTable LookupType(UINT32 id);
1492
1493 private:
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;
1501
1502     static int m_iNumberOfProcessors;
1503
1504 public:
1505     // Called by DestroySizedRefHandle
1506     void DecNumSizedRefHandles()
1507     {
1508         WRAPPER_NO_CONTRACT;
1509         LONG result;
1510         result = InterlockedDecrement((LONG*)&m_dwSizedRefHandles);
1511         _ASSERTE(result >= 0);
1512     }
1513
1514     DWORD GetNumSizedRefHandles()
1515     {
1516         return m_dwSizedRefHandles;
1517     }
1518
1519 #ifdef FEATURE_CODE_VERSIONING
1520 private:
1521     CodeVersionManager m_codeVersionManager;
1522
1523 public:
1524     CodeVersionManager* GetCodeVersionManager() { return &m_codeVersionManager; }
1525 #endif //FEATURE_CODE_VERSIONING
1526
1527 #ifdef FEATURE_TIERED_COMPILATION
1528 private:
1529     CallCounter m_callCounter;
1530
1531 public:
1532     CallCounter* GetCallCounter() { return &m_callCounter; }
1533 #endif
1534
1535 #ifdef DACCESS_COMPILE
1536 public:
1537     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
1538                                    bool enumThis);
1539 #endif
1540
1541 };  // class BaseDomain
1542
1543 enum
1544 {
1545     ATTACH_ASSEMBLY_LOAD = 0x1,
1546     ATTACH_MODULE_LOAD = 0x2,
1547     ATTACH_CLASS_LOAD = 0x4,
1548
1549     ATTACH_ALL = 0x7
1550 };
1551
1552 // This filters the output of IterateAssemblies. This ought to be declared more locally
1553 // but it would result in really verbose callsites.
1554 //
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.
1558 //
1559 // An assembly will be included in the results of IterateAssemblies only if
1560 // the appropriate bit is set for *both* characterizations.
1561 //
1562 // The flags can be combined so if you want all loaded assemblies, you must specify:
1563 //
1564 ///     kIncludeLoaded|kIncludeExecution
1565
1566 enum AssemblyIterationFlags
1567 {
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
1576
1577     // Execution / introspection flags
1578     kIncludeExecution     = 0x00000004, // include assemblies that are loaded for execution only
1579     
1580     kIncludeFailedToLoad  = 0x00000010, // include assemblies that failed to load 
1581
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.
1588
1589 };  // enum AssemblyIterationFlags
1590
1591 //---------------------------------------------------------------------------------------
1592 // 
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.
1595 // 
1596 // Each type of type parameter needs 2 methods implemented:
1597 //  code:CollectibleAssemblyHolderBase::GetLoaderAllocator
1598 //  code:CollectibleAssemblyHolderBase::IsCollectible
1599 // 
1600 template<typename _Type>
1601 class CollectibleAssemblyHolderBase
1602 {
1603 protected:
1604     _Type m_value;
1605 public:
1606     CollectibleAssemblyHolderBase(const _Type & value = NULL)
1607     {
1608         LIMITED_METHOD_CONTRACT;
1609         m_value = value;
1610     }
1611     void DoAcquire()
1612     {
1613         CONTRACTL
1614         {
1615             NOTHROW;
1616             GC_NOTRIGGER;
1617             MODE_ANY;
1618         }
1619         CONTRACTL_END;
1620         
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))
1624         {
1625             LoaderAllocator * pLoaderAllocator = GetLoaderAllocator(m_value);
1626             pLoaderAllocator->AddReference();
1627         }
1628 #endif //!DACCESS_COMPILE
1629     }
1630     void DoRelease()
1631     {
1632         CONTRACTL
1633         {
1634             NOTHROW;
1635             GC_NOTRIGGER;
1636             MODE_ANY;
1637         }
1638         CONTRACTL_END;
1639         
1640 #ifndef DACCESS_COMPILE
1641         if (this->IsCollectible(m_value))
1642         {
1643             LoaderAllocator * pLoaderAllocator = GetLoaderAllocator(m_value);
1644             pLoaderAllocator->Release();
1645         }
1646 #endif //!DACCESS_COMPILE
1647     }
1648     
1649 private:
1650     LoaderAllocator * GetLoaderAllocator(DomainAssembly * pDomainAssembly)
1651     {
1652         WRAPPER_NO_CONTRACT;
1653         return pDomainAssembly->GetLoaderAllocator();
1654     }
1655     BOOL IsCollectible(DomainAssembly * pDomainAssembly)
1656     {
1657         WRAPPER_NO_CONTRACT;
1658         return pDomainAssembly->IsCollectible();
1659     }
1660     LoaderAllocator * GetLoaderAllocator(Assembly * pAssembly)
1661     {
1662         WRAPPER_NO_CONTRACT;
1663         return pAssembly->GetLoaderAllocator();
1664     }
1665     BOOL IsCollectible(Assembly * pAssembly)
1666     {
1667         WRAPPER_NO_CONTRACT;
1668         return pAssembly->IsCollectible();
1669     }
1670 };  // class CollectibleAssemblyHolderBase<>
1671
1672 //---------------------------------------------------------------------------------------
1673 // 
1674 // Holder of assembly reference which keeps collectible assembly alive while the holder is valid.
1675 // 
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.
1680 // 
1681 // #CAH_DAC
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.
1684 // 
1685 template<typename _Type>
1686 class CollectibleAssemblyHolder : public BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >
1687 {
1688 public:
1689     FORCEINLINE 
1690     CollectibleAssemblyHolder(const _Type & value = NULL, BOOL fTake = TRUE)
1691         : BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >(value, fTake)
1692     {
1693         STATIC_CONTRACT_WRAPPER;
1694     }
1695     
1696     FORCEINLINE 
1697     CollectibleAssemblyHolder & 
1698     operator=(const _Type & value)
1699     {
1700         STATIC_CONTRACT_WRAPPER;
1701         BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >::operator=(value);
1702         return *this;
1703     }
1704     
1705     // Operator & is overloaded in parent, therefore we have to get to 'this' pointer explicitly.
1706     FORCEINLINE 
1707     CollectibleAssemblyHolder<_Type> * 
1708     This()
1709     {
1710         LIMITED_METHOD_CONTRACT;
1711         return this;
1712     }
1713 };  // class CollectibleAssemblyHolder<>
1714
1715 //---------------------------------------------------------------------------------------
1716 // 
1717 #ifdef FEATURE_LOADER_OPTIMIZATION
1718 class SharedAssemblyLocator
1719 {
1720 public:
1721     enum
1722     {
1723         DOMAINASSEMBLY      = 1,
1724         PEASSEMBLY          = 2,
1725         PEASSEMBLYEXACT     = 3
1726     };
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)
1732     {
1733         LIMITED_METHOD_CONTRACT;
1734         m_type=DOMAINASSEMBLY;
1735         m_value=pAssembly;
1736     }
1737     SharedAssemblyLocator(PEAssembly* pFile, DWORD type = PEASSEMBLY)
1738     {
1739         LIMITED_METHOD_CONTRACT;
1740         m_type = type;
1741         m_value = pFile;
1742     }
1743 #endif // DACCESS_COMPILE
1744
1745     DWORD Hash();
1746 protected:
1747     DWORD m_type;
1748     LPVOID m_value;
1749     ULONG   m_uIdentityHash;
1750 };
1751 #endif // FEATURE_LOADER_OPTIMIZATION
1752
1753 //
1754 // Stores binding information about failed assembly loads for DAC
1755 //
1756 struct FailedAssembly {
1757     SString displayName;
1758     SString location;
1759     HRESULT error;
1760
1761     void Initialize(AssemblySpec *pSpec, Exception *ex)
1762     {
1763         CONTRACTL
1764         {
1765             THROWS;
1766             GC_TRIGGERS;
1767             MODE_ANY;
1768         }
1769         CONTRACTL_END;
1770
1771         displayName.SetASCII(pSpec->GetName());
1772         location.Set(pSpec->GetCodeBase());
1773         error = ex->GetHR();
1774
1775         // 
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.
1780         //
1781     }
1782 };
1783
1784 #ifdef FEATURE_COMINTEROP
1785
1786 // Cache used by COM Interop
1787 struct NameToTypeMapEntry
1788 {
1789     // Host space representation of the key
1790     struct Key
1791     {
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
1794     };
1795     struct DacKey
1796     {
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
1799     } m_key;
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
1802     BYTE m_bFlags;
1803 };
1804
1805 typedef DPTR(NameToTypeMapEntry) PTR_NameToTypeMapEntry;
1806
1807 class NameToTypeMapTraits : public NoRemoveSHashTraits< DefaultSHashTraits<NameToTypeMapEntry> >
1808 {
1809 public:
1810     typedef NameToTypeMapEntry::Key key_t;
1811
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) 
1815     {
1816         key_t key;
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;
1819
1820         return key;
1821     }
1822     static count_t Hash(const key_t &key) { WRAPPER_NO_CONTRACT; return HashStringN(key.m_wzName, key.m_cchName); }
1823     
1824     static BOOL Equals(const key_t &lhs, const key_t &rhs)
1825     {
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;
1828     }
1829     
1830     void OnDestructPerEntryCleanupAction(const NameToTypeMapEntry& e)
1831     {
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
1837     }
1838     static const bool s_DestructPerEntryCleanupAction = true;
1839 };
1840
1841 typedef SHash<NameToTypeMapTraits> NameToTypeMapTable;
1842
1843 typedef DPTR(NameToTypeMapTable) PTR_NameToTypeMapTable;
1844
1845 struct WinRTFactoryCacheEntry
1846 {
1847     typedef MethodTable *Key;           
1848     Key          key;                   // Type as KEY
1849     
1850     CtxEntry    *m_pCtxEntry;           // Context entry - used to verify whether the cache is a match
1851     OBJECTHANDLE m_ohFactoryObject;     // Handle to factory object
1852 };
1853
1854 class WinRTFactoryCacheTraits : public DefaultSHashTraits<WinRTFactoryCacheEntry>
1855 {
1856 public:
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; }
1866
1867     static void OnDestructPerEntryCleanupAction(const WinRTFactoryCacheEntry& e);
1868     static const bool s_DestructPerEntryCleanupAction = true;
1869 };
1870
1871 typedef SHash<WinRTFactoryCacheTraits> WinRTFactoryCache;
1872
1873 #endif // FEATURE_COMINTEROP
1874
1875 class AppDomainIterator;
1876
1877 const DWORD DefaultADID = 1;
1878
1879 template <class AppDomainType> class AppDomainCreationHolder;
1880
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.
1884 // 
1885 // Threads are always running in the context of a particular AppDomain.  See
1886 // file:threads.h#RuntimeThreadLocals for more details.  
1887 // 
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
1890 // 
1891 class AppDomain : public BaseDomain
1892 {
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;
1903
1904     VPTR_VTABLE_CLASS(AppDomain, BaseDomain)
1905
1906 public:
1907 #ifndef DACCESS_COMPILE
1908     AppDomain();
1909     virtual ~AppDomain();
1910 #endif
1911     DomainAssembly* FindDomainAssembly(Assembly*);
1912     void EnterContext(Thread* pThread, Context* pCtx,ContextTransitionFrame *pFrame);
1913
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
1920     
1921     //-----------------------------------------------------------------------------------------------------------------
1922     // Initializes an AppDomain. (this functions is not called from the SystemDomain)
1923     void Init();
1924
1925 #if defined(FEATURE_COMINTEROP)
1926     HRESULT SetWinrtApplicationContext(SString &appLocalWinMD);
1927 #endif // FEATURE_COMINTEROP
1928
1929     BOOL CanReversePInvokeEnter();
1930     void SetReversePInvokeCannotEnter();
1931     bool MustForceTrivialWaitOperations();
1932     void SetForceTrivialWaitOperations();
1933
1934     //****************************************************************************************
1935     //
1936     // Stop deletes all the assemblies but does not remove other resources like
1937     // the critical sections
1938     void Stop();
1939
1940     // Gets rid of resources
1941     void Terminate();
1942
1943 #ifdef  FEATURE_PREJIT
1944     //assembly cleanup that requires suspended runtime
1945     void DeleteNativeCodeRanges();
1946 #endif
1947
1948     // final assembly cleanup
1949     void ShutdownAssemblies();
1950     void ShutdownFreeLoaderAllocators(BOOL bFromManagedCode);
1951     
1952     void ReleaseDomainBoundInfo();
1953     void ReleaseFiles();
1954     
1955
1956     // Remove the Appdomain for the system and cleans up. This call should not be
1957     // called from shut down code.
1958     void CloseDomain();
1959
1960     virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; }
1961     virtual PTR_AppDomain AsAppDomain() { LIMITED_METHOD_CONTRACT; return dac_cast<PTR_AppDomain>(this); }
1962
1963
1964     OBJECTREF DoSetup(OBJECTREF* setupInfo);
1965
1966     OBJECTREF GetExposedObject();
1967     OBJECTREF GetRawExposedObject() {
1968         CONTRACTL
1969         {
1970             NOTHROW;
1971             GC_NOTRIGGER;
1972             SO_TOLERANT;
1973             MODE_COOPERATIVE;
1974         }
1975         CONTRACTL_END;
1976         if (m_ExposedObject) {
1977             return ObjectFromHandle(m_ExposedObject);
1978         }
1979         else {
1980             return NULL;
1981         }
1982     }
1983
1984     OBJECTHANDLE GetRawExposedObjectHandleForDebugger() { LIMITED_METHOD_DAC_CONTRACT; return m_ExposedObject; }
1985
1986 #ifdef FEATURE_COMINTEROP
1987     HRESULT GetComIPForExposedObject(IUnknown **pComIP);
1988
1989     MethodTable *GetRedirectedType(WinMDAdapter::RedirectedTypeIndex index);
1990 #endif // FEATURE_COMINTEROP
1991
1992
1993     //****************************************************************************************
1994
1995 protected:
1996     // Multi-thread safe access to the list of assemblies
1997     class DomainAssemblyList
1998     {
1999     private:
2000         ArrayList m_array;
2001 #ifdef _DEBUG
2002         AppDomain * dbg_m_pAppDomain;
2003     public:
2004         void Debug_SetAppDomain(AppDomain * pAppDomain)
2005         {
2006             dbg_m_pAppDomain = pAppDomain;
2007         }
2008 #endif //_DEBUG
2009     public:
2010         bool IsEmpty()
2011         {
2012             CONTRACTL {
2013                 NOTHROW;
2014                 GC_NOTRIGGER;
2015                 MODE_ANY;
2016             } CONTRACTL_END;
2017             
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);
2021         }
2022         void Clear(AppDomain * pAppDomain)
2023         {
2024             CONTRACTL {
2025                 NOTHROW;
2026                 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2027                 MODE_ANY;
2028             } CONTRACTL_END;
2029             
2030             _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2031             
2032             CrstHolder ch(pAppDomain->GetAssemblyListLock());
2033             m_array.Clear();
2034         }
2035         
2036         DWORD GetCount(AppDomain * pAppDomain)
2037         {
2038             CONTRACTL {
2039                 NOTHROW;
2040                 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2041                 MODE_ANY;
2042             } CONTRACTL_END;
2043             
2044             _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2045             
2046             CrstHolder ch(pAppDomain->GetAssemblyListLock());
2047             return GetCount_Unlocked();
2048         }
2049         DWORD GetCount_Unlocked()
2050         {
2051             CONTRACTL {
2052                 NOTHROW;
2053                 GC_NOTRIGGER;
2054                 MODE_ANY;
2055             } CONTRACTL_END;
2056             
2057 #ifndef DACCESS_COMPILE
2058             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2059 #endif
2060             // code:Append_Unlock guarantees that we do not have more than MAXDWORD items
2061             return m_array.GetCount();
2062         }
2063         
2064         void Get(AppDomain * pAppDomain, DWORD index, CollectibleAssemblyHolder<DomainAssembly *> * pAssemblyHolder)
2065         {
2066             CONTRACTL {
2067                 NOTHROW;
2068                 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2069                 MODE_ANY;
2070             } CONTRACTL_END;
2071             
2072             _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2073             
2074             CrstHolder ch(pAppDomain->GetAssemblyListLock());
2075             Get_Unlocked(index, pAssemblyHolder);
2076         }
2077         void Get_Unlocked(DWORD index, CollectibleAssemblyHolder<DomainAssembly *> * pAssemblyHolder)
2078         {
2079             CONTRACTL {
2080                 NOTHROW;
2081                 GC_NOTRIGGER;
2082                 MODE_ANY;
2083             } CONTRACTL_END;
2084             
2085             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2086             *pAssemblyHolder = dac_cast<PTR_DomainAssembly>(m_array.Get(index));
2087         }
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)
2091         {
2092             CONTRACTL {
2093                 NOTHROW;
2094                 GC_NOTRIGGER;
2095                 MODE_ANY;
2096                 SUPPORTS_DAC;
2097             } CONTRACTL_END;
2098             
2099 #ifndef DACCESS_COMPILE
2100             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2101 #endif
2102             return dac_cast<PTR_DomainAssembly>(m_array.Get(index));
2103         }
2104         
2105 #ifndef DACCESS_COMPILE
2106         void Set(AppDomain * pAppDomain, DWORD index, DomainAssembly * pAssembly)
2107         {
2108             CONTRACTL {
2109                 NOTHROW;
2110                 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2111                 MODE_ANY;
2112             } CONTRACTL_END;
2113             
2114             _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2115             
2116             CrstHolder ch(pAppDomain->GetAssemblyListLock());
2117             return Set_Unlocked(index, pAssembly);
2118         }
2119         void Set_Unlocked(DWORD index, DomainAssembly * pAssembly)
2120         {
2121             CONTRACTL {
2122                 NOTHROW;
2123                 GC_NOTRIGGER;
2124                 MODE_ANY;
2125             } CONTRACTL_END;
2126             
2127             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2128             m_array.Set(index, pAssembly);
2129         }
2130         
2131         HRESULT Append_Unlocked(DomainAssembly * pAssembly)
2132         {
2133             CONTRACTL {
2134                 NOTHROW;
2135                 GC_NOTRIGGER;
2136                 MODE_ANY;
2137             } CONTRACTL_END;
2138             
2139             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2140             return m_array.Append(pAssembly);
2141         }
2142 #else //DACCESS_COMPILE
2143         void 
2144         EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2145         {
2146             SUPPORTS_DAC;
2147             
2148             m_array.EnumMemoryRegions(flags);
2149         }
2150 #endif // DACCESS_COMPILE
2151         
2152         // Should be used only by code:AssemblyIterator::Create
2153         ArrayList::Iterator GetArrayListIterator()
2154         {
2155             return m_array.Iterate();
2156         }
2157     };  // class DomainAssemblyList
2158     
2159     // Conceptually a list of code:Assembly structures, protected by lock code:GetAssemblyListLock
2160     DomainAssemblyList m_Assemblies;
2161     
2162 public:
2163     // Note that this lock switches thread into GC_NOTRIGGER region as GC can take it too.
2164     CrstExplicitInit * GetAssemblyListLock()
2165     {
2166         LIMITED_METHOD_CONTRACT;
2167         return &m_crstAssemblyList;
2168     }
2169     
2170 public:
2171     class AssemblyIterator
2172     {
2173         // AppDomain context with the assembly list
2174         AppDomain *            m_pAppDomain;
2175         ArrayList::Iterator    m_Iterator;
2176         AssemblyIterationFlags m_assemblyIterationFlags;
2177
2178     public:
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
2183     private:
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);
2187 #endif
2188
2189     private:
2190         inline DWORD GetIndex()
2191         {
2192             LIMITED_METHOD_CONTRACT;
2193             return m_Iterator.GetIndex();
2194         }
2195
2196     private:
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)
2200         {
2201             LIMITED_METHOD_CONTRACT;
2202             AssemblyIterator i;
2203
2204             i.m_pAppDomain = pAppDomain;
2205             i.m_Iterator = pAppDomain->m_Assemblies.GetArrayListIterator();
2206             i.m_assemblyIterationFlags = assemblyIterationFlags;
2207             return i;
2208         }
2209     };  // class AssemblyIterator
2210
2211     AssemblyIterator IterateAssembliesEx(AssemblyIterationFlags assemblyIterationFlags)
2212     {
2213         LIMITED_METHOD_CONTRACT;
2214         return AssemblyIterator::Create(this, assemblyIterationFlags);
2215     }
2216
2217 private:
2218     struct NativeImageDependenciesEntry
2219     {
2220         BaseAssemblySpec m_AssemblySpec;
2221         GUID m_guidMVID;
2222     };
2223
2224     class NativeImageDependenciesTraits : public DeleteElementsOnDestructSHashTraits<DefaultSHashTraits<NativeImageDependenciesEntry *> >
2225     {
2226     public:
2227         typedef BaseAssemblySpec *key_t;
2228         static key_t GetKey(NativeImageDependenciesEntry * e) { return &(e->m_AssemblySpec); }
2229
2230         static count_t Hash(key_t k)
2231         {
2232             return k->Hash();
2233         }
2234
2235         static BOOL Equals(key_t lhs, key_t rhs)
2236         {
2237             return lhs->CompareEx(rhs);
2238         }
2239     };
2240
2241     SHash<NativeImageDependenciesTraits> m_NativeImageDependencies;
2242
2243 public:
2244     void CheckForMismatchedNativeImages(AssemblySpec * pSpec, const GUID * pGuid);
2245     BOOL RemoveNativeImageDependency(AssemblySpec* pSpec);
2246
2247 public:
2248     class PathIterator
2249     {
2250         friend class AppDomain;
2251
2252         ArrayList::Iterator m_i;
2253
2254     public:
2255         BOOL Next()
2256         {
2257             WRAPPER_NO_CONTRACT;
2258             return m_i.Next();
2259         }
2260
2261         SString* GetPath()
2262         {
2263             WRAPPER_NO_CONTRACT;
2264             return dac_cast<PTR_SString>(m_i.GetElement());
2265         }
2266     };
2267     BOOL BindingByManifestFile();
2268
2269     PathIterator IterateNativeDllSearchDirectories();
2270     void SetNativeDllSearchDirectories(LPCWSTR paths);
2271     BOOL HasNativeDllSearchDirectories();
2272     void ShutdownNativeDllSearchDirectories();
2273
2274 public:
2275     SIZE_T GetAssemblyCount()
2276     {
2277         WRAPPER_NO_CONTRACT;
2278         return m_Assemblies.GetCount(this);
2279     }
2280
2281     CHECK CheckCanLoadTypes(Assembly *pAssembly);
2282     CHECK CheckCanExecuteManagedCode(MethodDesc* pMD);
2283     CHECK CheckLoading(DomainFile *pFile, FileLoadLevel level);
2284
2285     FileLoadLevel GetDomainFileLoadLevel(DomainFile *pFile);
2286     BOOL IsLoading(DomainFile *pFile, FileLoadLevel level);
2287     static FileLoadLevel GetThreadFileLoadLevel();
2288
2289     void LoadDomainFile(DomainFile *pFile,
2290                         FileLoadLevel targetLevel);
2291
2292     enum FindAssemblyOptions
2293     {
2294         FindAssemblyOptions_None                    = 0x0,
2295         FindAssemblyOptions_IncludeFailedToLoad     = 0x1
2296     };
2297
2298     DomainAssembly * FindAssembly(PEAssembly * pFile, FindAssemblyOptions options = FindAssemblyOptions_None) DAC_EMPTY_RET(NULL);
2299
2300
2301     Assembly *LoadAssembly(AssemblySpec* pIdentity,
2302                            PEAssembly *pFile,
2303                            FileLoadLevel targetLevel);
2304
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,
2312                                                 PEAssembly *pFile,
2313                                                 FileLoadLevel targetLevel);
2314
2315     DomainAssembly *LoadDomainAssembly( AssemblySpec* pIdentity,
2316                                         PEAssembly *pFile,
2317                                         FileLoadLevel targetLevel);
2318
2319
2320     CHECK CheckValidModule(Module *pModule);
2321 #ifdef FEATURE_LOADER_OPTIMIZATION    
2322     DomainFile *LoadDomainNeutralModuleDependency(Module *pModule, FileLoadLevel targetLevel);
2323 #endif
2324
2325     // private:
2326     void LoadSystemAssemblies();
2327
2328     DomainFile *LoadDomainFile(FileLoadLock *pLock,
2329                                FileLoadLevel targetLevel);
2330
2331     void TryIncrementalLoad(DomainFile *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder);
2332
2333     Assembly *LoadAssemblyHelper(LPCWSTR wszAssembly,
2334                                  LPCWSTR wszCodeBase);
2335
2336 #ifndef DACCESS_COMPILE // needs AssemblySpec
2337
2338     void GetCacheAssemblyList(SetSHash<PTR_DomainAssembly>& assemblyList);
2339
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)
2344     {
2345         WRAPPER_NO_CONTRACT;
2346         return m_AssemblyCache.LookupAssembly(pSpec, fThrow);
2347     }
2348
2349     PEAssembly* FindCachedFile(AssemblySpec* pSpec, BOOL fThrow = TRUE);
2350     BOOL IsCached(AssemblySpec *pSpec);
2351 #endif // DACCESS_COMPILE
2352     void CacheStringsForDAC();
2353
2354     BOOL AddFileToCache(AssemblySpec* pSpec, PEAssembly *pFile, BOOL fAllowFailure = FALSE);
2355     BOOL RemoveFileFromCache(PEAssembly *pFile);
2356
2357     BOOL AddAssemblyToCache(AssemblySpec* pSpec, DomainAssembly *pAssembly);
2358     BOOL RemoveAssemblyFromCache(DomainAssembly* pAssembly);
2359
2360     BOOL AddExceptionToCache(AssemblySpec* pSpec, Exception *ex);
2361     void AddUnmanagedImageToCache(LPCWSTR libraryName, HMODULE hMod);
2362     HMODULE FindUnmanagedImageInCache(LPCWSTR libraryName);
2363     //****************************************************************************************
2364     //
2365     // Adds or removes an assembly to the domain.
2366     void AddAssembly(DomainAssembly * assem);
2367     void RemoveAssembly(DomainAssembly * pAsm);
2368
2369     BOOL ContainsAssembly(Assembly * assem);
2370
2371 #ifdef FEATURE_LOADER_OPTIMIZATION    
2372     enum SharePolicy
2373     {
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)
2379
2380         SHARE_POLICY_COUNT,
2381         SHARE_POLICY_MASK = 0x3,
2382
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,
2386     };
2387
2388     SharePolicy GetSharePolicy();
2389 #endif // FEATURE_LOADER_OPTIMIZATION
2390
2391     //****************************************************************************************
2392     //
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.
2396     ULONG AddRef(void);
2397     ULONG Release(void) DAC_EMPTY_RET(0);
2398
2399     //****************************************************************************************
2400     LPCWSTR GetFriendlyName(BOOL fDebuggerCares = TRUE);
2401     LPCWSTR GetFriendlyNameForDebugger();
2402     LPCWSTR GetFriendlyNameForLogging();
2403 #ifdef DACCESS_COMPILE
2404     PVOID GetFriendlyNameNoSet(bool* isUtf8);
2405 #endif
2406     void SetFriendlyName(LPCWSTR pwzFriendlyName, BOOL fDebuggerCares = TRUE);
2407     void ResetFriendlyName(BOOL fDebuggerCares = TRUE);
2408
2409     //****************************************************************************************
2410
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);
2419
2420     HRESULT BindAssemblySpecForHostedBinder(
2421         AssemblySpec *   pSpec, 
2422         IAssemblyName *  pAssemblyName, 
2423         ICLRPrivBinder * pBinder, 
2424         PEAssembly **    ppAssembly) DAC_EMPTY_RET(E_FAIL);
2425     
2426     HRESULT BindHostedPrivAssembly(
2427         PEAssembly *       pParentPEAssembly,
2428         ICLRPrivAssembly * pPrivAssembly, 
2429         IAssemblyName *    pAssemblyName, 
2430         PEAssembly **      ppAssembly) DAC_EMPTY_RET(S_OK);
2431
2432
2433     PEAssembly *TryResolveAssembly(AssemblySpec *pSpec, BOOL fPreBind);
2434
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.
2438     //
2439     // Right now we only cache assembly binds for "probing" type
2440     // binding situations, basically when loading domain neutral assemblies or
2441     // zap files.
2442     //
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>
2446     //
2447     // Returns TRUE if stored
2448     //         FALSE if it's a duplicate (caller should clean up args)
2449     BOOL StoreBindAssemblySpecResult(AssemblySpec *pSpec,
2450                                      PEAssembly *pFile,
2451                                      BOOL clone = TRUE);
2452
2453     BOOL StoreBindAssemblySpecError(AssemblySpec *pSpec,
2454                                     HRESULT hr,
2455                                     OBJECTREF *pThrowable,
2456                                     BOOL clone = TRUE);
2457
2458     //****************************************************************************************
2459     //
2460     //****************************************************************************************
2461     //
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
2464     // assemblies
2465 #ifndef DACCESS_COMPILE
2466     void OnAssemblyLoad(Assembly *assem);
2467     void OnAssemblyLoadUnlocked(Assembly *assem);
2468     static BOOL OnUnhandledException(OBJECTREF *pThrowable, BOOL isTerminating = TRUE);
2469     
2470 #endif
2471
2472     // True iff a debugger is attached to the process (same as CORDebuggerAttached)
2473     BOOL IsDebuggerAttached (void);
2474
2475 #ifdef DEBUGGING_SUPPORTED
2476     // Notify debugger of all assemblies, modules, and possibly classes in this AppDomain
2477     BOOL NotifyDebuggerLoad(int flags, BOOL attaching);
2478
2479     // Send unload notifications to the debugger for all assemblies, modules and classes in this AppDomain
2480     void NotifyDebuggerUnload();
2481 #endif // DEBUGGING_SUPPORTED
2482
2483     void SetSystemAssemblyLoadEventSent (BOOL fFlag);
2484     BOOL WasSystemAssemblyLoadEventSent (void);
2485
2486 #ifndef DACCESS_COMPILE
2487     OBJECTREF* AllocateStaticFieldObjRefPtrs(int nRequested, OBJECTREF** ppLazyAllocate = NULL)
2488     {
2489         WRAPPER_NO_CONTRACT;
2490
2491         return AllocateObjRefPtrsInLargeTable(nRequested, ppLazyAllocate);
2492     }
2493
2494     OBJECTREF* AllocateStaticFieldObjRefPtrsCrossDomain(int nRequested, OBJECTREF** ppLazyAllocate = NULL)
2495     {
2496         WRAPPER_NO_CONTRACT;
2497
2498         return AllocateObjRefPtrsInLargeTable(nRequested, ppLazyAllocate, TRUE);
2499     }
2500 #endif // DACCESS_COMPILE
2501
2502     void              EnumStaticGCRefs(promote_func* fn, ScanContext* sc);
2503
2504     DomainLocalBlock *GetDomainLocalBlock()
2505     {
2506         LIMITED_METHOD_DAC_CONTRACT;
2507
2508         return &m_sDomainLocalBlock;
2509     }
2510
2511     static SIZE_T GetOffsetOfModuleSlotsPointer()
2512     {
2513         WRAPPER_NO_CONTRACT;
2514
2515         return offsetof(AppDomain,m_sDomainLocalBlock) + DomainLocalBlock::GetOffsetOfModuleSlotsPointer();
2516     }
2517
2518     void SetupSharedStatics();
2519
2520     //****************************************************************************************
2521     //
2522     // Create a quick lookup for classes loaded into this domain based on their GUID.
2523     //
2524     void InsertClassForCLSID(MethodTable* pMT, BOOL fForceInsert = FALSE);
2525     void InsertClassForCLSID(MethodTable* pMT, GUID *pGuid);
2526
2527 #ifdef FEATURE_COMINTEROP
2528 private:
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);
2531 public:
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);
2536
2537 #ifndef DACCESS_COMPILE
2538     inline BOOL CanCacheWinRTTypeByGuid(TypeHandle typeHandle)
2539     { 
2540         CONTRACTL
2541         {
2542             THROWS;
2543             GC_NOTRIGGER;
2544             MODE_ANY;
2545         }
2546         CONTRACTL_END;
2547         
2548         // Only allow caching guid/types maps for types loaded during 
2549         // "normal" domain operation
2550         if (IsCompilationDomain() || (m_Stage < STAGE_OPEN))
2551             return FALSE;
2552
2553         MethodTable *pMT = typeHandle.GetMethodTable();
2554         if (pMT != NULL)
2555         {
2556             // Don't cache mscorlib-internal declarations of WinRT types.
2557             if (pMT->GetModule()->IsSystem() && pMT->IsProjectedFromWinRT())
2558                 return FALSE;
2559
2560             // Don't cache redirected WinRT types.
2561             if (WinRTTypeNameConverter::IsRedirectedWinRTSourceType(pMT))
2562                 return FALSE;
2563         }
2564
2565         return TRUE;
2566     }
2567 #endif // !DACCESS_COMPILE
2568
2569     void CacheWinRTTypeByGuid(TypeHandle typeHandle);
2570     void GetCachedWinRTTypes(SArray<PTR_MethodTable> * pTypes, SArray<GUID> * pGuids, UINT minEpoch, UINT * pCurEpoch);
2571
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);
2576
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
2582
2583 #ifndef DACCESS_COMPILE
2584     MethodTable* LookupClass(REFIID iid)
2585     {
2586         WRAPPER_NO_CONTRACT;
2587
2588         MethodTable *pMT = (MethodTable*) m_clsidHash.LookupValue((UPTR) GetKeyFromGUID(&iid), (LPVOID)&iid);
2589         return (pMT == (MethodTable*) INVALIDENTRY
2590             ? NULL
2591             : pMT);
2592     }
2593 #endif // DACCESS_COMPILE
2594
2595     //<TODO>@todo get a better key</TODO>
2596     ULONG GetKeyFromGUID(const GUID *pguid)
2597     {
2598         LIMITED_METHOD_CONTRACT;
2599
2600         return *(ULONG *) pguid;
2601     }
2602
2603 #ifdef FEATURE_COMINTEROP
2604     ComCallWrapperCache* GetComCallWrapperCache();
2605     RCWCache *GetRCWCache()
2606     {
2607         WRAPPER_NO_CONTRACT;
2608         if (m_pRCWCache) 
2609             return m_pRCWCache;
2610
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();
2614     }
2615 private:
2616     RCWCache *CreateRCWCache();
2617 public:
2618     RCWCache *GetRCWCacheNoCreate()
2619     {
2620         LIMITED_METHOD_CONTRACT;
2621         return m_pRCWCache;
2622     }
2623
2624     RCWRefCache *GetRCWRefCache();
2625
2626     void ResetComCallWrapperCache()
2627     {
2628         LIMITED_METHOD_CONTRACT;
2629         m_pComCallWrapperCache = NULL;
2630     }
2631
2632     MethodTable* GetLicenseInteropHelperMethodTable();
2633 #endif // FEATURE_COMINTEROP
2634
2635     //****************************************************************************************
2636     // Get the proxy for this app domain
2637
2638     ADIndex GetIndex()
2639     {
2640         LIMITED_METHOD_CONTRACT;
2641         SUPPORTS_DAC;
2642
2643         return m_dwIndex;
2644     }
2645
2646     TPIndex GetTPIndex()
2647     {
2648         LIMITED_METHOD_CONTRACT;
2649         return m_tpIndex;
2650     }
2651
2652     void InitializeDomainContext(BOOL allowRedirects, LPCWSTR pwszPath, LPCWSTR pwszConfig);
2653
2654     IUnknown *CreateFusionContext();
2655
2656     void OverrideDefaultContextBinder(IUnknown *pOverrideBinder)
2657     {
2658         LIMITED_METHOD_CONTRACT;
2659         
2660         _ASSERTE(pOverrideBinder != NULL);
2661         pOverrideBinder->AddRef();
2662         m_pFusionContext->Release();
2663         m_pFusionContext = pOverrideBinder;
2664     }
2665     
2666
2667 #ifdef FEATURE_PREJIT
2668     CorCompileConfigFlags GetNativeConfigFlags();
2669 #endif // FEATURE_PREJIT
2670
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);
2676
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);
2680
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()
2685     {
2686         LIMITED_METHOD_CONTRACT;
2687
2688         m_dwFlags |= USER_CREATED_DOMAIN;
2689     }
2690
2691     BOOL IsUserCreatedDomain()
2692     {
2693         LIMITED_METHOD_CONTRACT;
2694
2695         return (m_dwFlags & USER_CREATED_DOMAIN);
2696     }
2697
2698     void SetIgnoreUnhandledExceptions()
2699     {
2700         LIMITED_METHOD_CONTRACT;
2701
2702         m_dwFlags |= IGNORE_UNHANDLED_EXCEPTIONS;
2703     }
2704
2705     BOOL IgnoreUnhandledExceptions()
2706     {
2707         LIMITED_METHOD_CONTRACT;
2708
2709         return (m_dwFlags & IGNORE_UNHANDLED_EXCEPTIONS);
2710     }
2711
2712     void SetPassiveDomain()
2713     {
2714         LIMITED_METHOD_CONTRACT;
2715
2716         m_dwFlags |= PASSIVE_DOMAIN;
2717     }
2718
2719     BOOL IsPassiveDomain()
2720     {
2721         LIMITED_METHOD_CONTRACT;
2722
2723         return (m_dwFlags & PASSIVE_DOMAIN);
2724     }
2725
2726     void SetVerificationDomain()
2727     {
2728         LIMITED_METHOD_CONTRACT;
2729
2730         m_dwFlags |= VERIFICATION_DOMAIN;
2731     }
2732
2733     BOOL IsVerificationDomain()
2734     {
2735         LIMITED_METHOD_CONTRACT;
2736
2737         return (m_dwFlags & VERIFICATION_DOMAIN);
2738     }
2739
2740     void SetIllegalVerificationDomain()
2741     {
2742         LIMITED_METHOD_CONTRACT;
2743
2744         m_dwFlags |= ILLEGAL_VERIFICATION_DOMAIN;
2745     }
2746
2747     BOOL IsIllegalVerificationDomain()
2748     {
2749         LIMITED_METHOD_CONTRACT;
2750
2751         return (m_dwFlags & ILLEGAL_VERIFICATION_DOMAIN);
2752     }
2753
2754     void SetCompilationDomain()
2755     {
2756         LIMITED_METHOD_CONTRACT;
2757
2758         m_dwFlags |= (PASSIVE_DOMAIN|COMPILATION_DOMAIN);
2759     }
2760
2761     BOOL IsCompilationDomain();
2762
2763     PTR_CompilationDomain ToCompilationDomain()
2764     {
2765         LIMITED_METHOD_CONTRACT;
2766
2767         _ASSERTE(IsCompilationDomain());
2768         return dac_cast<PTR_CompilationDomain>(this);
2769     }
2770
2771     void SetRemotingConfigured()
2772     {
2773         LIMITED_METHOD_CONTRACT;
2774         STATIC_CONTRACT_SO_TOLERANT;
2775         FastInterlockOr((ULONG*)&m_dwFlags, REMOTING_CONFIGURED_FOR_DOMAIN);
2776     }
2777
2778     BOOL IsRemotingConfigured()
2779     {
2780         LIMITED_METHOD_CONTRACT;
2781         STATIC_CONTRACT_SO_TOLERANT;
2782         return m_dwFlags & REMOTING_CONFIGURED_FOR_DOMAIN;
2783     }
2784
2785     void SetOrphanedLocks()
2786     {
2787         LIMITED_METHOD_CONTRACT;
2788         STATIC_CONTRACT_SO_TOLERANT;
2789         FastInterlockOr((ULONG*)&m_dwFlags, ORPHANED_LOCKS);
2790     }
2791
2792     BOOL HasOrphanedLocks()
2793     {
2794         LIMITED_METHOD_CONTRACT;
2795         STATIC_CONTRACT_SO_TOLERANT;
2796         return m_dwFlags & ORPHANED_LOCKS;
2797     }
2798
2799     static void ExceptionUnwind(Frame *pFrame);
2800
2801 #ifdef _DEBUG
2802     void TrackADThreadEnter(Thread *pThread, Frame *pFrame);
2803     void TrackADThreadExit(Thread *pThread, Frame *pFrame);
2804     void DumpADThreadTrack();
2805 #endif
2806
2807 #ifndef DACCESS_COMPILE
2808     void ThreadEnter(Thread *pThread, Frame *pFrame)
2809     {
2810         STATIC_CONTRACT_NOTHROW;
2811         STATIC_CONTRACT_GC_NOTRIGGER;
2812
2813 #ifdef _DEBUG
2814         if (LoggingOn(LF_APPDOMAIN, LL_INFO100))
2815             TrackADThreadEnter(pThread, pFrame);
2816         else
2817 #endif
2818         {
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());
2827 #endif
2828         }
2829     }
2830
2831     void ThreadExit(Thread *pThread, Frame *pFrame)
2832     {
2833         STATIC_CONTRACT_NOTHROW;
2834         STATIC_CONTRACT_GC_NOTRIGGER;
2835
2836 #ifdef _DEBUG
2837         if (LoggingOn(LF_APPDOMAIN, LL_INFO100)) {
2838             TrackADThreadExit(pThread, pFrame);
2839         }
2840         else
2841 #endif
2842         {
2843             LONG result;
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()));
2849 #if _DEBUG_ADUNLOAD
2850             printf("AppDomain::ThreadExit %x from [%d] (%8.8x) %S count %d\n",
2851                    pThread->GetThreadId(), this, GetId().m_dwId,
2852                    GetFriendlyNameForLogging(), GetThreadEnterCount());
2853 #endif
2854         }
2855     }
2856 #endif // DACCESS_COMPILE
2857
2858     ULONG GetThreadEnterCount()
2859     {
2860         LIMITED_METHOD_CONTRACT;
2861         return m_dwThreadEnterCount;
2862     }
2863
2864     BOOL OnlyOneThreadLeft()
2865     {
2866         LIMITED_METHOD_CONTRACT;
2867         return m_dwThreadEnterCount==1 || m_dwThreadsStillInAppDomain ==1;
2868     }
2869
2870     Context *GetDefaultContext()
2871     {
2872         LIMITED_METHOD_CONTRACT;
2873         return m_pDefaultContext;
2874     }
2875
2876     BOOL CanLoadCode()
2877     {
2878         LIMITED_METHOD_CONTRACT;
2879         return m_Stage >= STAGE_READYFORMANAGEDCODE;
2880     }
2881
2882     void SetAnonymouslyHostedDynamicMethodsAssembly(DomainAssembly * pDomainAssembly)
2883     {
2884         LIMITED_METHOD_CONTRACT;
2885         _ASSERTE(pDomainAssembly != NULL);
2886         _ASSERTE(m_anonymouslyHostedDynamicMethodsAssembly == NULL);
2887         m_anonymouslyHostedDynamicMethodsAssembly = pDomainAssembly;
2888     }
2889
2890     DomainAssembly * GetAnonymouslyHostedDynamicMethodsAssembly()
2891     {
2892         LIMITED_METHOD_CONTRACT;
2893         return m_anonymouslyHostedDynamicMethodsAssembly;
2894     }
2895
2896     static void RefTakerAcquire(AppDomain* pDomain)
2897     {
2898         WRAPPER_NO_CONTRACT;
2899         if(!pDomain)
2900             return;
2901         pDomain->AddRef();
2902 #ifdef _DEBUG
2903         FastInterlockIncrement(&pDomain->m_dwRefTakers);
2904 #endif
2905     }
2906
2907     static void RefTakerRelease(AppDomain* pDomain)
2908     {
2909         WRAPPER_NO_CONTRACT;
2910         if(!pDomain)
2911             return;
2912 #ifdef _DEBUG
2913         _ASSERTE(pDomain->m_dwRefTakers);
2914         FastInterlockDecrement(&pDomain->m_dwRefTakers);
2915 #endif
2916         pDomain->Release();
2917     }
2918
2919 #ifdef _DEBUG 
2920
2921     BOOL IsHeldByIterator()
2922     {
2923         LIMITED_METHOD_CONTRACT;
2924         return m_dwIterHolders>0;
2925     }
2926
2927     BOOL IsHeldByRefTaker()
2928     {
2929         LIMITED_METHOD_CONTRACT;
2930         return m_dwRefTakers>0;
2931     }
2932
2933     void IteratorRelease()
2934     {
2935         LIMITED_METHOD_CONTRACT;
2936         _ASSERTE(m_dwIterHolders);
2937         FastInterlockDecrement(&m_dwIterHolders);
2938     }
2939
2940       
2941     void IteratorAcquire()
2942     {
2943         LIMITED_METHOD_CONTRACT;
2944         FastInterlockIncrement(&m_dwIterHolders);
2945     }
2946     
2947 #endif    
2948     BOOL IsActive()
2949     {
2950         LIMITED_METHOD_DAC_CONTRACT;
2951
2952         return m_Stage >= STAGE_ACTIVE;
2953     }
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)
2958     BOOL IsUserActive()
2959     {
2960         LIMITED_METHOD_DAC_CONTRACT;
2961
2962         return m_Stage >= STAGE_ACTIVE && m_Stage <= STAGE_OPEN;
2963     }
2964     BOOL IsValid()
2965     {
2966         LIMITED_METHOD_DAC_CONTRACT;
2967
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.
2971         return TRUE;
2972 #else
2973         return m_Stage > STAGE_CREATING;
2974 #endif
2975     }
2976
2977 #ifdef _DEBUG
2978     BOOL IsBeingCreated()
2979     {
2980         LIMITED_METHOD_CONTRACT;
2981
2982         return m_dwCreationHolders > 0;
2983     }
2984
2985     void IncCreationCount()
2986     {
2987         LIMITED_METHOD_CONTRACT;
2988
2989         FastInterlockIncrement(&m_dwCreationHolders);
2990         _ASSERTE(m_dwCreationHolders > 0);
2991     }
2992
2993     void DecCreationCount()
2994     {
2995         LIMITED_METHOD_CONTRACT;
2996
2997         FastInterlockDecrement(&m_dwCreationHolders);
2998         _ASSERTE(m_dwCreationHolders > -1);
2999     }
3000 #endif
3001     BOOL IsRunningIn(Thread* pThread);
3002
3003     BOOL NotReadyForManagedCode()
3004     {
3005         LIMITED_METHOD_CONTRACT;
3006
3007         return m_Stage < STAGE_READYFORMANAGEDCODE;
3008     }
3009
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);
3014
3015 private:
3016     CrstExplicitInit    m_ReflectionCrst;
3017     CrstExplicitInit    m_RefClassFactCrst;
3018
3019
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
3025
3026     MethodTable* m_rpCLRTypes[WinMDAdapter::RedirectedTypeIndex_Count];
3027
3028     MethodTable* LoadRedirectedType(WinMDAdapter::RedirectedTypeIndex index, WinMDAdapter::FrameworkAssemblyIndex assembly);
3029 #endif // FEATURE_COMINTEROP
3030
3031 public:
3032
3033     CrstBase *GetRefClassFactCrst()
3034     {
3035         LIMITED_METHOD_CONTRACT;
3036
3037         return &m_RefClassFactCrst;
3038     }
3039
3040 #ifndef DACCESS_COMPILE
3041     EEClassFactoryInfoHashTable* GetClassFactHash()
3042     {
3043         STATIC_CONTRACT_THROWS;
3044         STATIC_CONTRACT_GC_TRIGGERS;
3045         STATIC_CONTRACT_FAULT;
3046
3047         if (m_pRefClassFactHash != NULL) {
3048             return m_pRefClassFactHash;
3049         }
3050
3051         return SetupClassFactHash();
3052     }
3053 #endif // DACCESS_COMPILE
3054
3055 #ifdef FEATURE_COMINTEROP
3056     DispIDCache* GetRefDispIDCache()
3057     {
3058         STATIC_CONTRACT_THROWS;
3059         STATIC_CONTRACT_GC_TRIGGERS;
3060         STATIC_CONTRACT_FAULT;
3061
3062         if (m_pRefDispIDCache != NULL) {
3063             return m_pRefDispIDCache;
3064         }
3065
3066         return SetupRefDispIDCache();
3067     }
3068 #endif // FEATURE_COMINTEROP
3069
3070     PTR_LoaderHeap GetStubHeap();
3071     PTR_LoaderHeap GetLowFrequencyHeap();
3072     PTR_LoaderHeap GetHighFrequencyHeap();
3073     virtual PTR_LoaderAllocator GetLoaderAllocator();
3074
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
3079
3080     inline ULONGLONG GetAllocBytes()
3081     {
3082         LIMITED_METHOD_CONTRACT;
3083         ULONGLONG ullTotalAllocBytes = 0;
3084
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)
3088         {
3089             for (DWORD i = 0; i < m_dwNumHeaps; i++)
3090             {
3091                 ullTotalAllocBytes += m_pullAllocBytes[i * ARM_CACHE_LINE_SIZE_ULL];
3092             }
3093         }
3094         return ullTotalAllocBytes;
3095     }
3096
3097     void RecordAllocBytes(size_t allocatedBytes, DWORD dwHeapNumber)
3098     {
3099         LIMITED_METHOD_CONTRACT;
3100         _ASSERTE(dwHeapNumber < m_dwNumHeaps);
3101         
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)
3105         {
3106             m_pullAllocBytes[dwHeapNumber * ARM_CACHE_LINE_SIZE_ULL] += allocatedBytes;
3107         }
3108
3109         ULONGLONG ullTotalAllocBytes = GetAllocBytes();
3110
3111         if ((ullTotalAllocBytes - m_ullLastEtwAllocBytes) >= ARM_ETW_ALLOC_THRESHOLD)
3112         {
3113             m_ullLastEtwAllocBytes = ullTotalAllocBytes;
3114             FireEtwAppDomainMemAllocated((ULONGLONG)this, ullTotalAllocBytes, GetClrInstanceId());
3115         }
3116     }
3117
3118     inline ULONGLONG GetSurvivedBytes()
3119     {
3120         LIMITED_METHOD_CONTRACT;
3121         ULONGLONG ullTotalSurvivedBytes = 0;
3122
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)
3126         {
3127             for (DWORD i = 0; i < m_dwNumHeaps; i++)
3128             {
3129                 ullTotalSurvivedBytes += m_pullSurvivedBytes[i * ARM_CACHE_LINE_SIZE_ULL];
3130             }
3131         }
3132         return ullTotalSurvivedBytes;
3133     }
3134
3135     void RecordSurvivedBytes(size_t promotedBytes, DWORD dwHeapNumber)
3136     {
3137         WRAPPER_NO_CONTRACT;
3138         _ASSERTE(dwHeapNumber < m_dwNumHeaps);
3139    
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)
3143         {
3144             m_pullSurvivedBytes[dwHeapNumber * ARM_CACHE_LINE_SIZE_ULL] += promotedBytes;
3145         }
3146     }
3147
3148     inline void ResetSurvivedBytes()
3149     {
3150         LIMITED_METHOD_CONTRACT;
3151         
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)
3155         {
3156             for (DWORD i = 0; i < m_dwNumHeaps; i++)
3157             {
3158                 m_pullSurvivedBytes[i * ARM_CACHE_LINE_SIZE_ULL] = 0;
3159             }
3160         }
3161     }
3162
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();
3166
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
3171
3172 private:
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
3181
3182     void InitializeDefaultDomainManager ();
3183
3184 public:
3185
3186 protected:
3187     BOOL PostBindResolveAssembly(AssemblySpec  *pPrePolicySpec,
3188                                  AssemblySpec  *pPostPolicySpec,
3189                                  HRESULT        hrBindResult,
3190                                  AssemblySpec **ppFailedSpec);
3191
3192 #ifdef FEATURE_COMINTEROP
3193 public:
3194     void ReleaseRCWs(LPVOID pCtxCookie);
3195     void DetachRCWs();
3196
3197 protected:
3198 #endif // FEATURE_COMINTEROP
3199
3200     LPWSTR m_pwDynamicDir;
3201
3202 private:
3203     void RaiseLoadingAssemblyEvent(DomainAssembly* pAssembly);
3204
3205     friend class DomainAssembly;
3206
3207 private:
3208
3209     BOOL RaiseUnhandledExceptionEvent(OBJECTREF *pSender, OBJECTREF *pThrowable, BOOL isTerminating);
3210     BOOL HasUnhandledExceptionEventHandler();
3211     BOOL RaiseUnhandledExceptionEventNoThrow(OBJECTREF *pSender, OBJECTREF *pThrowable, BOOL isTerminating);
3212     
3213     struct RaiseUnhandled_Args
3214     {
3215         AppDomain *pExceptionDomain;
3216         AppDomain *pTargetDomain;
3217         OBJECTREF *pSender;
3218         OBJECTREF *pThrowable;
3219         BOOL isTerminating;
3220         BOOL *pResult;
3221     };
3222
3223
3224     enum Stage {
3225         STAGE_CREATING,
3226         STAGE_READYFORMANAGEDCODE,
3227         STAGE_ACTIVE,
3228         STAGE_OPEN,
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 
3232         // of the runtime.
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
3242     };
3243     void SetStage(Stage stage)
3244     {
3245         CONTRACTL
3246         {
3247             NOTHROW;
3248             GC_NOTRIGGER;
3249             SO_TOLERANT;
3250             MODE_ANY;
3251         }
3252         CONTRACTL_END;
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);
3258     };
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);
3264
3265     AppDomainLoaderAllocator m_LoaderAllocator;
3266
3267     // List of unloaded LoaderAllocators, protected by code:GetLoaderAllocatorReferencesLock (for now)
3268     LoaderAllocator * m_pDelayedLoaderAllocatorUnloadList;
3269     
3270 public:
3271     
3272     // Register the loader allocator for deletion in code:ShutdownFreeLoaderAllocators.
3273     void RegisterLoaderAllocatorForDeletion(LoaderAllocator * pLoaderAllocator);
3274     
3275 public:
3276     void SetGCRefPoint(int gccounter)
3277     {
3278         LIMITED_METHOD_CONTRACT;
3279         m_LoaderAllocator.SetGCRefPoint(gccounter);
3280     }
3281     int  GetGCRefPoint()
3282     {
3283         LIMITED_METHOD_CONTRACT;
3284         return m_LoaderAllocator.GetGCRefPoint();
3285     }
3286
3287     static USHORT GetOffsetOfId()
3288     {
3289         LIMITED_METHOD_CONTRACT;
3290         size_t ofs = offsetof(class AppDomain, m_dwId);
3291         _ASSERTE(FitsInI2(ofs));
3292         return (USHORT)ofs;
3293     }
3294
3295     
3296     void AddMemoryPressure();
3297     void RemoveMemoryPressure();
3298
3299     void UnlinkClass(MethodTable *pMT);
3300
3301     Assembly *GetRootAssembly()
3302     {
3303         LIMITED_METHOD_CONTRACT;
3304         return m_pRootAssembly;
3305     }
3306
3307 #ifndef DACCESS_COMPILE
3308     void SetRootAssembly(Assembly *pAssembly)
3309     {
3310         LIMITED_METHOD_CONTRACT;
3311         m_pRootAssembly = pAssembly;
3312     }
3313 #endif
3314
3315 private:
3316     SString         m_friendlyName;
3317     PTR_Assembly    m_pRootAssembly;
3318
3319     // General purpose flags.
3320     DWORD           m_dwFlags;
3321
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.
3325
3326     OBJECTHANDLE    m_ExposedObject;
3327
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;
3335 #endif
3336
3337     IUnknown        *m_pComIPForExposedObject;
3338
3339     // Hash table that maps a clsid to a type
3340     PtrHashMap          m_clsidHash;
3341
3342 #ifdef FEATURE_COMINTEROP
3343     // Hash table that maps WinRT class names to MethodTables.
3344     PTR_NameToTypeMapTable m_pNameToTypeMap;
3345     UINT                m_vNameToTypeMapVersion;
3346
3347     UINT                m_nEpoch; // incremented each time m_pNameToTypeMap is enumerated
3348
3349     // Hash table that remembers the last cached WinRT factory object per type per appdomain.
3350     WinRTFactoryCache   *m_pWinRTFactoryCache;
3351
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;
3355     
3356     // this cache stores the RCWs in this domain
3357     RCWCache *m_pRCWCache;
3358
3359     // this cache stores the RCW -> CCW references in this domain
3360     RCWRefCache *m_pRCWRefCache;
3361     
3362     // The method table used for LicenseInteropHelper
3363     MethodTable*    m_pLicenseInteropHelperMT;
3364 #endif // FEATURE_COMINTEROP
3365
3366     AssemblySink*      m_pAsyncPool;  // asynchronous retrival object pool (only one is kept)
3367
3368     // The index of this app domain among existing app domains (starting from 1)
3369     ADIndex m_dwIndex;
3370
3371     // The thread-pool index of this app domain among existing app domains (starting from 1)
3372     TPIndex m_tpIndex;
3373
3374 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
3375     ULONGLONG* m_pullAllocBytes;
3376     ULONGLONG* m_pullSurvivedBytes;
3377     DWORD m_dwNumHeaps;
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
3381     // made.
3382     Volatile<ULONGLONG> m_ullTotalProcessorUsage;
3383 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
3384
3385 #ifdef _DEBUG
3386     struct ThreadTrackInfo;
3387     typedef CDynArray<ThreadTrackInfo *> ThreadTrackInfoList;
3388     ThreadTrackInfoList *m_pThreadTrackInfoList;
3389     DWORD m_TrackSpinLock;
3390 #endif
3391
3392
3393     // IL stub cache with fabricated MethodTable parented by a random module in this AD.
3394     ILStubCache         m_ILStubCache;
3395
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;
3400
3401     Volatile<Stage> m_Stage;
3402
3403     // The default context for this domain
3404     Context *m_pDefaultContext;
3405
3406     ArrayList        m_failedAssemblies;
3407
3408     DomainAssembly * m_anonymouslyHostedDynamicMethodsAssembly;
3409
3410 #ifdef _DEBUG
3411     Volatile<LONG> m_dwIterHolders;
3412     Volatile<LONG> m_dwRefTakers;
3413     Volatile<LONG> m_dwCreationHolders;
3414 #endif
3415
3416     //
3417     // DAC iterator for failed assembly loads
3418     //
3419     class FailedAssemblyIterator
3420     {
3421         ArrayList::Iterator m_i;
3422         
3423       public:
3424         BOOL Next()
3425         {
3426             WRAPPER_NO_CONTRACT;
3427             return m_i.Next();
3428         }
3429         FailedAssembly *GetFailedAssembly()
3430         {
3431             WRAPPER_NO_CONTRACT;
3432             return dac_cast<PTR_FailedAssembly>(m_i.GetElement());
3433         }
3434         SIZE_T GetIndex()
3435         {
3436             WRAPPER_NO_CONTRACT;
3437             return m_i.GetIndex();
3438         }
3439
3440       private:
3441         friend class AppDomain;
3442         // Cannot have constructor so this iterator can be used inside a union
3443         static FailedAssemblyIterator Create(AppDomain *pDomain)
3444         {
3445             WRAPPER_NO_CONTRACT;
3446             FailedAssemblyIterator i;
3447
3448             i.m_i = pDomain->m_failedAssemblies.Iterate();
3449             return i;
3450         }
3451     };
3452     friend class FailedAssemblyIterator;
3453
3454     FailedAssemblyIterator IterateFailedAssembliesEx()
3455     {
3456         WRAPPER_NO_CONTRACT;
3457         return FailedAssemblyIterator::Create(this);
3458     }
3459
3460     //---------------------------------------------------------
3461     // Stub caches for Method stubs
3462     //---------------------------------------------------------
3463
3464 public:
3465
3466 private:
3467     Volatile<BOOL> m_fIsBindingModelLocked;
3468 public:
3469     BOOL IsHostAssemblyResolverInUse();
3470     BOOL IsBindingModelLocked();
3471     BOOL LockBindingModel();
3472
3473     ILStubCache* GetILStubCache()
3474     {
3475         LIMITED_METHOD_CONTRACT;
3476         return &m_ILStubCache;
3477     }
3478
3479     static AppDomain* GetDomain(ILStubCache* pILStubCache)
3480     {
3481         return CONTAINING_RECORD(pILStubCache, AppDomain, m_ILStubCache);
3482     }
3483
3484     enum {
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
3500     };
3501
3502     AssemblySpecBindingCache  m_AssemblyCache;
3503     DomainAssemblyCache       m_UnmanagedCache;
3504     size_t                    m_MemoryPressure;
3505
3506     ArrayList m_NativeDllSearchDirectories;
3507     BOOL m_ReversePInvokeCanEnter;
3508     bool m_ForceTrivialWaitOperations;
3509
3510 public:
3511
3512     BOOL IsImageFromTrustedPath(PEImage* pImage);
3513
3514 #ifdef FEATURE_TYPEEQUIVALENCE
3515 private:
3516     VolatilePtr<TypeEquivalenceHashTable> m_pTypeEquivalenceTable;
3517     CrstExplicitInit m_TypeEquivalenceCrst;
3518 public:
3519     TypeEquivalenceHashTable * GetTypeEquivalenceCache();
3520 #endif
3521
3522     private:
3523
3524 #ifdef DACCESS_COMPILE
3525 public:
3526     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
3527                                    bool enumThis);
3528 #endif
3529
3530 #ifdef FEATURE_MULTICOREJIT
3531
3532 private:
3533     MulticoreJitManager m_MulticoreJitManager;
3534
3535 public:
3536     MulticoreJitManager & GetMulticoreJitManager()
3537     {
3538         LIMITED_METHOD_CONTRACT;
3539
3540         return m_MulticoreJitManager;
3541     }
3542
3543 #endif
3544
3545 #if defined(FEATURE_TIERED_COMPILATION)
3546
3547 public:
3548     TieredCompilationManager * GetTieredCompilationManager()
3549     {
3550         LIMITED_METHOD_CONTRACT;
3551         return &m_tieredCompilationManager;
3552     }
3553
3554 private:
3555     TieredCompilationManager m_tieredCompilationManager;
3556
3557 #endif
3558
3559 #ifdef FEATURE_COMINTEROP
3560
3561 private:
3562
3563 #endif //FEATURE_COMINTEROP
3564
3565 public:
3566
3567 private:
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;
3571
3572     // -------------------------
3573     // IMPORTANT!
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     // -------------------------
3578     
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;
3582
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;
3587
3588 public:
3589     // Returns the current hosted binder, or null if none available.
3590     inline
3591     ICLRPrivBinder * GetCurrentLoadContextHostBinder() const
3592     {
3593         LIMITED_METHOD_CONTRACT;
3594         return m_pCurrentContextHostBinder;
3595     }
3596
3597     // Returns the shared context binder, or null if none available.
3598     inline
3599     ICLRPrivBinder * GetSharedContextHostBinder() const
3600     {
3601         LIMITED_METHOD_CONTRACT;
3602         return m_pSharedContextHostBinder;
3603     }
3604
3605     // Returns the load context binder, or null if none available.
3606     inline
3607     ICLRPrivBinder * GetLoadContextHostBinder() const
3608     {
3609         LIMITED_METHOD_CONTRACT;
3610         return m_pLoadContextHostBinder;
3611     }
3612
3613 #ifndef DACCESS_COMPILE
3614
3615     // This is only called from the ImmersiveDesignerContext code
3616     // It is protected with a managed monitor lock
3617     inline
3618     void SetSharedContextHostBinder(ICLRPrivBinder * pBinder)
3619     {
3620         LIMITED_METHOD_CONTRACT;
3621         pBinder->AddRef();
3622         m_pSharedContextHostBinder = pBinder;
3623     }
3624
3625     // This is called from CorHost2's implementation of ICLRPrivRuntime::CreateAppDomain.
3626     // Should only be called during AppDomain creation.
3627     inline
3628     void SetLoadContextHostBinder(ICLRPrivBinder * pBinder)
3629     {
3630         LIMITED_METHOD_CONTRACT;
3631         pBinder->AddRef();
3632         m_pLoadContextHostBinder = m_pCurrentContextHostBinder = pBinder;
3633     }
3634
3635     inline
3636     void SetCurrentContextHostBinder(ICLRPrivBinder * pBinder)
3637     {
3638         CONTRACTL
3639         {
3640             THROWS;
3641             GC_TRIGGERS;
3642         }
3643         CONTRACTL_END;
3644
3645         LockHolder lh(this);
3646
3647 #ifdef FEATURE_COMINTEROP
3648         if (m_pNameToTypeMap != nullptr)
3649         {
3650             delete m_pNameToTypeMap;
3651             m_pNameToTypeMap = nullptr;
3652         }
3653
3654         m_vNameToTypeMapVersion++;
3655 #endif
3656
3657         m_pCurrentContextHostBinder = pBinder;
3658     }
3659
3660 #endif // DACCESS_COMPILE
3661
3662     // Indicates that a hosted binder is present.
3663     inline
3664     bool HasLoadContextHostBinder()
3665     {
3666         LIMITED_METHOD_CONTRACT;
3667         return m_pLoadContextHostBinder != nullptr;
3668     }
3669
3670     class ComInterfaceReleaseList
3671     {
3672         SArray<IUnknown *> m_objects;
3673     public:
3674         ~ComInterfaceReleaseList()
3675         {
3676             WRAPPER_NO_CONTRACT;
3677
3678             for (COUNT_T i = 0; i < m_objects.GetCount(); i++)
3679             {
3680                 IUnknown *pItf = *(m_objects.GetElements() + i);
3681                 if (pItf != nullptr)
3682                     pItf->Release();
3683             }
3684         }
3685
3686         // Append to the list of object to free. Only use under the AppDomain "LockHolder(pAppDomain)"
3687         void Append(IUnknown *pInterfaceToRelease)
3688         {
3689             WRAPPER_NO_CONTRACT;
3690             m_objects.Append(pInterfaceToRelease);
3691         }
3692     } AppDomainInterfaceReleaseList;
3693
3694 private:
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>
3701     {
3702     public:
3703         typedef PTR_ICLRPrivAssembly key_t;
3704         
3705         static key_t GetKey(element_t const & elem)
3706         {
3707             STATIC_CONTRACT_WRAPPER;
3708             return elem->GetFile()->GetHostAssembly();
3709         }
3710         
3711         static BOOL Equals(key_t key1, key_t key2) 
3712         {
3713             LIMITED_METHOD_CONTRACT;
3714             return dac_cast<TADDR>(key1) == dac_cast<TADDR>(key2);
3715         }
3716         
3717         static count_t Hash(key_t key)
3718         {
3719             STATIC_CONTRACT_LIMITED_METHOD;
3720             //return reinterpret_cast<count_t>(dac_cast<TADDR>(key));
3721             return (count_t)(dac_cast<TADDR>(key));
3722         }
3723         
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; }
3728     };
3729
3730     struct OriginalFileHostAssemblyHashTraits : public HostAssemblyHashTraits
3731     {
3732     public:
3733         static key_t GetKey(element_t const & elem)
3734         {
3735             STATIC_CONTRACT_WRAPPER;
3736             return elem->GetOriginalFile()->GetHostAssembly();
3737         }
3738     };
3739     
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;
3747
3748 public:
3749     // Returns DomainAssembly.
3750     PTR_DomainAssembly FindAssembly(PTR_ICLRPrivAssembly pHostAssembly);
3751     
3752 #ifndef DACCESS_COMPILE
3753 private:
3754     friend void DomainAssembly::Allocate();
3755     friend DomainAssembly::~DomainAssembly();
3756
3757     // Called from DomainAssembly::Begin.
3758     void PublishHostedAssembly(
3759         DomainAssembly* pAssembly);
3760
3761     // Called from DomainAssembly::UpdatePEFile.
3762     void UpdatePublishHostedAssembly(
3763         DomainAssembly* pAssembly,
3764         PTR_PEFile pFile);
3765
3766     // Called from DomainAssembly::~DomainAssembly
3767     void UnPublishHostedAssembly(
3768         DomainAssembly* pAssembly);
3769 #endif // DACCESS_COMPILE
3770
3771 #ifdef FEATURE_PREJIT
3772     friend void DomainFile::InsertIntoDomainFileWithNativeImageList();
3773     Volatile<DomainFile *> m_pDomainFileWithNativeImageList;
3774 public:
3775     DomainFile *GetDomainFilesWithNativeImagesList()
3776     {
3777         LIMITED_METHOD_CONTRACT;
3778         return m_pDomainFileWithNativeImageList;
3779     }
3780 #endif
3781 };  // class AppDomain
3782
3783
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;
3787
3788 // Just a ref holder
3789 typedef ReleaseHolder<AppDomain> AppDomainRefHolder;
3790
3791 typedef VPTR(class SystemDomain) PTR_SystemDomain;
3792
3793 class SystemDomain : public BaseDomain
3794 {
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);
3800
3801     VPTR_VTABLE_CLASS(SystemDomain, BaseDomain)
3802     VPTR_UNIQUE(VPTR_UNIQUE_SystemDomain)
3803     static AppDomain *GetAppDomainAtId(ADID indx);
3804
3805 public:  
3806     static PTR_LoaderAllocator GetGlobalLoaderAllocator();
3807     virtual PTR_LoaderAllocator GetLoaderAllocator() { WRAPPER_NO_CONTRACT; return GetGlobalLoaderAllocator(); }
3808     static AppDomain* GetAppDomainFromId(ADID indx,DWORD ADValidityKind)
3809     {
3810         CONTRACTL
3811         {
3812             NOTHROW;
3813             GC_NOTRIGGER;
3814             MODE_COOPERATIVE;
3815         }
3816         CONTRACTL_END;
3817         AppDomain* pRetVal;
3818         if (indx.m_dwId==DefaultADID)
3819             pRetVal= SystemDomain::System()->DefaultDomain();
3820         else
3821             pRetVal= GetAppDomainAtId(indx);
3822 #ifdef _DEBUG
3823         // Only call CheckADValidity in DEBUG builds for non-NULL return values
3824         if (pRetVal != NULL)
3825             CheckADValidity(pRetVal, ADValidityKind);
3826 #endif        
3827         return pRetVal;
3828     }
3829     //****************************************************************************************
3830     //
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();
3834
3835     //****************************************************************************************
3836     //
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();
3841
3842     //****************************************************************************************
3843     //
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();
3848
3849     //****************************************************************************************
3850     //
3851     // Initializes and shutdowns the single instance of the SystemDomain
3852     // in the EE
3853 #ifndef DACCESS_COMPILE
3854     void *operator new(size_t size, void *pInPlace);
3855     void operator delete(void *pMem);
3856 #endif
3857     void Init();
3858     void Stop();
3859     void Terminate();
3860     static void LazyInitGlobalStringLiteralMap();
3861
3862     //****************************************************************************************
3863     //
3864     // Load the base system classes, these classes are required before
3865     // any other classes are loaded
3866     void LoadBaseSystemClasses();
3867
3868     AppDomain* DefaultDomain()
3869     {
3870         LIMITED_METHOD_DAC_CONTRACT;
3871
3872         return m_pDefaultDomain;
3873     }
3874
3875     // Notification when an assembly is loaded into the system domain
3876     void OnAssemblyLoad(Assembly *assem);
3877
3878     //****************************************************************************************
3879     //
3880     // Global Static to get the one and only system domain
3881     static SystemDomain * System()
3882     {
3883         LIMITED_METHOD_DAC_CONTRACT;
3884
3885         return m_pSystemDomain;
3886     }
3887
3888     static PEAssembly* SystemFile()
3889     {
3890         WRAPPER_NO_CONTRACT;
3891
3892         _ASSERTE(m_pSystemDomain);
3893         return System()->m_pSystemFile;
3894     }
3895
3896     static Assembly* SystemAssembly()
3897     {
3898         WRAPPER_NO_CONTRACT;
3899
3900         return System()->m_pSystemAssembly;
3901     }
3902
3903     static Module* SystemModule()
3904     {
3905         WRAPPER_NO_CONTRACT;
3906
3907         return SystemAssembly()->GetManifestModule();
3908     }
3909
3910     static BOOL IsSystemLoaded()
3911     {
3912         WRAPPER_NO_CONTRACT;
3913
3914         return System()->m_pSystemAssembly != NULL;
3915     }
3916
3917 #ifndef DACCESS_COMPILE
3918     static GlobalStringLiteralMap *GetGlobalStringLiteralMap()
3919     {
3920         WRAPPER_NO_CONTRACT;
3921
3922         if (m_pGlobalStringLiteralMap == NULL)
3923         {
3924             SystemDomain::LazyInitGlobalStringLiteralMap();
3925         }
3926         _ASSERTE(m_pGlobalStringLiteralMap);
3927         return m_pGlobalStringLiteralMap;
3928     }
3929     static GlobalStringLiteralMap *GetGlobalStringLiteralMapNoCreate()
3930     {
3931         LIMITED_METHOD_CONTRACT;
3932
3933         _ASSERTE(m_pGlobalStringLiteralMap);
3934         return m_pGlobalStringLiteralMap;
3935     }
3936 #endif // DACCESS_COMPILE
3937
3938     static void ActivateApplication(int *pReturnValue);
3939
3940     static void InitializeDefaultDomain(BOOL allowRedirects, ICLRPrivBinder * pBinder = NULL);
3941     static void SetupDefaultDomain();
3942     static HRESULT SetupDefaultDomainNoThrow();
3943
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);
3947 #endif
3948     static BOOL SetGlobalSharePolicyUsingAttribute(IMDInternalImport* pScope, mdMethodDef mdMethod);
3949
3950
3951     //****************************************************************************************
3952     //
3953     // Use an already exising & inited Application Domain (e.g. a subclass).
3954     static void LoadDomain(AppDomain     *pDomain);
3955
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);
3964
3965     static bool IsReflectionInvocationMethod(MethodDesc* pMeth);
3966
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()
3971     {
3972         WRAPPER_NO_CONTRACT;
3973         return ::GetAppDomain();
3974     }
3975 #endif //!DACCESS_COMPILE
3976
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
3983
3984     //****************************************************************************************
3985     // Helper function to remove a domain from the system
3986     BOOL RemoveDomain(AppDomain* pDomain); // Does not decrement the reference
3987
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();
3993
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
3999
4000     //****************************************************************************************
4001     // return the dev path
4002
4003 #ifndef DACCESS_COMPILE
4004     void IncrementNumAppDomains ()
4005     {
4006         LIMITED_METHOD_CONTRACT;
4007
4008         s_dNumAppDomains++;
4009     }
4010
4011     void DecrementNumAppDomains ()
4012     {
4013         LIMITED_METHOD_CONTRACT;
4014
4015         s_dNumAppDomains--;
4016     }
4017
4018     ULONG GetNumAppDomains ()
4019     {
4020         LIMITED_METHOD_CONTRACT;
4021
4022         return s_dNumAppDomains;
4023     }
4024 #endif // DACCESS_COMPILE
4025
4026     //
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.
4031     //
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.
4035     //<TODO>
4036     // @todo:
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
4039     //      remoting code.
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.
4043     //</TODO>
4044
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()
4050     {
4051         WRAPPER_NO_CONTRACT;
4052
4053         ArrayListStatic* list = (ArrayListStatic *)&m_appDomainIndexList;
4054         PREFIX_ASSUME(list!=NULL);
4055         return list->GetCount();
4056     }
4057
4058     static ADID GetNewAppDomainId(AppDomain *pAppDomain);
4059     static void ReleaseAppDomainId(ADID indx);
4060     
4061 #ifndef DACCESS_COMPILE
4062     static ADID GetCurrentAppDomainMaxId() { ADID id; id.m_dwId=m_appDomainIdList.GetCount(); return id;}
4063 #endif // DACCESS_COMPILE
4064
4065
4066 #ifndef DACCESS_COMPILE
4067     DWORD RequireAppDomainCleanup()
4068     {
4069         LIMITED_METHOD_CONTRACT;
4070         return m_pDelayedUnloadListOfLoaderAllocators != 0;
4071     }
4072
4073     void AddToDelayedUnloadList(LoaderAllocator * pAllocator)
4074     {
4075         CONTRACTL
4076         {
4077             NOTHROW;
4078             GC_NOTRIGGER;
4079             MODE_COOPERATIVE;
4080         }
4081         CONTRACTL_END;
4082
4083         CrstHolder lh(&m_DelayedUnloadCrst);
4084         pAllocator->m_pLoaderAllocatorDestroyNext=m_pDelayedUnloadListOfLoaderAllocators;
4085         m_pDelayedUnloadListOfLoaderAllocators=pAllocator;
4086
4087         int iGCRefPoint=GCHeapUtilities::GetGCHeap()->CollectionCount(GCHeapUtilities::GetGCHeap()->GetMaxGeneration());
4088         if (GCHeapUtilities::IsGCInProgress())
4089             iGCRefPoint++;
4090         pAllocator->SetGCRefPoint(iGCRefPoint);
4091     }
4092
4093     void ProcessDelayedUnloadLoaderAllocators();
4094     
4095     static void EnumAllStaticGCRefs(promote_func* fn, ScanContext* sc);
4096
4097 #endif // DACCESS_COMPILE
4098
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()
4106     {
4107         LIMITED_METHOD_CONTRACT;
4108         return m_totalSurvivedBytes;
4109     }
4110 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
4111
4112     //****************************************************************************************
4113     // Routines to deal with the base library (currently mscorlib.dll)
4114     LPCWSTR BaseLibrary()
4115     {
4116         WRAPPER_NO_CONTRACT;
4117
4118         return m_BaseLibrary;
4119     }
4120
4121 #ifndef DACCESS_COMPILE
4122     BOOL IsBaseLibrary(SString &path)
4123     {
4124         WRAPPER_NO_CONTRACT;
4125
4126         // See if it is the installation path to mscorlib
4127         if (path.EqualsCaseInsensitive(m_BaseLibrary, PEImage::GetFileSystemLocale()))
4128             return TRUE;
4129
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()))
4134             return TRUE;
4135
4136         return FALSE;
4137     }
4138
4139     BOOL IsBaseLibrarySatellite(SString &path)
4140     {
4141         WRAPPER_NO_CONTRACT;
4142
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()))
4146             return TRUE;
4147
4148         // workaround!  Must implement some code to do this string comparison for
4149         // mscorlib.resources in a culture-specific directory in the GAC.
4150
4151         /*
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()))
4156             return TRUE;
4157         */
4158
4159         return FALSE;
4160     }
4161 #endif // DACCESS_COMPILE
4162
4163     // Return the system directory
4164     LPCWSTR SystemDirectory()
4165     {
4166         WRAPPER_NO_CONTRACT;
4167
4168         return m_SystemDirectory;
4169     }
4170
4171 private:
4172
4173     //****************************************************************************************
4174     // Helper function to create the single COM domain
4175     void CreateDefaultDomain();
4176
4177     //****************************************************************************************
4178     // Helper function to add a domain to the global list
4179     void AddDomain(AppDomain* pDomain);
4180
4181     void CreatePreallocatedExceptions();
4182
4183     void PreallocateSpecialObjects();
4184
4185     //****************************************************************************************
4186     //
4187     static StackWalkAction CallersMethodCallback(CrawlFrame* pCrawlFrame, VOID* pClientData);
4188     static StackWalkAction CallersMethodCallbackWithStackMark(CrawlFrame* pCrawlFrame, VOID* pClientData);
4189
4190 #ifndef DACCESS_COMPILE
4191     // This class is not to be created through normal allocation.
4192     SystemDomain() 
4193     {
4194         STANDARD_VM_CONTRACT;
4195
4196         m_pDefaultDomain = NULL;
4197         m_pDelayedUnloadListOfLoaderAllocators=NULL;
4198
4199         m_GlobalAllocator.Init(this);
4200     }
4201 #endif
4202
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.
4206
4207     GlobalLoaderAllocator m_GlobalAllocator;
4208
4209
4210     InlineSString<100>  m_BaseLibrary;
4211
4212     InlineSString<100>  m_SystemDirectory;
4213
4214
4215     LPWSTR      m_pwDevpath;
4216     DWORD       m_dwDevpath;
4217     BOOL        m_fDevpath;  // have we searched the environment
4218
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>
4221
4222     // Global domain that every one uses
4223     SPTR_DECL(SystemDomain, m_pSystemDomain);
4224
4225     LoaderAllocator * m_pDelayedUnloadListOfLoaderAllocators;
4226
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
4231
4232     SVAL_DECL(ArrayListStatic, m_appDomainIndexList);
4233 #ifndef DACCESS_COMPILE
4234     static CrstStatic m_DelayedUnloadCrst;
4235     static CrstStatic       m_SystemDomainCrst;
4236
4237
4238     static ArrayListStatic  m_appDomainIdList;
4239
4240     static GlobalStringLiteralMap *m_pGlobalStringLiteralMap;
4241
4242     static ULONG       s_dNumAppDomains;  // Maintain a count of children app domains.
4243
4244     static DWORD        m_dwLowestFreeIndex;
4245 #endif // DACCESS_COMPILE
4246
4247 protected:
4248
4249     // These flags let the correct native image of mscorlib to be loaded.
4250     // This is important for hardbinding to it
4251
4252     SVAL_DECL(BOOL, s_fForceDebug);
4253     SVAL_DECL(BOOL, s_fForceProfiling);
4254     SVAL_DECL(BOOL, s_fForceInstrument);
4255
4256 public:
4257     static void     SetCompilationOverrides(BOOL fForceDebug,
4258                                             BOOL fForceProfiling,
4259                                             BOOL fForceInstrument);
4260
4261     static void     GetCompilationOverrides(BOOL * fForceDebug,
4262                                             BOOL * fForceProfiling,
4263                                             BOOL * fForceInstrument);
4264 public:
4265     //****************************************************************************************
4266     //
4267
4268 #ifndef DACCESS_COMPILE
4269 #ifdef _DEBUG
4270 inline static BOOL IsUnderDomainLock() { LIMITED_METHOD_CONTRACT; return m_SystemDomainCrst.OwnedByCurrentThread();};
4271 #endif
4272
4273     // This lock controls adding and removing domains from the system domain
4274     class LockHolder : public CrstHolder
4275     {
4276     public:
4277         LockHolder()
4278             : CrstHolder(&m_SystemDomainCrst)
4279         {
4280             WRAPPER_NO_CONTRACT;
4281         }
4282     };
4283 #endif // DACCESS_COMPILE
4284
4285 public:
4286     DWORD GetTotalNumSizedRefHandles();
4287
4288 #ifdef DACCESS_COMPILE
4289 public:
4290     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
4291                                    bool enumThis);
4292 #endif
4293
4294 };  // class SystemDomain
4295
4296
4297 //
4298 // an UnsafeAppDomainIterator is used to iterate over all existing domains
4299 //
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.)
4304 //
4305 class UnsafeAppDomainIterator
4306 {
4307     friend class SystemDomain;
4308 public:
4309     UnsafeAppDomainIterator(BOOL bOnlyActive)
4310     {
4311         m_bOnlyActive = bOnlyActive;
4312     }
4313
4314     void Init()
4315     {
4316         LIMITED_METHOD_CONTRACT;
4317         SystemDomain* sysDomain = SystemDomain::System();
4318         if (sysDomain)
4319         {
4320             ArrayListStatic* list = &sysDomain->m_appDomainIndexList;
4321             PREFIX_ASSUME(list != NULL);
4322             m_i = list->Iterate();
4323         }
4324         else
4325         {
4326             m_i.SetEmpty();
4327         }
4328
4329         m_pCurrent = NULL;
4330     }
4331
4332     BOOL Next()
4333     {
4334         WRAPPER_NO_CONTRACT;
4335
4336         while (m_i.Next())
4337         {
4338             m_pCurrent = dac_cast<PTR_AppDomain>(m_i.GetElement());
4339             if (m_pCurrent != NULL &&
4340                 (m_bOnlyActive ?
4341                  m_pCurrent->IsActive() : m_pCurrent->IsValid()))
4342             {
4343                 return TRUE;
4344             }
4345         }
4346
4347         m_pCurrent = NULL;
4348         return FALSE;
4349     }
4350
4351     AppDomain * GetDomain()
4352     {
4353         LIMITED_METHOD_DAC_CONTRACT;
4354
4355         return m_pCurrent;
4356     }
4357
4358   private:
4359
4360     ArrayList::Iterator m_i;
4361     AppDomain *         m_pCurrent;
4362     BOOL                m_bOnlyActive;
4363 };  // class UnsafeAppDomainIterator
4364
4365 //
4366 // an AppDomainIterator is used to iterate over all existing domains.
4367 //
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.
4372 //
4373
4374 class AppDomainIterator : public UnsafeAppDomainIterator
4375 {
4376     friend class SystemDomain;
4377
4378   public:
4379     AppDomainIterator(BOOL bOnlyActive) : UnsafeAppDomainIterator(bOnlyActive)
4380     {
4381         WRAPPER_NO_CONTRACT;
4382         Init();
4383     }
4384
4385     ~AppDomainIterator()
4386     {
4387         WRAPPER_NO_CONTRACT;
4388
4389 #ifndef DACCESS_COMPILE
4390         if (GetDomain() != NULL)
4391         {
4392 #ifdef _DEBUG            
4393             GetDomain()->IteratorRelease();
4394 #endif            
4395             GetDomain()->Release();
4396         }
4397 #endif
4398     }
4399
4400     BOOL Next()
4401     {
4402         WRAPPER_NO_CONTRACT;
4403
4404 #ifndef DACCESS_COMPILE
4405         if (GetDomain() != NULL)
4406         {
4407 #ifdef _DEBUG            
4408             GetDomain()->IteratorRelease();
4409 #endif            
4410             GetDomain()->Release();
4411         }
4412
4413         SystemDomain::LockHolder lh;
4414 #endif
4415
4416         if (UnsafeAppDomainIterator::Next())
4417         {
4418 #ifndef DACCESS_COMPILE
4419             GetDomain()->AddRef();
4420 #ifdef _DEBUG            
4421             GetDomain()->IteratorAcquire();
4422 #endif
4423 #endif
4424             return TRUE;
4425         }
4426
4427         return FALSE;
4428     }
4429 };  // class AppDomainIterator
4430
4431 typedef VPTR(class SharedDomain) PTR_SharedDomain;
4432
4433 class SharedDomain : public BaseDomain
4434 {
4435     VPTR_VTABLE_CLASS_AND_CTOR(SharedDomain, BaseDomain)
4436
4437 public:
4438
4439     static void Attach();
4440     static void Detach();
4441
4442     virtual BOOL IsSharedDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; }
4443     virtual PTR_LoaderAllocator GetLoaderAllocator() { WRAPPER_NO_CONTRACT; return SystemDomain::GetGlobalLoaderAllocator(); }
4444
4445     virtual PTR_AppDomain AsAppDomain()
4446     {
4447         LIMITED_METHOD_CONTRACT;
4448         STATIC_CONTRACT_SO_TOLERANT;
4449         _ASSERTE(!"Not an AppDomain");
4450         return NULL;
4451     }
4452
4453     static SharedDomain * GetDomain();
4454
4455     void Init();
4456     void Terminate();
4457
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);
4462
4463 #ifdef FEATURE_LOADER_OPTIMIZATION
4464     void AddShareableAssembly(Assembly * pAssembly);
4465
4466     class SharedAssemblyIterator
4467     {
4468         PtrHashMap::PtrIterator i;
4469         Assembly * m_pAssembly;
4470
4471       public:
4472         SharedAssemblyIterator() :
4473           i(GetDomain() ? GetDomain()->m_assemblyMap.firstBucket() : NULL)
4474         { LIMITED_METHOD_DAC_CONTRACT; }
4475
4476         BOOL Next()
4477         {
4478             WRAPPER_NO_CONTRACT;
4479             SUPPORTS_DAC;
4480
4481             if (i.end())
4482                 return FALSE;
4483
4484             m_pAssembly = PTR_Assembly(dac_cast<TADDR>(i.GetValue()));
4485             ++i;
4486             return TRUE;
4487         }
4488
4489         Assembly * GetAssembly()
4490         {
4491             LIMITED_METHOD_DAC_CONTRACT;
4492
4493             return m_pAssembly;
4494         }
4495
4496       private:
4497         friend class SharedDomain;
4498     };
4499     
4500     Assembly * FindShareableAssembly(SharedAssemblyLocator * pLocator);
4501     SIZE_T GetShareableAssemblyCount();
4502 #endif //FEATURE_LOADER_OPTIMIZATION
4503
4504 private:
4505     friend class SharedAssemblyIterator;
4506     friend class SharedFileLockHolder;
4507     friend class ClrDataAccess;
4508
4509 #ifndef DACCESS_COMPILE
4510     void *operator new(size_t size, void *pInPlace);
4511     void operator delete(void *pMem);
4512 #endif
4513
4514     SPTR_DECL(SharedDomain, m_pSharedDomain);
4515
4516 #ifdef FEATURE_LOADER_OPTIMIZATION
4517     PEFileListLock          m_FileCreateLock;
4518     SIZE_T                  m_nextClassIndex;
4519     PtrHashMap              m_assemblyMap;
4520 #endif
4521     
4522 public:
4523 #ifdef DACCESS_COMPILE
4524     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
4525                                    bool enumThis);
4526 #endif
4527
4528 #ifdef FEATURE_LOADER_OPTIMIZATION
4529     // Hash map comparison function`
4530     static BOOL CompareSharedAssembly(UPTR u1, UPTR u2);
4531 #endif
4532 };
4533
4534 #ifdef FEATURE_LOADER_OPTIMIZATION
4535 class SharedFileLockHolderBase : protected HolderBase<PEFile *>
4536 {
4537   protected:
4538     PEFileListLock      *m_pLock;
4539     ListLockEntry   *m_pLockElement;
4540
4541     SharedFileLockHolderBase(PEFile *value)
4542       : HolderBase<PEFile *>(value)
4543     {
4544         LIMITED_METHOD_CONTRACT;
4545
4546         m_pLock = NULL;
4547         m_pLockElement = NULL;
4548     }
4549
4550 #ifndef DACCESS_COMPILE
4551     void DoAcquire()
4552     {
4553         STATIC_CONTRACT_THROWS;
4554         STATIC_CONTRACT_GC_TRIGGERS;
4555         STATIC_CONTRACT_FAULT;
4556
4557         PEFileListLockHolder lockHolder(m_pLock);
4558
4559         m_pLockElement = m_pLock->FindFileLock(m_value);
4560         if (m_pLockElement == NULL)
4561         {
4562             m_pLockElement = new ListLockEntry(m_pLock, m_value);
4563             m_pLock->AddElement(m_pLockElement);
4564         }
4565         else
4566             m_pLockElement->AddRef();
4567
4568         lockHolder.Release();
4569
4570         m_pLockElement->Enter();
4571     }
4572
4573     void DoRelease()
4574     {
4575         STATIC_CONTRACT_NOTHROW;
4576         STATIC_CONTRACT_GC_TRIGGERS;
4577         STATIC_CONTRACT_FORBID_FAULT;
4578
4579         m_pLockElement->Leave();
4580         m_pLockElement->Release();
4581         m_pLockElement = NULL;
4582     }
4583 #endif // DACCESS_COMPILE
4584 };
4585
4586 class SharedFileLockHolder : public BaseHolder<PEFile *, SharedFileLockHolderBase>
4587 {
4588   public:
4589     DEBUG_NOINLINE SharedFileLockHolder(SharedDomain *pDomain, PEFile *pFile, BOOL Take = TRUE)
4590       : BaseHolder<PEFile *, SharedFileLockHolderBase>(pFile, FALSE)
4591     {
4592         STATIC_CONTRACT_THROWS;
4593         STATIC_CONTRACT_GC_TRIGGERS;
4594         STATIC_CONTRACT_FAULT;
4595         ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
4596
4597         m_pLock = &pDomain->m_FileCreateLock;
4598         if (Take)
4599             Acquire();
4600     }
4601 };
4602 #endif // FEATURE_LOADER_OPTIMIZATION
4603
4604 inline BOOL BaseDomain::IsDefaultDomain()
4605
4606     LIMITED_METHOD_DAC_CONTRACT; 
4607     return (SystemDomain::System()->DefaultDomain() == this);
4608 }
4609
4610 #include "comreflectioncache.inl"
4611
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 
4617 {
4618 private:
4619     // disable the copy ctor
4620     AppDomainCreationHolder(const AppDomainCreationHolder<AppDomainType>&) {}
4621
4622 protected:
4623     AppDomainType* m_pDomain;
4624     BOOL       m_bAcquired;
4625     void ReleaseAppDomainDuringCreation()
4626     {
4627         CONTRACTL
4628         {
4629             NOTHROW;
4630             WRAPPER(GC_TRIGGERS);
4631             PRECONDITION(m_bAcquired);
4632             PRECONDITION(CheckPointer(m_pDomain));
4633         }
4634         CONTRACTL_END;
4635
4636         if (m_pDomain->NotReadyForManagedCode())
4637         {
4638             m_pDomain->Release();
4639         }
4640     };
4641     
4642 public:
4643     AppDomainCreationHolder() 
4644     {
4645         m_pDomain=NULL;
4646         m_bAcquired=FALSE;
4647     };
4648     ~AppDomainCreationHolder()
4649     {
4650         if (m_bAcquired) 
4651         {
4652             Release();
4653         }
4654     };
4655     void Assign(AppDomainType* pDomain)
4656     {
4657         if(m_bAcquired)
4658             Release();
4659         m_pDomain=pDomain;
4660         if(m_pDomain)
4661         {
4662             AppDomain::RefTakerAcquire(m_pDomain);
4663 #ifdef _DEBUG
4664             m_pDomain->IncCreationCount();
4665 #endif // _DEBUG
4666         }
4667         m_bAcquired=TRUE;
4668     };
4669     
4670     void Release()
4671     {
4672         _ASSERTE(m_bAcquired);
4673         if(m_pDomain)
4674         {
4675 #ifdef _DEBUG
4676             m_pDomain->DecCreationCount();
4677 #endif // _DEBUG
4678             if(!m_pDomain->IsDefaultDomain())
4679                 ReleaseAppDomainDuringCreation();
4680             AppDomain::RefTakerRelease(m_pDomain);
4681         };
4682         m_bAcquired=FALSE;
4683     };
4684
4685     AppDomainType* Extract()
4686     {
4687         _ASSERTE(m_bAcquired);
4688         if(m_pDomain)
4689         {
4690 #ifdef _DEBUG
4691             m_pDomain->DecCreationCount();
4692 #endif // _DEBUG
4693             AppDomain::RefTakerRelease(m_pDomain);
4694         }
4695         m_bAcquired=FALSE;
4696         return m_pDomain;
4697     };
4698
4699     AppDomainType* operator ->()
4700     {
4701         _ASSERTE(m_bAcquired);
4702         return m_pDomain;
4703     }
4704
4705     operator AppDomainType*()
4706     {
4707         _ASSERTE(m_bAcquired);
4708         return m_pDomain;
4709     }
4710
4711     void DoneCreating()
4712     {
4713         Extract();
4714     }
4715 };
4716 #endif // !DACCESS_COMPILE && !CROSSGEN_COMPILE
4717
4718 #define INVALID_APPDOMAIN_ID ((DWORD)-1)
4719 #define CURRENT_APPDOMAIN_ID ((ADID)(DWORD)0)
4720
4721 #endif