Set visibility option to hidden (#21924)
[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 "testhookmgr.h"
29 #include "gcheaputilities.h"
30 #include "gchandleutilities.h"
31 #include "../binder/inc/applicationcontext.hpp"
32 #include "rejit.h"
33
34 #ifdef FEATURE_MULTICOREJIT
35 #include "multicorejit.h"
36 #endif
37
38 #ifdef FEATURE_COMINTEROP
39 #include "clrprivbinderwinrt.h"
40 #include "..\md\winmd\inc\adapter.h"
41 #include "winrttypenameconverter.h"
42 #endif // FEATURE_COMINTEROP
43
44 #include "appxutil.h"
45
46 #include "tieredcompilation.h"
47
48 #include "codeversion.h"
49
50 class BaseDomain;
51 class SystemDomain;
52 class AppDomain;
53 class CompilationDomain;
54 class AppDomainEnum;
55 class AssemblySink;
56 class EEMarshalingData;
57 class GlobalStringLiteralMap;
58 class StringLiteralMap;
59 class MngStdInterfacesInfo;
60 class DomainModule;
61 class DomainAssembly;
62 struct InteropMethodTableData;
63 class LoadLevelLimiter;
64 class TypeEquivalenceHashTable;
65 class StringArrayList;
66
67 extern INT64 g_PauseTime;  // Total time in millisecond the CLR has been paused
68
69 #ifdef FEATURE_COMINTEROP
70 class ComCallWrapperCache;
71 struct SimpleComCallWrapper;
72 class RCWRefCache;
73 #endif // FEATURE_COMINTEROP
74
75 #ifdef _MSC_VER
76 #pragma warning(push)
77 #pragma warning(disable : 4200) // Disable zero-sized array warning
78 #endif
79
80
81 GPTR_DECL(IdDispenser,       g_pModuleIndexDispenser);
82
83 // This enum is aligned to System.ExceptionCatcherType. 
84 enum ExceptionCatcher {
85     ExceptionCatcher_ManagedCode = 0,
86     ExceptionCatcher_AppDomainTransition = 1,
87     ExceptionCatcher_COMInterop = 2,    
88 };
89
90 // We would like *ALLOCATECLASS_FLAG to AV (in order to catch errors), so don't change it
91 struct ClassInitFlags {
92     enum
93     {
94         INITIALIZED_FLAG_BIT    = 0,
95         INITIALIZED_FLAG        = 1<<INITIALIZED_FLAG_BIT,
96         ERROR_FLAG_BIT          = 1,
97         ERROR_FLAG              = 1<<ERROR_FLAG_BIT,
98         ALLOCATECLASS_FLAG_BIT  = 2,                    // Bit to avoid racing for InstantiateStaticHandles
99         ALLOCATECLASS_FLAG      = 1<<ALLOCATECLASS_FLAG_BIT,
100         COLLECTIBLE_FLAG_BIT    = 3,
101         COLLECTIBLE_FLAG        = 1<<COLLECTIBLE_FLAG_BIT
102     };
103 };
104
105 struct DomainLocalModule
106 {
107     friend class ClrDataAccess;
108     friend class CheckAsmOffsets;
109     friend struct ThreadLocalModule;
110
111 // 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
112 // It is critically important that no GC is allowed to occur before this pointer is used.
113 #define GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLoaderAllocator, dynamicClassInfoParam, pGCStatics) \
114     {\
115         DomainLocalModule::PTR_DynamicClassInfo dynamicClassInfo = dac_cast<DomainLocalModule::PTR_DynamicClassInfo>(dynamicClassInfoParam);\
116         DomainLocalModule::PTR_DynamicEntry pDynamicEntry = dac_cast<DomainLocalModule::PTR_DynamicEntry>((DomainLocalModule::DynamicEntry*)dynamicClassInfo->m_pDynamicEntry.Load()); \
117         if ((dynamicClassInfo->m_dwFlags) & ClassInitFlags::COLLECTIBLE_FLAG) \
118         {\
119             PTRARRAYREF objArray;\
120             objArray = (PTRARRAYREF)pLoaderAllocator->GetHandleValueFastCannotFailType2( \
121                                         (dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hGCStatics);\
122             *(pGCStatics) = dac_cast<PTR_BYTE>(PTR_READ(PTR_TO_TADDR(OBJECTREFToObject( objArray )) + offsetof(PtrArray, m_Array), objArray->GetNumComponents() * sizeof(void*))) ;\
123         }\
124         else\
125         {\
126             *(pGCStatics) = (dac_cast<DomainLocalModule::PTR_NormalDynamicEntry>(pDynamicEntry))->GetGCStaticsBasePointer();\
127         }\
128     }\
129
130 #define GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLoaderAllocator, dynamicClassInfoParam, pNonGCStatics) \
131     {\
132         DomainLocalModule::PTR_DynamicClassInfo dynamicClassInfo = dac_cast<DomainLocalModule::PTR_DynamicClassInfo>(dynamicClassInfoParam);\
133         DomainLocalModule::PTR_DynamicEntry pDynamicEntry = dac_cast<DomainLocalModule::PTR_DynamicEntry>((DomainLocalModule::DynamicEntry*)(dynamicClassInfo)->m_pDynamicEntry.Load()); \
134         if (((dynamicClassInfo)->m_dwFlags) & ClassInitFlags::COLLECTIBLE_FLAG) \
135         {\
136             if ((dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hNonGCStatics != 0) \
137             { \
138                 U1ARRAYREF objArray;\
139                 objArray = (U1ARRAYREF)pLoaderAllocator->GetHandleValueFastCannotFailType2( \
140                                             (dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hNonGCStatics);\
141                 *(pNonGCStatics) = dac_cast<PTR_BYTE>(PTR_READ( \
142                         PTR_TO_TADDR(OBJECTREFToObject( objArray )) + sizeof(ArrayBase) - DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob(), \
143                             objArray->GetNumComponents() * (DWORD)objArray->GetComponentSize() + DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob())); \
144             } else (*pNonGCStatics) = NULL; \
145         }\
146         else\
147         {\
148             *(pNonGCStatics) = dac_cast<DomainLocalModule::PTR_NormalDynamicEntry>(pDynamicEntry)->GetNonGCStaticsBasePointer();\
149         }\
150     }\
151
152     struct DynamicEntry
153     {
154         static DWORD GetOffsetOfDataBlob();
155     };
156     typedef DPTR(DynamicEntry) PTR_DynamicEntry;
157
158     struct CollectibleDynamicEntry : public DynamicEntry
159     {
160         LOADERHANDLE    m_hGCStatics;
161         LOADERHANDLE    m_hNonGCStatics;
162     };
163     typedef DPTR(CollectibleDynamicEntry) PTR_CollectibleDynamicEntry;
164
165     struct NormalDynamicEntry : public DynamicEntry
166     {
167         PTR_OBJECTREF   m_pGCStatics;
168 #ifdef FEATURE_64BIT_ALIGNMENT
169         // Padding to make m_pDataBlob aligned at MAX_PRIMITIVE_FIELD_SIZE
170         // code:MethodTableBuilder::PlaceRegularStaticFields assumes that the start of the data blob is aligned 
171         SIZE_T          m_padding;
172 #endif
173         BYTE            m_pDataBlob[0];
174
175         inline PTR_BYTE GetGCStaticsBasePointer()
176         {
177             LIMITED_METHOD_CONTRACT;
178             SUPPORTS_DAC;
179             return dac_cast<PTR_BYTE>(m_pGCStatics);
180         }
181         inline PTR_BYTE GetNonGCStaticsBasePointer()
182         {
183             LIMITED_METHOD_CONTRACT
184             SUPPORTS_DAC;
185             return dac_cast<PTR_BYTE>(this);
186         }
187     };
188     typedef DPTR(NormalDynamicEntry) PTR_NormalDynamicEntry;
189
190     struct DynamicClassInfo
191     {
192         VolatilePtr<DynamicEntry, PTR_DynamicEntry>  m_pDynamicEntry;
193         Volatile<DWORD>             m_dwFlags;
194     };
195     typedef DPTR(DynamicClassInfo) PTR_DynamicClassInfo;
196     
197     inline UMEntryThunk * GetADThunkTable()
198     {
199         LIMITED_METHOD_CONTRACT
200         return m_pADThunkTable;
201     }
202
203     inline void SetADThunkTable(UMEntryThunk* pADThunkTable)
204     {
205         LIMITED_METHOD_CONTRACT
206         InterlockedCompareExchangeT(m_pADThunkTable.GetPointer(), pADThunkTable, NULL);
207     }
208
209     // Note the difference between:
210     // 
211     //  GetPrecomputedNonGCStaticsBasePointer() and
212     //  GetPrecomputedStaticsClassData()
213     //
214     //  GetPrecomputedNonGCStaticsBasePointer returns the pointer that should be added to field offsets to retrieve statics
215     //  GetPrecomputedStaticsClassData returns a pointer to the first byte of the precomputed statics block
216     inline TADDR GetPrecomputedNonGCStaticsBasePointer()
217     {
218         LIMITED_METHOD_CONTRACT
219         return dac_cast<TADDR>(this);
220     }
221
222     inline PTR_BYTE GetPrecomputedStaticsClassData()
223     {
224         LIMITED_METHOD_CONTRACT
225         return dac_cast<PTR_BYTE>(this) + offsetof(DomainLocalModule, m_pDataBlob);
226     }
227
228     static SIZE_T GetOffsetOfDataBlob() { return offsetof(DomainLocalModule, m_pDataBlob); }
229     static SIZE_T GetOffsetOfGCStaticPointer() { return offsetof(DomainLocalModule, m_pGCStatics); }
230
231     inline DomainFile* GetDomainFile()
232     {
233         LIMITED_METHOD_CONTRACT
234         SUPPORTS_DAC;
235         return m_pDomainFile;
236     }
237
238 #ifndef DACCESS_COMPILE
239     inline void        SetDomainFile(DomainFile* pDomainFile)
240     {
241         LIMITED_METHOD_CONTRACT
242         m_pDomainFile = pDomainFile;
243     }
244 #endif
245
246     inline PTR_OBJECTREF  GetPrecomputedGCStaticsBasePointer()
247     {
248         LIMITED_METHOD_CONTRACT        
249         return m_pGCStatics;
250     }
251
252     inline PTR_OBJECTREF * GetPrecomputedGCStaticsBasePointerAddress()
253     {
254         LIMITED_METHOD_CONTRACT        
255         return &m_pGCStatics;
256     }
257
258     // Returns bytes so we can add offsets
259     inline PTR_BYTE GetGCStaticsBasePointer(MethodTable * pMT)
260     {
261         WRAPPER_NO_CONTRACT
262         SUPPORTS_DAC;
263
264         if (pMT->IsDynamicStatics())
265         {
266             _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics());
267             return GetDynamicEntryGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator());
268         }
269         else
270         {
271             return dac_cast<PTR_BYTE>(m_pGCStatics);
272         }
273     }
274
275     inline PTR_BYTE GetNonGCStaticsBasePointer(MethodTable * pMT)
276     {
277         WRAPPER_NO_CONTRACT
278         SUPPORTS_DAC;
279
280         if (pMT->IsDynamicStatics())
281         {
282             _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics());
283             return GetDynamicEntryNonGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator());
284         }
285         else
286         {
287             return dac_cast<PTR_BYTE>(this);
288         }
289     }
290
291     inline DynamicClassInfo* GetDynamicClassInfo(DWORD n)
292     {
293         LIMITED_METHOD_CONTRACT
294         SUPPORTS_DAC;
295         _ASSERTE(m_pDynamicClassTable.Load() && m_aDynamicEntries > n);
296         dac_cast<PTR_DynamicEntry>(m_pDynamicClassTable[n].m_pDynamicEntry.Load());
297
298         return &m_pDynamicClassTable[n];
299     }
300
301     // These helpers can now return null, as the debugger may do queries on a type
302     // before the calls to PopulateClass happen
303     inline PTR_BYTE GetDynamicEntryGCStaticsBasePointer(DWORD n, PTR_LoaderAllocator pLoaderAllocator)
304     {
305         CONTRACTL
306         {
307             NOTHROW;
308             GC_NOTRIGGER;
309             MODE_COOPERATIVE;
310             SUPPORTS_DAC;
311         }
312         CONTRACTL_END;
313
314
315         if (n >= m_aDynamicEntries)
316         {
317             return NULL;
318         }
319         
320         DynamicClassInfo* pClassInfo = GetDynamicClassInfo(n);
321         if (!pClassInfo->m_pDynamicEntry)
322         {
323             return NULL;
324         }
325
326         PTR_BYTE retval = NULL;
327
328         GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLoaderAllocator, pClassInfo, &retval);
329
330         return retval;
331     }
332
333     inline PTR_BYTE GetDynamicEntryNonGCStaticsBasePointer(DWORD n, PTR_LoaderAllocator pLoaderAllocator)
334     {
335         CONTRACTL
336         {
337             NOTHROW;
338             GC_NOTRIGGER;
339             MODE_COOPERATIVE;
340             SUPPORTS_DAC;
341         }
342         CONTRACTL_END;
343
344         
345         if (n >= m_aDynamicEntries)
346         {
347             return NULL;
348         }
349         
350         DynamicClassInfo* pClassInfo = GetDynamicClassInfo(n);
351         if (!pClassInfo->m_pDynamicEntry)
352         {
353             return NULL;
354         }
355
356         PTR_BYTE retval = NULL;
357
358         GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLoaderAllocator, pClassInfo, &retval);
359
360         return retval;
361     }
362
363     FORCEINLINE PTR_DynamicClassInfo GetDynamicClassInfoIfInitialized(DWORD n)
364     {
365         WRAPPER_NO_CONTRACT;
366
367         // m_aDynamicEntries is set last, it needs to be checked first
368         if (n >= m_aDynamicEntries)
369         {
370             return NULL;
371         }
372
373         _ASSERTE(m_pDynamicClassTable.Load() != NULL);
374         PTR_DynamicClassInfo pDynamicClassInfo = (PTR_DynamicClassInfo)(m_pDynamicClassTable.Load() + n);
375
376         // INITIALIZED_FLAG is set last, it needs to be checked first
377         if ((pDynamicClassInfo->m_dwFlags & ClassInitFlags::INITIALIZED_FLAG) == 0)
378         {
379             return NULL;
380         }
381
382         PREFIX_ASSUME(pDynamicClassInfo != NULL);
383         return pDynamicClassInfo;
384     }
385
386     // iClassIndex is slightly expensive to compute, so if we already know
387     // it, we can use this helper
388     inline BOOL IsClassInitialized(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
389     {
390         WRAPPER_NO_CONTRACT;
391         return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::INITIALIZED_FLAG) != 0;
392     }
393
394     inline BOOL IsPrecomputedClassInitialized(DWORD classID)
395     {
396         return GetPrecomputedStaticsClassData()[classID] & ClassInitFlags::INITIALIZED_FLAG;
397     }
398     
399     inline BOOL IsClassAllocated(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
400     {
401         WRAPPER_NO_CONTRACT;
402         return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::ALLOCATECLASS_FLAG) != 0;
403     }
404
405     BOOL IsClassInitError(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
406     {
407         WRAPPER_NO_CONTRACT;
408         return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::ERROR_FLAG) != 0;
409     }
410
411     void    SetClassInitialized(MethodTable* pMT);
412     void    SetClassInitError(MethodTable* pMT);
413
414     void    EnsureDynamicClassIndex(DWORD dwID);
415
416     void    AllocateDynamicClass(MethodTable *pMT);
417
418     void    PopulateClass(MethodTable *pMT);
419
420 #ifdef DACCESS_COMPILE
421     void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
422 #endif
423
424     static DWORD OffsetOfDataBlob()
425     {
426         LIMITED_METHOD_CONTRACT;
427         return offsetof(DomainLocalModule, m_pDataBlob);
428     }
429
430     FORCEINLINE MethodTable * GetMethodTableFromClassDomainID(DWORD dwClassDomainID)
431     {
432         DWORD rid = (DWORD)(dwClassDomainID) + 1;
433         TypeHandle th = GetDomainFile()->GetModule()->LookupTypeDef(TokenFromRid(rid, mdtTypeDef));
434         _ASSERTE(!th.IsNull());
435         MethodTable * pMT = th.AsMethodTable();
436         PREFIX_ASSUME(pMT != NULL);
437         return pMT;
438     }
439
440 private:
441     friend void EmitFastGetSharedStaticBase(CPUSTUBLINKER *psl, CodeLabel *init, bool bCCtorCheck);
442
443     void SetClassFlags(MethodTable* pMT, DWORD dwFlags);
444     DWORD GetClassFlags(MethodTable* pMT, DWORD iClassIndex);
445
446     PTR_DomainFile           m_pDomainFile;
447     VolatilePtr<DynamicClassInfo, PTR_DynamicClassInfo> m_pDynamicClassTable;   // used for generics and reflection.emit in memory
448     Volatile<SIZE_T>         m_aDynamicEntries;      // number of entries in dynamic table
449     VolatilePtr<UMEntryThunk> m_pADThunkTable;
450     PTR_OBJECTREF            m_pGCStatics;           // Handle to GC statics of the module
451
452     // In addition to storing the ModuleIndex in the Module class, we also
453     // keep a copy of the ModuleIndex in the DomainLocalModule class. This
454     // allows the thread static JIT helpers to quickly convert a pointer to
455     // a DomainLocalModule into a ModuleIndex.
456     ModuleIndex             m_ModuleIndex;
457
458     // Note that the static offset calculation in code:Module::BuildStaticsOffsets takes the offset m_pDataBlob
459     // into consideration for alignment so we do not need any padding to ensure that the start of the data blob is aligned
460
461     BYTE                     m_pDataBlob[0];         // First byte of the statics blob
462
463     // Layout of m_pDataBlob is:
464     //              ClassInit bytes (hold flags for cctor run, cctor error, etc)
465     //              Non GC Statics
466
467 public:
468
469     // The Module class need to be able to initialized ModuleIndex,
470     // so for now I will make it a friend..
471     friend class Module;
472
473     FORCEINLINE ModuleIndex GetModuleIndex()
474     {
475         LIMITED_METHOD_DAC_CONTRACT;
476         return m_ModuleIndex;
477     }
478
479 };  // struct DomainLocalModule
480
481 #define OFFSETOF__DomainLocalModule__m_pDataBlob_                    (6 * TARGET_POINTER_SIZE)
482 #ifdef FEATURE_64BIT_ALIGNMENT
483 #define OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob (TARGET_POINTER_SIZE /* m_pGCStatics */ + TARGET_POINTER_SIZE /* m_padding */)
484 #else
485 #define OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob TARGET_POINTER_SIZE /* m_pGCStatics */
486 #endif
487
488 typedef DPTR(class DomainLocalBlock) PTR_DomainLocalBlock;
489 class DomainLocalBlock
490 {
491     friend class ClrDataAccess;
492     friend class CheckAsmOffsets;
493
494 private:
495     PTR_AppDomain          m_pDomain;
496     DPTR(PTR_DomainLocalModule) m_pModuleSlots;
497     SIZE_T                 m_aModuleIndices;               // Module entries the shared block has allocated
498
499 public: // used by code generators
500     static SIZE_T GetOffsetOfModuleSlotsPointer() { return offsetof(DomainLocalBlock, m_pModuleSlots);}
501
502 public:
503
504 #ifndef DACCESS_COMPILE
505     DomainLocalBlock()
506       : m_pDomain(NULL),  m_pModuleSlots(NULL), m_aModuleIndices(0) {}
507
508     void    EnsureModuleIndex(ModuleIndex index);
509
510     void Init(AppDomain *pDomain) { LIMITED_METHOD_CONTRACT; m_pDomain = pDomain; }
511 #endif
512
513     void SetModuleSlot(ModuleIndex index, PTR_DomainLocalModule pLocalModule);
514
515     FORCEINLINE PTR_DomainLocalModule GetModuleSlot(ModuleIndex index)
516     {
517         WRAPPER_NO_CONTRACT;
518         SUPPORTS_DAC;
519         _ASSERTE(index.m_dwIndex < m_aModuleIndices);
520         return m_pModuleSlots[index.m_dwIndex];
521     }
522
523     inline PTR_DomainLocalModule GetModuleSlot(MethodTable* pMT)
524     {
525         WRAPPER_NO_CONTRACT;
526         return GetModuleSlot(pMT->GetModuleForStatics()->GetModuleIndex());
527     }
528
529     DomainFile* TryGetDomainFile(ModuleIndex index)
530     {
531         WRAPPER_NO_CONTRACT;
532         SUPPORTS_DAC;
533
534         // the publishing of m_aModuleIndices and m_pModuleSlots is dependent
535         // on the order of accesses; we must ensure that we read from m_aModuleIndices
536         // before m_pModuleSlots.
537         if (index.m_dwIndex < m_aModuleIndices)
538         {
539             MemoryBarrier();
540             if (m_pModuleSlots[index.m_dwIndex])
541             {
542                 return m_pModuleSlots[index.m_dwIndex]->GetDomainFile();
543             }
544         }
545
546         return NULL;
547     }
548
549     DomainFile* GetDomainFile(SIZE_T ModuleID)
550     {
551         WRAPPER_NO_CONTRACT;
552         ModuleIndex index = Module::IDToIndex(ModuleID);
553         _ASSERTE(index.m_dwIndex < m_aModuleIndices);
554         return m_pModuleSlots[index.m_dwIndex]->GetDomainFile();
555     }
556
557 #ifndef DACCESS_COMPILE
558     void SetDomainFile(ModuleIndex index, DomainFile* pDomainFile)
559     {
560         WRAPPER_NO_CONTRACT;
561         _ASSERTE(index.m_dwIndex < m_aModuleIndices);
562         m_pModuleSlots[index.m_dwIndex]->SetDomainFile(pDomainFile);
563     }
564 #endif
565
566 #ifdef DACCESS_COMPILE
567     void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
568 #endif
569
570
571 private:
572
573     //
574     // Low level routines to get & set class entries
575     //
576
577 };
578
579 #ifdef _MSC_VER
580 #pragma warning(pop)
581 #endif
582
583
584 // The large heap handle bucket class is used to contain handles allocated
585 // from an array contained in the large heap.
586 class LargeHeapHandleBucket
587 {
588 public:
589     // Constructor and desctructor.
590     LargeHeapHandleBucket(LargeHeapHandleBucket *pNext, DWORD Size, BaseDomain *pDomain, BOOL bCrossAD = FALSE);
591     ~LargeHeapHandleBucket();
592
593     // This returns the next bucket.
594     LargeHeapHandleBucket *GetNext()
595     {
596         LIMITED_METHOD_CONTRACT;
597
598         return m_pNext;
599     }
600
601     // This returns the number of remaining handle slots.
602     DWORD GetNumRemainingHandles()
603     {
604         LIMITED_METHOD_CONTRACT;
605
606         return m_ArraySize - m_CurrentPos;
607     }
608
609     void ConsumeRemaining()
610     {
611         LIMITED_METHOD_CONTRACT;
612         
613         m_CurrentPos = m_ArraySize;
614     }
615
616     OBJECTREF *TryAllocateEmbeddedFreeHandle();       
617
618     // Allocate handles from the bucket.
619     OBJECTREF* AllocateHandles(DWORD nRequested);
620     OBJECTREF* CurrentPos()
621     {
622         LIMITED_METHOD_CONTRACT;
623         return m_pArrayDataPtr + m_CurrentPos;
624     }
625
626 private:
627     LargeHeapHandleBucket *m_pNext;
628     int m_ArraySize;
629     int m_CurrentPos;
630     int m_CurrentEmbeddedFreePos;
631     OBJECTHANDLE m_hndHandleArray;
632     OBJECTREF *m_pArrayDataPtr;
633 };
634
635
636
637 // The large heap handle table is used to allocate handles that are pointers
638 // to objects stored in an array in the large object heap.
639 class LargeHeapHandleTable
640 {
641 public:
642     // Constructor and desctructor.
643     LargeHeapHandleTable(BaseDomain *pDomain, DWORD InitialBucketSize);
644     ~LargeHeapHandleTable();
645
646     // Allocate handles from the large heap handle table.
647     OBJECTREF* AllocateHandles(DWORD nRequested, BOOL bCrossAD = FALSE);
648
649     // Release object handles allocated using AllocateHandles().
650     void ReleaseHandles(OBJECTREF *pObjRef, DWORD nReleased);    
651
652 private:
653     // The buckets of object handles.
654     LargeHeapHandleBucket *m_pHead;
655
656     // We need to know the containing domain so we know where to allocate handles
657     BaseDomain *m_pDomain;
658
659     // The size of the LargeHeapHandleBuckets.
660     DWORD m_NextBucketSize;
661
662     // for finding and re-using embedded free items in the list
663     LargeHeapHandleBucket *m_pFreeSearchHint;
664     DWORD m_cEmbeddedFree;   
665
666 #ifdef _DEBUG
667
668     // these functions are present to enforce that there is a locking mechanism in place
669     // for each LargeHeapHandleTable even though the code itself does not do the locking
670     // you must tell the table which lock you intend to use and it will verify that it has
671     // in fact been taken before performing any operations
672
673 public:
674     void RegisterCrstDebug(CrstBase *pCrst)
675     {
676         LIMITED_METHOD_CONTRACT;
677
678         // this function must be called exactly once
679         _ASSERTE(pCrst != NULL);
680         _ASSERTE(m_pCrstDebug == NULL);
681         m_pCrstDebug = pCrst;
682     }
683
684 private:
685     // we will assert that this Crst is held before using the object
686     CrstBase *m_pCrstDebug;
687
688 #endif
689     
690 };
691
692 class LargeHeapHandleBlockHolder;
693 void LargeHeapHandleBlockHolder__StaticFree(LargeHeapHandleBlockHolder*);
694
695
696 class LargeHeapHandleBlockHolder:public Holder<LargeHeapHandleBlockHolder*,DoNothing,LargeHeapHandleBlockHolder__StaticFree>
697
698 {
699     LargeHeapHandleTable* m_pTable;
700     DWORD m_Count;
701     OBJECTREF* m_Data;
702 public:
703     FORCEINLINE LargeHeapHandleBlockHolder(LargeHeapHandleTable* pOwner, DWORD nCount)
704     {
705         WRAPPER_NO_CONTRACT;
706         m_Data = pOwner->AllocateHandles(nCount);
707         m_Count=nCount;
708         m_pTable=pOwner;
709     };
710
711     FORCEINLINE void FreeData()
712     {
713         WRAPPER_NO_CONTRACT;
714         for (DWORD i=0;i< m_Count;i++)
715             ClearObjectReference(m_Data+i);
716         m_pTable->ReleaseHandles(m_Data, m_Count);
717     };
718     FORCEINLINE OBJECTREF* operator[] (DWORD idx)
719     {
720         LIMITED_METHOD_CONTRACT;
721         _ASSERTE(idx<m_Count);
722         return &(m_Data[idx]);
723     }
724 };
725
726 FORCEINLINE  void LargeHeapHandleBlockHolder__StaticFree(LargeHeapHandleBlockHolder* pHolder)
727 {
728     WRAPPER_NO_CONTRACT;
729     pHolder->FreeData();
730 };
731
732
733
734
735
736 // The large heap handle bucket class is used to contain handles allocated
737 // from an array contained in the large heap.
738 class ThreadStaticHandleBucket
739 {
740 public:
741     // Constructor and desctructor.
742     ThreadStaticHandleBucket(ThreadStaticHandleBucket *pNext, DWORD Size, BaseDomain *pDomain);
743     ~ThreadStaticHandleBucket();
744
745     // This returns the next bucket.
746     ThreadStaticHandleBucket *GetNext()
747     {
748         LIMITED_METHOD_CONTRACT;
749
750         return m_pNext;
751     }
752
753     // Allocate handles from the bucket.
754     OBJECTHANDLE GetHandles();
755
756 private:
757     ThreadStaticHandleBucket *m_pNext;
758     int m_ArraySize;
759     OBJECTHANDLE m_hndHandleArray;
760 };
761
762
763 // The large heap handle table is used to allocate handles that are pointers
764 // to objects stored in an array in the large object heap.
765 class ThreadStaticHandleTable
766 {
767 public:
768     // Constructor and desctructor.
769     ThreadStaticHandleTable(BaseDomain *pDomain);
770     ~ThreadStaticHandleTable();
771
772     // Allocate handles from the large heap handle table.
773     OBJECTHANDLE AllocateHandles(DWORD nRequested);
774
775 private:
776     // The buckets of object handles.
777     ThreadStaticHandleBucket *m_pHead;
778
779     // We need to know the containing domain so we know where to allocate handles
780     BaseDomain *m_pDomain;
781 };
782
783
784
785
786 //--------------------------------------------------------------------------------------
787 // Base class for domains. It provides an abstract way of finding the first assembly and
788 // for creating assemblies in the the domain. The system domain only has one assembly, it
789 // contains the classes that are logically shared between domains. All other domains can
790 // have multiple assemblies. Iteration is done be getting the first assembly and then
791 // calling the Next() method on the assembly.
792 //
793 // The system domain should be as small as possible, it includes object, exceptions, etc.
794 // which are the basic classes required to load other assemblies. All other classes
795 // should be loaded into the domain. Of coarse there is a trade off between loading the
796 // same classes multiple times, requiring all domains to load certain assemblies (working
797 // set) and being able to specify specific versions.
798 //
799
800 #define LOW_FREQUENCY_HEAP_RESERVE_SIZE        (3 * GetOsPageSize())
801 #define LOW_FREQUENCY_HEAP_COMMIT_SIZE         (1 * GetOsPageSize())
802
803 #define HIGH_FREQUENCY_HEAP_RESERVE_SIZE       (10 * GetOsPageSize())
804 #define HIGH_FREQUENCY_HEAP_COMMIT_SIZE        (1 * GetOsPageSize())
805
806 #define STUB_HEAP_RESERVE_SIZE                 (3 * GetOsPageSize())
807 #define STUB_HEAP_COMMIT_SIZE                  (1 * GetOsPageSize())
808
809 // --------------------------------------------------------------------------------
810 // PE File List lock - for creating list locks on PE files
811 // --------------------------------------------------------------------------------
812
813 class PEFileListLock : public ListLock
814 {
815 public:
816 #ifndef DACCESS_COMPILE
817     ListLockEntry *FindFileLock(PEFile *pFile)
818     {
819         STATIC_CONTRACT_NOTHROW;
820         STATIC_CONTRACT_GC_NOTRIGGER;
821         STATIC_CONTRACT_FORBID_FAULT;
822
823         PRECONDITION(HasLock());
824
825         ListLockEntry *pEntry;
826
827         for (pEntry = m_pHead;
828              pEntry != NULL;
829              pEntry = pEntry->m_pNext)
830         {
831             if (((PEFile *)pEntry->m_data)->Equals(pFile))
832             {
833                 return pEntry;
834             }
835         }
836
837         return NULL;
838     }
839 #endif // DACCESS_COMPILE
840
841     DEBUG_NOINLINE static void HolderEnter(PEFileListLock *pThis)
842     {
843         WRAPPER_NO_CONTRACT;
844         ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
845         
846         pThis->Enter();
847     }
848
849     DLLEXPORT DEBUG_NOINLINE static void HolderLeave(PEFileListLock *pThis)
850     {
851         WRAPPER_NO_CONTRACT;
852         ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
853
854         pThis->Leave();
855     }
856
857     typedef Wrapper<PEFileListLock*, PEFileListLock::HolderEnter, PEFileListLock::HolderLeave> Holder;
858 };
859
860 typedef PEFileListLock::Holder PEFileListLockHolder;
861
862 // Loading infrastructure:
863 //
864 // a DomainFile is a file being loaded.  Files are loaded in layers to enable loading in the
865 // presence of dependency loops.
866 //
867 // FileLoadLevel describes the various levels available.  These are implemented slightly
868 // differently for assemblies and modules, but the basic structure is the same.
869 //
870 // LoadLock and FileLoadLock form the ListLock data structures for files. The FileLoadLock
871 // is specialized in that it allows taking a lock at a particular level.  Basicall any
872 // thread may obtain the lock at a level at which the file has previously been loaded to, but
873 // only one thread may obtain the lock at its current level.
874 //
875 // The PendingLoadQueue is a per thread data structure which serves two purposes.  First, it
876 // holds a "load limit" which automatically restricts the level of recursive loads to be
877 // one less than the current load which is preceding.  This, together with the AppDomain
878 // LoadLock level behavior, will prevent any deadlocks from occuring due to circular
879 // dependencies.  (Note that it is important that the loading logic understands this restriction,
880 // and any given level of loading must deal with the fact that any recursive loads will be partially
881 // unfulfilled in a specific way.)
882 //
883 // The second function is to queue up any unfulfilled load requests for the thread.  These
884 // are then delivered immediately after the current load request is dealt with.
885
886 class FileLoadLock : public ListLockEntry
887 {
888 private:
889     FileLoadLevel           m_level;
890     DomainFile              *m_pDomainFile;
891     HRESULT                 m_cachedHR;
892     ADID                    m_AppDomainId;
893
894 public:
895     static FileLoadLock *Create(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile);
896
897     ~FileLoadLock();
898     DomainFile *GetDomainFile();
899     ADID GetAppDomainId();
900     FileLoadLevel GetLoadLevel();
901
902     // CanAcquire will return FALSE if Acquire will definitely not take the lock due
903     // to levels or deadlock.
904     // (Note that there is a race exiting from the function, where Acquire may end
905     // up not taking the lock anyway if another thread did work in the meantime.)
906     BOOL CanAcquire(FileLoadLevel targetLevel);
907
908     // Acquire will return FALSE and not take the lock if the file
909     // has already been loaded to the target level.  Otherwise,
910     // it will return TRUE and take the lock.
911     //
912     // Note that the taker must release the lock via IncrementLoadLevel.
913     BOOL Acquire(FileLoadLevel targetLevel);
914
915     // CompleteLoadLevel can be called after Acquire returns true
916     // returns TRUE if it updated load level, FALSE if the level was set already
917     BOOL CompleteLoadLevel(FileLoadLevel level, BOOL success);
918
919     void SetError(Exception *ex);
920
921     void AddRef();
922     UINT32 Release() DAC_EMPTY_RET(0);
923
924 private:
925
926     FileLoadLock(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile);
927
928     static void HolderLeave(FileLoadLock *pThis);
929
930 public:
931     typedef Wrapper<FileLoadLock *, DoNothing, FileLoadLock::HolderLeave> Holder;
932
933 };
934
935 typedef FileLoadLock::Holder FileLoadLockHolder;
936
937 #ifndef DACCESS_COMPILE
938     typedef ReleaseHolder<FileLoadLock> FileLoadLockRefHolder;
939 #endif // DACCESS_COMPILE
940
941     typedef ListLockBase<NativeCodeVersion> JitListLock;
942     typedef ListLockEntryBase<NativeCodeVersion> JitListLockEntry;
943
944
945 #ifdef _MSC_VER
946 #pragma warning(push)
947 #pragma warning (disable: 4324) //sometimes 64bit compilers complain about alignment
948 #endif
949 class LoadLevelLimiter
950 {
951     FileLoadLevel                   m_currentLevel;
952     LoadLevelLimiter* m_previousLimit;
953     BOOL m_bActive;
954
955 public:
956
957     LoadLevelLimiter()
958       : m_currentLevel(FILE_ACTIVE),
959       m_previousLimit(NULL),
960       m_bActive(FALSE)
961     {
962         LIMITED_METHOD_CONTRACT;
963     }
964
965     void Activate()
966     {
967         WRAPPER_NO_CONTRACT;
968         m_previousLimit=GetThread()->GetLoadLevelLimiter();
969         if(m_previousLimit)
970             m_currentLevel=m_previousLimit->GetLoadLevel();
971         GetThread()->SetLoadLevelLimiter(this);       
972         m_bActive=TRUE;
973     }
974
975     void Deactivate()
976     {
977         WRAPPER_NO_CONTRACT;
978         if (m_bActive)
979         {
980             GetThread()->SetLoadLevelLimiter(m_previousLimit);
981             m_bActive=FALSE;
982         }
983     }
984
985     ~LoadLevelLimiter()
986     {
987         WRAPPER_NO_CONTRACT;
988
989         // PendingLoadQueues are allocated on the stack during a load, and
990         // shared with all nested loads on the same thread.
991
992         // Make sure the thread pointer gets reset after the
993         // top level queue goes out of scope.
994         if(m_bActive)
995         {
996             Deactivate();
997         }
998     }
999
1000     FileLoadLevel GetLoadLevel()
1001     {
1002         LIMITED_METHOD_CONTRACT;
1003         return m_currentLevel;
1004     }
1005
1006     void SetLoadLevel(FileLoadLevel level)
1007     {
1008         LIMITED_METHOD_CONTRACT;
1009         m_currentLevel = level;
1010     }
1011 };
1012 #ifdef _MSC_VER
1013 #pragma warning (pop) //4324
1014 #endif
1015
1016 #define OVERRIDE_LOAD_LEVEL_LIMIT(newLimit)                    \
1017     LoadLevelLimiter __newLimit;                                                    \
1018     __newLimit.Activate();                                                              \
1019     __newLimit.SetLoadLevel(newLimit);
1020
1021 // A BaseDomain much basic information in a code:AppDomain including
1022 // 
1023 //    * code:#AppdomainHeaps - Heaps for any data structures that will be freed on appdomain unload
1024 //    
1025 class BaseDomain
1026 {
1027     friend class Assembly;
1028     friend class AssemblySpec;
1029     friend class AppDomain;
1030     friend class AppDomainNative;
1031
1032     VPTR_BASE_VTABLE_CLASS(BaseDomain)
1033     VPTR_UNIQUE(VPTR_UNIQUE_BaseDomain)
1034
1035 protected:
1036     // These 2 variables are only used on the AppDomain, but by placing them here
1037     // we reduce the cost of keeping the asmconstants file up to date.
1038
1039     // The creation sequence number of this app domain (starting from 1)
1040     // This ID is generated by the code:SystemDomain::GetNewAppDomainId routine
1041     // The ID are recycled. 
1042     // 
1043     // see also code:ADID 
1044     ADID m_dwId;
1045
1046     DomainLocalBlock    m_sDomainLocalBlock;
1047
1048 public:
1049
1050     class AssemblyIterator;
1051     friend class AssemblyIterator;
1052
1053     // Static initialization.
1054     static void Attach();
1055
1056     //****************************************************************************************
1057     //
1058     // Initialization/shutdown routines for every instance of an BaseDomain.
1059
1060     BaseDomain();
1061     virtual ~BaseDomain() {}
1062     void Init();
1063     void Stop();
1064     void Terminate();
1065
1066     // ID to uniquely identify this AppDomain - used by the AppDomain publishing
1067     // service (to publish the list of all appdomains present in the process),
1068     // which in turn is used by, for eg., the debugger (to decide which App-
1069     // Domain(s) to attach to).
1070     // This is also used by Remoting for routing cross-appDomain calls.
1071     ADID GetId (void)
1072     {
1073         LIMITED_METHOD_DAC_CONTRACT;
1074         return m_dwId;
1075     }
1076     
1077     virtual BOOL IsAppDomain()    { LIMITED_METHOD_DAC_CONTRACT; return FALSE; }
1078
1079     BOOL IsSharedDomain() { LIMITED_METHOD_DAC_CONTRACT; return FALSE; }
1080     BOOL IsDefaultDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; }
1081
1082     PTR_LoaderAllocator GetLoaderAllocator();
1083     virtual PTR_AppDomain AsAppDomain()
1084     {
1085         LIMITED_METHOD_CONTRACT;
1086         _ASSERTE(!"Not an AppDomain");
1087         return NULL;
1088     }
1089
1090 #ifdef FEATURE_COMINTEROP
1091     //****************************************************************************************
1092     //
1093     // This will look up interop data for a method table
1094     //
1095
1096 #endif // FEATURE_COMINTEROP
1097
1098     void SetDisableInterfaceCache()
1099     {
1100         m_fDisableInterfaceCache = TRUE;
1101     }
1102     BOOL GetDisableInterfaceCache()
1103     {
1104         return m_fDisableInterfaceCache;
1105     }
1106
1107 #ifdef FEATURE_COMINTEROP
1108     MngStdInterfacesInfo * GetMngStdInterfacesInfo()
1109     {
1110         LIMITED_METHOD_CONTRACT;
1111
1112         return m_pMngStdInterfacesInfo;
1113     }
1114     
1115     PTR_CLRPrivBinderWinRT GetWinRtBinder()
1116     {
1117         return m_pWinRtBinder;
1118     }
1119 #endif // FEATURE_COMINTEROP
1120     
1121 #ifdef _DEBUG
1122     BOOL OwnDomainLocalBlockLock()
1123     {
1124         WRAPPER_NO_CONTRACT;
1125
1126         return m_DomainLocalBlockCrst.OwnedByCurrentThread();
1127     }
1128 #endif
1129
1130     //****************************************************************************************
1131     // Get the class init lock. The method is limited to friends because inappropriate use
1132     // will cause deadlocks in the system
1133     ListLock*  GetClassInitLock()
1134     {
1135         LIMITED_METHOD_CONTRACT;
1136
1137         return &m_ClassInitLock;
1138     }
1139
1140     JitListLock* GetJitLock()
1141     {
1142         LIMITED_METHOD_CONTRACT;
1143         return &m_JITLock;
1144     }
1145
1146     ListLock* GetILStubGenLock()
1147     {
1148         LIMITED_METHOD_CONTRACT;
1149         return &m_ILStubGenLock;
1150     }
1151
1152     STRINGREF *IsStringInterned(STRINGREF *pString);
1153     STRINGREF *GetOrInternString(STRINGREF *pString);
1154
1155     // Returns an array of OBJECTREF* that can be used to store domain specific data.
1156     // Statics and reflection info (Types, MemberInfo,..) are stored this way
1157     // If ppLazyAllocate != 0, allocation will only take place if *ppLazyAllocate != 0 (and the allocation
1158     // will be properly serialized)
1159     OBJECTREF *AllocateObjRefPtrsInLargeTable(int nRequested, OBJECTREF** ppLazyAllocate = NULL, BOOL bCrossAD = FALSE);
1160
1161 #ifdef FEATURE_PREJIT
1162     // Ensures that the file for logging profile data is open (we only open it once)
1163     // return false on failure
1164     static BOOL EnsureNGenLogFileOpen();
1165 #endif
1166
1167     //****************************************************************************************
1168     // Handles
1169
1170 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
1171     OBJECTHANDLE CreateTypedHandle(OBJECTREF object, HandleType type)
1172     {
1173         WRAPPER_NO_CONTRACT;
1174         return ::CreateHandleCommon(m_handleStore, object, type);
1175     }
1176
1177     OBJECTHANDLE CreateHandle(OBJECTREF object)
1178     {
1179         WRAPPER_NO_CONTRACT;
1180         CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL)
1181         return ::CreateHandle(m_handleStore, object);
1182     }
1183
1184     OBJECTHANDLE CreateWeakHandle(OBJECTREF object)
1185     {
1186         WRAPPER_NO_CONTRACT;
1187         return ::CreateWeakHandle(m_handleStore, object);
1188     }
1189
1190     OBJECTHANDLE CreateShortWeakHandle(OBJECTREF object)
1191     {
1192         WRAPPER_NO_CONTRACT;
1193         return ::CreateShortWeakHandle(m_handleStore, object);
1194     }
1195
1196     OBJECTHANDLE CreateLongWeakHandle(OBJECTREF object)
1197     {
1198         WRAPPER_NO_CONTRACT;
1199         CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL)
1200         return ::CreateLongWeakHandle(m_handleStore, object);
1201     }
1202
1203     OBJECTHANDLE CreateStrongHandle(OBJECTREF object)
1204     {
1205         WRAPPER_NO_CONTRACT;
1206         return ::CreateStrongHandle(m_handleStore, object);
1207     }
1208
1209     OBJECTHANDLE CreatePinningHandle(OBJECTREF object)
1210     {
1211         WRAPPER_NO_CONTRACT;
1212         return ::CreatePinningHandle(m_handleStore, object);
1213     }
1214
1215     OBJECTHANDLE CreateSizedRefHandle(OBJECTREF object)
1216     {
1217         WRAPPER_NO_CONTRACT;
1218         OBJECTHANDLE h;
1219         if (GCHeapUtilities::IsServerHeap())
1220         {
1221             h = ::CreateSizedRefHandle(m_handleStore, object, m_dwSizedRefHandles % m_iNumberOfProcessors);
1222         }
1223         else
1224         {
1225             h = ::CreateSizedRefHandle(m_handleStore, object);
1226         }
1227
1228         InterlockedIncrement((LONG*)&m_dwSizedRefHandles);
1229         return h;
1230     }
1231
1232 #ifdef FEATURE_COMINTEROP
1233     OBJECTHANDLE CreateRefcountedHandle(OBJECTREF object)
1234     {
1235         WRAPPER_NO_CONTRACT;
1236         return ::CreateRefcountedHandle(m_handleStore, object);
1237     }
1238
1239     OBJECTHANDLE CreateWinRTWeakHandle(OBJECTREF object, IWeakReference* pWinRTWeakReference)
1240     {
1241         WRAPPER_NO_CONTRACT;
1242         return ::CreateWinRTWeakHandle(m_handleStore, object, pWinRTWeakReference);
1243     }
1244 #endif // FEATURE_COMINTEROP
1245
1246     OBJECTHANDLE CreateVariableHandle(OBJECTREF object, UINT type)
1247     {
1248         WRAPPER_NO_CONTRACT;
1249         return ::CreateVariableHandle(m_handleStore, object, type);
1250     }
1251
1252     OBJECTHANDLE CreateDependentHandle(OBJECTREF primary, OBJECTREF secondary)
1253     {
1254         WRAPPER_NO_CONTRACT;
1255         return ::CreateDependentHandle(m_handleStore, primary, secondary);
1256     }
1257
1258 #endif // DACCESS_COMPILE && !CROSSGEN_COMPILE
1259
1260     IUnknown *GetFusionContext() {LIMITED_METHOD_CONTRACT;  return m_pFusionContext; }
1261     
1262     CLRPrivBinderCoreCLR *GetTPABinderContext() {LIMITED_METHOD_CONTRACT;  return m_pTPABinderContext; }
1263
1264
1265     CrstExplicitInit * GetLoaderAllocatorReferencesLock()
1266     {
1267         LIMITED_METHOD_CONTRACT;
1268         return &m_crstLoaderAllocatorReferences;
1269     }
1270     
1271 protected:
1272     
1273     //****************************************************************************************
1274     // Helper method to initialize the large heap handle table.
1275     void InitLargeHeapHandleTable();
1276
1277     //****************************************************************************************
1278     // Adds an assembly to the domain.
1279     void AddAssemblyNoLock(Assembly* assem);
1280
1281     //****************************************************************************************
1282     //
1283     // Hash table that maps a MethodTable to COM Interop compatibility data.
1284     PtrHashMap          m_interopDataHash;
1285
1286     // Critical sections & locks
1287     PEFileListLock   m_FileLoadLock;            // Protects the list of assemblies in the domain
1288     CrstExplicitInit m_DomainCrst;              // General Protection for the Domain
1289     CrstExplicitInit m_DomainCacheCrst;         // Protects the Assembly and Unmanaged caches
1290     CrstExplicitInit m_DomainLocalBlockCrst;
1291     CrstExplicitInit m_InteropDataCrst;         // Used for COM Interop compatiblilty
1292     // Used to protect the reference lists in the collectible loader allocators attached to this appdomain
1293     CrstExplicitInit m_crstLoaderAllocatorReferences;
1294     CrstExplicitInit m_WinRTFactoryCacheCrst;   // For WinRT factory cache
1295     
1296     //#AssemblyListLock
1297     // Used to protect the assembly list. Taken also by GC or debugger thread, therefore we have to avoid 
1298     // triggering GC while holding this lock (by switching the thread to GC_NOTRIGGER while it is held).
1299     CrstExplicitInit m_crstAssemblyList;
1300     BOOL             m_fDisableInterfaceCache;  // RCW COM interface cache
1301     ListLock         m_ClassInitLock;
1302     JitListLock      m_JITLock;
1303     ListLock         m_ILStubGenLock;
1304
1305     // Fusion context, used for adding assemblies to the is domain. It defines
1306     // fusion properties for finding assemblyies such as SharedBinPath,
1307     // PrivateBinPath, Application Directory, etc.
1308     IUnknown *m_pFusionContext; // Current binding context for the domain
1309
1310     CLRPrivBinderCoreCLR *m_pTPABinderContext; // Reference to the binding context that holds TPA list details
1311
1312     IGCHandleStore* m_handleStore;
1313
1314     // The large heap handle table.
1315     LargeHeapHandleTable        *m_pLargeHeapHandleTable;
1316
1317     // The large heap handle table critical section.
1318     CrstExplicitInit             m_LargeHeapHandleTableCrst;
1319
1320 #ifdef FEATURE_COMINTEROP
1321     // Information regarding the managed standard interfaces.
1322     MngStdInterfacesInfo        *m_pMngStdInterfacesInfo;
1323     
1324     // WinRT binder
1325     PTR_CLRPrivBinderWinRT m_pWinRtBinder;
1326 #endif // FEATURE_COMINTEROP
1327
1328     // Protects allocation of slot IDs for thread statics
1329     static CrstStatic   m_SpecialStaticsCrst;
1330
1331 public:
1332     // Only call this routine when you can guarantee there are no
1333     // loads in progress.
1334     void ClearFusionContext();
1335
1336     //****************************************************************************************
1337     // Synchronization holders.
1338
1339     class LockHolder : public CrstHolder
1340     {
1341     public:
1342         LockHolder(BaseDomain *pD)
1343             : CrstHolder(&pD->m_DomainCrst)
1344         {
1345             WRAPPER_NO_CONTRACT;
1346         }
1347     };
1348     friend class LockHolder;
1349
1350     class CacheLockHolder : public CrstHolder
1351     {
1352     public:
1353         CacheLockHolder(BaseDomain *pD)
1354             : CrstHolder(&pD->m_DomainCacheCrst)
1355         {
1356             WRAPPER_NO_CONTRACT;
1357         }
1358     };
1359     friend class CacheLockHolder;
1360
1361     class DomainLocalBlockLockHolder : public CrstHolder
1362     {
1363     public:
1364         DomainLocalBlockLockHolder(BaseDomain *pD)
1365             : CrstHolder(&pD->m_DomainLocalBlockCrst)
1366         {
1367             WRAPPER_NO_CONTRACT;
1368         }
1369     };
1370     friend class DomainLocalBlockLockHolder;
1371
1372     class LoadLockHolder :  public PEFileListLockHolder
1373     {
1374     public:
1375         LoadLockHolder(BaseDomain *pD, BOOL Take = TRUE)
1376           : PEFileListLockHolder(&pD->m_FileLoadLock, Take)
1377         {
1378             CONTRACTL
1379             {
1380                 NOTHROW;
1381                 GC_NOTRIGGER;
1382                 MODE_ANY;
1383                 CAN_TAKE_LOCK;
1384             }
1385             CONTRACTL_END;
1386         }
1387     };
1388     friend class LoadLockHolder;
1389     class WinRTFactoryCacheLockHolder : public CrstHolder
1390     {
1391     public:
1392         WinRTFactoryCacheLockHolder(BaseDomain *pD)
1393             : CrstHolder(&pD->m_WinRTFactoryCacheCrst)
1394         {
1395             WRAPPER_NO_CONTRACT;
1396         }
1397     };
1398     friend class WinRTFactoryCacheLockHolder;
1399
1400 public:
1401     void InitVSD();
1402     RangeList *GetCollectibleVSDRanges() { return &m_collVSDRanges; }
1403
1404 private:
1405     TypeIDMap m_typeIDMap;
1406     // Range list for collectible types. Maps VSD PCODEs back to the VirtualCallStubManager they belong to
1407     LockedRangeList m_collVSDRanges;
1408
1409 public:
1410     UINT32 GetTypeID(PTR_MethodTable pMT);
1411     UINT32 LookupTypeID(PTR_MethodTable pMT);
1412     PTR_MethodTable LookupType(UINT32 id);
1413 #ifndef DACCESS_COMPILE
1414     void RemoveTypesFromTypeIDMap(LoaderAllocator* pLoaderAllocator);
1415 #endif // DACCESS_COMPILE
1416
1417 private:
1418     // I have yet to figure out an efficent way to get the number of handles 
1419     // of a particular type that's currently used by the process without 
1420     // spending more time looking at the handle table code. We know that 
1421     // our only customer (asp.net) in Dev10 is not going to create many of 
1422     // these handles so I am taking a shortcut for now and keep the sizedref
1423     // handle count on the AD itself.
1424     DWORD m_dwSizedRefHandles;
1425
1426     static int m_iNumberOfProcessors;
1427
1428 public:
1429     // Called by DestroySizedRefHandle
1430     void DecNumSizedRefHandles()
1431     {
1432         WRAPPER_NO_CONTRACT;
1433         LONG result;
1434         result = InterlockedDecrement((LONG*)&m_dwSizedRefHandles);
1435         _ASSERTE(result >= 0);
1436     }
1437
1438     DWORD GetNumSizedRefHandles()
1439     {
1440         return m_dwSizedRefHandles;
1441     }
1442
1443 #ifdef FEATURE_CODE_VERSIONING
1444 private:
1445     CodeVersionManager m_codeVersionManager;
1446
1447 public:
1448     CodeVersionManager* GetCodeVersionManager() { return &m_codeVersionManager; }
1449 #endif //FEATURE_CODE_VERSIONING
1450
1451 #ifdef DACCESS_COMPILE
1452 public:
1453     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
1454                                    bool enumThis);
1455 #endif
1456
1457 };  // class BaseDomain
1458
1459 enum
1460 {
1461     ATTACH_ASSEMBLY_LOAD = 0x1,
1462     ATTACH_MODULE_LOAD = 0x2,
1463     ATTACH_CLASS_LOAD = 0x4,
1464
1465     ATTACH_ALL = 0x7
1466 };
1467
1468 // This filters the output of IterateAssemblies. This ought to be declared more locally
1469 // but it would result in really verbose callsites.
1470 //
1471 // Assemblies can be categorized by their load status (loaded, loading, or loaded just
1472 // enough that they would be made available to profilers)
1473 // Independently, they can also be categorized as execution or introspection.
1474 //
1475 // An assembly will be included in the results of IterateAssemblies only if
1476 // the appropriate bit is set for *both* characterizations.
1477 //
1478 // The flags can be combined so if you want all loaded assemblies, you must specify:
1479 //
1480 ///     kIncludeLoaded|kIncludeExecution
1481
1482 enum AssemblyIterationFlags
1483 {
1484     // load status flags
1485     kIncludeLoaded        = 0x00000001, // include assemblies that are already loaded
1486                                         // (m_level >= code:FILE_LOAD_DELIVER_EVENTS)
1487     kIncludeLoading       = 0x00000002, // include assemblies that are still in the process of loading
1488                                         // (all m_level values)
1489     kIncludeAvailableToProfilers
1490                           = 0x00000020, // include assemblies available to profilers
1491                                         // See comment at code:DomainFile::IsAvailableToProfilers
1492
1493     // Execution / introspection flags
1494     kIncludeExecution     = 0x00000004, // include assemblies that are loaded for execution only
1495     
1496     kIncludeFailedToLoad  = 0x00000010, // include assemblies that failed to load 
1497
1498     // Collectible assemblies flags
1499     kExcludeCollectible   = 0x00000040, // Exclude all collectible assemblies
1500     kIncludeCollected     = 0x00000080, 
1501         // Include assemblies which were collected and cannot be referenced anymore. Such assemblies are not 
1502         // AddRef-ed. Any manipulation with them should be protected by code:GetAssemblyListLock.
1503         // Should be used only by code:LoaderAllocator::GCLoaderAllocators.
1504
1505 };  // enum AssemblyIterationFlags
1506
1507 //---------------------------------------------------------------------------------------
1508 // 
1509 // Base class for holder code:CollectibleAssemblyHolder (see code:HolderBase).
1510 // Manages AddRef/Release for collectible assemblies. It is no-op for 'normal' non-collectible assemblies.
1511 // 
1512 // Each type of type parameter needs 2 methods implemented:
1513 //  code:CollectibleAssemblyHolderBase::GetLoaderAllocator
1514 //  code:CollectibleAssemblyHolderBase::IsCollectible
1515 // 
1516 template<typename _Type>
1517 class CollectibleAssemblyHolderBase
1518 {
1519 protected:
1520     _Type m_value;
1521 public:
1522     CollectibleAssemblyHolderBase(const _Type & value = NULL)
1523     {
1524         LIMITED_METHOD_CONTRACT;
1525         m_value = value;
1526     }
1527     void DoAcquire()
1528     {
1529         CONTRACTL
1530         {
1531             NOTHROW;
1532             GC_NOTRIGGER;
1533             MODE_ANY;
1534         }
1535         CONTRACTL_END;
1536         
1537         // We don't need to keep the assembly alive in DAC - see code:#CAH_DAC
1538 #ifndef DACCESS_COMPILE
1539         if (this->IsCollectible(m_value))
1540         {
1541             LoaderAllocator * pLoaderAllocator = GetLoaderAllocator(m_value);
1542             pLoaderAllocator->AddReference();
1543         }
1544 #endif //!DACCESS_COMPILE
1545     }
1546     void DoRelease()
1547     {
1548         CONTRACTL
1549         {
1550             NOTHROW;
1551             GC_NOTRIGGER;
1552             MODE_ANY;
1553         }
1554         CONTRACTL_END;
1555         
1556 #ifndef DACCESS_COMPILE
1557         if (this->IsCollectible(m_value))
1558         {
1559             LoaderAllocator * pLoaderAllocator = GetLoaderAllocator(m_value);
1560             pLoaderAllocator->Release();
1561         }
1562 #endif //!DACCESS_COMPILE
1563     }
1564     
1565 private:
1566     LoaderAllocator * GetLoaderAllocator(DomainAssembly * pDomainAssembly)
1567     {
1568         WRAPPER_NO_CONTRACT;
1569         return pDomainAssembly->GetLoaderAllocator();
1570     }
1571     BOOL IsCollectible(DomainAssembly * pDomainAssembly)
1572     {
1573         WRAPPER_NO_CONTRACT;
1574         return pDomainAssembly->IsCollectible();
1575     }
1576     LoaderAllocator * GetLoaderAllocator(Assembly * pAssembly)
1577     {
1578         WRAPPER_NO_CONTRACT;
1579         return pAssembly->GetLoaderAllocator();
1580     }
1581     BOOL IsCollectible(Assembly * pAssembly)
1582     {
1583         WRAPPER_NO_CONTRACT;
1584         return pAssembly->IsCollectible();
1585     }
1586 };  // class CollectibleAssemblyHolderBase<>
1587
1588 //---------------------------------------------------------------------------------------
1589 // 
1590 // Holder of assembly reference which keeps collectible assembly alive while the holder is valid.
1591 // 
1592 // Collectible assembly can be collected at any point when GC happens. Almost instantly all native data 
1593 // structures of the assembly (e.g. code:DomainAssembly, code:Assembly) could be deallocated. 
1594 // Therefore any usage of (collectible) assembly data structures from native world, has to prevent the 
1595 // deallocation by increasing ref-count on the assembly / associated loader allocator.
1596 // 
1597 // #CAH_DAC
1598 // In DAC we don't AddRef/Release as the assembly doesn't have to be kept alive: The process is stopped when 
1599 // DAC is used and therefore the assembly cannot just disappear.
1600 // 
1601 template<typename _Type>
1602 class CollectibleAssemblyHolder : public BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >
1603 {
1604 public:
1605     FORCEINLINE 
1606     CollectibleAssemblyHolder(const _Type & value = NULL, BOOL fTake = TRUE)
1607         : BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >(value, fTake)
1608     {
1609         STATIC_CONTRACT_WRAPPER;
1610     }
1611     
1612     FORCEINLINE 
1613     CollectibleAssemblyHolder & 
1614     operator=(const _Type & value)
1615     {
1616         STATIC_CONTRACT_WRAPPER;
1617         BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >::operator=(value);
1618         return *this;
1619     }
1620     
1621     // Operator & is overloaded in parent, therefore we have to get to 'this' pointer explicitly.
1622     FORCEINLINE 
1623     CollectibleAssemblyHolder<_Type> * 
1624     This()
1625     {
1626         LIMITED_METHOD_CONTRACT;
1627         return this;
1628     }
1629 };  // class CollectibleAssemblyHolder<>
1630
1631 //---------------------------------------------------------------------------------------
1632 //
1633 // Stores binding information about failed assembly loads for DAC
1634 //
1635 struct FailedAssembly {
1636     SString displayName;
1637     SString location;
1638     HRESULT error;
1639
1640     void Initialize(AssemblySpec *pSpec, Exception *ex)
1641     {
1642         CONTRACTL
1643         {
1644             THROWS;
1645             GC_TRIGGERS;
1646             MODE_ANY;
1647         }
1648         CONTRACTL_END;
1649
1650         displayName.SetASCII(pSpec->GetName());
1651         location.Set(pSpec->GetCodeBase());
1652         error = ex->GetHR();
1653
1654         // 
1655         // Determine the binding context assembly would have been in.
1656         // If the parent has been set, use its binding context.
1657         // If the parent hasn't been set but the code base has, use LoadFrom.
1658         // Otherwise, use the default.
1659         //
1660     }
1661 };
1662
1663 #ifdef FEATURE_COMINTEROP
1664
1665 // Cache used by COM Interop
1666 struct NameToTypeMapEntry
1667 {
1668     // Host space representation of the key
1669     struct Key
1670     {
1671         LPCWSTR m_wzName;     // The type name or registry string representation of the GUID "{<guid>}"
1672         SIZE_T  m_cchName;    // wcslen(m_wzName) for faster hashtable lookup
1673     };
1674     struct DacKey
1675     {
1676         PTR_CWSTR m_wzName;   // The type name or registry string representation of the GUID "{<guid>}"
1677         SIZE_T    m_cchName;  // wcslen(m_wzName) for faster hashtable lookup
1678     } m_key;
1679     TypeHandle m_typeHandle;  // Using TypeHandle instead of MethodTable* to avoid losing information when sharing method tables.
1680     UINT m_nEpoch;            // tracks creation Epoch. This is incremented each time an external reader enumerate the cache
1681     BYTE m_bFlags;
1682 };
1683
1684 typedef DPTR(NameToTypeMapEntry) PTR_NameToTypeMapEntry;
1685
1686 class NameToTypeMapTraits : public NoRemoveSHashTraits< DefaultSHashTraits<NameToTypeMapEntry> >
1687 {
1688 public:
1689     typedef NameToTypeMapEntry::Key key_t;
1690
1691     static const NameToTypeMapEntry Null() { NameToTypeMapEntry e; e.m_key.m_wzName = NULL; e.m_key.m_cchName = 0; return e; }
1692     static bool IsNull(const NameToTypeMapEntry &e) { return e.m_key.m_wzName == NULL; }
1693     static const key_t GetKey(const NameToTypeMapEntry &e) 
1694     {
1695         key_t key;
1696         key.m_wzName = (LPCWSTR)(e.m_key.m_wzName); // this cast brings the string over to the host, in a DAC build
1697         key.m_cchName = e.m_key.m_cchName;
1698
1699         return key;
1700     }
1701     static count_t Hash(const key_t &key) { WRAPPER_NO_CONTRACT; return HashStringN(key.m_wzName, key.m_cchName); }
1702     
1703     static BOOL Equals(const key_t &lhs, const key_t &rhs)
1704     {
1705         WRAPPER_NO_CONTRACT;
1706         return (lhs.m_cchName == rhs.m_cchName) && memcmp(lhs.m_wzName, rhs.m_wzName, lhs.m_cchName * sizeof(WCHAR)) == 0;
1707     }
1708     
1709     void OnDestructPerEntryCleanupAction(const NameToTypeMapEntry& e)
1710     {
1711         WRAPPER_NO_CONTRACT;
1712         _ASSERTE(e.m_key.m_cchName == wcslen(e.m_key.m_wzName));
1713 #ifndef DACCESS_COMPILE
1714         delete [] e.m_key.m_wzName;
1715 #endif // DACCESS_COMPILE
1716     }
1717     static const bool s_DestructPerEntryCleanupAction = true;
1718 };
1719
1720 typedef SHash<NameToTypeMapTraits> NameToTypeMapTable;
1721
1722 typedef DPTR(NameToTypeMapTable) PTR_NameToTypeMapTable;
1723
1724 struct WinRTFactoryCacheEntry
1725 {
1726     typedef MethodTable *Key;           
1727     Key          key;                   // Type as KEY
1728     
1729     CtxEntry    *m_pCtxEntry;           // Context entry - used to verify whether the cache is a match
1730     OBJECTHANDLE m_ohFactoryObject;     // Handle to factory object
1731 };
1732
1733 class WinRTFactoryCacheTraits : public DefaultSHashTraits<WinRTFactoryCacheEntry>
1734 {
1735 public:
1736     typedef WinRTFactoryCacheEntry::Key key_t;
1737     static const WinRTFactoryCacheEntry Null() { WinRTFactoryCacheEntry e; e.key = NULL; return e; }
1738     static bool IsNull(const WinRTFactoryCacheEntry &e) { return e.key == NULL; }
1739     static const WinRTFactoryCacheEntry::Key GetKey(const WinRTFactoryCacheEntry& e) { return e.key; }
1740     static count_t Hash(WinRTFactoryCacheEntry::Key key) { return (count_t)((size_t)key); }
1741     static BOOL Equals(WinRTFactoryCacheEntry::Key lhs, WinRTFactoryCacheEntry::Key rhs)
1742     { return lhs == rhs; }
1743     static const WinRTFactoryCacheEntry Deleted() { WinRTFactoryCacheEntry e; e.key = (MethodTable *)-1; return e; }
1744     static bool IsDeleted(const WinRTFactoryCacheEntry &e) { return e.key == (MethodTable *)-1; }
1745
1746     static void OnDestructPerEntryCleanupAction(const WinRTFactoryCacheEntry& e);
1747     static const bool s_DestructPerEntryCleanupAction = true;
1748 };
1749
1750 typedef SHash<WinRTFactoryCacheTraits> WinRTFactoryCache;
1751
1752 #endif // FEATURE_COMINTEROP
1753
1754 class AppDomainIterator;
1755
1756 const DWORD DefaultADID = 1;
1757
1758 // An Appdomain is the managed equivalent of a process.  It is an isolation unit (conceptually you don't
1759 // have pointers directly from one appdomain to another, but rather go through remoting proxies).  It is
1760 // also a unit of unloading.
1761 // 
1762 // Threads are always running in the context of a particular AppDomain.  See
1763 // file:threads.h#RuntimeThreadLocals for more details.  
1764 // 
1765 // see code:BaseDomain for much of the meat of a AppDomain (heaps locks, etc)
1766 //     * code:AppDomain.m_Assemblies - is a list of code:Assembly in the appdomain
1767 // 
1768 class AppDomain : public BaseDomain
1769 {
1770     friend class SystemDomain;
1771     friend class AssemblySink;
1772     friend class AppDomainNative;
1773     friend class AssemblyNative;
1774     friend class AssemblySpec;
1775     friend class ClassLoader;
1776     friend class ThreadNative;
1777     friend class RCWCache;
1778     friend class ClrDataAccess;
1779     friend class CheckAsmOffsets;
1780
1781     VPTR_VTABLE_CLASS(AppDomain, BaseDomain)
1782
1783 public:
1784 #ifndef DACCESS_COMPILE
1785     AppDomain();
1786     virtual ~AppDomain();
1787     static void Create();
1788 #endif
1789
1790     DomainAssembly* FindDomainAssembly(Assembly*);
1791
1792     //-----------------------------------------------------------------------------------------------------------------
1793     // Convenience wrapper for ::GetAppDomain to provide better encapsulation.
1794     static PTR_AppDomain GetCurrentDomain()
1795     { return m_pTheAppDomain; }
1796     
1797     //-----------------------------------------------------------------------------------------------------------------
1798     // Initializes an AppDomain. (this functions is not called from the SystemDomain)
1799     void Init();
1800
1801 #if defined(FEATURE_COMINTEROP)
1802     HRESULT SetWinrtApplicationContext(LPCWSTR pwzAppLocalWinMD);
1803 #endif // FEATURE_COMINTEROP
1804
1805     bool MustForceTrivialWaitOperations();
1806     void SetForceTrivialWaitOperations();
1807
1808     //****************************************************************************************
1809     //
1810     // Stop deletes all the assemblies but does not remove other resources like
1811     // the critical sections
1812     void Stop();
1813
1814     // Gets rid of resources
1815     void Terminate();
1816
1817 #ifdef  FEATURE_PREJIT
1818     //assembly cleanup that requires suspended runtime
1819     void DeleteNativeCodeRanges();
1820 #endif
1821
1822     // final assembly cleanup
1823     void ShutdownAssemblies();
1824     void ShutdownFreeLoaderAllocators(BOOL bFromManagedCode);
1825     
1826     void ReleaseDomainBoundInfo();
1827     void ReleaseFiles();
1828     
1829
1830     // Remove the Appdomain for the system and cleans up. This call should not be
1831     // called from shut down code.
1832     void CloseDomain();
1833
1834     virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; }
1835     virtual PTR_AppDomain AsAppDomain() { LIMITED_METHOD_CONTRACT; return dac_cast<PTR_AppDomain>(this); }
1836
1837     OBJECTREF GetRawExposedObject() { LIMITED_METHOD_CONTRACT; return NULL; }
1838     OBJECTHANDLE GetRawExposedObjectHandleForDebugger() { LIMITED_METHOD_DAC_CONTRACT; return NULL; }
1839
1840 #ifdef FEATURE_COMINTEROP
1841     MethodTable *GetRedirectedType(WinMDAdapter::RedirectedTypeIndex index);
1842 #endif // FEATURE_COMINTEROP
1843
1844
1845     //****************************************************************************************
1846
1847 protected:
1848     // Multi-thread safe access to the list of assemblies
1849     class DomainAssemblyList
1850     {
1851     private:
1852         ArrayList m_array;
1853 #ifdef _DEBUG
1854         AppDomain * dbg_m_pAppDomain;
1855     public:
1856         void Debug_SetAppDomain(AppDomain * pAppDomain)
1857         {
1858             dbg_m_pAppDomain = pAppDomain;
1859         }
1860 #endif //_DEBUG
1861     public:
1862         bool IsEmpty()
1863         {
1864             CONTRACTL {
1865                 NOTHROW;
1866                 GC_NOTRIGGER;
1867                 MODE_ANY;
1868             } CONTRACTL_END;
1869             
1870             // This function can be reliably called without taking the lock, because the first assembly
1871             // added to the arraylist is non-collectible, and the ArrayList itself allows lockless read access
1872             return (m_array.GetCount() == 0);
1873         }
1874         void Clear(AppDomain * pAppDomain)
1875         {
1876             CONTRACTL {
1877                 NOTHROW;
1878                 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
1879                 MODE_ANY;
1880             } CONTRACTL_END;
1881             
1882             _ASSERTE(dbg_m_pAppDomain == pAppDomain);
1883             
1884             CrstHolder ch(pAppDomain->GetAssemblyListLock());
1885             m_array.Clear();
1886         }
1887         
1888         DWORD GetCount(AppDomain * pAppDomain)
1889         {
1890             CONTRACTL {
1891                 NOTHROW;
1892                 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
1893                 MODE_ANY;
1894             } CONTRACTL_END;
1895             
1896             _ASSERTE(dbg_m_pAppDomain == pAppDomain);
1897             
1898             CrstHolder ch(pAppDomain->GetAssemblyListLock());
1899             return GetCount_Unlocked();
1900         }
1901         DWORD GetCount_Unlocked()
1902         {
1903             CONTRACTL {
1904                 NOTHROW;
1905                 GC_NOTRIGGER;
1906                 MODE_ANY;
1907             } CONTRACTL_END;
1908             
1909 #ifndef DACCESS_COMPILE
1910             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
1911 #endif
1912             // code:Append_Unlock guarantees that we do not have more than MAXDWORD items
1913             return m_array.GetCount();
1914         }
1915         
1916         void Get(AppDomain * pAppDomain, DWORD index, CollectibleAssemblyHolder<DomainAssembly *> * pAssemblyHolder)
1917         {
1918             CONTRACTL {
1919                 NOTHROW;
1920                 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
1921                 MODE_ANY;
1922             } CONTRACTL_END;
1923             
1924             _ASSERTE(dbg_m_pAppDomain == pAppDomain);
1925             
1926             CrstHolder ch(pAppDomain->GetAssemblyListLock());
1927             Get_Unlocked(index, pAssemblyHolder);
1928         }
1929         void Get_Unlocked(DWORD index, CollectibleAssemblyHolder<DomainAssembly *> * pAssemblyHolder)
1930         {
1931             CONTRACTL {
1932                 NOTHROW;
1933                 GC_NOTRIGGER;
1934                 MODE_ANY;
1935             } CONTRACTL_END;
1936             
1937             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
1938             *pAssemblyHolder = dac_cast<PTR_DomainAssembly>(m_array.Get(index));
1939         }
1940         // Doesn't lock the assembly list (caller has to hold the lock already).
1941         // Doesn't AddRef the returned assembly (if collectible).
1942         DomainAssembly * Get_UnlockedNoReference(DWORD index)
1943         {
1944             CONTRACTL {
1945                 NOTHROW;
1946                 GC_NOTRIGGER;
1947                 MODE_ANY;
1948                 SUPPORTS_DAC;
1949             } CONTRACTL_END;
1950             
1951 #ifndef DACCESS_COMPILE
1952             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
1953 #endif
1954             return dac_cast<PTR_DomainAssembly>(m_array.Get(index));
1955         }
1956         
1957 #ifndef DACCESS_COMPILE
1958         void Set(AppDomain * pAppDomain, DWORD index, DomainAssembly * pAssembly)
1959         {
1960             CONTRACTL {
1961                 NOTHROW;
1962                 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
1963                 MODE_ANY;
1964             } CONTRACTL_END;
1965             
1966             _ASSERTE(dbg_m_pAppDomain == pAppDomain);
1967             
1968             CrstHolder ch(pAppDomain->GetAssemblyListLock());
1969             return Set_Unlocked(index, pAssembly);
1970         }
1971         void Set_Unlocked(DWORD index, DomainAssembly * pAssembly)
1972         {
1973             CONTRACTL {
1974                 NOTHROW;
1975                 GC_NOTRIGGER;
1976                 MODE_ANY;
1977             } CONTRACTL_END;
1978             
1979             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
1980             m_array.Set(index, pAssembly);
1981         }
1982         
1983         HRESULT Append_Unlocked(DomainAssembly * pAssembly)
1984         {
1985             CONTRACTL {
1986                 NOTHROW;
1987                 GC_NOTRIGGER;
1988                 MODE_ANY;
1989             } CONTRACTL_END;
1990             
1991             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
1992             return m_array.Append(pAssembly);
1993         }
1994 #else //DACCESS_COMPILE
1995         void 
1996         EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
1997         {
1998             SUPPORTS_DAC;
1999             
2000             m_array.EnumMemoryRegions(flags);
2001         }
2002 #endif // DACCESS_COMPILE
2003         
2004         // Should be used only by code:AssemblyIterator::Create
2005         ArrayList::Iterator GetArrayListIterator()
2006         {
2007             return m_array.Iterate();
2008         }
2009     };  // class DomainAssemblyList
2010     
2011     // Conceptually a list of code:Assembly structures, protected by lock code:GetAssemblyListLock
2012     DomainAssemblyList m_Assemblies;
2013     
2014 public:
2015     // Note that this lock switches thread into GC_NOTRIGGER region as GC can take it too.
2016     CrstExplicitInit * GetAssemblyListLock()
2017     {
2018         LIMITED_METHOD_CONTRACT;
2019         return &m_crstAssemblyList;
2020     }
2021     
2022 public:
2023     class AssemblyIterator
2024     {
2025         // AppDomain context with the assembly list
2026         AppDomain *            m_pAppDomain;
2027         ArrayList::Iterator    m_Iterator;
2028         AssemblyIterationFlags m_assemblyIterationFlags;
2029
2030     public:
2031         BOOL Next(CollectibleAssemblyHolder<DomainAssembly *> * pDomainAssemblyHolder);
2032         // Note: Does not lock the assembly list, but AddRefs collectible assemblies.
2033         BOOL Next_Unlocked(CollectibleAssemblyHolder<DomainAssembly *> * pDomainAssemblyHolder);
2034 #ifndef DACCESS_COMPILE
2035     private:
2036         // Can be called only from AppDomain shutdown code:AppDomain::ShutdownAssemblies.
2037         // Note: Does not lock the assembly list and does not AddRefs collectible assemblies.
2038         BOOL Next_UnsafeNoAddRef(DomainAssembly ** ppDomainAssembly);
2039 #endif
2040
2041     private:
2042         inline DWORD GetIndex()
2043         {
2044             LIMITED_METHOD_CONTRACT;
2045             return m_Iterator.GetIndex();
2046         }
2047
2048     private:
2049         friend class AppDomain;
2050         // Cannot have constructor so this iterator can be used inside a union
2051         static AssemblyIterator Create(AppDomain * pAppDomain, AssemblyIterationFlags assemblyIterationFlags)
2052         {
2053             LIMITED_METHOD_CONTRACT;
2054             AssemblyIterator i;
2055
2056             i.m_pAppDomain = pAppDomain;
2057             i.m_Iterator = pAppDomain->m_Assemblies.GetArrayListIterator();
2058             i.m_assemblyIterationFlags = assemblyIterationFlags;
2059             return i;
2060         }
2061     };  // class AssemblyIterator
2062
2063     AssemblyIterator IterateAssembliesEx(AssemblyIterationFlags assemblyIterationFlags)
2064     {
2065         LIMITED_METHOD_CONTRACT;
2066         return AssemblyIterator::Create(this, assemblyIterationFlags);
2067     }
2068
2069 private:
2070     struct NativeImageDependenciesEntry
2071     {
2072         BaseAssemblySpec m_AssemblySpec;
2073         GUID m_guidMVID;
2074     };
2075
2076     class NativeImageDependenciesTraits : public DeleteElementsOnDestructSHashTraits<DefaultSHashTraits<NativeImageDependenciesEntry *> >
2077     {
2078     public:
2079         typedef BaseAssemblySpec *key_t;
2080         static key_t GetKey(NativeImageDependenciesEntry * e) { return &(e->m_AssemblySpec); }
2081
2082         static count_t Hash(key_t k)
2083         {
2084             return k->Hash();
2085         }
2086
2087         static BOOL Equals(key_t lhs, key_t rhs)
2088         {
2089             return lhs->CompareEx(rhs);
2090         }
2091     };
2092
2093     SHash<NativeImageDependenciesTraits> m_NativeImageDependencies;
2094
2095 public:
2096     void CheckForMismatchedNativeImages(AssemblySpec * pSpec, const GUID * pGuid);
2097     BOOL RemoveNativeImageDependency(AssemblySpec* pSpec);
2098
2099 public:
2100     class PathIterator
2101     {
2102         friend class AppDomain;
2103
2104         ArrayList::Iterator m_i;
2105
2106     public:
2107         BOOL Next()
2108         {
2109             WRAPPER_NO_CONTRACT;
2110             return m_i.Next();
2111         }
2112
2113         SString* GetPath()
2114         {
2115             WRAPPER_NO_CONTRACT;
2116             return dac_cast<PTR_SString>(m_i.GetElement());
2117         }
2118     };
2119
2120     PathIterator IterateNativeDllSearchDirectories();
2121     void SetNativeDllSearchDirectories(LPCWSTR paths);
2122     BOOL HasNativeDllSearchDirectories();
2123     void ShutdownNativeDllSearchDirectories();
2124
2125 public:
2126     SIZE_T GetAssemblyCount()
2127     {
2128         WRAPPER_NO_CONTRACT;
2129         return m_Assemblies.GetCount(this);
2130     }
2131
2132     CHECK CheckCanLoadTypes(Assembly *pAssembly);
2133     CHECK CheckCanExecuteManagedCode(MethodDesc* pMD);
2134     CHECK CheckLoading(DomainFile *pFile, FileLoadLevel level);
2135
2136     FileLoadLevel GetDomainFileLoadLevel(DomainFile *pFile);
2137     BOOL IsLoading(DomainFile *pFile, FileLoadLevel level);
2138     static FileLoadLevel GetThreadFileLoadLevel();
2139
2140     void LoadDomainFile(DomainFile *pFile,
2141                         FileLoadLevel targetLevel);
2142
2143     enum FindAssemblyOptions
2144     {
2145         FindAssemblyOptions_None                    = 0x0,
2146         FindAssemblyOptions_IncludeFailedToLoad     = 0x1
2147     };
2148
2149     DomainAssembly * FindAssembly(PEAssembly * pFile, FindAssemblyOptions options = FindAssemblyOptions_None) DAC_EMPTY_RET(NULL);
2150
2151
2152     Assembly *LoadAssembly(AssemblySpec* pIdentity,
2153                            PEAssembly *pFile,
2154                            FileLoadLevel targetLevel);
2155
2156     // this function does not provide caching, you must use LoadDomainAssembly
2157     // unless the call is guaranteed to succeed or you don't need the caching 
2158     // (e.g. if you will FailFast or tear down the AppDomain anyway)
2159     // The main point that you should not bypass caching if you might try to load the same file again, 
2160     // resulting in multiple DomainAssembly objects that share the same PEAssembly for ngen image 
2161     //which is violating our internal assumptions
2162     DomainAssembly *LoadDomainAssemblyInternal( AssemblySpec* pIdentity,
2163                                                 PEAssembly *pFile,
2164                                                 FileLoadLevel targetLevel);
2165
2166     DomainAssembly *LoadDomainAssembly( AssemblySpec* pIdentity,
2167                                         PEAssembly *pFile,
2168                                         FileLoadLevel targetLevel);
2169
2170
2171     CHECK CheckValidModule(Module *pModule);
2172
2173     // private:
2174     void LoadSystemAssemblies();
2175
2176     DomainFile *LoadDomainFile(FileLoadLock *pLock,
2177                                FileLoadLevel targetLevel);
2178
2179     void TryIncrementalLoad(DomainFile *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder);
2180
2181     Assembly *LoadAssemblyHelper(LPCWSTR wszAssembly,
2182                                  LPCWSTR wszCodeBase);
2183
2184 #ifndef DACCESS_COMPILE // needs AssemblySpec
2185
2186     void GetCacheAssemblyList(SetSHash<PTR_DomainAssembly>& assemblyList);
2187
2188     //****************************************************************************************
2189     // Returns and Inserts assemblies into a lookup cache based on the binding information
2190     // in the AssemblySpec. There can be many AssemblySpecs to a single assembly.
2191     DomainAssembly* FindCachedAssembly(AssemblySpec* pSpec, BOOL fThrow=TRUE)
2192     {
2193         WRAPPER_NO_CONTRACT;
2194         return m_AssemblyCache.LookupAssembly(pSpec, fThrow);
2195     }
2196
2197     PEAssembly* FindCachedFile(AssemblySpec* pSpec, BOOL fThrow = TRUE);
2198     BOOL IsCached(AssemblySpec *pSpec);
2199 #endif // DACCESS_COMPILE
2200     void CacheStringsForDAC();
2201
2202     BOOL AddFileToCache(AssemblySpec* pSpec, PEAssembly *pFile, BOOL fAllowFailure = FALSE);
2203     BOOL RemoveFileFromCache(PEAssembly *pFile);
2204
2205     BOOL AddAssemblyToCache(AssemblySpec* pSpec, DomainAssembly *pAssembly);
2206     BOOL RemoveAssemblyFromCache(DomainAssembly* pAssembly);
2207
2208     BOOL AddExceptionToCache(AssemblySpec* pSpec, Exception *ex);
2209     void AddUnmanagedImageToCache(LPCWSTR libraryName, HMODULE hMod);
2210     HMODULE FindUnmanagedImageInCache(LPCWSTR libraryName);
2211     //****************************************************************************************
2212     //
2213     // Adds or removes an assembly to the domain.
2214     void AddAssembly(DomainAssembly * assem);
2215     void RemoveAssembly(DomainAssembly * pAsm);
2216
2217     BOOL ContainsAssembly(Assembly * assem);
2218
2219     //****************************************************************************************
2220     //
2221     // Reference count. When an appdomain is first created the reference is bump
2222     // to one when it is added to the list of domains (see SystemDomain). An explicit
2223     // Removal from the list is necessary before it will be deleted.
2224     ULONG AddRef(void);
2225     ULONG Release(void) DAC_EMPTY_RET(0);
2226
2227     //****************************************************************************************
2228     LPCWSTR GetFriendlyName(BOOL fDebuggerCares = TRUE);
2229     LPCWSTR GetFriendlyNameForDebugger();
2230     LPCWSTR GetFriendlyNameForLogging();
2231 #ifdef DACCESS_COMPILE
2232     PVOID GetFriendlyNameNoSet(bool* isUtf8);
2233 #endif
2234     void SetFriendlyName(LPCWSTR pwzFriendlyName, BOOL fDebuggerCares = TRUE);
2235
2236     //****************************************************************************************
2237
2238     // This can be used to override the binding behavior of the appdomain.   It
2239     // is overridden in the compilation domain.  It is important that all
2240     // static binding goes through this path.
2241     virtual PEAssembly * BindAssemblySpec(
2242         AssemblySpec *pSpec,
2243         BOOL fThrowOnFileNotFound,
2244         BOOL fUseHostBinderIfAvailable = TRUE) DAC_EMPTY_RET(NULL);
2245
2246     HRESULT BindAssemblySpecForHostedBinder(
2247         AssemblySpec *   pSpec, 
2248         IAssemblyName *  pAssemblyName, 
2249         ICLRPrivBinder * pBinder, 
2250         PEAssembly **    ppAssembly) DAC_EMPTY_RET(E_FAIL);
2251     
2252     HRESULT BindHostedPrivAssembly(
2253         PEAssembly *       pParentPEAssembly,
2254         ICLRPrivAssembly * pPrivAssembly, 
2255         IAssemblyName *    pAssemblyName, 
2256         PEAssembly **      ppAssembly) DAC_EMPTY_RET(S_OK);
2257
2258
2259     PEAssembly *TryResolveAssembly(AssemblySpec *pSpec);
2260
2261     // Store a successful binding into the cache.  This will keep the file from
2262     // being physically unmapped, as well as shortcutting future attempts to bind
2263     // the same spec throught the Cached entry point.
2264     //
2265     // Right now we only cache assembly binds for "probing" type
2266     // binding situations, basically when loading domain neutral assemblies or
2267     // zap files.
2268     //
2269     // <TODO>@todo: We may want to be more aggressive about this if
2270     // there are other situations where we are repeatedly binding the
2271     // same assembly specs, though.</TODO>
2272     //
2273     // Returns TRUE if stored
2274     //         FALSE if it's a duplicate (caller should clean up args)
2275     BOOL StoreBindAssemblySpecResult(AssemblySpec *pSpec,
2276                                      PEAssembly *pFile,
2277                                      BOOL clone = TRUE);
2278
2279     BOOL StoreBindAssemblySpecError(AssemblySpec *pSpec,
2280                                     HRESULT hr,
2281                                     OBJECTREF *pThrowable,
2282                                     BOOL clone = TRUE);
2283
2284     //****************************************************************************************
2285     //
2286     //****************************************************************************************
2287     //
2288     // Uses the first assembly to add an application base to the Context. This is done
2289     // in a lazy fashion so executables do not take the perf hit unless the load other
2290     // assemblies
2291 #ifndef DACCESS_COMPILE
2292     void OnAssemblyLoad(Assembly *assem);
2293     void OnAssemblyLoadUnlocked(Assembly *assem);
2294     static BOOL OnUnhandledException(OBJECTREF *pThrowable, BOOL isTerminating = TRUE);
2295     
2296 #endif
2297
2298     // True iff a debugger is attached to the process (same as CORDebuggerAttached)
2299     BOOL IsDebuggerAttached (void);
2300
2301 #ifdef DEBUGGING_SUPPORTED
2302     // Notify debugger of all assemblies, modules, and possibly classes in this AppDomain
2303     BOOL NotifyDebuggerLoad(int flags, BOOL attaching);
2304
2305     // Send unload notifications to the debugger for all assemblies, modules and classes in this AppDomain
2306     void NotifyDebuggerUnload();
2307 #endif // DEBUGGING_SUPPORTED
2308
2309     void SetSystemAssemblyLoadEventSent (BOOL fFlag);
2310     BOOL WasSystemAssemblyLoadEventSent (void);
2311
2312 #ifndef DACCESS_COMPILE
2313     OBJECTREF* AllocateStaticFieldObjRefPtrs(int nRequested, OBJECTREF** ppLazyAllocate = NULL)
2314     {
2315         WRAPPER_NO_CONTRACT;
2316
2317         return AllocateObjRefPtrsInLargeTable(nRequested, ppLazyAllocate);
2318     }
2319
2320     OBJECTREF* AllocateStaticFieldObjRefPtrsCrossDomain(int nRequested, OBJECTREF** ppLazyAllocate = NULL)
2321     {
2322         WRAPPER_NO_CONTRACT;
2323
2324         return AllocateObjRefPtrsInLargeTable(nRequested, ppLazyAllocate, TRUE);
2325     }
2326 #endif // DACCESS_COMPILE
2327
2328     void              EnumStaticGCRefs(promote_func* fn, ScanContext* sc);
2329
2330     DomainLocalBlock *GetDomainLocalBlock()
2331     {
2332         LIMITED_METHOD_DAC_CONTRACT;
2333
2334         return &m_sDomainLocalBlock;
2335     }
2336
2337     static SIZE_T GetOffsetOfModuleSlotsPointer()
2338     {
2339         WRAPPER_NO_CONTRACT;
2340
2341         return offsetof(AppDomain,m_sDomainLocalBlock) + DomainLocalBlock::GetOffsetOfModuleSlotsPointer();
2342     }
2343
2344     void SetupSharedStatics();
2345
2346     //****************************************************************************************
2347     //
2348     // Create a quick lookup for classes loaded into this domain based on their GUID.
2349     //
2350     void InsertClassForCLSID(MethodTable* pMT, BOOL fForceInsert = FALSE);
2351     void InsertClassForCLSID(MethodTable* pMT, GUID *pGuid);
2352
2353 #ifdef FEATURE_COMINTEROP
2354 private:
2355     void CacheTypeByNameWorker(const SString &ssClassName, const UINT vCacheVersion, TypeHandle typeHandle, BYTE flags, BOOL bReplaceExisting = FALSE);
2356     TypeHandle LookupTypeByNameWorker(const SString &ssClassName, UINT *pvCacheVersion, BYTE *pbFlags);
2357 public:
2358     // Used by COM Interop for mapping WinRT runtime class names to real types.
2359     void CacheTypeByName(const SString &ssClassName, const UINT vCacheVersion, TypeHandle typeHandle, BYTE flags, BOOL bReplaceExisting = FALSE);
2360     TypeHandle LookupTypeByName(const SString &ssClassName, UINT *pvCacheVersion, BYTE *pbFlags);
2361     PTR_MethodTable LookupTypeByGuid(const GUID & guid);
2362
2363 #ifndef DACCESS_COMPILE
2364     inline BOOL CanCacheWinRTTypeByGuid(TypeHandle typeHandle)
2365     { 
2366         CONTRACTL
2367         {
2368             THROWS;
2369             GC_NOTRIGGER;
2370             MODE_ANY;
2371         }
2372         CONTRACTL_END;
2373         
2374         // Only allow caching guid/types maps for types loaded during 
2375         // "normal" domain operation
2376         if (IsCompilationDomain() || (m_Stage < STAGE_OPEN))
2377             return FALSE;
2378
2379         MethodTable *pMT = typeHandle.GetMethodTable();
2380         if (pMT != NULL)
2381         {
2382             // Don't cache mscorlib-internal declarations of WinRT types.
2383             if (pMT->GetModule()->IsSystem() && pMT->IsProjectedFromWinRT())
2384                 return FALSE;
2385
2386             // Don't cache redirected WinRT types.
2387             if (WinRTTypeNameConverter::IsRedirectedWinRTSourceType(pMT))
2388                 return FALSE;
2389         }
2390
2391         return TRUE;
2392     }
2393 #endif // !DACCESS_COMPILE
2394
2395     void CacheWinRTTypeByGuid(TypeHandle typeHandle);
2396     void GetCachedWinRTTypes(SArray<PTR_MethodTable> * pTypes, SArray<GUID> * pGuids, UINT minEpoch, UINT * pCurEpoch);
2397
2398     // Used by COM Interop for caching WinRT factory objects.
2399     void CacheWinRTFactoryObject(MethodTable *pClassMT, OBJECTREF *refFactory, LPVOID lpCtxCookie);
2400     OBJECTREF LookupWinRTFactoryObject(MethodTable *pClassMT, LPVOID lpCtxCookie);
2401     void RemoveWinRTFactoryObjects(LPVOID pCtxCookie);
2402
2403     MethodTable *LoadCOMClass(GUID clsid, BOOL bLoadRecord = FALSE, BOOL* pfAssemblyInReg = NULL);
2404     OBJECTREF GetMissingObject();    // DispatchInfo will call function to retrieve the Missing.Value object.
2405 #endif // FEATURE_COMINTEROP
2406
2407 #ifndef DACCESS_COMPILE
2408     MethodTable* LookupClass(REFIID iid)
2409     {
2410         WRAPPER_NO_CONTRACT;
2411
2412         MethodTable *pMT = (MethodTable*) m_clsidHash.LookupValue((UPTR) GetKeyFromGUID(&iid), (LPVOID)&iid);
2413         return (pMT == (MethodTable*) INVALIDENTRY
2414             ? NULL
2415             : pMT);
2416     }
2417 #endif // DACCESS_COMPILE
2418
2419     //<TODO>@todo get a better key</TODO>
2420     ULONG GetKeyFromGUID(const GUID *pguid)
2421     {
2422         LIMITED_METHOD_CONTRACT;
2423
2424         return *(ULONG *) pguid;
2425     }
2426
2427 #ifdef FEATURE_COMINTEROP
2428     RCWCache *GetRCWCache()
2429     {
2430         WRAPPER_NO_CONTRACT;
2431         if (m_pRCWCache) 
2432             return m_pRCWCache;
2433
2434         // By separating the cache creation from the common lookup, we
2435         // can keep the (x86) EH prolog/epilog off the path.
2436         return CreateRCWCache();
2437     }
2438 private:
2439     RCWCache *CreateRCWCache();
2440 public:
2441     RCWCache *GetRCWCacheNoCreate()
2442     {
2443         LIMITED_METHOD_CONTRACT;
2444         return m_pRCWCache;
2445     }
2446
2447     RCWRefCache *GetRCWRefCache();
2448
2449     MethodTable* GetLicenseInteropHelperMethodTable();
2450 #endif // FEATURE_COMINTEROP
2451
2452     //****************************************************************************************
2453     // Get the proxy for this app domain
2454
2455     ADIndex GetIndex()
2456     {
2457         LIMITED_METHOD_CONTRACT;
2458         SUPPORTS_DAC;
2459
2460         return m_dwIndex;
2461     }
2462
2463     TPIndex GetTPIndex()
2464     {
2465         LIMITED_METHOD_CONTRACT;
2466         return m_tpIndex;
2467     }
2468
2469     IUnknown *CreateFusionContext();
2470
2471     void SetIgnoreUnhandledExceptions()
2472     {
2473         LIMITED_METHOD_CONTRACT;
2474
2475         m_dwFlags |= IGNORE_UNHANDLED_EXCEPTIONS;
2476     }
2477
2478     BOOL IgnoreUnhandledExceptions()
2479     {
2480         LIMITED_METHOD_CONTRACT;
2481
2482         return (m_dwFlags & IGNORE_UNHANDLED_EXCEPTIONS);
2483     }
2484
2485     void SetCompilationDomain()
2486     {
2487         LIMITED_METHOD_CONTRACT;
2488
2489         m_dwFlags |= COMPILATION_DOMAIN;
2490     }
2491
2492     BOOL IsCompilationDomain();
2493
2494     PTR_CompilationDomain ToCompilationDomain()
2495     {
2496         LIMITED_METHOD_CONTRACT;
2497
2498         _ASSERTE(IsCompilationDomain());
2499         return dac_cast<PTR_CompilationDomain>(this);
2500     }
2501
2502     static void ExceptionUnwind(Frame *pFrame);
2503
2504 #ifdef _DEBUG
2505     void TrackADThreadEnter(Thread *pThread, Frame *pFrame);
2506     void TrackADThreadExit(Thread *pThread, Frame *pFrame);
2507     void DumpADThreadTrack();
2508 #endif
2509
2510 #ifndef DACCESS_COMPILE
2511     void ThreadEnter(Thread *pThread, Frame *pFrame)
2512     {
2513         STATIC_CONTRACT_NOTHROW;
2514         STATIC_CONTRACT_GC_NOTRIGGER;
2515
2516 #ifdef _DEBUG
2517         if (LoggingOn(LF_APPDOMAIN, LL_INFO100))
2518             TrackADThreadEnter(pThread, pFrame);
2519         else
2520 #endif
2521         {
2522             InterlockedIncrement((LONG*)&m_dwThreadEnterCount);
2523             LOG((LF_APPDOMAIN, LL_INFO1000, "AppDomain::ThreadEnter  %p to [%d] (%8.8x) %S count %d\n", 
2524                  pThread,GetId().m_dwId, this,
2525                  GetFriendlyNameForLogging(),GetThreadEnterCount()));
2526 #if _DEBUG_AD_UNLOAD
2527             printf("AppDomain::ThreadEnter %p to [%d] (%8.8x) %S count %d\n",
2528                    pThread, GetId().m_dwId, this,
2529                    GetFriendlyNameForLogging(), GetThreadEnterCount());
2530 #endif
2531         }
2532     }
2533
2534     void ThreadExit(Thread *pThread, Frame *pFrame)
2535     {
2536         STATIC_CONTRACT_NOTHROW;
2537         STATIC_CONTRACT_GC_NOTRIGGER;
2538
2539 #ifdef _DEBUG
2540         if (LoggingOn(LF_APPDOMAIN, LL_INFO100)) {
2541             TrackADThreadExit(pThread, pFrame);
2542         }
2543         else
2544 #endif
2545         {
2546             LONG result;
2547             result = InterlockedDecrement((LONG*)&m_dwThreadEnterCount);
2548             _ASSERTE(result >= 0);
2549             LOG((LF_APPDOMAIN, LL_INFO1000, "AppDomain::ThreadExit from [%d] (%8.8x) %S count %d\n",
2550                  this, GetId().m_dwId,
2551                  GetFriendlyNameForLogging(), GetThreadEnterCount()));
2552 #if _DEBUG_ADUNLOAD
2553             printf("AppDomain::ThreadExit %x from [%d] (%8.8x) %S count %d\n",
2554                    pThread->GetThreadId(), this, GetId().m_dwId,
2555                    GetFriendlyNameForLogging(), GetThreadEnterCount());
2556 #endif
2557         }
2558     }
2559 #endif // DACCESS_COMPILE
2560
2561     ULONG GetThreadEnterCount()
2562     {
2563         LIMITED_METHOD_CONTRACT;
2564         return m_dwThreadEnterCount;
2565     }
2566
2567     BOOL OnlyOneThreadLeft()
2568     {
2569         LIMITED_METHOD_CONTRACT;
2570         return m_dwThreadEnterCount==1 || m_dwThreadsStillInAppDomain ==1;
2571     }
2572
2573     static void RefTakerAcquire(AppDomain* pDomain)
2574     {
2575         WRAPPER_NO_CONTRACT;
2576         if(!pDomain)
2577             return;
2578         pDomain->AddRef();
2579 #ifdef _DEBUG
2580         FastInterlockIncrement(&pDomain->m_dwRefTakers);
2581 #endif
2582     }
2583
2584     static void RefTakerRelease(AppDomain* pDomain)
2585     {
2586         WRAPPER_NO_CONTRACT;
2587         if(!pDomain)
2588             return;
2589 #ifdef _DEBUG
2590         _ASSERTE(pDomain->m_dwRefTakers);
2591         FastInterlockDecrement(&pDomain->m_dwRefTakers);
2592 #endif
2593         pDomain->Release();
2594     }
2595
2596 #ifdef _DEBUG 
2597
2598     BOOL IsHeldByIterator()
2599     {
2600         LIMITED_METHOD_CONTRACT;
2601         return m_dwIterHolders>0;
2602     }
2603
2604     BOOL IsHeldByRefTaker()
2605     {
2606         LIMITED_METHOD_CONTRACT;
2607         return m_dwRefTakers>0;
2608     }
2609
2610     void IteratorRelease()
2611     {
2612         LIMITED_METHOD_CONTRACT;
2613         _ASSERTE(m_dwIterHolders);
2614         FastInterlockDecrement(&m_dwIterHolders);
2615     }
2616
2617       
2618     void IteratorAcquire()
2619     {
2620         LIMITED_METHOD_CONTRACT;
2621         FastInterlockIncrement(&m_dwIterHolders);
2622     }
2623     
2624 #endif    
2625     BOOL IsActive()
2626     {
2627         LIMITED_METHOD_DAC_CONTRACT;
2628
2629         return m_Stage >= STAGE_ACTIVE;
2630     }
2631     // Range for normal execution of code in the appdomain, currently used for
2632     // appdomain resource monitoring since we don't care to update resource usage
2633     // unless it's in these stages (as fields of AppDomain may not be valid if it's
2634     // not within these stages)
2635     BOOL IsUserActive()
2636     {
2637         LIMITED_METHOD_DAC_CONTRACT;
2638
2639         return m_Stage >= STAGE_ACTIVE && m_Stage <= STAGE_OPEN;
2640     }
2641     BOOL IsValid()
2642     {
2643         LIMITED_METHOD_DAC_CONTRACT;
2644
2645 #ifdef DACCESS_COMPILE
2646         // We want to see all appdomains in SOS, even the about to be destructed ones.
2647         // There is no risk of races under DAC, so we will pretend to be unconditionally valid.
2648         return TRUE;
2649 #else
2650         return m_Stage > STAGE_CREATING;
2651 #endif
2652     }
2653
2654 #ifdef _DEBUG
2655     BOOL IsBeingCreated()
2656     {
2657         LIMITED_METHOD_CONTRACT;
2658
2659         return m_dwCreationHolders > 0;
2660     }
2661
2662     void IncCreationCount()
2663     {
2664         LIMITED_METHOD_CONTRACT;
2665
2666         FastInterlockIncrement(&m_dwCreationHolders);
2667         _ASSERTE(m_dwCreationHolders > 0);
2668     }
2669
2670     void DecCreationCount()
2671     {
2672         LIMITED_METHOD_CONTRACT;
2673
2674         FastInterlockDecrement(&m_dwCreationHolders);
2675         _ASSERTE(m_dwCreationHolders > -1);
2676     }
2677 #endif
2678     BOOL IsRunningIn(Thread* pThread);
2679
2680     BOOL NotReadyForManagedCode()
2681     {
2682         LIMITED_METHOD_CONTRACT;
2683
2684         return m_Stage < STAGE_READYFORMANAGEDCODE;
2685     }
2686
2687     static void RaiseExitProcessEvent();
2688     Assembly* RaiseResourceResolveEvent(DomainAssembly* pAssembly, LPCSTR szName);
2689     DomainAssembly* RaiseTypeResolveEventThrowing(DomainAssembly* pAssembly, LPCSTR szName, ASSEMBLYREF *pResultingAssemblyRef);
2690     Assembly* RaiseAssemblyResolveEvent(AssemblySpec *pSpec);
2691
2692 private:
2693     CrstExplicitInit    m_ReflectionCrst;
2694     CrstExplicitInit    m_RefClassFactCrst;
2695
2696
2697     EEClassFactoryInfoHashTable *m_pRefClassFactHash;   // Hash table that maps a class factory info to a COM comp.
2698 #ifdef FEATURE_COMINTEROP
2699     DispIDCache *m_pRefDispIDCache;
2700     OBJECTHANDLE  m_hndMissing;     //Handle points to Missing.Value Object which is used for [Optional] arg scenario during IDispatch CCW Call
2701
2702     MethodTable* m_rpCLRTypes[WinMDAdapter::RedirectedTypeIndex_Count];
2703
2704     MethodTable* LoadRedirectedType(WinMDAdapter::RedirectedTypeIndex index, WinMDAdapter::FrameworkAssemblyIndex assembly);
2705 #endif // FEATURE_COMINTEROP
2706
2707 public:
2708
2709     CrstBase *GetRefClassFactCrst()
2710     {
2711         LIMITED_METHOD_CONTRACT;
2712
2713         return &m_RefClassFactCrst;
2714     }
2715
2716 #ifndef DACCESS_COMPILE
2717     EEClassFactoryInfoHashTable* GetClassFactHash()
2718     {
2719         STATIC_CONTRACT_THROWS;
2720         STATIC_CONTRACT_GC_TRIGGERS;
2721         STATIC_CONTRACT_FAULT;
2722
2723         if (m_pRefClassFactHash != NULL) {
2724             return m_pRefClassFactHash;
2725         }
2726
2727         return SetupClassFactHash();
2728     }
2729 #endif // DACCESS_COMPILE
2730
2731 #ifdef FEATURE_COMINTEROP
2732     DispIDCache* GetRefDispIDCache()
2733     {
2734         STATIC_CONTRACT_THROWS;
2735         STATIC_CONTRACT_GC_TRIGGERS;
2736         STATIC_CONTRACT_FAULT;
2737
2738         if (m_pRefDispIDCache != NULL) {
2739             return m_pRefDispIDCache;
2740         }
2741
2742         return SetupRefDispIDCache();
2743     }
2744 #endif // FEATURE_COMINTEROP
2745
2746     PTR_LoaderHeap GetStubHeap();
2747     PTR_LoaderHeap GetLowFrequencyHeap();
2748     PTR_LoaderHeap GetHighFrequencyHeap();
2749
2750 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
2751     #define ARM_ETW_ALLOC_THRESHOLD (4 * 1024 * 1024)
2752     // cache line size in ULONGLONG - 128 bytes which are 16 ULONGLONG's
2753     #define ARM_CACHE_LINE_SIZE_ULL 16
2754
2755     inline ULONGLONG GetAllocBytes()
2756     {
2757         LIMITED_METHOD_CONTRACT;
2758         ULONGLONG ullTotalAllocBytes = 0;
2759
2760         // Ensure that m_pullAllocBytes is non-null to avoid an AV in a race between GC and AD unload.
2761         // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullAllocBytes, causing the AD unload.
2762         if(NULL != m_pullAllocBytes)
2763         {
2764             for (DWORD i = 0; i < m_dwNumHeaps; i++)
2765             {
2766                 ullTotalAllocBytes += m_pullAllocBytes[i * ARM_CACHE_LINE_SIZE_ULL];
2767             }
2768         }
2769         return ullTotalAllocBytes;
2770     }
2771
2772     void RecordAllocBytes(size_t allocatedBytes, DWORD dwHeapNumber)
2773     {
2774         LIMITED_METHOD_CONTRACT;
2775         _ASSERTE(dwHeapNumber < m_dwNumHeaps);
2776         
2777         // Ensure that m_pullAllocBytes is non-null to avoid an AV in a race between GC and AD unload.
2778         // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullAllocBytes, causing the AD unload.
2779         if(NULL != m_pullAllocBytes)
2780         {
2781             m_pullAllocBytes[dwHeapNumber * ARM_CACHE_LINE_SIZE_ULL] += allocatedBytes;
2782         }
2783
2784         ULONGLONG ullTotalAllocBytes = GetAllocBytes();
2785
2786         if ((ullTotalAllocBytes - m_ullLastEtwAllocBytes) >= ARM_ETW_ALLOC_THRESHOLD)
2787         {
2788             m_ullLastEtwAllocBytes = ullTotalAllocBytes;
2789             FireEtwAppDomainMemAllocated((ULONGLONG)this, ullTotalAllocBytes, GetClrInstanceId());
2790         }
2791     }
2792
2793     inline ULONGLONG GetSurvivedBytes()
2794     {
2795         LIMITED_METHOD_CONTRACT;
2796         ULONGLONG ullTotalSurvivedBytes = 0;
2797
2798         // Ensure that m_pullSurvivedBytes is non-null to avoid an AV in a race between GC and AD unload.
2799         // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullSurvivedBytes, causing the AD unload.
2800         if(NULL != m_pullSurvivedBytes)
2801         {
2802             for (DWORD i = 0; i < m_dwNumHeaps; i++)
2803             {
2804                 ullTotalSurvivedBytes += m_pullSurvivedBytes[i * ARM_CACHE_LINE_SIZE_ULL];
2805             }
2806         }
2807         return ullTotalSurvivedBytes;
2808     }
2809
2810     void RecordSurvivedBytes(size_t promotedBytes, DWORD dwHeapNumber)
2811     {
2812         WRAPPER_NO_CONTRACT;
2813         _ASSERTE(dwHeapNumber < m_dwNumHeaps);
2814    
2815         // Ensure that m_pullSurvivedBytes is non-null to avoid an AV in a race between GC and AD unload.
2816         // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullSurvivedBytes, causing the AD unload.
2817         if(NULL != m_pullSurvivedBytes)
2818         {
2819             m_pullSurvivedBytes[dwHeapNumber * ARM_CACHE_LINE_SIZE_ULL] += promotedBytes;
2820         }
2821     }
2822
2823     inline void ResetSurvivedBytes()
2824     {
2825         LIMITED_METHOD_CONTRACT;
2826         
2827         // Ensure that m_pullSurvivedBytes is non-null to avoid an AV in a race between GC and AD unload.
2828         // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullSurvivedBytes, causing the AD unload.
2829         if(NULL != m_pullSurvivedBytes)
2830         {
2831             for (DWORD i = 0; i < m_dwNumHeaps; i++)
2832             {
2833                 m_pullSurvivedBytes[i * ARM_CACHE_LINE_SIZE_ULL] = 0;
2834             }
2835         }
2836     }
2837
2838     // Return the total processor time (user and kernel) used by threads executing in this AppDomain so far.
2839     // The result is in 100ns units.
2840     ULONGLONG QueryProcessorUsage();
2841
2842     // Add to the current count of processor time used by threads within this AppDomain. This API is called by
2843     // threads transitioning between AppDomains.
2844     void UpdateProcessorUsage(ULONGLONG ullAdditionalUsage);
2845 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
2846
2847 private:
2848     size_t EstimateSize();
2849     EEClassFactoryInfoHashTable* SetupClassFactHash();
2850 #ifdef FEATURE_COMINTEROP
2851     DispIDCache* SetupRefDispIDCache();
2852 #endif // FEATURE_COMINTEROP
2853
2854 protected:
2855     BOOL PostBindResolveAssembly(AssemblySpec  *pPrePolicySpec,
2856                                  AssemblySpec  *pPostPolicySpec,
2857                                  HRESULT        hrBindResult,
2858                                  AssemblySpec **ppFailedSpec);
2859
2860 #ifdef FEATURE_COMINTEROP
2861 public:
2862     void ReleaseRCWs(LPVOID pCtxCookie);
2863     void DetachRCWs();
2864
2865 protected:
2866 #endif // FEATURE_COMINTEROP
2867
2868 private:
2869     void RaiseLoadingAssemblyEvent(DomainAssembly* pAssembly);
2870
2871     friend class DomainAssembly;
2872
2873 private:
2874     BOOL RaiseUnhandledExceptionEvent(OBJECTREF *pThrowable, BOOL isTerminating);
2875
2876     enum Stage {
2877         STAGE_CREATING,
2878         STAGE_READYFORMANAGEDCODE,
2879         STAGE_ACTIVE,
2880         STAGE_OPEN,
2881         // Don't delete the following *_DONOTUSE members and in case a new member needs to be added,
2882         // add it at the end. The reason is that debugger stuff has its own copy of this enum and 
2883         // it can use the members that are marked as *_DONOTUSE here when debugging older version 
2884         // of the runtime.
2885         STAGE_UNLOAD_REQUESTED_DONOTUSE,
2886         STAGE_EXITING_DONOTUSE,
2887         STAGE_EXITED_DONOTUSE,
2888         STAGE_FINALIZING_DONOTUSE,
2889         STAGE_FINALIZED_DONOTUSE,
2890         STAGE_HANDLETABLE_NOACCESS_DONOTUSE,
2891         STAGE_CLEARED_DONOTUSE,
2892         STAGE_COLLECTED_DONOTUSE,
2893         STAGE_CLOSED_DONOTUSE
2894     };
2895     void SetStage(Stage stage)
2896     {
2897         CONTRACTL
2898         {
2899             NOTHROW;
2900             GC_NOTRIGGER;
2901             MODE_ANY;
2902         }
2903         CONTRACTL_END;
2904         STRESS_LOG2(LF_APPDOMAIN, LL_INFO100,"Updating AD stage, ADID=%d, stage=%d\n",GetId().m_dwId,stage);
2905         TESTHOOKCALL(AppDomainStageChanged(GetId().m_dwId,m_Stage,stage));
2906         Stage lastStage=m_Stage;
2907         while (lastStage !=stage) 
2908             lastStage = (Stage)FastInterlockCompareExchange((LONG*)&m_Stage,stage,lastStage);
2909     };
2910     void UnwindThreads();
2911     // Return TRUE if EE is stopped
2912     // Return FALSE if more work is needed
2913     BOOL StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnloadRequestThread);
2914
2915     // List of unloaded LoaderAllocators, protected by code:GetLoaderAllocatorReferencesLock (for now)
2916     LoaderAllocator * m_pDelayedLoaderAllocatorUnloadList;
2917     
2918 public:
2919     
2920     // Register the loader allocator for deletion in code:ShutdownFreeLoaderAllocators.
2921     void RegisterLoaderAllocatorForDeletion(LoaderAllocator * pLoaderAllocator);
2922     
2923 public:
2924     void SetGCRefPoint(int gccounter)
2925     {
2926         LIMITED_METHOD_CONTRACT;
2927         GetLoaderAllocator()->SetGCRefPoint(gccounter);
2928     }
2929     int  GetGCRefPoint()
2930     {
2931         LIMITED_METHOD_CONTRACT;
2932         return GetLoaderAllocator()->GetGCRefPoint();
2933     }
2934
2935     static USHORT GetOffsetOfId()
2936     {
2937         LIMITED_METHOD_CONTRACT;
2938         size_t ofs = offsetof(class AppDomain, m_dwId);
2939         _ASSERTE(FitsInI2(ofs));
2940         return (USHORT)ofs;
2941     }
2942
2943     
2944     void AddMemoryPressure();
2945     void RemoveMemoryPressure();
2946
2947     void UnlinkClass(MethodTable *pMT);
2948
2949     Assembly *GetRootAssembly()
2950     {
2951         LIMITED_METHOD_CONTRACT;
2952         return m_pRootAssembly;
2953     }
2954
2955 #ifndef DACCESS_COMPILE
2956     void SetRootAssembly(Assembly *pAssembly)
2957     {
2958         LIMITED_METHOD_CONTRACT;
2959         m_pRootAssembly = pAssembly;
2960     }
2961 #endif
2962
2963 private:
2964     // The one and only AppDomain
2965     SPTR_DECL(AppDomain, m_pTheAppDomain);
2966
2967     SString         m_friendlyName;
2968     PTR_Assembly    m_pRootAssembly;
2969
2970     // General purpose flags.
2971     DWORD           m_dwFlags;
2972
2973     // When an application domain is created the ref count is artifically incremented
2974     // by one. For it to hit zero an explicit close must have happened.
2975     LONG        m_cRef;                    // Ref count.
2976
2977     // Hash table that maps a clsid to a type
2978     PtrHashMap          m_clsidHash;
2979
2980 #ifdef FEATURE_COMINTEROP
2981     // Hash table that maps WinRT class names to MethodTables.
2982     PTR_NameToTypeMapTable m_pNameToTypeMap;
2983     UINT                m_vNameToTypeMapVersion;
2984
2985     UINT                m_nEpoch; // incremented each time m_pNameToTypeMap is enumerated
2986
2987     // Hash table that remembers the last cached WinRT factory object per type per appdomain.
2988     WinRTFactoryCache   *m_pWinRTFactoryCache;
2989
2990     // this cache stores the RCWs in this domain
2991     RCWCache *m_pRCWCache;
2992
2993     // this cache stores the RCW -> CCW references in this domain
2994     RCWRefCache *m_pRCWRefCache;
2995     
2996     // The method table used for LicenseInteropHelper
2997     MethodTable*    m_pLicenseInteropHelperMT;
2998 #endif // FEATURE_COMINTEROP
2999
3000     // The index of this app domain among existing app domains (starting from 1)
3001     ADIndex m_dwIndex;
3002
3003     // The thread-pool index of this app domain among existing app domains (starting from 1)
3004     TPIndex m_tpIndex;
3005
3006 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
3007     ULONGLONG* m_pullAllocBytes;
3008     ULONGLONG* m_pullSurvivedBytes;
3009     DWORD m_dwNumHeaps;
3010     ULONGLONG m_ullLastEtwAllocBytes;
3011     // Total processor time (user and kernel) utilized by threads running in this AppDomain so far. May not
3012     // account for threads currently executing in the AppDomain until a call to QueryProcessorUsage() is
3013     // made.
3014     Volatile<ULONGLONG> m_ullTotalProcessorUsage;
3015 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
3016
3017 #ifdef _DEBUG
3018     struct ThreadTrackInfo;
3019     typedef CDynArray<ThreadTrackInfo *> ThreadTrackInfoList;
3020     ThreadTrackInfoList *m_pThreadTrackInfoList;
3021     DWORD m_TrackSpinLock;
3022 #endif
3023
3024     // The number of  times we have entered this AD
3025     ULONG m_dwThreadEnterCount;
3026     // The number of threads that have entered this AD, for ADU only
3027     ULONG m_dwThreadsStillInAppDomain;
3028
3029     Volatile<Stage> m_Stage;
3030
3031     ArrayList        m_failedAssemblies;
3032
3033 #ifdef _DEBUG
3034     Volatile<LONG> m_dwIterHolders;
3035     Volatile<LONG> m_dwRefTakers;
3036     Volatile<LONG> m_dwCreationHolders;
3037 #endif
3038
3039     //
3040     // DAC iterator for failed assembly loads
3041     //
3042     class FailedAssemblyIterator
3043     {
3044         ArrayList::Iterator m_i;
3045         
3046       public:
3047         BOOL Next()
3048         {
3049             WRAPPER_NO_CONTRACT;
3050             return m_i.Next();
3051         }
3052         FailedAssembly *GetFailedAssembly()
3053         {
3054             WRAPPER_NO_CONTRACT;
3055             return dac_cast<PTR_FailedAssembly>(m_i.GetElement());
3056         }
3057         SIZE_T GetIndex()
3058         {
3059             WRAPPER_NO_CONTRACT;
3060             return m_i.GetIndex();
3061         }
3062
3063       private:
3064         friend class AppDomain;
3065         // Cannot have constructor so this iterator can be used inside a union
3066         static FailedAssemblyIterator Create(AppDomain *pDomain)
3067         {
3068             WRAPPER_NO_CONTRACT;
3069             FailedAssemblyIterator i;
3070
3071             i.m_i = pDomain->m_failedAssemblies.Iterate();
3072             return i;
3073         }
3074     };
3075     friend class FailedAssemblyIterator;
3076
3077     FailedAssemblyIterator IterateFailedAssembliesEx()
3078     {
3079         WRAPPER_NO_CONTRACT;
3080         return FailedAssemblyIterator::Create(this);
3081     }
3082
3083     //---------------------------------------------------------
3084     // Stub caches for Method stubs
3085     //---------------------------------------------------------
3086
3087 public:
3088
3089     enum {
3090         CONTEXT_INITIALIZED =               0x0001,
3091         LOAD_SYSTEM_ASSEMBLY_EVENT_SENT =   0x0040,
3092         COMPILATION_DOMAIN =                0x0400, // Are we ngenning?
3093         IGNORE_UNHANDLED_EXCEPTIONS =      0x10000, // AppDomain was created using the APPDOMAIN_IGNORE_UNHANDLED_EXCEPTIONS flag
3094     };
3095
3096     AssemblySpecBindingCache  m_AssemblyCache;
3097     DomainAssemblyCache       m_UnmanagedCache;
3098     size_t                    m_MemoryPressure;
3099
3100     ArrayList m_NativeDllSearchDirectories;
3101     BOOL m_ReversePInvokeCanEnter;
3102     bool m_ForceTrivialWaitOperations;
3103
3104 public:
3105
3106 #ifdef FEATURE_TYPEEQUIVALENCE
3107 private:
3108     VolatilePtr<TypeEquivalenceHashTable> m_pTypeEquivalenceTable;
3109     CrstExplicitInit m_TypeEquivalenceCrst;
3110 public:
3111     TypeEquivalenceHashTable * GetTypeEquivalenceCache();
3112 #endif
3113
3114     private:
3115
3116 #ifdef DACCESS_COMPILE
3117 public:
3118     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
3119                                    bool enumThis);
3120 #endif
3121
3122 #ifdef FEATURE_MULTICOREJIT
3123
3124 private:
3125     MulticoreJitManager m_MulticoreJitManager;
3126
3127 public:
3128     MulticoreJitManager & GetMulticoreJitManager()
3129     {
3130         LIMITED_METHOD_CONTRACT;
3131
3132         return m_MulticoreJitManager;
3133     }
3134
3135 #endif
3136
3137 #if defined(FEATURE_TIERED_COMPILATION)
3138
3139 public:
3140     TieredCompilationManager * GetTieredCompilationManager()
3141     {
3142         LIMITED_METHOD_CONTRACT;
3143         return &m_tieredCompilationManager;
3144     }
3145
3146 private:
3147     TieredCompilationManager m_tieredCompilationManager;
3148
3149 #endif
3150
3151 #ifdef FEATURE_COMINTEROP
3152
3153 private:
3154
3155 #endif //FEATURE_COMINTEROP
3156
3157 public:
3158
3159     class ComInterfaceReleaseList
3160     {
3161         SArray<IUnknown *> m_objects;
3162     public:
3163         ~ComInterfaceReleaseList()
3164         {
3165             WRAPPER_NO_CONTRACT;
3166
3167             for (COUNT_T i = 0; i < m_objects.GetCount(); i++)
3168             {
3169                 IUnknown *pItf = *(m_objects.GetElements() + i);
3170                 if (pItf != nullptr)
3171                     pItf->Release();
3172             }
3173         }
3174
3175         // Append to the list of object to free. Only use under the AppDomain "LockHolder(pAppDomain)"
3176         void Append(IUnknown *pInterfaceToRelease)
3177         {
3178             WRAPPER_NO_CONTRACT;
3179             m_objects.Append(pInterfaceToRelease);
3180         }
3181     } AppDomainInterfaceReleaseList;
3182
3183 private:
3184     //-----------------------------------------------------------
3185     // Static ICLRPrivAssembly -> DomainAssembly mapping functions.
3186     // This map does not maintain a reference count to either key or value.
3187     // PEFile maintains a reference count on the ICLRPrivAssembly through its code:PEFile::m_pHostAssembly field.
3188     // It is removed from this hash table by code:DomainAssembly::~DomainAssembly.
3189     struct HostAssemblyHashTraits : public DefaultSHashTraits<PTR_DomainAssembly>
3190     {
3191     public:
3192         typedef PTR_ICLRPrivAssembly key_t;
3193         
3194         static key_t GetKey(element_t const & elem)
3195         {
3196             STATIC_CONTRACT_WRAPPER;
3197             return elem->GetFile()->GetHostAssembly();
3198         }
3199         
3200         static BOOL Equals(key_t key1, key_t key2) 
3201         {
3202             LIMITED_METHOD_CONTRACT;
3203             return dac_cast<TADDR>(key1) == dac_cast<TADDR>(key2);
3204         }
3205         
3206         static count_t Hash(key_t key)
3207         {
3208             STATIC_CONTRACT_LIMITED_METHOD;
3209             //return reinterpret_cast<count_t>(dac_cast<TADDR>(key));
3210             return (count_t)(dac_cast<TADDR>(key));
3211         }
3212         
3213         static element_t Null() { return NULL; }
3214         static element_t Deleted() { return (element_t)(TADDR)-1; }
3215         static bool IsNull(const element_t & e) { return e == NULL; }
3216         static bool IsDeleted(const element_t & e) { return dac_cast<TADDR>(e) == (TADDR)-1; }
3217     };
3218
3219     struct OriginalFileHostAssemblyHashTraits : public HostAssemblyHashTraits
3220     {
3221     public:
3222         static key_t GetKey(element_t const & elem)
3223         {
3224             STATIC_CONTRACT_WRAPPER;
3225             return elem->GetOriginalFile()->GetHostAssembly();
3226         }
3227     };
3228     
3229     typedef SHash<HostAssemblyHashTraits> HostAssemblyMap;
3230     typedef SHash<OriginalFileHostAssemblyHashTraits> OriginalFileHostAssemblyMap;
3231     HostAssemblyMap   m_hostAssemblyMap;
3232     OriginalFileHostAssemblyMap   m_hostAssemblyMapForOrigFile;
3233     CrstExplicitInit  m_crstHostAssemblyMap;
3234     // Lock to serialize all Add operations (in addition to the "read-lock" above)
3235     CrstExplicitInit  m_crstHostAssemblyMapAdd;
3236
3237 public:
3238     // Returns DomainAssembly.
3239     PTR_DomainAssembly FindAssembly(PTR_ICLRPrivAssembly pHostAssembly);
3240     
3241 #ifndef DACCESS_COMPILE
3242 private:
3243     friend void DomainAssembly::Allocate();
3244     friend DomainAssembly::~DomainAssembly();
3245
3246     // Called from DomainAssembly::Begin.
3247     void PublishHostedAssembly(
3248         DomainAssembly* pAssembly);
3249
3250     // Called from DomainAssembly::UpdatePEFile.
3251     void UpdatePublishHostedAssembly(
3252         DomainAssembly* pAssembly,
3253         PTR_PEFile pFile);
3254
3255     // Called from DomainAssembly::~DomainAssembly
3256     void UnPublishHostedAssembly(
3257         DomainAssembly* pAssembly);
3258 #endif // DACCESS_COMPILE
3259
3260 #ifdef FEATURE_PREJIT
3261     friend void DomainFile::InsertIntoDomainFileWithNativeImageList();
3262     Volatile<DomainFile *> m_pDomainFileWithNativeImageList;
3263 public:
3264     DomainFile *GetDomainFilesWithNativeImagesList()
3265     {
3266         LIMITED_METHOD_CONTRACT;
3267         return m_pDomainFileWithNativeImageList;
3268     }
3269 #endif
3270 };  // class AppDomain
3271
3272
3273 // This holder is to be used to take a reference to make sure AppDomain* is still valid
3274 // Please do not use if you are aleady ADU-safe
3275 typedef Wrapper<AppDomain*,AppDomain::RefTakerAcquire,AppDomain::RefTakerRelease,NULL> AppDomainRefTaker;
3276
3277 // Just a ref holder
3278 typedef ReleaseHolder<AppDomain> AppDomainRefHolder;
3279
3280 typedef VPTR(class SystemDomain) PTR_SystemDomain;
3281
3282 class SystemDomain : public BaseDomain
3283 {
3284     friend class AppDomainNative;
3285     friend class AppDomainIterator;
3286     friend class UnsafeAppDomainIterator;
3287     friend class ClrDataAccess;
3288     friend Frame *Thread::IsRunningIn(AppDomain* pDomain, int *count);
3289
3290     VPTR_VTABLE_CLASS(SystemDomain, BaseDomain)
3291     VPTR_UNIQUE(VPTR_UNIQUE_SystemDomain)
3292     static AppDomain *GetAppDomainAtId(ADID indx);
3293
3294 public:  
3295     static PTR_LoaderAllocator GetGlobalLoaderAllocator();
3296     static AppDomain* GetAppDomainFromId(ADID indx,DWORD ADValidityKind)
3297     {
3298         CONTRACTL
3299         {
3300             NOTHROW;
3301             GC_NOTRIGGER;
3302             MODE_COOPERATIVE;
3303         }
3304         CONTRACTL_END;
3305         AppDomain* pRetVal;
3306         if (indx.m_dwId==DefaultADID)
3307             pRetVal= SystemDomain::System()->DefaultDomain();
3308         else
3309             pRetVal= GetAppDomainAtId(indx);
3310 #ifdef _DEBUG
3311         // Only call CheckADValidity in DEBUG builds for non-NULL return values
3312         if (pRetVal != NULL)
3313             CheckADValidity(pRetVal, ADValidityKind);
3314 #endif        
3315         return pRetVal;
3316     }
3317     //****************************************************************************************
3318     //
3319     // To be run during the initial start up of the EE. This must be
3320     // performed prior to any class operations.
3321     static void Attach();
3322
3323     //****************************************************************************************
3324     //
3325     // To be run during shutdown. This must be done after all operations
3326     // that require the use of system classes (i.e., exceptions).
3327     // DetachBegin stops all domains, while DetachEnd deallocates domain resources.
3328     static void DetachBegin();
3329
3330     //****************************************************************************************
3331     //
3332     // To be run during shutdown. This must be done after all operations
3333     // that require the use of system classes (i.e., exceptions).
3334     // DetachBegin stops release resources held by systemdomain and the default domain.
3335     static void DetachEnd();
3336
3337     //****************************************************************************************
3338     //
3339     // Initializes and shutdowns the single instance of the SystemDomain
3340     // in the EE
3341 #ifndef DACCESS_COMPILE
3342     void *operator new(size_t size, void *pInPlace);
3343     void operator delete(void *pMem);
3344 #endif
3345     void Init();
3346     void Stop();
3347     void Terminate();
3348     static void LazyInitGlobalStringLiteralMap();
3349
3350     //****************************************************************************************
3351     //
3352     // Load the base system classes, these classes are required before
3353     // any other classes are loaded
3354     void LoadBaseSystemClasses();
3355
3356     AppDomain* DefaultDomain()
3357     {
3358         LIMITED_METHOD_DAC_CONTRACT;
3359
3360         return AppDomain::GetCurrentDomain();
3361     }
3362
3363     // Notification when an assembly is loaded into the system domain
3364     void OnAssemblyLoad(Assembly *assem);
3365
3366     //****************************************************************************************
3367     //
3368     // Global Static to get the one and only system domain
3369     static SystemDomain * System()
3370     {
3371         LIMITED_METHOD_DAC_CONTRACT;
3372
3373         return m_pSystemDomain;
3374     }
3375
3376     static PEAssembly* SystemFile()
3377     {
3378         WRAPPER_NO_CONTRACT;
3379
3380         _ASSERTE(m_pSystemDomain);
3381         return System()->m_pSystemFile;
3382     }
3383
3384     static Assembly* SystemAssembly()
3385     {
3386         WRAPPER_NO_CONTRACT;
3387
3388         return System()->m_pSystemAssembly;
3389     }
3390
3391     static Module* SystemModule()
3392     {
3393         WRAPPER_NO_CONTRACT;
3394
3395         return SystemAssembly()->GetManifestModule();
3396     }
3397
3398     static BOOL IsSystemLoaded()
3399     {
3400         WRAPPER_NO_CONTRACT;
3401
3402         return System()->m_pSystemAssembly != NULL;
3403     }
3404
3405 #ifndef DACCESS_COMPILE
3406     static GlobalStringLiteralMap *GetGlobalStringLiteralMap()
3407     {
3408         WRAPPER_NO_CONTRACT;
3409
3410         if (m_pGlobalStringLiteralMap == NULL)
3411         {
3412             SystemDomain::LazyInitGlobalStringLiteralMap();
3413         }
3414         _ASSERTE(m_pGlobalStringLiteralMap);
3415         return m_pGlobalStringLiteralMap;
3416     }
3417     static GlobalStringLiteralMap *GetGlobalStringLiteralMapNoCreate()
3418     {
3419         LIMITED_METHOD_CONTRACT;
3420
3421         _ASSERTE(m_pGlobalStringLiteralMap);
3422         return m_pGlobalStringLiteralMap;
3423     }
3424 #endif // DACCESS_COMPILE
3425
3426 #if defined(FEATURE_COMINTEROP_APARTMENT_SUPPORT) && !defined(CROSSGEN_COMPILE)
3427     static Thread::ApartmentState GetEntryPointThreadAptState(IMDInternalImport* pScope, mdMethodDef mdMethod);
3428     static void SetThreadAptState(Thread::ApartmentState state);
3429 #endif
3430
3431     //****************************************************************************************
3432     //
3433     // Use an already exising & inited Application Domain (e.g. a subclass).
3434     static void LoadDomain(AppDomain     *pDomain);
3435
3436     //****************************************************************************************
3437     // Methods used to get the callers module and hence assembly and app domain.
3438     __declspec(deprecated("This method is deprecated, use the version that takes a StackCrawlMark instead"))
3439     static Module* GetCallersModule(int skip);
3440     static MethodDesc* GetCallersMethod(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
3441     static MethodTable* GetCallersType(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
3442     static Module* GetCallersModule(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
3443     static Assembly* GetCallersAssembly(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
3444
3445     static bool IsReflectionInvocationMethod(MethodDesc* pMeth);
3446
3447 #ifndef DACCESS_COMPILE
3448     //****************************************************************************************
3449     // Returns the domain associated with the current context. (this can only be a child domain)
3450     static inline AppDomain * GetCurrentDomain()
3451     {
3452         WRAPPER_NO_CONTRACT;
3453         return ::GetAppDomain();
3454     }
3455 #endif //!DACCESS_COMPILE
3456
3457 #ifdef DEBUGGING_SUPPORTED
3458     //****************************************************************************************
3459     // Debugger/Publisher helper function to indicate creation of new app domain to debugger
3460     // and publishing it in the IPC block
3461     static void PublishAppDomainAndInformDebugger (AppDomain *pDomain);
3462 #endif // DEBUGGING_SUPPORTED
3463
3464     //****************************************************************************************
3465     // Helper function to remove a domain from the system
3466     BOOL RemoveDomain(AppDomain* pDomain); // Does not decrement the reference
3467
3468 #ifdef PROFILING_SUPPORTED
3469     //****************************************************************************************
3470     // Tell profiler about system created domains which are created before the profiler is
3471     // actually activated.
3472     static void NotifyProfilerStartup();
3473
3474     //****************************************************************************************
3475     // Tell profiler at shutdown that system created domains are going away.  They are not
3476     // torn down using the normal sequence.
3477     static HRESULT NotifyProfilerShutdown();
3478 #endif // PROFILING_SUPPORTED
3479
3480     //****************************************************************************************
3481     // return the dev path
3482
3483 #ifndef DACCESS_COMPILE
3484     void IncrementNumAppDomains ()
3485     {
3486         LIMITED_METHOD_CONTRACT;
3487
3488         s_dNumAppDomains++;
3489     }
3490
3491     void DecrementNumAppDomains ()
3492     {
3493         LIMITED_METHOD_CONTRACT;
3494
3495         s_dNumAppDomains--;
3496     }
3497
3498     ULONG GetNumAppDomains ()
3499     {
3500         LIMITED_METHOD_CONTRACT;
3501
3502         return s_dNumAppDomains;
3503     }
3504 #endif // DACCESS_COMPILE
3505
3506     //
3507     // AppDomains currently have both an index and an ID.  The
3508     // index is "densely" assigned; indices are reused as domains
3509     // are unloaded.  The Id's on the other hand, are not reclaimed
3510     // so may be sparse.
3511     //
3512     // Another important difference - it's OK to call GetAppDomainAtId for
3513     // an unloaded domain (it will return NULL), while GetAppDomainAtIndex
3514     // will assert if the domain is unloaded.
3515     //<TODO>
3516     // @todo:
3517     // I'm not really happy with this situation, but
3518     //  (a) we need an ID for a domain which will last the process lifetime for the
3519     //      remoting code.
3520     //  (b) we need a dense ID, for the handle table index.
3521     // So for now, I'm leaving both, but hopefully in the future we can come up
3522     // with something better.
3523     //</TODO>
3524
3525     static ADIndex GetNewAppDomainIndex(AppDomain * pAppDomain);
3526     static void ReleaseAppDomainIndex(ADIndex indx);
3527     static PTR_AppDomain GetAppDomainAtIndex(ADIndex indx);
3528     static PTR_AppDomain TestGetAppDomainAtIndex(ADIndex indx);
3529     static DWORD GetCurrentAppDomainMaxIndex()
3530     {
3531         WRAPPER_NO_CONTRACT;
3532
3533         ArrayListStatic* list = (ArrayListStatic *)&m_appDomainIndexList;
3534         PREFIX_ASSUME(list!=NULL);
3535         return list->GetCount();
3536     }
3537
3538     static ADID GetNewAppDomainId(AppDomain *pAppDomain);
3539     static void ReleaseAppDomainId(ADID indx);
3540     
3541 #ifndef DACCESS_COMPILE
3542     static ADID GetCurrentAppDomainMaxId() { ADID id; id.m_dwId=m_appDomainIdList.GetCount(); return id;}
3543 #endif // DACCESS_COMPILE
3544
3545
3546 #ifndef DACCESS_COMPILE
3547     DWORD RequireAppDomainCleanup()
3548     {
3549         LIMITED_METHOD_CONTRACT;
3550         return m_pDelayedUnloadListOfLoaderAllocators != 0;
3551     }
3552
3553     void AddToDelayedUnloadList(LoaderAllocator * pAllocator)
3554     {
3555         CONTRACTL
3556         {
3557             NOTHROW;
3558             GC_NOTRIGGER;
3559             MODE_COOPERATIVE;
3560         }
3561         CONTRACTL_END;
3562
3563         CrstHolder lh(&m_DelayedUnloadCrst);
3564         pAllocator->m_pLoaderAllocatorDestroyNext=m_pDelayedUnloadListOfLoaderAllocators;
3565         m_pDelayedUnloadListOfLoaderAllocators=pAllocator;
3566
3567         int iGCRefPoint=GCHeapUtilities::GetGCHeap()->CollectionCount(GCHeapUtilities::GetGCHeap()->GetMaxGeneration());
3568         if (GCHeapUtilities::IsGCInProgress())
3569             iGCRefPoint++;
3570         pAllocator->SetGCRefPoint(iGCRefPoint);
3571     }
3572
3573     void ProcessDelayedUnloadLoaderAllocators();
3574     
3575     static void EnumAllStaticGCRefs(promote_func* fn, ScanContext* sc);
3576
3577 #endif // DACCESS_COMPILE
3578
3579 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
3580     // The *AD* methods are what we got from tracing through EE roots.
3581     // RecordTotalSurvivedBytes is the total promoted from a GC.
3582     static void ResetADSurvivedBytes();
3583     static ULONGLONG GetADSurvivedBytes();
3584     static void RecordTotalSurvivedBytes(size_t totalSurvivedBytes);
3585     static ULONGLONG GetTotalSurvivedBytes()
3586     {
3587         LIMITED_METHOD_CONTRACT;
3588         return m_totalSurvivedBytes;
3589     }
3590 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
3591
3592     //****************************************************************************************
3593     // Routines to deal with the base library (currently mscorlib.dll)
3594     LPCWSTR BaseLibrary()
3595     {
3596         WRAPPER_NO_CONTRACT;
3597
3598         return m_BaseLibrary;
3599     }
3600
3601 #ifndef DACCESS_COMPILE
3602     BOOL IsBaseLibrary(SString &path)
3603     {
3604         WRAPPER_NO_CONTRACT;
3605
3606         // See if it is the installation path to mscorlib
3607         if (path.EqualsCaseInsensitive(m_BaseLibrary, PEImage::GetFileSystemLocale()))
3608             return TRUE;
3609
3610         // Or, it might be the GAC location of mscorlib
3611         if (System()->SystemAssembly() != NULL
3612             && path.EqualsCaseInsensitive(System()->SystemAssembly()->GetManifestFile()->GetPath(),
3613                                           PEImage::GetFileSystemLocale()))
3614             return TRUE;
3615
3616         return FALSE;
3617     }
3618
3619     BOOL IsBaseLibrarySatellite(SString &path)
3620     {
3621         WRAPPER_NO_CONTRACT;
3622
3623         // See if it is the installation path to mscorlib.resources
3624         SString s(SString::Ascii,g_psBaseLibrarySatelliteAssemblyName);
3625         if (path.EqualsCaseInsensitive(s, PEImage::GetFileSystemLocale()))
3626             return TRUE;
3627
3628         // workaround!  Must implement some code to do this string comparison for
3629         // mscorlib.resources in a culture-specific directory in the GAC.
3630
3631         /*
3632         // Or, it might be the GAC location of mscorlib.resources
3633         if (System()->SystemAssembly() != NULL
3634             && path.EqualsCaseInsensitive(System()->SystemAssembly()->GetManifestFile()->GetPath(),
3635                                           PEImage::GetFileSystemLocale()))
3636             return TRUE;
3637         */
3638
3639         return FALSE;
3640     }
3641 #endif // DACCESS_COMPILE
3642
3643     // Return the system directory
3644     LPCWSTR SystemDirectory()
3645     {
3646         WRAPPER_NO_CONTRACT;
3647
3648         return m_SystemDirectory;
3649     }
3650
3651 private:
3652
3653     //****************************************************************************************
3654     // Helper function to create the single COM domain
3655     void CreateDefaultDomain();
3656
3657     //****************************************************************************************
3658     // Helper function to add a domain to the global list
3659     void AddDomain(AppDomain* pDomain);
3660
3661     void CreatePreallocatedExceptions();
3662
3663     void PreallocateSpecialObjects();
3664
3665     //****************************************************************************************
3666     //
3667     static StackWalkAction CallersMethodCallback(CrawlFrame* pCrawlFrame, VOID* pClientData);
3668     static StackWalkAction CallersMethodCallbackWithStackMark(CrawlFrame* pCrawlFrame, VOID* pClientData);
3669
3670 #ifndef DACCESS_COMPILE
3671     // This class is not to be created through normal allocation.
3672     SystemDomain() 
3673     {
3674         STANDARD_VM_CONTRACT;
3675
3676         m_pDelayedUnloadListOfLoaderAllocators=NULL;
3677
3678         m_GlobalAllocator.Init(this);
3679     }
3680 #endif
3681
3682     PTR_PEAssembly  m_pSystemFile;      // Single assembly (here for quicker reference);
3683     PTR_Assembly    m_pSystemAssembly;  // Single assembly (here for quicker reference);
3684
3685     GlobalLoaderAllocator m_GlobalAllocator;
3686
3687
3688     InlineSString<100>  m_BaseLibrary;
3689
3690     InlineSString<100>  m_SystemDirectory;
3691
3692     // <TODO>@TODO: CTS, we can keep the com modules in a single assembly or in different assemblies.
3693     // We are currently using different assemblies but this is potentitially to slow...</TODO>
3694
3695     // Global domain that every one uses
3696     SPTR_DECL(SystemDomain, m_pSystemDomain);
3697
3698     LoaderAllocator * m_pDelayedUnloadListOfLoaderAllocators;
3699
3700 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
3701     // This is what gets promoted for the whole GC heap.
3702     static size_t m_totalSurvivedBytes;
3703 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
3704
3705     SVAL_DECL(ArrayListStatic, m_appDomainIndexList);
3706 #ifndef DACCESS_COMPILE
3707     static CrstStatic m_DelayedUnloadCrst;
3708     static CrstStatic       m_SystemDomainCrst;
3709
3710
3711     static ArrayListStatic  m_appDomainIdList;
3712
3713     static GlobalStringLiteralMap *m_pGlobalStringLiteralMap;
3714
3715     static ULONG       s_dNumAppDomains;  // Maintain a count of children app domains.
3716
3717     static DWORD        m_dwLowestFreeIndex;
3718 #endif // DACCESS_COMPILE
3719
3720 protected:
3721
3722     // These flags let the correct native image of mscorlib to be loaded.
3723     // This is important for hardbinding to it
3724
3725     SVAL_DECL(BOOL, s_fForceDebug);
3726     SVAL_DECL(BOOL, s_fForceProfiling);
3727     SVAL_DECL(BOOL, s_fForceInstrument);
3728
3729 public:
3730     static void     SetCompilationOverrides(BOOL fForceDebug,
3731                                             BOOL fForceProfiling,
3732                                             BOOL fForceInstrument);
3733
3734     static void     GetCompilationOverrides(BOOL * fForceDebug,
3735                                             BOOL * fForceProfiling,
3736                                             BOOL * fForceInstrument);
3737 public:
3738     //****************************************************************************************
3739     //
3740
3741 #ifndef DACCESS_COMPILE
3742 #ifdef _DEBUG
3743 inline static BOOL IsUnderDomainLock() { LIMITED_METHOD_CONTRACT; return m_SystemDomainCrst.OwnedByCurrentThread();};
3744 #endif
3745
3746     // This lock controls adding and removing domains from the system domain
3747     class LockHolder : public CrstHolder
3748     {
3749     public:
3750         LockHolder()
3751             : CrstHolder(&m_SystemDomainCrst)
3752         {
3753             WRAPPER_NO_CONTRACT;
3754         }
3755     };
3756 #endif // DACCESS_COMPILE
3757
3758 public:
3759     DWORD GetTotalNumSizedRefHandles();
3760
3761 #ifdef DACCESS_COMPILE
3762 public:
3763     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
3764                                    bool enumThis);
3765 #endif
3766
3767 };  // class SystemDomain
3768
3769
3770 //
3771 // an UnsafeAppDomainIterator is used to iterate over all existing domains
3772 //
3773 // The iteration is guaranteed to include all domains that exist at the
3774 // start & end of the iteration. This iterator is considered unsafe because it does not
3775 // reference count the various appdomains, and can only be used when the runtime is stopped,
3776 // or external synchronization is used. (and therefore no other thread may cause the appdomain list to change.)
3777 //
3778 class UnsafeAppDomainIterator
3779 {
3780     friend class SystemDomain;
3781 public:
3782     UnsafeAppDomainIterator(BOOL bOnlyActive)
3783     {
3784         m_bOnlyActive = bOnlyActive;
3785     }
3786
3787     void Init()
3788     {
3789         LIMITED_METHOD_CONTRACT;
3790         SystemDomain* sysDomain = SystemDomain::System();
3791         if (sysDomain)
3792         {
3793             ArrayListStatic* list = &sysDomain->m_appDomainIndexList;
3794             PREFIX_ASSUME(list != NULL);
3795             m_i = list->Iterate();
3796         }
3797         else
3798         {
3799             m_i.SetEmpty();
3800         }
3801
3802         m_pCurrent = NULL;
3803     }
3804
3805     BOOL Next()
3806     {
3807         WRAPPER_NO_CONTRACT;
3808
3809         while (m_i.Next())
3810         {
3811             m_pCurrent = dac_cast<PTR_AppDomain>(m_i.GetElement());
3812             if (m_pCurrent != NULL &&
3813                 (m_bOnlyActive ?
3814                  m_pCurrent->IsActive() : m_pCurrent->IsValid()))
3815             {
3816                 return TRUE;
3817             }
3818         }
3819
3820         m_pCurrent = NULL;
3821         return FALSE;
3822     }
3823
3824     AppDomain * GetDomain()
3825     {
3826         LIMITED_METHOD_DAC_CONTRACT;
3827
3828         return m_pCurrent;
3829     }
3830
3831   private:
3832
3833     ArrayList::Iterator m_i;
3834     AppDomain *         m_pCurrent;
3835     BOOL                m_bOnlyActive;
3836 };  // class UnsafeAppDomainIterator
3837
3838 //
3839 // an AppDomainIterator is used to iterate over all existing domains.
3840 //
3841 // The iteration is guaranteed to include all domains that exist at the
3842 // start & end of the iteration.  Any domains added or deleted during
3843 // iteration may or may not be included.  The iterator also guarantees
3844 // that the current iterated appdomain (GetDomain()) will not be deleted.
3845 //
3846
3847 class AppDomainIterator : public UnsafeAppDomainIterator
3848 {
3849     friend class SystemDomain;
3850
3851   public:
3852     AppDomainIterator(BOOL bOnlyActive) : UnsafeAppDomainIterator(bOnlyActive)
3853     {
3854         WRAPPER_NO_CONTRACT;
3855         Init();
3856     }
3857
3858     ~AppDomainIterator()
3859     {
3860         WRAPPER_NO_CONTRACT;
3861
3862 #ifndef DACCESS_COMPILE
3863         if (GetDomain() != NULL)
3864         {
3865 #ifdef _DEBUG            
3866             GetDomain()->IteratorRelease();
3867 #endif            
3868             GetDomain()->Release();
3869         }
3870 #endif
3871     }
3872
3873     BOOL Next()
3874     {
3875         WRAPPER_NO_CONTRACT;
3876
3877 #ifndef DACCESS_COMPILE
3878         if (GetDomain() != NULL)
3879         {
3880 #ifdef _DEBUG            
3881             GetDomain()->IteratorRelease();
3882 #endif            
3883             GetDomain()->Release();
3884         }
3885
3886         SystemDomain::LockHolder lh;
3887 #endif
3888
3889         if (UnsafeAppDomainIterator::Next())
3890         {
3891 #ifndef DACCESS_COMPILE
3892             GetDomain()->AddRef();
3893 #ifdef _DEBUG            
3894             GetDomain()->IteratorAcquire();
3895 #endif
3896 #endif
3897             return TRUE;
3898         }
3899
3900         return FALSE;
3901     }
3902 };  // class AppDomainIterator
3903
3904 #include "comreflectioncache.inl"
3905
3906 #define INVALID_APPDOMAIN_ID ((DWORD)-1)
3907 #define CURRENT_APPDOMAIN_ID ((ADID)(DWORD)0)
3908
3909 #endif