Add a fourth parameter to the DEFINE_DACVAR macro that is the actual fully qualified...
[platform/upstream/coreclr.git] / src / vm / appdomain.hpp
1 //
2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
4 //
5
6 /*============================================================
7 **
8 ** Header:  AppDomain.cpp
9 ** 
10
11 **
12 ** Purpose: Implements AppDomain (loader domain) architecture
13 **
14 **
15 ===========================================================*/
16 #ifndef _APPDOMAIN_H
17 #define _APPDOMAIN_H
18
19 #ifndef CLR_STANDALONE_BINDER
20 #include "eventtrace.h"
21 #include "assembly.hpp"
22 #include "clsload.hpp"
23 #include "eehash.h"
24 #ifdef FEATURE_FUSION
25 #include "fusion.h"
26 #endif
27 #include "arraylist.h"
28 #include "comreflectioncache.hpp"
29 #include "comutilnative.h"
30 #include "domainfile.h"
31 #include "objectlist.h"
32 #include "fptrstubs.h"
33 #include "ilstubcache.h"
34 #include "testhookmgr.h"
35 #ifdef FEATURE_VERSIONING
36 #include "../binder/inc/applicationcontext.hpp"
37 #endif // FEATURE_VERSIONING
38 #include "rejit.h"
39
40 #ifdef FEATURE_MULTICOREJIT
41 #include "multicorejit.h"
42 #endif
43
44 #ifdef FEATURE_COMINTEROP
45 #include "clrprivbinderwinrt.h"
46 #ifndef FEATURE_CORECLR
47 #include "clrprivbinderreflectiononlywinrt.h"
48 #include "clrprivtypecachereflectiononlywinrt.h"
49 #endif
50 #include "..\md\winmd\inc\adapter.h"
51 #include "winrttypenameconverter.h"
52 #endif // FEATURE_COMINTEROP
53
54 #else // CLR_STANDALONE_BINDER
55 class DomainFile;
56 class CPUSTUBLINKER;
57 struct CodeLabel;
58 class IdDispenser;
59 typedef DPTR(OBJECTREF) PTR_OBJECTREF;
60 typedef DPTR(DomainFile) PTR_DomainFile;
61 typedef DPTR(IdDispenser) PTR_IdDispenser;
62 #include "..\md\winmd\inc\adapter.h"
63 #endif // CLR_STANDALONE_BINDER
64
65 #include "appxutil.h"
66
67 class BaseDomain;
68 class SystemDomain;
69 class SharedDomain;
70 class AppDomain;
71 class CompilationDomain;
72 class AppDomainEnum;
73 class AssemblySink;
74 class EEMarshalingData;
75 class Context;
76 class GlobalStringLiteralMap;
77 class StringLiteralMap;
78 struct SecurityContext;
79 class MngStdInterfacesInfo;
80 class DomainModule;
81 class DomainAssembly;
82 struct InteropMethodTableData;
83 class LoadLevelLimiter;
84 class UMEntryThunkCache;
85 class TypeEquivalenceHashTable;
86 class IApplicationSecurityDescriptor;
87 class StringArrayList;
88
89 typedef VPTR(IApplicationSecurityDescriptor) PTR_IApplicationSecurityDescriptor;
90
91 extern INT64 g_PauseTime;  // Total time in millisecond the CLR has been paused
92
93 #ifdef FEATURE_COMINTEROP
94 class ComCallWrapperCache;
95 struct SimpleComCallWrapper;
96
97 class RCWRefCache;
98
99 // This enum is used to specify whether user want COM or remoting
100 enum COMorRemotingFlag {
101     COMorRemoting_NotInitialized = 0,
102     COMorRemoting_COM            = 1, // COM will be used both cross-domain and cross-runtime
103     COMorRemoting_Remoting       = 2, // Remoting will be used cross-domain; cross-runtime will use Remoting only if it looks like it's expected (default)
104     COMorRemoting_LegacyMode     = 3  // Remoting will be used both cross-domain and cross-runtime
105 };
106
107 #endif // FEATURE_COMINTEROP
108
109 #ifdef _MSC_VER
110 #pragma warning(push)
111 #pragma warning(disable : 4200) // Disable zero-sized array warning
112 #endif
113
114
115 GPTR_DECL(IdDispenser,       g_pModuleIndexDispenser);
116
117 // This enum is aligned to System.ExceptionCatcherType. 
118 enum ExceptionCatcher {
119     ExceptionCatcher_ManagedCode = 0,
120     ExceptionCatcher_AppDomainTransition = 1,
121     ExceptionCatcher_COMInterop = 2,    
122 };
123
124 // We would like *ALLOCATECLASS_FLAG to AV (in order to catch errors), so don't change it
125 struct ClassInitFlags {
126     enum
127     {
128         INITIALIZED_FLAG_BIT    = 0,
129         INITIALIZED_FLAG        = 1<<INITIALIZED_FLAG_BIT,
130         ERROR_FLAG_BIT          = 1,
131         ERROR_FLAG              = 1<<ERROR_FLAG_BIT,
132         ALLOCATECLASS_FLAG_BIT  = 2,                    // Bit to avoid racing for InstantiateStaticHandles
133         ALLOCATECLASS_FLAG      = 1<<ALLOCATECLASS_FLAG_BIT,
134         COLLECTIBLE_FLAG_BIT    = 3,
135         COLLECTIBLE_FLAG        = 1<<COLLECTIBLE_FLAG_BIT
136     };
137 };
138
139 struct DomainLocalModule
140 {
141     friend class ClrDataAccess;
142     friend class CheckAsmOffsets;
143     friend struct ThreadLocalModule;
144
145 // After these macros complete, they may have returned an interior pointer into a gc object. This pointer will have been cast to a byte pointer
146 // It is critically important that no GC is allowed to occur before this pointer is used.
147 #define GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLoaderAllocator, dynamicClassInfoParam, pGCStatics) \
148     {\
149         DomainLocalModule::PTR_DynamicClassInfo dynamicClassInfo = dac_cast<DomainLocalModule::PTR_DynamicClassInfo>(dynamicClassInfoParam);\
150         DomainLocalModule::PTR_DynamicEntry pDynamicEntry = dac_cast<DomainLocalModule::PTR_DynamicEntry>((DomainLocalModule::DynamicEntry*)dynamicClassInfo->m_pDynamicEntry.Load()); \
151         if ((dynamicClassInfo->m_dwFlags) & ClassInitFlags::COLLECTIBLE_FLAG) \
152         {\
153             PTRARRAYREF objArray;\
154             objArray = (PTRARRAYREF)pLoaderAllocator->GetHandleValueFastCannotFailType2( \
155                                         (dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hGCStatics);\
156             *(pGCStatics) = dac_cast<PTR_BYTE>(PTR_READ(PTR_TO_TADDR(OBJECTREFToObject( objArray )) + offsetof(PtrArray, m_Array), objArray->GetNumComponents() * sizeof(void*))) ;\
157         }\
158         else\
159         {\
160             *(pGCStatics) = (dac_cast<DomainLocalModule::PTR_NormalDynamicEntry>(pDynamicEntry))->GetGCStaticsBasePointer();\
161         }\
162     }\
163
164 #define GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLoaderAllocator, dynamicClassInfoParam, pNonGCStatics) \
165     {\
166         DomainLocalModule::PTR_DynamicClassInfo dynamicClassInfo = dac_cast<DomainLocalModule::PTR_DynamicClassInfo>(dynamicClassInfoParam);\
167         DomainLocalModule::PTR_DynamicEntry pDynamicEntry = dac_cast<DomainLocalModule::PTR_DynamicEntry>((DomainLocalModule::DynamicEntry*)(dynamicClassInfo)->m_pDynamicEntry.Load()); \
168         if (((dynamicClassInfo)->m_dwFlags) & ClassInitFlags::COLLECTIBLE_FLAG) \
169         {\
170             if ((dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hNonGCStatics != 0) \
171             { \
172                 U1ARRAYREF objArray;\
173                 objArray = (U1ARRAYREF)pLoaderAllocator->GetHandleValueFastCannotFailType2( \
174                                             (dac_cast<DomainLocalModule::PTR_CollectibleDynamicEntry>(pDynamicEntry))->m_hNonGCStatics);\
175                 *(pNonGCStatics) = dac_cast<PTR_BYTE>(PTR_READ( \
176                         PTR_TO_TADDR(OBJECTREFToObject( objArray )) + sizeof(ArrayBase) - DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob(), \
177                             objArray->GetNumComponents() * (DWORD)objArray->GetComponentSize() + DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob())); \
178             } else (*pNonGCStatics) = NULL; \
179         }\
180         else\
181         {\
182             *(pNonGCStatics) = dac_cast<DomainLocalModule::PTR_NormalDynamicEntry>(pDynamicEntry)->GetNonGCStaticsBasePointer();\
183         }\
184     }\
185
186     struct DynamicEntry
187     {
188         static DWORD GetOffsetOfDataBlob();
189     };
190     typedef DPTR(DynamicEntry) PTR_DynamicEntry;
191
192     struct CollectibleDynamicEntry : public DynamicEntry
193     {
194         LOADERHANDLE    m_hGCStatics;
195         LOADERHANDLE    m_hNonGCStatics;
196     };
197     typedef DPTR(CollectibleDynamicEntry) PTR_CollectibleDynamicEntry;
198
199     struct NormalDynamicEntry : public DynamicEntry
200     {
201         PTR_OBJECTREF   m_pGCStatics;
202 #ifdef FEATURE_64BIT_ALIGNMENT
203         // Padding to make m_pDataBlob aligned at MAX_PRIMITIVE_FIELD_SIZE
204         // code:MethodTableBuilder::PlaceRegularStaticFields assumes that the start of the data blob is aligned 
205         SIZE_T          m_padding;
206 #endif
207         BYTE            m_pDataBlob[0];
208
209         inline PTR_BYTE GetGCStaticsBasePointer()
210         {
211             LIMITED_METHOD_CONTRACT;
212             SUPPORTS_DAC;
213             return dac_cast<PTR_BYTE>(m_pGCStatics);
214         }
215         inline PTR_BYTE GetNonGCStaticsBasePointer()
216         {
217             LIMITED_METHOD_CONTRACT
218             SUPPORTS_DAC;
219             return dac_cast<PTR_BYTE>(this);
220         }
221     };
222     typedef DPTR(NormalDynamicEntry) PTR_NormalDynamicEntry;
223
224     struct DynamicClassInfo
225     {
226         VolatilePtr<DynamicEntry, PTR_DynamicEntry>  m_pDynamicEntry;
227         Volatile<DWORD>             m_dwFlags;
228     };
229     typedef DPTR(DynamicClassInfo) PTR_DynamicClassInfo;
230     
231     inline UMEntryThunk * GetADThunkTable()
232     {
233         LIMITED_METHOD_CONTRACT
234         return m_pADThunkTable;
235     }
236
237     inline void SetADThunkTable(UMEntryThunk* pADThunkTable)
238     {
239         LIMITED_METHOD_CONTRACT
240         InterlockedCompareExchangeT(m_pADThunkTable.GetPointer(), pADThunkTable, NULL);
241     }
242
243     // Note the difference between:
244     // 
245     //  GetPrecomputedNonGCStaticsBasePointer() and
246     //  GetPrecomputedStaticsClassData()
247     //
248     //  GetPrecomputedNonGCStaticsBasePointer returns the pointer that should be added to field offsets to retrieve statics
249     //  GetPrecomputedStaticsClassData returns a pointer to the first byte of the precomputed statics block
250     inline TADDR GetPrecomputedNonGCStaticsBasePointer()
251     {
252         LIMITED_METHOD_CONTRACT
253         return dac_cast<TADDR>(this);
254     }
255
256     inline PTR_BYTE GetPrecomputedStaticsClassData()
257     {
258         LIMITED_METHOD_CONTRACT
259         return dac_cast<PTR_BYTE>(this) + offsetof(DomainLocalModule, m_pDataBlob);
260     }
261
262     static SIZE_T GetOffsetOfDataBlob() { return offsetof(DomainLocalModule, m_pDataBlob); }
263     static SIZE_T GetOffsetOfGCStaticPointer() { return offsetof(DomainLocalModule, m_pGCStatics); }
264
265     inline DomainFile* GetDomainFile()
266     {
267         LIMITED_METHOD_CONTRACT
268         SUPPORTS_DAC;
269         return m_pDomainFile;
270     }
271
272 #ifndef DACCESS_COMPILE
273     inline void        SetDomainFile(DomainFile* pDomainFile)
274     {
275         LIMITED_METHOD_CONTRACT
276         m_pDomainFile = pDomainFile;
277     }
278 #endif
279
280     inline PTR_OBJECTREF  GetPrecomputedGCStaticsBasePointer()
281     {
282         LIMITED_METHOD_CONTRACT        
283         return m_pGCStatics;
284     }
285
286     inline PTR_OBJECTREF * GetPrecomputedGCStaticsBasePointerAddress()
287     {
288         LIMITED_METHOD_CONTRACT        
289         return &m_pGCStatics;
290     }
291
292 #ifndef CLR_STANDALONE_BINDER
293     // Returns bytes so we can add offsets
294     inline PTR_BYTE GetGCStaticsBasePointer(MethodTable * pMT)
295     {
296         WRAPPER_NO_CONTRACT
297         SUPPORTS_DAC;
298
299         if (pMT->IsDynamicStatics())
300         {
301             _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics());
302             return GetDynamicEntryGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator());
303         }
304         else
305         {
306             return dac_cast<PTR_BYTE>(m_pGCStatics);
307         }
308     }
309
310     inline PTR_BYTE GetNonGCStaticsBasePointer(MethodTable * pMT)
311     {
312         WRAPPER_NO_CONTRACT
313         SUPPORTS_DAC;
314
315         if (pMT->IsDynamicStatics())
316         {
317             _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics());
318             return GetDynamicEntryNonGCStaticsBasePointer(pMT->GetModuleDynamicEntryID(), pMT->GetLoaderAllocator());
319         }
320         else
321         {
322             return dac_cast<PTR_BYTE>(this);
323         }
324     }
325 #endif // !CLR_STANDALONE_BINDER
326
327     inline DynamicClassInfo* GetDynamicClassInfo(DWORD n)
328     {
329         LIMITED_METHOD_CONTRACT
330         SUPPORTS_DAC;
331         _ASSERTE(m_pDynamicClassTable.Load() && m_aDynamicEntries > n);
332         dac_cast<PTR_DynamicEntry>(m_pDynamicClassTable[n].m_pDynamicEntry.Load());
333
334         return &m_pDynamicClassTable[n];
335     }
336
337 #ifndef CLR_STANDALONE_BINDER
338     // These helpers can now return null, as the debugger may do queries on a type
339     // before the calls to PopulateClass happen
340     inline PTR_BYTE GetDynamicEntryGCStaticsBasePointer(DWORD n, PTR_LoaderAllocator pLoaderAllocator)
341     {
342         CONTRACTL
343         {
344             NOTHROW;
345             GC_NOTRIGGER;
346             SO_TOLERANT;
347             MODE_COOPERATIVE;
348             SUPPORTS_DAC;
349         }
350         CONTRACTL_END;
351
352
353         if (n >= m_aDynamicEntries)
354         {
355             return NULL;
356         }
357         
358         DynamicClassInfo* pClassInfo = GetDynamicClassInfo(n);
359         if (!pClassInfo->m_pDynamicEntry)
360         {
361             return NULL;
362         }
363
364         PTR_BYTE retval = NULL;
365
366         GET_DYNAMICENTRY_GCSTATICS_BASEPOINTER(pLoaderAllocator, pClassInfo, &retval);
367
368         return retval;
369     }
370
371     inline PTR_BYTE GetDynamicEntryNonGCStaticsBasePointer(DWORD n, PTR_LoaderAllocator pLoaderAllocator)
372     {
373         CONTRACTL
374         {
375             NOTHROW;
376             GC_NOTRIGGER;
377             SO_TOLERANT;
378             MODE_COOPERATIVE;
379             SUPPORTS_DAC;
380         }
381         CONTRACTL_END;
382
383         
384         if (n >= m_aDynamicEntries)
385         {
386             return NULL;
387         }
388         
389         DynamicClassInfo* pClassInfo = GetDynamicClassInfo(n);
390         if (!pClassInfo->m_pDynamicEntry)
391         {
392             return NULL;
393         }
394
395         PTR_BYTE retval = NULL;
396
397         GET_DYNAMICENTRY_NONGCSTATICS_BASEPOINTER(pLoaderAllocator, pClassInfo, &retval);
398
399         return retval;
400     }
401 #endif // CLR_STANDALONE_BINDER
402
403     FORCEINLINE PTR_DynamicClassInfo GetDynamicClassInfoIfInitialized(DWORD n)
404     {
405         WRAPPER_NO_CONTRACT;
406
407         // m_aDynamicEntries is set last, it needs to be checked first
408         if (n >= m_aDynamicEntries)
409         {
410             return NULL;
411         }
412
413         _ASSERTE(m_pDynamicClassTable.Load() != NULL);
414         PTR_DynamicClassInfo pDynamicClassInfo = (PTR_DynamicClassInfo)(m_pDynamicClassTable.Load() + n);
415
416         // INITIALIZED_FLAG is set last, it needs to be checked first
417         if ((pDynamicClassInfo->m_dwFlags & ClassInitFlags::INITIALIZED_FLAG) == 0)
418         {
419             return NULL;
420         }
421
422         PREFIX_ASSUME(pDynamicClassInfo != NULL);
423         return pDynamicClassInfo;
424     }
425
426     // iClassIndex is slightly expensive to compute, so if we already know
427     // it, we can use this helper
428     inline BOOL IsClassInitialized(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
429     {
430         WRAPPER_NO_CONTRACT;
431         return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::INITIALIZED_FLAG) != 0;
432     }
433
434     inline BOOL IsPrecomputedClassInitialized(DWORD classID)
435     {
436         return GetPrecomputedStaticsClassData()[classID] & ClassInitFlags::INITIALIZED_FLAG;
437     }
438     
439     inline BOOL IsClassAllocated(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
440     {
441         WRAPPER_NO_CONTRACT;
442         return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::ALLOCATECLASS_FLAG) != 0;
443     }
444
445     BOOL IsClassInitError(MethodTable* pMT, DWORD iClassIndex = (DWORD)-1)
446     {
447         WRAPPER_NO_CONTRACT;
448         return (GetClassFlags(pMT, iClassIndex) & ClassInitFlags::ERROR_FLAG) != 0;
449     }
450
451     void    SetClassInitialized(MethodTable* pMT);
452     void    SetClassInitError(MethodTable* pMT);
453
454     void    EnsureDynamicClassIndex(DWORD dwID);
455
456     void    AllocateDynamicClass(MethodTable *pMT);
457
458     void    PopulateClass(MethodTable *pMT);
459
460 #ifdef DACCESS_COMPILE
461     void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
462 #endif
463
464     static DWORD OffsetOfDataBlob()
465     {
466         LIMITED_METHOD_CONTRACT;
467         return offsetof(DomainLocalModule, m_pDataBlob);
468     }
469
470 #ifndef CLR_STANDALONE_BINDER
471     FORCEINLINE MethodTable * GetMethodTableFromClassDomainID(DWORD dwClassDomainID)
472     {
473         DWORD rid = (DWORD)(dwClassDomainID) + 1;
474         TypeHandle th = GetDomainFile()->GetModule()->LookupTypeDef(TokenFromRid(rid, mdtTypeDef));
475         _ASSERTE(!th.IsNull());
476         MethodTable * pMT = th.AsMethodTable();
477         PREFIX_ASSUME(pMT != NULL);
478         return pMT;
479     }
480 #endif // CLR_STANDALONE_BINDER
481     
482 private:
483     friend void EmitFastGetSharedStaticBase(CPUSTUBLINKER *psl, CodeLabel *init, bool bCCtorCheck);
484
485     void SetClassFlags(MethodTable* pMT, DWORD dwFlags);
486     DWORD GetClassFlags(MethodTable* pMT, DWORD iClassIndex);
487
488     PTR_DomainFile           m_pDomainFile;
489     VolatilePtr<DynamicClassInfo, PTR_DynamicClassInfo> m_pDynamicClassTable;   // used for generics and reflection.emit in memory
490     Volatile<SIZE_T>         m_aDynamicEntries;      // number of entries in dynamic table
491     VolatilePtr<UMEntryThunk> m_pADThunkTable;
492     PTR_OBJECTREF            m_pGCStatics;           // Handle to GC statics of the module
493
494     // In addition to storing the ModuleIndex in the Module class, we also
495     // keep a copy of the ModuleIndex in the DomainLocalModule class. This
496     // allows the thread static JIT helpers to quickly convert a pointer to
497     // a DomainLocalModule into a ModuleIndex.
498     ModuleIndex             m_ModuleIndex;
499
500     // Note that the static offset calculation in code:Module::BuildStaticsOffsets takes the offset m_pDataBlob
501     // into consideration for alignment so we do not need any padding to ensure that the start of the data blob is aligned
502
503     BYTE                     m_pDataBlob[0];         // First byte of the statics blob
504
505     // Layout of m_pDataBlob is:
506     //              ClassInit bytes (hold flags for cctor run, cctor error, etc)
507     //              Non GC Statics
508
509 public:
510
511     // The Module class need to be able to initialized ModuleIndex,
512     // so for now I will make it a friend..
513     friend class Module;
514
515     FORCEINLINE ModuleIndex GetModuleIndex()
516     {
517         LIMITED_METHOD_DAC_CONTRACT;
518         return m_ModuleIndex;
519     }
520
521 };  // struct DomainLocalModule
522
523
524 #ifndef CLR_STANDALONE_BINDER
525
526 typedef DPTR(class DomainLocalBlock) PTR_DomainLocalBlock;
527 class DomainLocalBlock
528 {
529     friend class ClrDataAccess;
530     friend class CheckAsmOffsets;
531
532 private:
533     PTR_AppDomain          m_pDomain;
534     DPTR(PTR_DomainLocalModule) m_pModuleSlots;
535     SIZE_T                 m_aModuleIndices;               // Module entries the shared block has allocated
536
537 public: // used by code generators
538     static SIZE_T GetOffsetOfModuleSlotsPointer() { return offsetof(DomainLocalBlock, m_pModuleSlots);}
539
540 public:
541
542 #ifndef DACCESS_COMPILE
543     DomainLocalBlock()
544       : m_pDomain(NULL),  m_pModuleSlots(NULL), m_aModuleIndices(0) {}
545
546     void    EnsureModuleIndex(ModuleIndex index);
547
548     void Init(AppDomain *pDomain) { LIMITED_METHOD_CONTRACT; m_pDomain = pDomain; }
549 #endif
550
551     void SetModuleSlot(ModuleIndex index, PTR_DomainLocalModule pLocalModule);
552
553     FORCEINLINE PTR_DomainLocalModule GetModuleSlot(ModuleIndex index)
554     {
555         WRAPPER_NO_CONTRACT;
556         SUPPORTS_DAC;
557         _ASSERTE(index.m_dwIndex < m_aModuleIndices);
558         return m_pModuleSlots[index.m_dwIndex];
559     }
560
561     inline PTR_DomainLocalModule GetModuleSlot(MethodTable* pMT)
562     {
563         WRAPPER_NO_CONTRACT;
564         return GetModuleSlot(pMT->GetModuleForStatics()->GetModuleIndex());
565     }
566
567     DomainFile* TryGetDomainFile(ModuleIndex index)
568     {
569         WRAPPER_NO_CONTRACT;
570         SUPPORTS_DAC;
571
572         // the publishing of m_aModuleIndices and m_pModuleSlots is dependent
573         // on the order of accesses; we must ensure that we read from m_aModuleIndices
574         // before m_pModuleSlots.
575         if (index.m_dwIndex < m_aModuleIndices)
576         {
577             MemoryBarrier();
578             if (m_pModuleSlots[index.m_dwIndex])
579             {
580                 return m_pModuleSlots[index.m_dwIndex]->GetDomainFile();
581             }
582         }
583
584         return NULL;
585     }
586
587     DomainFile* GetDomainFile(SIZE_T ModuleID)
588     {
589         WRAPPER_NO_CONTRACT;
590         ModuleIndex index = Module::IDToIndex(ModuleID);
591         _ASSERTE(index.m_dwIndex < m_aModuleIndices);
592         return m_pModuleSlots[index.m_dwIndex]->GetDomainFile();
593     }
594
595 #ifndef DACCESS_COMPILE
596     void SetDomainFile(ModuleIndex index, DomainFile* pDomainFile)
597     {
598         WRAPPER_NO_CONTRACT;
599         _ASSERTE(index.m_dwIndex < m_aModuleIndices);
600         m_pModuleSlots[index.m_dwIndex]->SetDomainFile(pDomainFile);
601     }
602 #endif
603
604 #ifdef DACCESS_COMPILE
605     void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
606 #endif
607
608
609 private:
610
611     //
612     // Low level routines to get & set class entries
613     //
614
615 };
616
617 #ifdef _MSC_VER
618 #pragma warning(pop)
619 #endif
620
621
622 // The large heap handle bucket class is used to contain handles allocated
623 // from an array contained in the large heap.
624 class LargeHeapHandleBucket
625 {
626 public:
627     // Constructor and desctructor.
628     LargeHeapHandleBucket(LargeHeapHandleBucket *pNext, DWORD Size, BaseDomain *pDomain, BOOL bCrossAD = FALSE);
629     ~LargeHeapHandleBucket();
630
631     // This returns the next bucket.
632     LargeHeapHandleBucket *GetNext()
633     {
634         LIMITED_METHOD_CONTRACT;
635
636         return m_pNext;
637     }
638
639     // This returns the number of remaining handle slots.
640     DWORD GetNumRemainingHandles()
641     {
642         LIMITED_METHOD_CONTRACT;
643
644         return m_ArraySize - m_CurrentPos;
645     }
646
647     void ConsumeRemaining()
648     {
649         LIMITED_METHOD_CONTRACT;
650         
651         m_CurrentPos = m_ArraySize;
652     }
653
654     OBJECTREF *TryAllocateEmbeddedFreeHandle();       
655
656     // Allocate handles from the bucket.
657     OBJECTREF* AllocateHandles(DWORD nRequested);
658     OBJECTREF* CurrentPos()
659     {
660         LIMITED_METHOD_CONTRACT;
661         return m_pArrayDataPtr + m_CurrentPos;
662     }
663
664 private:
665     LargeHeapHandleBucket *m_pNext;
666     int m_ArraySize;
667     int m_CurrentPos;
668     int m_CurrentEmbeddedFreePos;
669     OBJECTHANDLE m_hndHandleArray;
670     OBJECTREF *m_pArrayDataPtr;
671 };
672
673
674
675 // The large heap handle table is used to allocate handles that are pointers
676 // to objects stored in an array in the large object heap.
677 class LargeHeapHandleTable
678 {
679 public:
680     // Constructor and desctructor.
681     LargeHeapHandleTable(BaseDomain *pDomain, DWORD InitialBucketSize);
682     ~LargeHeapHandleTable();
683
684     // Allocate handles from the large heap handle table.
685     OBJECTREF* AllocateHandles(DWORD nRequested, BOOL bCrossAD = FALSE);
686
687     // Release object handles allocated using AllocateHandles().
688     void ReleaseHandles(OBJECTREF *pObjRef, DWORD nReleased);    
689
690 private:
691     // The buckets of object handles.
692     LargeHeapHandleBucket *m_pHead;
693
694     // We need to know the containing domain so we know where to allocate handles
695     BaseDomain *m_pDomain;
696
697     // The size of the LargeHeapHandleBuckets.
698     DWORD m_NextBucketSize;
699
700     // for finding and re-using embedded free items in the list
701     LargeHeapHandleBucket *m_pFreeSearchHint;
702     DWORD m_cEmbeddedFree;   
703
704 #ifdef _DEBUG
705
706     // these functions are present to enforce that there is a locking mechanism in place
707     // for each LargeHeapHandleTable even though the code itself does not do the locking
708     // you must tell the table which lock you intend to use and it will verify that it has
709     // in fact been taken before performing any operations
710
711 public:
712     void RegisterCrstDebug(CrstBase *pCrst)
713     {
714         LIMITED_METHOD_CONTRACT;
715
716         // this function must be called exactly once
717         _ASSERTE(pCrst != NULL);
718         _ASSERTE(m_pCrstDebug == NULL);
719         m_pCrstDebug = pCrst;
720     }
721
722 private:
723     // we will assert that this Crst is held before using the object
724     CrstBase *m_pCrstDebug;
725
726 #endif
727     
728 };
729
730 class LargeHeapHandleBlockHolder;
731 void LargeHeapHandleBlockHolder__StaticFree(LargeHeapHandleBlockHolder*);
732
733
734 class LargeHeapHandleBlockHolder:public Holder<LargeHeapHandleBlockHolder*,DoNothing,LargeHeapHandleBlockHolder__StaticFree>
735
736 {
737     LargeHeapHandleTable* m_pTable;
738     DWORD m_Count;
739     OBJECTREF* m_Data;
740 public:
741     FORCEINLINE LargeHeapHandleBlockHolder(LargeHeapHandleTable* pOwner, DWORD nCount)
742     {
743         WRAPPER_NO_CONTRACT;
744         m_Data = pOwner->AllocateHandles(nCount);
745         m_Count=nCount;
746         m_pTable=pOwner;
747     };
748
749     FORCEINLINE void FreeData()
750     {
751         WRAPPER_NO_CONTRACT;
752         for (DWORD i=0;i< m_Count;i++)
753             ClearObjectReference(m_Data+i);
754         m_pTable->ReleaseHandles(m_Data, m_Count);
755     };
756     FORCEINLINE OBJECTREF* operator[] (DWORD idx)
757     {
758         LIMITED_METHOD_CONTRACT;
759         _ASSERTE(idx<m_Count);
760         return &(m_Data[idx]);
761     }
762 };
763
764 FORCEINLINE  void LargeHeapHandleBlockHolder__StaticFree(LargeHeapHandleBlockHolder* pHolder)
765 {
766     WRAPPER_NO_CONTRACT;
767     pHolder->FreeData();
768 };
769
770
771
772
773
774 // The large heap handle bucket class is used to contain handles allocated
775 // from an array contained in the large heap.
776 class ThreadStaticHandleBucket
777 {
778 public:
779     // Constructor and desctructor.
780     ThreadStaticHandleBucket(ThreadStaticHandleBucket *pNext, DWORD Size, BaseDomain *pDomain);
781     ~ThreadStaticHandleBucket();
782
783     // This returns the next bucket.
784     ThreadStaticHandleBucket *GetNext()
785     {
786         LIMITED_METHOD_CONTRACT;
787
788         return m_pNext;
789     }
790
791     // Allocate handles from the bucket.
792     OBJECTHANDLE GetHandles();
793
794 private:
795     ThreadStaticHandleBucket *m_pNext;
796     int m_ArraySize;
797     OBJECTHANDLE m_hndHandleArray;
798 };
799
800
801 // The large heap handle table is used to allocate handles that are pointers
802 // to objects stored in an array in the large object heap.
803 class ThreadStaticHandleTable
804 {
805 public:
806     // Constructor and desctructor.
807     ThreadStaticHandleTable(BaseDomain *pDomain);
808     ~ThreadStaticHandleTable();
809
810     // Allocate handles from the large heap handle table.
811     OBJECTHANDLE AllocateHandles(DWORD nRequested);
812
813 private:
814     // The buckets of object handles.
815     ThreadStaticHandleBucket *m_pHead;
816
817     // We need to know the containing domain so we know where to allocate handles
818     BaseDomain *m_pDomain;
819 };
820
821
822
823
824 //--------------------------------------------------------------------------------------
825 // Base class for domains. It provides an abstract way of finding the first assembly and
826 // for creating assemblies in the the domain. The system domain only has one assembly, it
827 // contains the classes that are logically shared between domains. All other domains can
828 // have multiple assemblies. Iteration is done be getting the first assembly and then
829 // calling the Next() method on the assembly.
830 //
831 // The system domain should be as small as possible, it includes object, exceptions, etc.
832 // which are the basic classes required to load other assemblies. All other classes
833 // should be loaded into the domain. Of coarse there is a trade off between loading the
834 // same classes multiple times, requiring all domains to load certain assemblies (working
835 // set) and being able to specify specific versions.
836 //
837
838 #define LOW_FREQUENCY_HEAP_RESERVE_SIZE        (3 * PAGE_SIZE)
839 #define LOW_FREQUENCY_HEAP_COMMIT_SIZE         (1 * PAGE_SIZE)
840
841 #define HIGH_FREQUENCY_HEAP_RESERVE_SIZE       (10 * PAGE_SIZE)
842 #define HIGH_FREQUENCY_HEAP_COMMIT_SIZE        (1 * PAGE_SIZE)
843
844 #define STUB_HEAP_RESERVE_SIZE                 (3 * PAGE_SIZE)
845 #define STUB_HEAP_COMMIT_SIZE                  (1 * PAGE_SIZE)
846
847 // --------------------------------------------------------------------------------
848 // PE File List lock - for creating list locks on PE files
849 // --------------------------------------------------------------------------------
850
851 class PEFileListLock : public ListLock
852 {
853 public:
854 #ifndef DACCESS_COMPILE
855     ListLockEntry *FindFileLock(PEFile *pFile)
856     {
857         STATIC_CONTRACT_NOTHROW;
858         STATIC_CONTRACT_GC_NOTRIGGER;
859         STATIC_CONTRACT_FORBID_FAULT;
860
861         PRECONDITION(HasLock());
862
863         ListLockEntry *pEntry;
864
865         for (pEntry = m_pHead;
866              pEntry != NULL;
867              pEntry = pEntry->m_pNext)
868         {
869             if (((PEFile *)pEntry->m_pData)->Equals(pFile))
870             {
871                 return pEntry;
872             }
873         }
874
875         return NULL;
876     }
877 #endif // DACCESS_COMPILE
878
879     DEBUG_NOINLINE static void HolderEnter(PEFileListLock *pThis) PUB
880     {
881         WRAPPER_NO_CONTRACT;
882         ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
883         
884         pThis->Enter();
885     }
886
887     DEBUG_NOINLINE static void HolderLeave(PEFileListLock *pThis) PUB
888     {
889         WRAPPER_NO_CONTRACT;
890         ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
891
892         pThis->Leave();
893     }
894
895     typedef Wrapper<PEFileListLock*, PEFileListLock::HolderEnter, PEFileListLock::HolderLeave> Holder;
896 };
897
898 typedef PEFileListLock::Holder PEFileListLockHolder;
899
900 // Loading infrastructure:
901 //
902 // a DomainFile is a file being loaded.  Files are loaded in layers to enable loading in the
903 // presence of dependency loops.
904 //
905 // FileLoadLevel describes the various levels available.  These are implemented slightly
906 // differently for assemblies and modules, but the basic structure is the same.
907 //
908 // LoadLock and FileLoadLock form the ListLock data structures for files. The FileLoadLock
909 // is specialized in that it allows taking a lock at a particular level.  Basicall any
910 // thread may obtain the lock at a level at which the file has previously been loaded to, but
911 // only one thread may obtain the lock at its current level.
912 //
913 // The PendingLoadQueue is a per thread data structure which serves two purposes.  First, it
914 // holds a "load limit" which automatically restricts the level of recursive loads to be
915 // one less than the current load which is preceding.  This, together with the AppDomain
916 // LoadLock level behavior, will prevent any deadlocks from occuring due to circular
917 // dependencies.  (Note that it is important that the loading logic understands this restriction,
918 // and any given level of loading must deal with the fact that any recursive loads will be partially
919 // unfulfilled in a specific way.)
920 //
921 // The second function is to queue up any unfulfilled load requests for the thread.  These
922 // are then delivered immediately after the current load request is dealt with.
923
924 class FileLoadLock : public ListLockEntry
925 {
926 private:
927     FileLoadLevel           m_level;
928     DomainFile              *m_pDomainFile;
929     HRESULT                 m_cachedHR;
930     ADID                    m_AppDomainId;
931
932 public:
933     static FileLoadLock *Create(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile);
934
935     ~FileLoadLock();
936     DomainFile *GetDomainFile();
937     ADID GetAppDomainId();
938     FileLoadLevel GetLoadLevel();
939
940     // CanAcquire will return FALSE if Acquire will definitely not take the lock due
941     // to levels or deadlock.
942     // (Note that there is a race exiting from the function, where Acquire may end
943     // up not taking the lock anyway if another thread did work in the meantime.)
944     BOOL CanAcquire(FileLoadLevel targetLevel);
945
946     // Acquire will return FALSE and not take the lock if the file
947     // has already been loaded to the target level.  Otherwise,
948     // it will return TRUE and take the lock.
949     //
950     // Note that the taker must release the lock via IncrementLoadLevel.
951     BOOL Acquire(FileLoadLevel targetLevel);
952
953     // CompleteLoadLevel can be called after Acquire returns true
954     // returns TRUE if it updated load level, FALSE if the level was set already
955     BOOL CompleteLoadLevel(FileLoadLevel level, BOOL success);
956
957     void SetError(Exception *ex);
958
959     void AddRef();
960     UINT32 Release() DAC_EMPTY_RET(0);
961
962 private:
963
964     FileLoadLock(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile);
965
966     static void HolderLeave(FileLoadLock *pThis);
967
968 public:
969     typedef Wrapper<FileLoadLock *, DoNothing, FileLoadLock::HolderLeave> Holder;
970
971 };
972
973 typedef FileLoadLock::Holder FileLoadLockHolder;
974
975 #ifndef DACCESS_COMPILE
976     typedef ReleaseHolder<FileLoadLock> FileLoadLockRefHolder;
977 #endif // DACCESS_COMPILE
978
979
980 #ifdef _MSC_VER
981 #pragma warning(push)
982 #pragma warning (disable: 4324) //sometimes 64bit compilers complain about alignment
983 #endif
984 class LoadLevelLimiter
985 {
986     FileLoadLevel                   m_currentLevel;
987     LoadLevelLimiter* m_previousLimit;
988     BOOL m_bActive;
989
990 public:
991
992     LoadLevelLimiter()
993       : m_currentLevel(FILE_ACTIVE),
994       m_previousLimit(NULL),
995       m_bActive(FALSE)
996     {
997         LIMITED_METHOD_CONTRACT;
998     }
999
1000     void Activate()
1001     {
1002         WRAPPER_NO_CONTRACT;
1003         m_previousLimit=GetThread()->GetLoadLevelLimiter();
1004         if(m_previousLimit)
1005             m_currentLevel=m_previousLimit->GetLoadLevel();
1006         GetThread()->SetLoadLevelLimiter(this);       
1007         m_bActive=TRUE;
1008     }
1009
1010     void Deactivate()
1011     {
1012         WRAPPER_NO_CONTRACT;
1013         if (m_bActive)
1014         {
1015             GetThread()->SetLoadLevelLimiter(m_previousLimit);
1016             m_bActive=FALSE;
1017         }
1018     }
1019
1020     ~LoadLevelLimiter()
1021     {
1022         WRAPPER_NO_CONTRACT;
1023
1024         // PendingLoadQueues are allocated on the stack during a load, and
1025         // shared with all nested loads on the same thread.
1026
1027         // Make sure the thread pointer gets reset after the
1028         // top level queue goes out of scope.
1029         if(m_bActive)
1030         {
1031             Deactivate();
1032         }
1033     }
1034
1035     FileLoadLevel GetLoadLevel()
1036     {
1037         LIMITED_METHOD_CONTRACT;
1038         return m_currentLevel;
1039     }
1040
1041     void SetLoadLevel(FileLoadLevel level)
1042     {
1043         LIMITED_METHOD_CONTRACT;
1044         m_currentLevel = level;
1045     }
1046 };
1047 #ifdef _MSC_VER
1048 #pragma warning (pop) //4324
1049 #endif
1050
1051 #define OVERRIDE_LOAD_LEVEL_LIMIT(newLimit)                    \
1052     LoadLevelLimiter __newLimit;                                                    \
1053     __newLimit.Activate();                                                              \
1054     __newLimit.SetLoadLevel(newLimit);
1055
1056 // A BaseDomain much basic information in a code:AppDomain including
1057 // 
1058 //    * code:#AppdomainHeaps - Heaps for any data structures that will be freed on appdomain unload
1059 //    
1060 class BaseDomain
1061 {
1062     friend class Assembly;
1063     friend class AssemblySpec;
1064     friend class AppDomain;
1065     friend class AppDomainNative;
1066
1067     VPTR_BASE_VTABLE_CLASS(BaseDomain)
1068     VPTR_UNIQUE(VPTR_UNIQUE_BaseDomain)
1069
1070 protected:
1071     // These 2 variables are only used on the AppDomain, but by placing them here
1072     // we reduce the cost of keeping the asmconstants file up to date.
1073
1074     // The creation sequence number of this app domain (starting from 1)
1075     // This ID is generated by the code:SystemDomain::GetNewAppDomainId routine
1076     // The ID are recycled. 
1077     // 
1078     // see also code:ADID 
1079     ADID m_dwId;
1080
1081     DomainLocalBlock    m_sDomainLocalBlock;
1082
1083 public:
1084
1085     class AssemblyIterator;
1086     friend class AssemblyIterator;
1087
1088     // Static initialization.
1089     static void Attach();
1090
1091     //****************************************************************************************
1092     //
1093     // Initialization/shutdown routines for every instance of an BaseDomain.
1094
1095     BaseDomain();
1096     void Init();
1097     void Stop();
1098     void Terminate();
1099
1100     // ID to uniquely identify this AppDomain - used by the AppDomain publishing
1101     // service (to publish the list of all appdomains present in the process),
1102     // which in turn is used by, for eg., the debugger (to decide which App-
1103     // Domain(s) to attach to).
1104     // This is also used by Remoting for routing cross-appDomain calls.
1105     ADID GetId (void)
1106     {
1107         LIMITED_METHOD_DAC_CONTRACT;
1108         STATIC_CONTRACT_SO_TOLERANT;
1109         return m_dwId;
1110     }
1111     
1112     virtual BOOL IsAppDomain()    { LIMITED_METHOD_DAC_CONTRACT; return FALSE; }
1113     virtual BOOL IsSharedDomain() { LIMITED_METHOD_DAC_CONTRACT; return FALSE; }
1114
1115     inline BOOL IsDefaultDomain();  // defined later in this file
1116     virtual PTR_LoaderAllocator GetLoaderAllocator() = 0;
1117     virtual PTR_AppDomain AsAppDomain()
1118     {
1119         LIMITED_METHOD_CONTRACT;
1120         STATIC_CONTRACT_SO_TOLERANT;
1121         _ASSERTE(!"Not an AppDomain");
1122         return NULL;
1123     }
1124
1125     
1126     // If one domain is the SharedDomain and one is an AppDomain then
1127     // return the AppDomain, i.e. return the domain with the shorter lifetime
1128     // of the two given domains.
1129     static PTR_BaseDomain ComputeBaseDomain(
1130          BaseDomain *pGenericDefinitionDomain,    // the domain that owns the generic type or method
1131          Instantiation classInst,                       // the type arguments to the type (if any)
1132          Instantiation methodInst = Instantiation());   // the type arguments to the method (if any)
1133
1134     static PTR_BaseDomain ComputeBaseDomain(TypeKey * pTypeKey);
1135
1136 #ifdef FEATURE_COMINTEROP
1137     //****************************************************************************************
1138     //
1139     // This will look up interop data for a method table
1140     //
1141
1142 #ifndef DACCESS_COMPILE
1143     // Returns the data pointer if present, NULL otherwise
1144     InteropMethodTableData *LookupComInteropData(MethodTable *pMT)
1145     {
1146         // Take the lock
1147         CrstHolder holder(&m_InteropDataCrst);
1148
1149         // Lookup
1150         InteropMethodTableData *pData = (InteropMethodTableData*) m_interopDataHash.LookupValue((UPTR) pMT, (LPVOID) NULL);
1151
1152         // Not there...
1153         if (pData == (InteropMethodTableData*) INVALIDENTRY)
1154             return NULL;
1155
1156         // Found it
1157         return pData;
1158     }
1159
1160     // Returns TRUE if successfully inserted, FALSE if this would be a duplicate entry
1161     BOOL InsertComInteropData(MethodTable* pMT, InteropMethodTableData *pData)
1162     {
1163         // We don't keep track of this kind of information for interfaces
1164         _ASSERTE(!pMT->IsInterface());
1165
1166         // Take the lock
1167         CrstHolder holder(&m_InteropDataCrst);
1168
1169         // Check to see that it's not already in there
1170         InteropMethodTableData *pDupData = (InteropMethodTableData*) m_interopDataHash.LookupValue((UPTR) pMT, (LPVOID) NULL);
1171         if (pDupData != (InteropMethodTableData*) INVALIDENTRY)
1172             return FALSE;
1173
1174         // Not in there, so insert
1175         m_interopDataHash.InsertValue((UPTR) pMT, (LPVOID) pData);
1176
1177         // Success
1178         return TRUE;
1179     }
1180 #endif // DACCESS_COMPILE
1181 #endif // FEATURE_COMINTEROP
1182
1183     void SetDisableInterfaceCache()
1184     {
1185         m_fDisableInterfaceCache = TRUE;
1186     }
1187     BOOL GetDisableInterfaceCache()
1188     {
1189         return m_fDisableInterfaceCache;
1190     }
1191
1192 #ifdef FEATURE_COMINTEROP
1193     MngStdInterfacesInfo * GetMngStdInterfacesInfo()
1194     {
1195         LIMITED_METHOD_CONTRACT;
1196
1197         return m_pMngStdInterfacesInfo;
1198     }
1199     
1200     PTR_CLRPrivBinderWinRT GetWinRtBinder()
1201     {
1202         return m_pWinRtBinder;
1203     }
1204 #endif // FEATURE_COMINTEROP
1205
1206     //****************************************************************************************
1207     // This method returns marshaling data that the EE uses that is stored on a per app domain
1208     // basis.
1209     EEMarshalingData *GetMarshalingData();
1210
1211     // Deletes marshaling data at shutdown (which contains cached factories that needs to be released)
1212     void DeleteMarshalingData();
1213     
1214 #ifdef _DEBUG
1215     BOOL OwnDomainLocalBlockLock()
1216     {
1217         WRAPPER_NO_CONTRACT;
1218
1219         return m_DomainLocalBlockCrst.OwnedByCurrentThread();
1220     }
1221 #endif
1222
1223     //****************************************************************************************
1224     //
1225
1226     virtual IApplicationSecurityDescriptor* GetSecurityDescriptor() { LIMITED_METHOD_CONTRACT; return NULL; }
1227
1228
1229     //****************************************************************************************
1230     // Get the class init lock. The method is limited to friends because inappropriate use
1231     // will cause deadlocks in the system
1232     ListLock*  GetClassInitLock()
1233     {
1234         LIMITED_METHOD_CONTRACT;
1235
1236         return &m_ClassInitLock;
1237     }
1238
1239     ListLock* GetJitLock()
1240     {
1241         LIMITED_METHOD_CONTRACT;
1242         return &m_JITLock;
1243     }
1244
1245     ListLock* GetILStubGenLock()
1246     {
1247         LIMITED_METHOD_CONTRACT;
1248         return &m_ILStubGenLock;
1249     }
1250
1251     STRINGREF *IsStringInterned(STRINGREF *pString);
1252     STRINGREF *GetOrInternString(STRINGREF *pString);
1253
1254     virtual BOOL CanUnload()   { LIMITED_METHOD_CONTRACT; return FALSE; }    // can never unload BaseDomain
1255
1256     // Returns an array of OBJECTREF* that can be used to store domain specific data.
1257     // Statics and reflection info (Types, MemberInfo,..) are stored this way
1258     // If ppLazyAllocate != 0, allocation will only take place if *ppLazyAllocate != 0 (and the allocation
1259     // will be properly serialized)
1260     OBJECTREF *AllocateObjRefPtrsInLargeTable(int nRequested, OBJECTREF** ppLazyAllocate = NULL, BOOL bCrossAD = FALSE);
1261
1262 #ifdef FEATURE_PREJIT
1263     // Ensures that the file for logging profile data is open (we only open it once)
1264     // return false on failure
1265     static BOOL EnsureNGenLogFileOpen();
1266 #endif
1267
1268     //****************************************************************************************
1269     // Handles
1270
1271 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) // needs GetCurrentThreadHomeHeapNumber
1272     OBJECTHANDLE CreateTypedHandle(OBJECTREF object, int type)
1273     {
1274         WRAPPER_NO_CONTRACT;
1275         return ::CreateTypedHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object, type);
1276     }
1277
1278     OBJECTHANDLE CreateHandle(OBJECTREF object)
1279     {
1280         WRAPPER_NO_CONTRACT;
1281         CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL)
1282         return ::CreateHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1283     }
1284
1285     OBJECTHANDLE CreateWeakHandle(OBJECTREF object)
1286     {
1287         WRAPPER_NO_CONTRACT;
1288         return ::CreateWeakHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1289     }
1290
1291     OBJECTHANDLE CreateShortWeakHandle(OBJECTREF object)
1292     {
1293         WRAPPER_NO_CONTRACT;
1294         return ::CreateShortWeakHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1295     }
1296
1297     OBJECTHANDLE CreateLongWeakHandle(OBJECTREF object)
1298     {
1299         WRAPPER_NO_CONTRACT;
1300         CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL)
1301         return ::CreateLongWeakHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1302     }
1303
1304     OBJECTHANDLE CreateStrongHandle(OBJECTREF object)
1305     {
1306         WRAPPER_NO_CONTRACT;
1307         return ::CreateStrongHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1308     }
1309
1310     OBJECTHANDLE CreatePinningHandle(OBJECTREF object)
1311     {
1312         WRAPPER_NO_CONTRACT;
1313 #if CHECK_APP_DOMAIN_LEAKS     
1314         if(IsAppDomain())
1315             object->TryAssignAppDomain((AppDomain*)this,TRUE);
1316 #endif
1317         return ::CreatePinningHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1318     }
1319
1320     OBJECTHANDLE CreateSizedRefHandle(OBJECTREF object)
1321     {
1322         WRAPPER_NO_CONTRACT;
1323         OBJECTHANDLE h = ::CreateSizedRefHandle(
1324             m_hHandleTableBucket->pTable[GCHeap::IsServerHeap() ? (m_dwSizedRefHandles % m_iNumberOfProcessors) : GetCurrentThreadHomeHeapNumber()], 
1325             object);
1326         InterlockedIncrement((LONG*)&m_dwSizedRefHandles);
1327         return h;
1328     }
1329
1330 #ifdef FEATURE_COMINTEROP
1331     OBJECTHANDLE CreateRefcountedHandle(OBJECTREF object)
1332     {
1333         WRAPPER_NO_CONTRACT;
1334         return ::CreateRefcountedHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object);
1335     }
1336
1337     OBJECTHANDLE CreateWinRTWeakHandle(OBJECTREF object, IWeakReference* pWinRTWeakReference)
1338     {
1339         CONTRACTL
1340         {
1341             THROWS;
1342             GC_NOTRIGGER;
1343             MODE_COOPERATIVE;
1344         }
1345         CONTRACTL_END;
1346
1347         return ::CreateWinRTWeakHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object, pWinRTWeakReference);
1348     }
1349 #endif // FEATURE_COMINTEROP
1350
1351     OBJECTHANDLE CreateVariableHandle(OBJECTREF object, UINT type)
1352     {
1353         WRAPPER_NO_CONTRACT;
1354         return ::CreateVariableHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object, type);
1355     }
1356
1357     OBJECTHANDLE CreateDependentHandle(OBJECTREF primary, OBJECTREF secondary)
1358     {
1359         WRAPPER_NO_CONTRACT;
1360         return ::CreateDependentHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], primary, secondary);
1361     }
1362 #endif // DACCESS_COMPILE && !CROSSGEN_COMPILE
1363
1364     BOOL ContainsOBJECTHANDLE(OBJECTHANDLE handle);
1365
1366 #ifdef FEATURE_FUSION
1367     IApplicationContext *GetFusionContext() {LIMITED_METHOD_CONTRACT;  return m_pFusionContext; }
1368 #else
1369     IUnknown *GetFusionContext() {LIMITED_METHOD_CONTRACT;  return m_pFusionContext; }
1370     
1371 #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)    
1372     CLRPrivBinderCoreCLR *GetTPABinderContext() {LIMITED_METHOD_CONTRACT;  return m_pTPABinderContext; }
1373 #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
1374
1375 #endif
1376
1377     CrstExplicitInit * GetLoaderAllocatorReferencesLock()
1378     {
1379         LIMITED_METHOD_CONTRACT;
1380         return &m_crstLoaderAllocatorReferences;
1381     }
1382     
1383 protected:
1384     
1385     //****************************************************************************************
1386     // Helper method to initialize the large heap handle table.
1387     void InitLargeHeapHandleTable();
1388
1389     //****************************************************************************************
1390     // Adds an assembly to the domain.
1391     void AddAssemblyNoLock(Assembly* assem);
1392
1393     //****************************************************************************************
1394     //
1395     // Hash table that maps a MethodTable to COM Interop compatibility data.
1396     PtrHashMap          m_interopDataHash;
1397
1398     // Critical sections & locks
1399     PEFileListLock   m_FileLoadLock;            // Protects the list of assemblies in the domain
1400     CrstExplicitInit m_DomainCrst;              // General Protection for the Domain
1401     CrstExplicitInit m_DomainCacheCrst;         // Protects the Assembly and Unmanaged caches
1402     CrstExplicitInit m_DomainLocalBlockCrst;
1403     CrstExplicitInit m_InteropDataCrst;         // Used for COM Interop compatiblilty
1404     // Used to protect the reference lists in the collectible loader allocators attached to this appdomain
1405     CrstExplicitInit m_crstLoaderAllocatorReferences;
1406     CrstExplicitInit m_WinRTFactoryCacheCrst;   // For WinRT factory cache
1407     
1408     //#AssemblyListLock
1409     // Used to protect the assembly list. Taken also by GC or debugger thread, therefore we have to avoid 
1410     // triggering GC while holding this lock (by switching the thread to GC_NOTRIGGER while it is held).
1411     CrstExplicitInit m_crstAssemblyList;
1412     BOOL             m_fDisableInterfaceCache;  // RCW COM interface cache
1413     ListLock         m_ClassInitLock;
1414     ListLock         m_JITLock;
1415     ListLock         m_ILStubGenLock;
1416
1417     // Fusion context, used for adding assemblies to the is domain. It defines
1418     // fusion properties for finding assemblyies such as SharedBinPath,
1419     // PrivateBinPath, Application Directory, etc.
1420 #ifdef FEATURE_FUSION    
1421     IApplicationContext* m_pFusionContext; // Binding context for the domain
1422 #else
1423     IUnknown *m_pFusionContext; // Current binding context for the domain
1424
1425 #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)    
1426     CLRPrivBinderCoreCLR *m_pTPABinderContext; // Reference to the binding context that holds TPA list details
1427 #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
1428
1429 #endif    
1430
1431     HandleTableBucket *m_hHandleTableBucket;
1432
1433     // The large heap handle table.
1434     LargeHeapHandleTable        *m_pLargeHeapHandleTable;
1435
1436     // The large heap handle table critical section.
1437     CrstExplicitInit             m_LargeHeapHandleTableCrst;
1438
1439     EEMarshalingData            *m_pMarshalingData;
1440
1441 #ifdef FEATURE_COMINTEROP
1442     // Information regarding the managed standard interfaces.
1443     MngStdInterfacesInfo        *m_pMngStdInterfacesInfo;
1444     
1445     // WinRT binder (only in classic = non-AppX; AppX has the WinRT binder inside code:CLRPrivBinderAppX)
1446     PTR_CLRPrivBinderWinRT m_pWinRtBinder;
1447 #endif // FEATURE_COMINTEROP
1448
1449     // Number of allocated slots for context local statics of this domain
1450     DWORD m_dwContextStatics;
1451
1452     // Protects allocation of slot IDs for thread and context statics
1453     static CrstStatic   m_SpecialStaticsCrst;
1454
1455 public:
1456     // Lazily allocate offset for context static
1457     DWORD AllocateContextStaticsOffset(DWORD* pOffsetSlot);
1458
1459 public:
1460     // Only call this routine when you can guarantee there are no
1461     // loads in progress.
1462     void ClearFusionContext();
1463
1464 public:
1465
1466     //****************************************************************************************
1467     // Synchronization holders.
1468
1469     class LockHolder : public CrstHolder
1470     {
1471     public:
1472         LockHolder(BaseDomain *pD)
1473             : CrstHolder(&pD->m_DomainCrst)
1474         {
1475             WRAPPER_NO_CONTRACT;
1476         }
1477     };
1478     friend class LockHolder;
1479
1480     class CacheLockHolder : public CrstHolder
1481     {
1482     public:
1483         CacheLockHolder(BaseDomain *pD)
1484             : CrstHolder(&pD->m_DomainCacheCrst)
1485         {
1486             WRAPPER_NO_CONTRACT;
1487         }
1488     };
1489     friend class CacheLockHolder;
1490
1491     class DomainLocalBlockLockHolder : public CrstHolder
1492     {
1493     public:
1494         DomainLocalBlockLockHolder(BaseDomain *pD)
1495             : CrstHolder(&pD->m_DomainLocalBlockCrst)
1496         {
1497             WRAPPER_NO_CONTRACT;
1498         }
1499     };
1500     friend class DomainLocalBlockLockHolder;
1501
1502     class LoadLockHolder :  public PEFileListLockHolder
1503     {
1504     public:
1505         LoadLockHolder(BaseDomain *pD, BOOL Take = TRUE)
1506           : PEFileListLockHolder(&pD->m_FileLoadLock, Take)
1507         {
1508             CONTRACTL
1509             {
1510                 NOTHROW;
1511                 GC_NOTRIGGER;
1512                 MODE_ANY;
1513                 CAN_TAKE_LOCK;
1514             }
1515             CONTRACTL_END;
1516         }
1517     };
1518     friend class LoadLockHolder;
1519     class WinRTFactoryCacheLockHolder : public CrstHolder
1520     {
1521     public:
1522         WinRTFactoryCacheLockHolder(BaseDomain *pD)
1523             : CrstHolder(&pD->m_WinRTFactoryCacheCrst)
1524         {
1525             WRAPPER_NO_CONTRACT;
1526         }
1527     };
1528     friend class WinRTFactoryCacheLockHolder;
1529
1530 public:
1531     void InitVSD();
1532     RangeList *GetCollectibleVSDRanges() { return &m_collVSDRanges; }
1533
1534 private:
1535     TypeIDMap m_typeIDMap;
1536     // Range list for collectible types. Maps VSD PCODEs back to the VirtualCallStubManager they belong to
1537     LockedRangeList m_collVSDRanges;
1538
1539 public:
1540     UINT32 GetTypeID(PTR_MethodTable pMT);
1541     UINT32 LookupTypeID(PTR_MethodTable pMT);
1542     PTR_MethodTable LookupType(UINT32 id);
1543
1544 private:
1545     // I have yet to figure out an efficent way to get the number of handles 
1546     // of a particular type that's currently used by the process without 
1547     // spending more time looking at the handle table code. We know that 
1548     // our only customer (asp.net) in Dev10 is not going to create many of 
1549     // these handles so I am taking a shortcut for now and keep the sizedref
1550     // handle count on the AD itself.
1551     DWORD m_dwSizedRefHandles;
1552
1553     static int m_iNumberOfProcessors;
1554
1555 public:
1556     // Called by DestroySizedRefHandle
1557     void DecNumSizedRefHandles()
1558     {
1559         WRAPPER_NO_CONTRACT;
1560         LONG result;
1561         result = InterlockedDecrement((LONG*)&m_dwSizedRefHandles);
1562         _ASSERTE(result >= 0);
1563     }
1564
1565     DWORD GetNumSizedRefHandles()
1566     {
1567         return m_dwSizedRefHandles;
1568     }
1569
1570     // Profiler rejit
1571 private:
1572     ReJitManager m_reJitMgr;
1573
1574 public:
1575     ReJitManager * GetReJitManager() { return &m_reJitMgr; }
1576
1577 #ifdef DACCESS_COMPILE
1578 public:
1579     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
1580                                    bool enumThis);
1581 #endif
1582
1583 #ifdef FEATURE_CORECLR
1584 public:
1585     enum AppDomainCompatMode
1586     {
1587         APPDOMAINCOMPAT_NONE
1588 #ifdef FEATURE_LEGACYNETCF
1589         , APPDOMAINCOMPAT_APP_EARLIER_THAN_WP8 // for "AppDomainCompatSwitch" == "WindowsPhone_3.7.0.0" or "AppDomainCompatSwitch" == "WindowsPhone_3.8.0.0"
1590 #endif
1591     };
1592     void SetAppDomainCompatMode(AppDomainCompatMode compatMode);
1593     AppDomainCompatMode GetAppDomainCompatMode();
1594     
1595 private:
1596     AppDomainCompatMode m_CompatMode;
1597 #endif // FEATURE_CORECLR   
1598
1599 };  // class BaseDomain
1600
1601 enum
1602 {
1603     ATTACH_ASSEMBLY_LOAD = 0x1,
1604     ATTACH_MODULE_LOAD = 0x2,
1605     ATTACH_CLASS_LOAD = 0x4,
1606
1607     ATTACH_ALL = 0x7
1608 };
1609
1610 class ADUnloadSink
1611 {
1612     
1613 protected:
1614     ~ADUnloadSink();
1615     CLREvent m_UnloadCompleteEvent;
1616     HRESULT   m_UnloadResult;
1617     Volatile<LONG> m_cRef;
1618 public:
1619     ADUnloadSink();
1620     void ReportUnloadResult (HRESULT hr, OBJECTREF* pException);
1621     void WaitUnloadCompletion();
1622     HRESULT GetUnloadResult() {LIMITED_METHOD_CONTRACT; return m_UnloadResult;};
1623     void Reset();
1624     ULONG AddRef();
1625     ULONG Release();
1626 };
1627
1628
1629 FORCEINLINE void ADUnloadSink__Release(ADUnloadSink* pADSink)
1630 {
1631     WRAPPER_NO_CONTRACT;
1632
1633     if (pADSink)
1634         pADSink->Release();
1635 }
1636
1637 typedef Wrapper <ADUnloadSink*,DoNothing,ADUnloadSink__Release,NULL> ADUnloadSinkHolder;
1638
1639 // This filters the output of IterateAssemblies. This ought to be declared more locally
1640 // but it would result in really verbose callsites.
1641 //
1642 // Assemblies can be categorized by their load status (loaded, loading, or loaded just
1643 // enough that they would be made available to profilers)
1644 // Independently, they can also be categorized as execution or introspection.
1645 //
1646 // An assembly will be included in the results of IterateAssemblies only if
1647 // the appropriate bit is set for *both* characterizations.
1648 //
1649 // The flags can be combined so if you want all loaded assemblies, you must specify:
1650 //
1651 ///     kIncludeLoaded|kIncludeExecution|kIncludeIntrospection
1652
1653 enum AssemblyIterationFlags
1654 {
1655     // load status flags
1656     kIncludeLoaded        = 0x00000001, // include assemblies that are already loaded
1657                                         // (m_level >= code:FILE_LOAD_DELIVER_EVENTS)
1658     kIncludeLoading       = 0x00000002, // include assemblies that are still in the process of loading
1659                                         // (all m_level values)
1660     kIncludeAvailableToProfilers
1661                           = 0x00000020, // include assemblies available to profilers
1662                                         // See comment at code:DomainFile::IsAvailableToProfilers
1663
1664     // Execution / introspection flags
1665     kIncludeExecution     = 0x00000004, // include assemblies that are loaded for execution only
1666     kIncludeIntrospection = 0x00000008, // include assemblies that are loaded for introspection only
1667     
1668     kIncludeFailedToLoad  = 0x00000010, // include assemblies that failed to load 
1669
1670     // Collectible assemblies flags
1671     kExcludeCollectible   = 0x00000040, // Exclude all collectible assemblies
1672     kIncludeCollected     = 0x00000080, 
1673         // Include assemblies which were collected and cannot be referenced anymore. Such assemblies are not 
1674         // AddRef-ed. Any manipulation with them should be protected by code:GetAssemblyListLock.
1675         // Should be used only by code:LoaderAllocator::GCLoaderAllocators.
1676
1677 };  // enum AssemblyIterationFlags
1678
1679 //---------------------------------------------------------------------------------------
1680 // 
1681 // Base class for holder code:CollectibleAssemblyHolder (see code:HolderBase).
1682 // Manages AddRef/Release for collectible assemblies. It is no-op for 'normal' non-collectible assemblies.
1683 // 
1684 // Each type of type parameter needs 2 methods implemented:
1685 //  code:CollectibleAssemblyHolderBase::GetLoaderAllocator
1686 //  code:CollectibleAssemblyHolderBase::IsCollectible
1687 // 
1688 template<typename _Type>
1689 class CollectibleAssemblyHolderBase
1690 {
1691 protected:
1692     _Type m_value;
1693 public:
1694     CollectibleAssemblyHolderBase(const _Type & value = NULL)
1695     {
1696         LIMITED_METHOD_CONTRACT;
1697         m_value = value;
1698     }
1699     void DoAcquire()
1700     {
1701         CONTRACTL
1702         {
1703             NOTHROW;
1704             GC_NOTRIGGER;
1705             MODE_ANY;
1706         }
1707         CONTRACTL_END;
1708         
1709         // We don't need to keep the assembly alive in DAC - see code:#CAH_DAC
1710 #ifndef DACCESS_COMPILE
1711         if (this->IsCollectible(m_value))
1712         {
1713             LoaderAllocator * pLoaderAllocator = GetLoaderAllocator(m_value);
1714             pLoaderAllocator->AddReference();
1715         }
1716 #endif //!DACCESS_COMPILE
1717     }
1718     void DoRelease()
1719     {
1720         CONTRACTL
1721         {
1722             NOTHROW;
1723             GC_NOTRIGGER;
1724             MODE_ANY;
1725         }
1726         CONTRACTL_END;
1727         
1728 #ifndef DACCESS_COMPILE
1729         if (this->IsCollectible(m_value))
1730         {
1731             LoaderAllocator * pLoaderAllocator = GetLoaderAllocator(m_value);
1732             pLoaderAllocator->Release();
1733         }
1734 #endif //!DACCESS_COMPILE
1735     }
1736     
1737 private:
1738     LoaderAllocator * GetLoaderAllocator(DomainAssembly * pDomainAssembly)
1739     {
1740         WRAPPER_NO_CONTRACT;
1741         return pDomainAssembly->GetLoaderAllocator();
1742     }
1743     BOOL IsCollectible(DomainAssembly * pDomainAssembly)
1744     {
1745         WRAPPER_NO_CONTRACT;
1746         return pDomainAssembly->IsCollectible();
1747     }
1748     LoaderAllocator * GetLoaderAllocator(Assembly * pAssembly)
1749     {
1750         WRAPPER_NO_CONTRACT;
1751         return pAssembly->GetLoaderAllocator();
1752     }
1753     BOOL IsCollectible(Assembly * pAssembly)
1754     {
1755         WRAPPER_NO_CONTRACT;
1756         return pAssembly->IsCollectible();
1757     }
1758 };  // class CollectibleAssemblyHolderBase<>
1759
1760 //---------------------------------------------------------------------------------------
1761 // 
1762 // Holder of assembly reference which keeps collectible assembly alive while the holder is valid.
1763 // 
1764 // Collectible assembly can be collected at any point when GC happens. Almost instantly all native data 
1765 // structures of the assembly (e.g. code:DomainAssembly, code:Assembly) could be deallocated. 
1766 // Therefore any usage of (collectible) assembly data structures from native world, has to prevent the 
1767 // deallocation by increasing ref-count on the assembly / associated loader allocator.
1768 // 
1769 // #CAH_DAC
1770 // In DAC we don't AddRef/Release as the assembly doesn't have to be kept alive: The process is stopped when 
1771 // DAC is used and therefore the assembly cannot just disappear.
1772 // 
1773 template<typename _Type>
1774 class CollectibleAssemblyHolder : public BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >
1775 {
1776 public:
1777     FORCEINLINE 
1778     CollectibleAssemblyHolder(const _Type & value = NULL, BOOL fTake = TRUE)
1779         : BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >(value, fTake)
1780     {
1781         STATIC_CONTRACT_WRAPPER;
1782     }
1783     
1784     FORCEINLINE 
1785     CollectibleAssemblyHolder & 
1786     operator=(const _Type & value)
1787     {
1788         STATIC_CONTRACT_WRAPPER;
1789         BaseWrapper<_Type, CollectibleAssemblyHolderBase<_Type> >::operator=(value);
1790         return *this;
1791     }
1792     
1793     // Operator & is overloaded in parent, therefore we have to get to 'this' pointer explicitly.
1794     FORCEINLINE 
1795     CollectibleAssemblyHolder<_Type> * 
1796     This()
1797     {
1798         LIMITED_METHOD_CONTRACT;
1799         return this;
1800     }
1801 };  // class CollectibleAssemblyHolder<>
1802
1803 //---------------------------------------------------------------------------------------
1804 // 
1805 #ifdef FEATURE_LOADER_OPTIMIZATION
1806 class SharedAssemblyLocator
1807 {
1808 public:
1809     enum
1810     {
1811         DOMAINASSEMBLY      = 1,
1812         PEASSEMBLY          = 2,
1813         PEASSEMBLYEXACT     = 3
1814     };
1815     DWORD GetType() {LIMITED_METHOD_CONTRACT; return m_type;};
1816 #ifndef DACCESS_COMPILE
1817     DomainAssembly* GetDomainAssembly() {LIMITED_METHOD_CONTRACT; _ASSERTE(m_type==DOMAINASSEMBLY); return (DomainAssembly*)m_value;};
1818     PEAssembly* GetPEAssembly() {LIMITED_METHOD_CONTRACT; _ASSERTE(m_type==PEASSEMBLY||m_type==PEASSEMBLYEXACT); return (PEAssembly*)m_value;};
1819     SharedAssemblyLocator(DomainAssembly* pAssembly)
1820     {
1821         LIMITED_METHOD_CONTRACT;
1822         m_type=DOMAINASSEMBLY;
1823         m_value=pAssembly;
1824     }
1825     SharedAssemblyLocator(PEAssembly* pFile, DWORD type = PEASSEMBLY)
1826     {
1827         LIMITED_METHOD_CONTRACT;
1828         m_type = type;
1829         m_value = pFile;
1830     }
1831 #endif // DACCESS_COMPILE
1832
1833     DWORD Hash();
1834 protected:
1835     DWORD m_type;
1836     LPVOID m_value;
1837 #if FEATURE_VERSIONING    
1838     ULONG   m_uIdentityHash;
1839 #endif
1840 };
1841 #endif // FEATURE_LOADER_OPTIMIZATION
1842
1843 //
1844 // Stores binding information about failed assembly loads for DAC
1845 //
1846 struct FailedAssembly {
1847     SString displayName;
1848     SString location;
1849 #ifdef FEATURE_FUSION    
1850     LOADCTX_TYPE context;
1851 #endif
1852     HRESULT error;
1853
1854     void Initialize(AssemblySpec *pSpec, Exception *ex)
1855     {
1856         CONTRACTL
1857         {
1858             THROWS;
1859             GC_NOTRIGGER;
1860             MODE_ANY;
1861         }
1862         CONTRACTL_END;
1863
1864         displayName.SetASCII(pSpec->GetName());
1865         location.Set(pSpec->GetCodeBase());
1866         error = ex->GetHR();
1867
1868         // 
1869         // Determine the binding context assembly would have been in.
1870         // If the parent has been set, use its binding context.
1871         // If the parent hasn't been set but the code base has, use LoadFrom.
1872         // Otherwise, use the default.
1873         //
1874 #ifdef FEATURE_FUSION        
1875         context = pSpec->GetParentIAssembly() ? pSpec->GetParentIAssembly()->GetFusionLoadContext() : LOADCTX_TYPE_LOADFROM;
1876 #endif // FEATURE_FUSION
1877     }
1878 };
1879
1880 #ifdef FEATURE_COMINTEROP
1881
1882 // Cache used by COM Interop
1883 struct NameToTypeMapEntry
1884 {
1885     // Host space representation of the key
1886     struct Key
1887     {
1888         LPCWSTR m_wzName;     // The type name or registry string representation of the GUID "{<guid>}"
1889         SIZE_T  m_cchName;    // wcslen(m_wzName) for faster hashtable lookup
1890     };
1891     struct DacKey
1892     {
1893         PTR_CWSTR m_wzName;   // The type name or registry string representation of the GUID "{<guid>}"
1894         SIZE_T    m_cchName;  // wcslen(m_wzName) for faster hashtable lookup
1895     } m_key;
1896     TypeHandle m_typeHandle;  // Using TypeHandle instead of MethodTable* to avoid losing information when sharing method tables.
1897     UINT m_nEpoch;            // tracks creation Epoch. This is incremented each time an external reader enumerate the cache
1898     BYTE m_bFlags;
1899 };
1900
1901 typedef DPTR(NameToTypeMapEntry) PTR_NameToTypeMapEntry;
1902
1903 class NameToTypeMapTraits : public NoRemoveSHashTraits< DefaultSHashTraits<NameToTypeMapEntry> >
1904 {
1905 public:
1906     typedef NameToTypeMapEntry::Key key_t;
1907
1908     static const NameToTypeMapEntry Null() { NameToTypeMapEntry e; e.m_key.m_wzName = NULL; e.m_key.m_cchName = 0; return e; }
1909     static bool IsNull(const NameToTypeMapEntry &e) { return e.m_key.m_wzName == NULL; }
1910     static const key_t GetKey(const NameToTypeMapEntry &e) 
1911     {
1912         key_t key;
1913         key.m_wzName = (LPCWSTR)(e.m_key.m_wzName); // this cast brings the string over to the host, in a DAC build
1914         key.m_cchName = e.m_key.m_cchName;
1915
1916         return key;
1917     }
1918     static count_t Hash(const key_t &key) { WRAPPER_NO_CONTRACT; return HashStringN(key.m_wzName, key.m_cchName); }
1919     
1920     static BOOL Equals(const key_t &lhs, const key_t &rhs)
1921     {
1922         WRAPPER_NO_CONTRACT;
1923         return (lhs.m_cchName == rhs.m_cchName) && memcmp(lhs.m_wzName, rhs.m_wzName, lhs.m_cchName * sizeof(WCHAR)) == 0;
1924     }
1925     
1926     void OnDestructPerEntryCleanupAction(const NameToTypeMapEntry& e)
1927     {
1928         WRAPPER_NO_CONTRACT;
1929         _ASSERTE(e.m_key.m_cchName == wcslen(e.m_key.m_wzName));
1930 #ifndef DACCESS_COMPILE
1931         delete [] e.m_key.m_wzName;
1932 #endif // DACCESS_COMPILE
1933     }
1934     static const bool s_DestructPerEntryCleanupAction = true;
1935 };
1936
1937 typedef SHash<NameToTypeMapTraits> NameToTypeMapTable;
1938
1939 typedef DPTR(NameToTypeMapTable) PTR_NameToTypeMapTable;
1940
1941 struct WinRTFactoryCacheEntry
1942 {
1943     typedef MethodTable *Key;           
1944     Key          key;                   // Type as KEY
1945     
1946     CtxEntry    *m_pCtxEntry;           // Context entry - used to verify whether the cache is a match
1947     OBJECTHANDLE m_ohFactoryObject;     // Handle to factory object
1948 };
1949
1950 class WinRTFactoryCacheTraits : public DefaultSHashTraits<WinRTFactoryCacheEntry>
1951 {
1952 public:
1953     typedef WinRTFactoryCacheEntry::Key key_t;
1954     static const WinRTFactoryCacheEntry Null() { WinRTFactoryCacheEntry e; e.key = NULL; return e; }
1955     static bool IsNull(const WinRTFactoryCacheEntry &e) { return e.key == NULL; }
1956     static const WinRTFactoryCacheEntry::Key GetKey(const WinRTFactoryCacheEntry& e) { return e.key; }
1957     static count_t Hash(WinRTFactoryCacheEntry::Key key) { return (count_t)((size_t)key); }
1958     static BOOL Equals(WinRTFactoryCacheEntry::Key lhs, WinRTFactoryCacheEntry::Key rhs)
1959     { return lhs == rhs; }
1960     static const WinRTFactoryCacheEntry Deleted() { WinRTFactoryCacheEntry e; e.key = (MethodTable *)-1; return e; }
1961     static bool IsDeleted(const WinRTFactoryCacheEntry &e) { return e.key == (MethodTable *)-1; }
1962
1963     static void OnDestructPerEntryCleanupAction(const WinRTFactoryCacheEntry& e);
1964     static const bool s_DestructPerEntryCleanupAction = true;
1965 };
1966
1967 typedef SHash<WinRTFactoryCacheTraits> WinRTFactoryCache;
1968
1969 #endif // FEATURE_COMINTEROP
1970
1971 class AppDomainIterator;
1972
1973 const DWORD DefaultADID = 1;
1974
1975 template <class AppDomainType> class AppDomainCreationHolder;
1976
1977 // An Appdomain is the managed equivalent of a process.  It is an isolation unit (conceptually you don't
1978 // have pointers directly from one appdomain to another, but rather go through remoting proxies).  It is
1979 // also a unit of unloading.
1980 // 
1981 // Threads are always running in the context of a particular AppDomain.  See
1982 // file:threads.h#RuntimeThreadLocals for more details.  
1983 // 
1984 // see code:BaseDomain for much of the meat of a AppDomain (heaps locks, etc)
1985 //     * code:AppDomain.m_Assemblies - is a list of code:Assembly in the appdomain
1986 // 
1987 class AppDomain : public BaseDomain
1988 {
1989     friend class ADUnloadSink;
1990     friend class SystemDomain;
1991     friend class AssemblySink;
1992     friend class AppDomainNative;
1993     friend class AssemblyNative;
1994     friend class AssemblySpec;
1995     friend class ClassLoader;
1996     friend class ThreadNative;
1997     friend class RCWCache;
1998     friend class ClrDataAccess;
1999     friend class CheckAsmOffsets;
2000     friend class AppDomainFromIDHolder;
2001
2002     VPTR_VTABLE_CLASS(AppDomain, BaseDomain)
2003
2004 public:
2005 #ifndef DACCESS_COMPILE
2006     AppDomain();
2007     virtual ~AppDomain();
2008 #endif
2009     static void DoADUnloadWork();
2010     DomainAssembly* FindDomainAssembly(Assembly*);
2011     void EnterContext(Thread* pThread, Context* pCtx,ContextTransitionFrame *pFrame);
2012
2013 #ifndef DACCESS_COMPILE
2014     //-----------------------------------------------------------------------------------------------------------------
2015     // Convenience wrapper for ::GetAppDomain to provide better encapsulation.
2016     static AppDomain * GetCurrentDomain()
2017     { return ::GetAppDomain(); }
2018 #endif //!DACCESS_COMPILE
2019     
2020     //-----------------------------------------------------------------------------------------------------------------
2021     // Initializes an AppDomain. (this functions is not called from the SystemDomain)
2022     void Init();
2023
2024     // creates only unamaged part
2025     static void CreateUnmanagedObject(AppDomainCreationHolder<AppDomain>& result);
2026     inline void SetAppDomainManagerInfo(LPCWSTR szAssemblyName, LPCWSTR szTypeName, EInitializeNewDomainFlags dwInitializeDomainFlags);
2027     inline BOOL HasAppDomainManagerInfo();
2028     inline LPCWSTR GetAppDomainManagerAsm();
2029     inline LPCWSTR GetAppDomainManagerType();
2030     inline EInitializeNewDomainFlags GetAppDomainManagerInitializeNewDomainFlags();
2031
2032 #ifndef FEATURE_CORECLR
2033     inline BOOL AppDomainManagerSetFromConfig();
2034     Assembly *GetAppDomainManagerEntryAssembly();
2035 #endif // FEATURE_CORECLR
2036
2037 #if defined(FEATURE_CORECLR) && defined(FEATURE_COMINTEROP)
2038     HRESULT SetWinrtApplicationContext(SString &appLocalWinMD);
2039 #endif // FEATURE_CORECLR && FEATURE_COMINTEROP
2040
2041     BOOL CanReversePInvokeEnter();
2042     void SetReversePInvokeCannotEnter();
2043     bool MustForceTrivialWaitOperations();
2044     void SetForceTrivialWaitOperations();
2045
2046     //****************************************************************************************
2047     //
2048     // Stop deletes all the assemblies but does not remove other resources like
2049     // the critical sections
2050     void Stop();
2051
2052     // Gets rid of resources
2053     void Terminate();
2054
2055 #ifdef  FEATURE_PREJIT
2056     //assembly cleanup that requires suspended runtime
2057     void DeleteNativeCodeRanges();
2058 #endif
2059
2060     // final assembly cleanup
2061     void ShutdownAssemblies();
2062     void ShutdownFreeLoaderAllocators(BOOL bFromManagedCode);
2063     
2064     void ReleaseDomainBoundInfo();
2065     void ReleaseFiles();
2066     
2067
2068     // Remove the Appdomain for the system and cleans up. This call should not be
2069     // called from shut down code.
2070     void CloseDomain();
2071
2072     virtual BOOL IsAppDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; }
2073     virtual PTR_AppDomain AsAppDomain() { LIMITED_METHOD_CONTRACT; return dac_cast<PTR_AppDomain>(this); }
2074
2075 #ifndef FEATURE_CORECLR
2076     void InitializeSorting(OBJECTREF* ppAppdomainSetup);
2077     void InitializeHashing(OBJECTREF* ppAppdomainSetup);
2078 #endif
2079
2080     OBJECTREF DoSetup(OBJECTREF* setupInfo);
2081
2082     OBJECTREF GetExposedObject();
2083     OBJECTREF GetRawExposedObject() {
2084         CONTRACTL
2085         {
2086             NOTHROW;
2087             GC_NOTRIGGER;
2088             SO_TOLERANT;
2089             MODE_COOPERATIVE;
2090         }
2091         CONTRACTL_END;
2092         if (m_ExposedObject) {
2093             return ObjectFromHandle(m_ExposedObject);
2094         }
2095         else {
2096             return NULL;
2097         }
2098     }
2099
2100     OBJECTHANDLE GetRawExposedObjectHandleForDebugger() { LIMITED_METHOD_DAC_CONTRACT; return m_ExposedObject; }
2101
2102 #ifdef FEATURE_COMINTEROP
2103     HRESULT GetComIPForExposedObject(IUnknown **pComIP);
2104
2105     MethodTable *GetRedirectedType(WinMDAdapter::RedirectedTypeIndex index);
2106     bool FindRedirectedAssembly(Assembly* pAssembly, WinMDAdapter::FrameworkAssemblyIndex* pIndex);
2107 #endif // FEATURE_COMINTEROP
2108
2109
2110     //****************************************************************************************
2111
2112 protected:
2113     // Multi-thread safe access to the list of assemblies
2114     class DomainAssemblyList
2115     {
2116     private:
2117         ArrayList m_array;
2118 #ifdef _DEBUG
2119         AppDomain * dbg_m_pAppDomain;
2120     public:
2121         void Debug_SetAppDomain(AppDomain * pAppDomain)
2122         {
2123             dbg_m_pAppDomain = pAppDomain;
2124         }
2125 #endif //_DEBUG
2126     public:
2127         bool IsEmpty()
2128         {
2129             CONTRACTL {
2130                 NOTHROW;
2131                 GC_NOTRIGGER;
2132                 MODE_ANY;
2133             } CONTRACTL_END;
2134             
2135             // This function can be reliably called without taking the lock, because the first assembly
2136             // added to the arraylist is non-collectible, and the ArrayList itself allows lockless read access
2137             return (m_array.GetCount() == 0);
2138         }
2139         void Clear(AppDomain * pAppDomain)
2140         {
2141             CONTRACTL {
2142                 NOTHROW;
2143                 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2144                 MODE_ANY;
2145             } CONTRACTL_END;
2146             
2147             _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2148             
2149             CrstHolder ch(pAppDomain->GetAssemblyListLock());
2150             m_array.Clear();
2151         }
2152         
2153         DWORD GetCount(AppDomain * pAppDomain)
2154         {
2155             CONTRACTL {
2156                 NOTHROW;
2157                 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2158                 MODE_ANY;
2159             } CONTRACTL_END;
2160             
2161             _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2162             
2163             CrstHolder ch(pAppDomain->GetAssemblyListLock());
2164             return GetCount_Unlocked();
2165         }
2166         DWORD GetCount_Unlocked()
2167         {
2168             CONTRACTL {
2169                 NOTHROW;
2170                 GC_NOTRIGGER;
2171                 MODE_ANY;
2172             } CONTRACTL_END;
2173             
2174 #ifndef DACCESS_COMPILE
2175             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2176 #endif
2177             // code:Append_Unlock guarantees that we do not have more than MAXDWORD items
2178             return m_array.GetCount();
2179         }
2180         
2181         void Get(AppDomain * pAppDomain, DWORD index, CollectibleAssemblyHolder<DomainAssembly *> * pAssemblyHolder)
2182         {
2183             CONTRACTL {
2184                 NOTHROW;
2185                 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2186                 MODE_ANY;
2187             } CONTRACTL_END;
2188             
2189             _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2190             
2191             CrstHolder ch(pAppDomain->GetAssemblyListLock());
2192             Get_Unlocked(index, pAssemblyHolder);
2193         }
2194         void Get_Unlocked(DWORD index, CollectibleAssemblyHolder<DomainAssembly *> * pAssemblyHolder)
2195         {
2196             CONTRACTL {
2197                 NOTHROW;
2198                 GC_NOTRIGGER;
2199                 MODE_ANY;
2200             } CONTRACTL_END;
2201             
2202             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2203             *pAssemblyHolder = dac_cast<PTR_DomainAssembly>(m_array.Get(index));
2204         }
2205         // Doesn't lock the assembly list (caller has to hold the lock already).
2206         // Doesn't AddRef the returned assembly (if collectible).
2207         DomainAssembly * Get_UnlockedNoReference(DWORD index)
2208         {
2209             CONTRACTL {
2210                 NOTHROW;
2211                 GC_NOTRIGGER;
2212                 MODE_ANY;
2213                 SUPPORTS_DAC;
2214             } CONTRACTL_END;
2215             
2216 #ifndef DACCESS_COMPILE
2217             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2218 #endif
2219             return dac_cast<PTR_DomainAssembly>(m_array.Get(index));
2220         }
2221         
2222 #ifndef DACCESS_COMPILE
2223         void Set(AppDomain * pAppDomain, DWORD index, DomainAssembly * pAssembly)
2224         {
2225             CONTRACTL {
2226                 NOTHROW;
2227                 WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
2228                 MODE_ANY;
2229             } CONTRACTL_END;
2230             
2231             _ASSERTE(dbg_m_pAppDomain == pAppDomain);
2232             
2233             CrstHolder ch(pAppDomain->GetAssemblyListLock());
2234             return Set_Unlocked(index, pAssembly);
2235         }
2236         void Set_Unlocked(DWORD index, DomainAssembly * pAssembly)
2237         {
2238             CONTRACTL {
2239                 NOTHROW;
2240                 GC_NOTRIGGER;
2241                 MODE_ANY;
2242             } CONTRACTL_END;
2243             
2244             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2245             m_array.Set(index, pAssembly);
2246         }
2247         
2248         HRESULT Append_Unlocked(DomainAssembly * pAssembly)
2249         {
2250             CONTRACTL {
2251                 NOTHROW;
2252                 GC_NOTRIGGER;
2253                 MODE_ANY;
2254             } CONTRACTL_END;
2255             
2256             _ASSERTE(dbg_m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
2257             return m_array.Append(pAssembly);
2258         }
2259 #else //DACCESS_COMPILE
2260         void 
2261         EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2262         {
2263             SUPPORTS_DAC;
2264             
2265             m_array.EnumMemoryRegions(flags);
2266         }
2267 #endif // DACCESS_COMPILE
2268         
2269         // Should be used only by code:AssemblyIterator::Create
2270         ArrayList::Iterator GetArrayListIterator()
2271         {
2272             return m_array.Iterate();
2273         }
2274     };  // class DomainAssemblyList
2275     
2276     // Conceptually a list of code:Assembly structures, protected by lock code:GetAssemblyListLock
2277     DomainAssemblyList m_Assemblies;
2278     
2279 public:
2280     // Note that this lock switches thread into GC_NOTRIGGER region as GC can take it too.
2281     CrstExplicitInit * GetAssemblyListLock()
2282     {
2283         LIMITED_METHOD_CONTRACT;
2284         return &m_crstAssemblyList;
2285     }
2286     
2287 public:
2288     class AssemblyIterator
2289     {
2290         // AppDomain context with the assembly list
2291         AppDomain *            m_pAppDomain;
2292         ArrayList::Iterator    m_Iterator;
2293         AssemblyIterationFlags m_assemblyIterationFlags;
2294
2295     public:
2296         BOOL Next(CollectibleAssemblyHolder<DomainAssembly *> * pDomainAssemblyHolder);
2297         // Note: Does not lock the assembly list, but AddRefs collectible assemblies.
2298         BOOL Next_Unlocked(CollectibleAssemblyHolder<DomainAssembly *> * pDomainAssemblyHolder);
2299 #ifndef DACCESS_COMPILE
2300     private:
2301         // Can be called only from AppDomain shutdown code:AppDomain::ShutdownAssemblies.
2302         // Note: Does not lock the assembly list and does not AddRefs collectible assemblies.
2303         BOOL Next_UnsafeNoAddRef(DomainAssembly ** ppDomainAssembly);
2304 #endif
2305
2306     private:
2307         inline DWORD GetIndex()
2308         {
2309             LIMITED_METHOD_CONTRACT;
2310             return m_Iterator.GetIndex();
2311         }
2312
2313     private:
2314         friend class AppDomain;
2315         // Cannot have constructor so this iterator can be used inside a union
2316         static AssemblyIterator Create(AppDomain * pAppDomain, AssemblyIterationFlags assemblyIterationFlags)
2317         {
2318             LIMITED_METHOD_CONTRACT;
2319             AssemblyIterator i;
2320
2321             i.m_pAppDomain = pAppDomain;
2322             i.m_Iterator = pAppDomain->m_Assemblies.GetArrayListIterator();
2323             i.m_assemblyIterationFlags = assemblyIterationFlags;
2324             return i;
2325         }
2326     };  // class AssemblyIterator
2327
2328     AssemblyIterator IterateAssembliesEx(AssemblyIterationFlags assemblyIterationFlags)
2329     {
2330         LIMITED_METHOD_CONTRACT;
2331         return AssemblyIterator::Create(this, assemblyIterationFlags);
2332     }
2333
2334 #ifdef FEATURE_CORECLR
2335 private:
2336     struct NativeImageDependenciesEntry
2337     {
2338         BaseAssemblySpec m_AssemblySpec;
2339         GUID m_guidMVID;
2340     };
2341
2342     class NativeImageDependenciesTraits : public NoRemoveSHashTraits<DefaultSHashTraits<NativeImageDependenciesEntry *> >
2343     {
2344     public:
2345         typedef BaseAssemblySpec *key_t;
2346         static key_t GetKey(NativeImageDependenciesEntry * e) { return &(e->m_AssemblySpec); }
2347
2348         static count_t Hash(key_t k)
2349         {
2350             return k->Hash();
2351         }
2352
2353         static BOOL Equals(key_t lhs, key_t rhs)
2354         {
2355             return lhs->CompareEx(rhs);
2356         }
2357     };
2358
2359     SHash<NativeImageDependenciesTraits> m_NativeImageDependencies;
2360
2361 public:
2362     void CheckForMismatchedNativeImages(AssemblySpec * pSpec, const GUID * pGuid);
2363
2364 public:
2365     class PathIterator
2366     {
2367         friend class AppDomain;
2368
2369         ArrayList::Iterator m_i;
2370
2371     public:
2372         BOOL Next()
2373         {
2374             WRAPPER_NO_CONTRACT;
2375             return m_i.Next();
2376         }
2377
2378         SString* GetPath()
2379         {
2380             WRAPPER_NO_CONTRACT;
2381             return dac_cast<PTR_SString>(m_i.GetElement());
2382         }
2383     };
2384     BOOL BindingByManifestFile();
2385
2386     PathIterator IterateNativeDllSearchDirectories();
2387     void SetNativeDllSearchDirectories(LPCWSTR paths);
2388     BOOL HasNativeDllSearchDirectories();
2389     void ShutdownNativeDllSearchDirectories();
2390 #endif // FEATURE_CORECLR
2391
2392 public:
2393     SIZE_T GetAssemblyCount()
2394     {
2395         WRAPPER_NO_CONTRACT;
2396         return m_Assemblies.GetCount(this);
2397     }
2398
2399     CHECK CheckCanLoadTypes(Assembly *pAssembly);
2400     CHECK CheckCanExecuteManagedCode(MethodDesc* pMD);
2401     CHECK CheckLoading(DomainFile *pFile, FileLoadLevel level);
2402
2403     FileLoadLevel GetDomainFileLoadLevel(DomainFile *pFile);
2404     BOOL IsLoading(DomainFile *pFile, FileLoadLevel level);
2405     static FileLoadLevel GetThreadFileLoadLevel();
2406
2407     void LoadDomainFile(DomainFile *pFile,
2408                         FileLoadLevel targetLevel);
2409
2410     enum FindAssemblyOptions
2411     {
2412         FindAssemblyOptions_None                    = 0x0,
2413         FindAssemblyOptions_IncludeFailedToLoad     = 0x1
2414     };
2415
2416     DomainAssembly * FindAssembly(PEAssembly * pFile, FindAssemblyOptions options = FindAssemblyOptions_None) DAC_EMPTY_RET(NULL);
2417
2418 #ifdef FEATURE_MIXEDMODE
2419     // Finds only loaded modules, elevates level if needed
2420     Module* GetIJWModule(HMODULE hMod) DAC_EMPTY_RET(NULL);
2421     // Finds loading modules
2422     DomainFile* FindIJWDomainFile(HMODULE hMod, const SString &path) DAC_EMPTY_RET(NULL);
2423 #endif //  FEATURE_MIXEDMODE
2424
2425     Assembly *LoadAssembly(AssemblySpec* pIdentity,
2426                            PEAssembly *pFile,
2427                            FileLoadLevel targetLevel,
2428                            AssemblyLoadSecurity *pLoadSecurity = NULL);
2429
2430     // this function does not provide caching, you must use LoadDomainAssembly
2431     // unless the call is guaranteed to succeed or you don't need the caching 
2432     // (e.g. if you will FailFast or tear down the AppDomain anyway)
2433     // The main point that you should not bypass caching if you might try to load the same file again, 
2434     // resulting in multiple DomainAssembly objects that share the same PEAssembly for ngen image 
2435     //which is violating our internal assumptions
2436     DomainAssembly *LoadDomainAssemblyInternal( AssemblySpec* pIdentity,
2437                                                 PEAssembly *pFile,
2438                                                 FileLoadLevel targetLevel,
2439                                                 AssemblyLoadSecurity *pLoadSecurity = NULL);
2440
2441     DomainAssembly *LoadDomainAssembly( AssemblySpec* pIdentity,
2442                                         PEAssembly *pFile,
2443                                         FileLoadLevel targetLevel,
2444                                         AssemblyLoadSecurity *pLoadSecurity = NULL);
2445
2446 #ifdef FEATURE_MULTIMODULE_ASSEMBLIES
2447     DomainModule *LoadDomainModule(DomainAssembly *pAssembly,
2448                                    PEModule *pFile,
2449                                    FileLoadLevel targetLevel);
2450 #endif 
2451
2452     CHECK CheckValidModule(Module *pModule);
2453 #ifdef FEATURE_LOADER_OPTIMIZATION    
2454     DomainFile *LoadDomainNeutralModuleDependency(Module *pModule, FileLoadLevel targetLevel);
2455 #endif
2456
2457 #ifdef FEATURE_FUSION
2458     PEAssembly *BindExplicitAssembly(HMODULE hMod, BOOL bindable);
2459     Assembly *LoadExplicitAssembly(HMODULE hMod, BOOL bindable);
2460     void GetFileFromFusion(IAssembly *pIAssembly, LPCWSTR wszModuleName,
2461                            SString &path);
2462 #endif
2463     // private:
2464     void LoadSystemAssemblies();
2465
2466     DomainFile *LoadDomainFile(FileLoadLock *pLock,
2467                                FileLoadLevel targetLevel);
2468
2469     void TryIncrementalLoad(DomainFile *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder);
2470
2471     Assembly *LoadAssemblyHelper(LPCWSTR wszAssembly,
2472                                  LPCWSTR wszCodeBase);
2473
2474 #ifndef DACCESS_COMPILE // needs AssemblySpec
2475     //****************************************************************************************
2476     // Returns and Inserts assemblies into a lookup cache based on the binding information
2477     // in the AssemblySpec. There can be many AssemblySpecs to a single assembly.
2478     DomainAssembly* FindCachedAssembly(AssemblySpec* pSpec, BOOL fThrow=TRUE)
2479     {
2480         WRAPPER_NO_CONTRACT;
2481         return m_AssemblyCache.LookupAssembly(pSpec, fThrow);
2482     }
2483
2484     PEAssembly* FindCachedFile(AssemblySpec* pSpec, BOOL fThrow = TRUE);
2485     BOOL IsCached(AssemblySpec *pSpec);
2486 #endif // DACCESS_COMPILE
2487     void CacheStringsForDAC();
2488
2489     BOOL AddFileToCache(AssemblySpec* pSpec, PEAssembly *pFile, BOOL fAllowFailure = FALSE);
2490     BOOL AddAssemblyToCache(AssemblySpec* pSpec, DomainAssembly *pAssembly);
2491     BOOL AddExceptionToCache(AssemblySpec* pSpec, Exception *ex);
2492     void AddUnmanagedImageToCache(LPCWSTR libraryName, HMODULE hMod);
2493     HMODULE FindUnmanagedImageInCache(LPCWSTR libraryName);
2494     //****************************************************************************************
2495     //
2496     // Adds an assembly to the domain.
2497     void AddAssembly(DomainAssembly * assem);
2498     void RemoveAssembly_Unlocked(DomainAssembly * pAsm);
2499
2500     BOOL ContainsAssembly(Assembly * assem);
2501
2502 #ifdef FEATURE_LOADER_OPTIMIZATION    
2503     enum SharePolicy
2504     {
2505         // Attributes to control when to use domain neutral assemblies
2506         SHARE_POLICY_UNSPECIFIED,   // Use the current default policy (LoaderOptimization.NotSpecified)
2507         SHARE_POLICY_NEVER,         // Do not share anything, except the system assembly (LoaderOptimization.SingleDomain)
2508         SHARE_POLICY_ALWAYS,        // Share everything possible (LoaderOptimization.MultiDomain)
2509         SHARE_POLICY_GAC,           // Share only GAC-bound assemblies (LoaderOptimization.MultiDomainHost)
2510
2511         SHARE_POLICY_COUNT,
2512         SHARE_POLICY_MASK = 0x3,
2513
2514         // NOTE that previously defined was a bit 0x40 which might be set on this value
2515         // in custom attributes.
2516         SHARE_POLICY_DEFAULT = SHARE_POLICY_NEVER,
2517     };
2518
2519     void SetSharePolicy(SharePolicy policy);
2520     SharePolicy GetSharePolicy();
2521     BOOL ReduceSharePolicyFromAlways();
2522
2523     //****************************************************************************************
2524     // Determines if the image is to be loaded into the shared assembly or an individual
2525     // appdomains.
2526 #ifndef FEATURE_CORECLR    
2527     BOOL ApplySharePolicy(DomainAssembly *pFile);
2528     BOOL ApplySharePolicyFlag(DomainAssembly *pFile);
2529 #endif    
2530 #endif // FEATURE_LOADER_OPTIMIZATION
2531
2532     BOOL HasSetSecurityPolicy();
2533
2534     FORCEINLINE IApplicationSecurityDescriptor* GetSecurityDescriptor()
2535     {
2536         LIMITED_METHOD_CONTRACT;
2537         STATIC_CONTRACT_SO_TOLERANT;
2538         return static_cast<IApplicationSecurityDescriptor*>(m_pSecDesc);
2539     }
2540
2541     void CreateSecurityDescriptor();
2542
2543     //****************************************************************************************
2544     //
2545     // Reference count. When an appdomain is first created the reference is bump
2546     // to one when it is added to the list of domains (see SystemDomain). An explicit
2547     // Removal from the list is necessary before it will be deleted.
2548     ULONG AddRef(void);
2549     ULONG Release(void) DAC_EMPTY_RET(0);
2550
2551     //****************************************************************************************
2552     LPCWSTR GetFriendlyName(BOOL fDebuggerCares = TRUE);
2553     LPCWSTR GetFriendlyNameForDebugger();
2554     LPCWSTR GetFriendlyNameForLogging();
2555 #ifdef DACCESS_COMPILE
2556     PVOID GetFriendlyNameNoSet(bool* isUtf8);
2557 #endif
2558     void SetFriendlyName(LPCWSTR pwzFriendlyName, BOOL fDebuggerCares = TRUE);
2559     void ResetFriendlyName(BOOL fDebuggerCares = TRUE);
2560
2561     //****************************************************************************************
2562
2563     // This can be used to override the binding behavior of the appdomain.   It
2564     // is overridden in the compilation domain.  It is important that all
2565     // static binding goes through this path.
2566     virtual PEAssembly * BindAssemblySpec(
2567         AssemblySpec *pSpec,
2568         BOOL fThrowOnFileNotFound,
2569         BOOL fRaisePrebindEvents,
2570         StackCrawlMark *pCallerStackMark = NULL,
2571         AssemblyLoadSecurity *pLoadSecurity = NULL,
2572         BOOL fUseHostBinderIfAvailable = TRUE) DAC_EMPTY_RET(NULL);
2573
2574 #ifdef FEATURE_HOSTED_BINDER
2575     HRESULT BindAssemblySpecForHostedBinder(
2576         AssemblySpec *   pSpec, 
2577         IAssemblyName *  pAssemblyName, 
2578         ICLRPrivBinder * pBinder, 
2579         PEAssembly **    ppAssembly) DAC_EMPTY_RET(E_FAIL);
2580     
2581     HRESULT BindHostedPrivAssembly(
2582         PEAssembly *       pParentPEAssembly,
2583         ICLRPrivAssembly * pPrivAssembly, 
2584         IAssemblyName *    pAssemblyName, 
2585         PEAssembly **      ppAssembly, 
2586         BOOL               fIsIntrospectionOnly = FALSE) DAC_EMPTY_RET(S_OK);
2587 #endif // FEATURE_HOSTED_BINDER
2588
2589 #ifdef FEATURE_REFLECTION_ONLY_LOAD    
2590     virtual DomainAssembly *BindAssemblySpecForIntrospectionDependencies(AssemblySpec *pSpec) DAC_EMPTY_RET(NULL);
2591 #endif
2592
2593     PEAssembly *TryResolveAssembly(AssemblySpec *pSpec, BOOL fPreBind);
2594
2595     // Store a successful binding into the cache.  This will keep the file from
2596     // being physically unmapped, as well as shortcutting future attempts to bind
2597     // the same spec throught the Cached entry point.
2598     //
2599     // Right now we only cache assembly binds for "probing" type
2600     // binding situations, basically when loading domain neutral assemblies or
2601     // zap files.
2602     //
2603     // <TODO>@todo: We may want to be more aggressive about this if
2604     // there are other situations where we are repeatedly binding the
2605     // same assembly specs, though.</TODO>
2606     //
2607     // Returns TRUE if stored
2608     //         FALSE if it's a duplicate (caller should clean up args)
2609     BOOL StoreBindAssemblySpecResult(AssemblySpec *pSpec,
2610                                      PEAssembly *pFile,
2611                                      BOOL clone = TRUE);
2612
2613     BOOL StoreBindAssemblySpecError(AssemblySpec *pSpec,
2614                                     HRESULT hr,
2615                                     OBJECTREF *pThrowable,
2616                                     BOOL clone = TRUE);
2617
2618     //****************************************************************************************
2619     //
2620 #ifdef FEATURE_FUSION    
2621     static BOOL SetContextProperty(IApplicationContext* pFusionContext,
2622                                    LPCWSTR pProperty,
2623                                    OBJECTREF* obj);
2624 #endif
2625     //****************************************************************************************
2626     //
2627     // Uses the first assembly to add an application base to the Context. This is done
2628     // in a lazy fashion so executables do not take the perf hit unless the load other
2629     // assemblies
2630 #ifdef FEATURE_FUSION    
2631     LPWSTR GetDynamicDir();
2632 #endif
2633 #ifndef DACCESS_COMPILE
2634     void OnAssemblyLoad(Assembly *assem);
2635     void OnAssemblyLoadUnlocked(Assembly *assem);
2636     static BOOL OnUnhandledException(OBJECTREF *pThrowable, BOOL isTerminating = TRUE);
2637     
2638 #endif
2639
2640     // True iff a debugger is attached to the process (same as CORDebuggerAttached)
2641     BOOL IsDebuggerAttached (void);
2642
2643 #ifdef DEBUGGING_SUPPORTED
2644     // Notify debugger of all assemblies, modules, and possibly classes in this AppDomain
2645     BOOL NotifyDebuggerLoad(int flags, BOOL attaching);
2646
2647     // Send unload notifications to the debugger for all assemblies, modules and classes in this AppDomain
2648     void NotifyDebuggerUnload();
2649 #endif // DEBUGGING_SUPPORTED
2650
2651     void SetSystemAssemblyLoadEventSent (BOOL fFlag);
2652     BOOL WasSystemAssemblyLoadEventSent (void);
2653
2654 #ifndef DACCESS_COMPILE
2655     OBJECTREF* AllocateStaticFieldObjRefPtrs(int nRequested, OBJECTREF** ppLazyAllocate = NULL)
2656     {
2657         WRAPPER_NO_CONTRACT;
2658
2659         return AllocateObjRefPtrsInLargeTable(nRequested, ppLazyAllocate);
2660     }
2661
2662     OBJECTREF* AllocateStaticFieldObjRefPtrsCrossDomain(int nRequested, OBJECTREF** ppLazyAllocate = NULL)
2663     {
2664         WRAPPER_NO_CONTRACT;
2665
2666         return AllocateObjRefPtrsInLargeTable(nRequested, ppLazyAllocate, TRUE);
2667     }
2668 #endif // DACCESS_COMPILE
2669
2670     void              EnumStaticGCRefs(promote_func* fn, ScanContext* sc);
2671
2672     DomainLocalBlock *GetDomainLocalBlock()
2673     {
2674         LIMITED_METHOD_DAC_CONTRACT;
2675
2676         return &m_sDomainLocalBlock;
2677     }
2678
2679     static SIZE_T GetOffsetOfModuleSlotsPointer()
2680     {
2681         WRAPPER_NO_CONTRACT;
2682
2683         return offsetof(AppDomain,m_sDomainLocalBlock) + DomainLocalBlock::GetOffsetOfModuleSlotsPointer();
2684     }
2685
2686     void SetupSharedStatics();
2687
2688     ADUnloadSink* PrepareForWaitUnloadCompletion();
2689
2690     //****************************************************************************************
2691     //
2692     // Create a quick lookup for classes loaded into this domain based on their GUID.
2693     //
2694     void InsertClassForCLSID(MethodTable* pMT, BOOL fForceInsert = FALSE);
2695     void InsertClassForCLSID(MethodTable* pMT, GUID *pGuid);
2696
2697 #ifdef FEATURE_COMINTEROP
2698 private:
2699     void CacheTypeByNameWorker(const SString &ssClassName, const UINT vCacheVersion, TypeHandle typeHandle, BYTE flags, BOOL bReplaceExisting = FALSE);
2700     TypeHandle LookupTypeByNameWorker(const SString &ssClassName, UINT *pvCacheVersion, BYTE *pbFlags);
2701 public:
2702     // Used by COM Interop for mapping WinRT runtime class names to real types.
2703     void CacheTypeByName(const SString &ssClassName, const UINT vCacheVersion, TypeHandle typeHandle, BYTE flags, BOOL bReplaceExisting = FALSE);
2704     TypeHandle LookupTypeByName(const SString &ssClassName, UINT *pvCacheVersion, BYTE *pbFlags);
2705     PTR_MethodTable LookupTypeByGuid(const GUID & guid);
2706
2707 #ifndef DACCESS_COMPILE
2708     inline BOOL CanCacheWinRTTypeByGuid(TypeHandle typeHandle)
2709     { 
2710         CONTRACTL
2711         {
2712             THROWS;
2713             GC_NOTRIGGER;
2714             MODE_ANY;
2715         }
2716         CONTRACTL_END;
2717         
2718         // Only allow caching guid/types maps for types loaded during 
2719         // "normal" domain operation
2720         if (IsCompilationDomain() || (m_Stage < STAGE_OPEN))
2721             return FALSE;
2722
2723         MethodTable *pMT = typeHandle.GetMethodTable();
2724         if (pMT != NULL)
2725         {
2726             // Don't cache mscorlib-internal declarations of WinRT types.
2727             if (pMT->GetModule()->IsSystem() && pMT->IsProjectedFromWinRT())
2728                 return FALSE;
2729
2730             // Don't cache redirected WinRT types.
2731             if (WinRTTypeNameConverter::IsRedirectedWinRTSourceType(pMT))
2732                 return FALSE;
2733         }
2734
2735         return TRUE;
2736     }
2737 #endif // !DACCESS_COMPILE
2738
2739     void CacheWinRTTypeByGuid(TypeHandle typeHandle);
2740     void GetCachedWinRTTypes(SArray<PTR_MethodTable> * pTypes, SArray<GUID> * pGuids, UINT minEpoch, UINT * pCurEpoch);
2741
2742     // Used by COM Interop for caching WinRT factory objects.
2743     void CacheWinRTFactoryObject(MethodTable *pClassMT, OBJECTREF *refFactory, LPVOID lpCtxCookie);
2744     OBJECTREF LookupWinRTFactoryObject(MethodTable *pClassMT, LPVOID lpCtxCookie);
2745     void RemoveWinRTFactoryObjects(LPVOID pCtxCookie);
2746
2747     MethodTable *LoadCOMClass(GUID clsid, BOOL bLoadRecord = FALSE, BOOL* pfAssemblyInReg = NULL);
2748     COMorRemotingFlag GetComOrRemotingFlag();
2749     BOOL GetPreferComInsteadOfManagedRemoting();
2750     OBJECTREF GetMissingObject();    // DispatchInfo will call function to retrieve the Missing.Value object.
2751 #endif // FEATURE_COMINTEROP
2752
2753 #ifndef DACCESS_COMPILE
2754     MethodTable* LookupClass(REFIID iid)
2755     {
2756         WRAPPER_NO_CONTRACT;
2757
2758         MethodTable *pMT = (MethodTable*) m_clsidHash.LookupValue((UPTR) GetKeyFromGUID(&iid), (LPVOID)&iid);
2759         return (pMT == (MethodTable*) INVALIDENTRY
2760             ? NULL
2761             : pMT);
2762     }
2763 #endif // DACCESS_COMPILE
2764
2765     //<TODO>@todo get a better key</TODO>
2766     ULONG GetKeyFromGUID(const GUID *pguid)
2767     {
2768         LIMITED_METHOD_CONTRACT;
2769
2770         return *(ULONG *) pguid;
2771     }
2772
2773 #ifdef FEATURE_COMINTEROP
2774     ComCallWrapperCache* GetComCallWrapperCache();
2775     RCWCache *GetRCWCache()
2776     {
2777         WRAPPER_NO_CONTRACT;
2778         if (m_pRCWCache) 
2779             return m_pRCWCache;
2780
2781         // By separating the cache creation from the common lookup, we
2782         // can keep the (x86) EH prolog/epilog off the path.
2783         return CreateRCWCache();
2784     }
2785 private:
2786     RCWCache *CreateRCWCache();
2787 public:
2788     RCWCache *GetRCWCacheNoCreate()
2789     {
2790         LIMITED_METHOD_CONTRACT;
2791         return m_pRCWCache;
2792     }
2793
2794     RCWRefCache *GetRCWRefCache();
2795
2796     void ResetComCallWrapperCache()
2797     {
2798         LIMITED_METHOD_CONTRACT;
2799         m_pComCallWrapperCache = NULL;
2800     }
2801
2802     MethodTable* GetLicenseInteropHelperMethodTable();
2803 #endif // FEATURE_COMINTEROP
2804
2805     //****************************************************************************************
2806     // Get the proxy for this app domain
2807 #ifdef FEATURE_REMOTING    
2808     OBJECTREF GetAppDomainProxy();
2809 #endif
2810
2811     ADIndex GetIndex()
2812     {
2813         LIMITED_METHOD_CONTRACT;
2814         SUPPORTS_DAC;
2815
2816         return m_dwIndex;
2817     }
2818
2819     TPIndex GetTPIndex()
2820     {
2821         LIMITED_METHOD_CONTRACT;
2822         return m_tpIndex;
2823     }
2824
2825     void InitializeDomainContext(BOOL allowRedirects, LPCWSTR pwszPath, LPCWSTR pwszConfig);
2826
2827 #ifdef FEATURE_FUSION
2828     IApplicationContext *CreateFusionContext();
2829     void SetupLoaderOptimization(DWORD optimization);
2830 #endif
2831 #ifdef FEATURE_VERSIONING
2832     IUnknown *CreateFusionContext();
2833 #endif // FEATURE_VERSIONING
2834
2835 #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
2836     void OverrideDefaultContextBinder(IUnknown *pOverrideBinder)
2837     {
2838         LIMITED_METHOD_CONTRACT;
2839         
2840         _ASSERTE(pOverrideBinder != NULL);
2841         pOverrideBinder->AddRef();
2842         m_pFusionContext->Release();
2843         m_pFusionContext = pOverrideBinder;
2844     }
2845     
2846 #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
2847
2848 #ifdef FEATURE_PREJIT
2849     CorCompileConfigFlags GetNativeConfigFlags();
2850 #endif // FEATURE_PREJIT
2851
2852     //****************************************************************************************
2853     // Create a domain context rooted at the fileName. The directory containing the file name
2854     // is the application base and the configuration file is the fileName appended with
2855     // .config. If no name is passed in then no domain is created.
2856     static AppDomain* CreateDomainContext(LPCWSTR fileName);
2857
2858     // Sets up the current domain's fusion context based on the given exe file name
2859     // (app base & config file)
2860     void SetupExecutableFusionContext(LPCWSTR exePath);
2861
2862     //****************************************************************************************
2863     // Manage a pool of asyncrhonous objects used to fetch assemblies.  When a sink is released
2864     // it places itself back on the pool list.  Only one object is kept in the pool.
2865 #ifdef FEATURE_FUSION
2866     AssemblySink* AllocateAssemblySink(AssemblySpec* pSpec);
2867 #endif
2868     void SetIsUserCreatedDomain()
2869     {
2870         LIMITED_METHOD_CONTRACT;
2871
2872         m_dwFlags |= USER_CREATED_DOMAIN;
2873     }
2874
2875     BOOL IsUserCreatedDomain()
2876     {
2877         LIMITED_METHOD_CONTRACT;
2878
2879         return (m_dwFlags & USER_CREATED_DOMAIN);
2880     }
2881
2882     void SetIgnoreUnhandledExceptions()
2883     {
2884         LIMITED_METHOD_CONTRACT;
2885
2886         m_dwFlags |= IGNORE_UNHANDLED_EXCEPTIONS;
2887     }
2888
2889     BOOL IgnoreUnhandledExceptions()
2890     {
2891         LIMITED_METHOD_CONTRACT;
2892
2893         return (m_dwFlags & IGNORE_UNHANDLED_EXCEPTIONS);
2894     }
2895
2896 #if defined(FEATURE_CORECLR)    
2897     void SetEnablePInvokeAndClassicComInterop()
2898     {
2899         LIMITED_METHOD_CONTRACT;
2900
2901         m_dwFlags |= ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP;
2902     }
2903
2904     BOOL EnablePInvokeAndClassicComInterop()
2905     {
2906         LIMITED_METHOD_CONTRACT;
2907
2908         return (m_dwFlags & ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP);
2909     }
2910
2911     void SetAllowPlatformSpecificAppAssemblies()
2912     {
2913         LIMITED_METHOD_CONTRACT;
2914
2915         m_dwFlags |= ENABLE_SKIP_PLAT_CHECKS;
2916     }
2917
2918     BOOL AllowPlatformSpecificAppAssemblies()
2919     {
2920         LIMITED_METHOD_CONTRACT;
2921         if(IsCompilationDomain())
2922             return TRUE;
2923
2924         return (m_dwFlags & ENABLE_SKIP_PLAT_CHECKS);
2925     }
2926
2927     void SetAllowLoadFile()
2928     {
2929         LIMITED_METHOD_CONTRACT;
2930
2931         m_dwFlags |= ENABLE_ASSEMBLY_LOADFILE;
2932     }
2933
2934     BOOL IsLoadFileAllowed()
2935     {
2936         LIMITED_METHOD_CONTRACT;
2937
2938         return (m_dwFlags & ENABLE_ASSEMBLY_LOADFILE);
2939      }
2940 #endif // defined(FEATURE_CORECLR)
2941
2942     void SetPassiveDomain()
2943     {
2944         LIMITED_METHOD_CONTRACT;
2945
2946         m_dwFlags |= PASSIVE_DOMAIN;
2947     }
2948
2949     BOOL IsPassiveDomain()
2950     {
2951         LIMITED_METHOD_CONTRACT;
2952
2953         return (m_dwFlags & PASSIVE_DOMAIN);
2954     }
2955
2956     void SetVerificationDomain()
2957     {
2958         LIMITED_METHOD_CONTRACT;
2959
2960         m_dwFlags |= VERIFICATION_DOMAIN;
2961     }
2962
2963     BOOL IsVerificationDomain()
2964     {
2965         LIMITED_METHOD_CONTRACT;
2966
2967         return (m_dwFlags & VERIFICATION_DOMAIN);
2968     }
2969
2970     void SetIllegalVerificationDomain()
2971     {
2972         LIMITED_METHOD_CONTRACT;
2973
2974         m_dwFlags |= ILLEGAL_VERIFICATION_DOMAIN;
2975     }
2976
2977     BOOL IsIllegalVerificationDomain()
2978     {
2979         LIMITED_METHOD_CONTRACT;
2980
2981         return (m_dwFlags & ILLEGAL_VERIFICATION_DOMAIN);
2982     }
2983
2984     void SetCompilationDomain()
2985     {
2986         LIMITED_METHOD_CONTRACT;
2987
2988         m_dwFlags |= (PASSIVE_DOMAIN|COMPILATION_DOMAIN);
2989     }
2990
2991     BOOL IsCompilationDomain();
2992
2993     PTR_CompilationDomain ToCompilationDomain()
2994     {
2995         LIMITED_METHOD_CONTRACT;
2996
2997         _ASSERTE(IsCompilationDomain());
2998         return dac_cast<PTR_CompilationDomain>(this);
2999     }
3000
3001 #ifdef MDIL
3002     void SetMDILCompilationDomain()
3003     {
3004
3005         LIMITED_METHOD_CONTRACT;
3006
3007         _ASSERTE(IsCompilationDomain());
3008         m_dwFlags |= MDIL_COMPILATION_DOMAIN;
3009     }
3010
3011     BOOL IsMDILCompilationDomain()
3012     {
3013
3014         LIMITED_METHOD_CONTRACT;
3015         return m_dwFlags & MDIL_COMPILATION_DOMAIN;
3016     }
3017
3018     void SetMinimalMDILCompilationDomain()
3019     {
3020         LIMITED_METHOD_CONTRACT;
3021
3022         _ASSERTE(IsCompilationDomain());
3023         m_dwFlags |= MINIMAL_MDIL_COMPILATION_DOMAIN;
3024     }
3025
3026     BOOL IsMinimalMDILCompilationDomain()
3027     {
3028         LIMITED_METHOD_CONTRACT;
3029         return m_dwFlags & MINIMAL_MDIL_COMPILATION_DOMAIN;
3030     }
3031
3032     void SetNoMDILCompilationDomain()
3033     {
3034         LIMITED_METHOD_CONTRACT;
3035
3036         _ASSERTE(IsCompilationDomain());
3037         m_dwFlags |= NO_MDIL_COMPILATION_DOMAIN;
3038     }
3039
3040     BOOL IsNoMDILCompilationDomain()
3041     {
3042         LIMITED_METHOD_CONTRACT;
3043         return m_dwFlags & NO_MDIL_COMPILATION_DOMAIN;
3044     }
3045 #endif // MDIL
3046
3047     void SetCanUnload()
3048     {
3049         LIMITED_METHOD_CONTRACT;
3050
3051         m_dwFlags |= APP_DOMAIN_CAN_BE_UNLOADED;
3052     }
3053
3054     BOOL CanUnload()
3055     {
3056         LIMITED_METHOD_CONTRACT;
3057         STATIC_CONTRACT_SO_TOLERANT;
3058         return m_dwFlags & APP_DOMAIN_CAN_BE_UNLOADED;
3059     }
3060
3061     void SetRemotingConfigured()
3062     {
3063         LIMITED_METHOD_CONTRACT;
3064         STATIC_CONTRACT_SO_TOLERANT;
3065         FastInterlockOr((ULONG*)&m_dwFlags, REMOTING_CONFIGURED_FOR_DOMAIN);
3066     }
3067
3068     BOOL IsRemotingConfigured()
3069     {
3070         LIMITED_METHOD_CONTRACT;
3071         STATIC_CONTRACT_SO_TOLERANT;
3072         return m_dwFlags & REMOTING_CONFIGURED_FOR_DOMAIN;
3073     }
3074
3075     void SetOrphanedLocks()
3076     {
3077         LIMITED_METHOD_CONTRACT;
3078         STATIC_CONTRACT_SO_TOLERANT;
3079         FastInterlockOr((ULONG*)&m_dwFlags, ORPHANED_LOCKS);
3080     }
3081
3082     BOOL HasOrphanedLocks()
3083     {
3084         LIMITED_METHOD_CONTRACT;
3085         STATIC_CONTRACT_SO_TOLERANT;
3086         return m_dwFlags & ORPHANED_LOCKS;
3087     }
3088
3089     // This function is used to relax asserts in the lock accounting.
3090     // It returns true if we are fine with hosed lock accounting in this domain.
3091     BOOL OkToIgnoreOrphanedLocks()
3092     {
3093         WRAPPER_NO_CONTRACT;
3094         return HasOrphanedLocks() && m_Stage >= STAGE_UNLOAD_REQUESTED;
3095     }
3096
3097     static void ExceptionUnwind(Frame *pFrame);
3098
3099 #ifdef _DEBUG
3100     void TrackADThreadEnter(Thread *pThread, Frame *pFrame);
3101     void TrackADThreadExit(Thread *pThread, Frame *pFrame);
3102     void DumpADThreadTrack();
3103 #endif
3104
3105 #ifndef DACCESS_COMPILE
3106     void ThreadEnter(Thread *pThread, Frame *pFrame)
3107     {
3108         STATIC_CONTRACT_NOTHROW;
3109         STATIC_CONTRACT_GC_NOTRIGGER;
3110
3111 #ifdef _DEBUG
3112         if (LoggingOn(LF_APPDOMAIN, LL_INFO100))
3113             TrackADThreadEnter(pThread, pFrame);
3114         else
3115 #endif
3116         {
3117             InterlockedIncrement((LONG*)&m_dwThreadEnterCount);
3118             LOG((LF_APPDOMAIN, LL_INFO1000, "AppDomain::ThreadEnter  %p to [%d] (%8.8x) %S count %d\n", 
3119                  pThread,GetId().m_dwId, this,
3120                  GetFriendlyNameForLogging(),GetThreadEnterCount()));
3121 #if _DEBUG_AD_UNLOAD
3122             printf("AppDomain::ThreadEnter %p to [%d] (%8.8x) %S count %d\n",
3123                    pThread, GetId().m_dwId, this,
3124                    GetFriendlyNameForLogging(), GetThreadEnterCount());
3125 #endif
3126         }
3127     }
3128
3129     void ThreadExit(Thread *pThread, Frame *pFrame)
3130     {
3131         STATIC_CONTRACT_NOTHROW;
3132         STATIC_CONTRACT_GC_NOTRIGGER;
3133
3134 #ifdef _DEBUG
3135         if (LoggingOn(LF_APPDOMAIN, LL_INFO100)) {
3136             TrackADThreadExit(pThread, pFrame);
3137         }
3138         else
3139 #endif
3140         {
3141             LONG result;
3142             result = InterlockedDecrement((LONG*)&m_dwThreadEnterCount);
3143             _ASSERTE(result >= 0);
3144             LOG((LF_APPDOMAIN, LL_INFO1000, "AppDomain::ThreadExit from [%d] (%8.8x) %S count %d\n",
3145                  this, GetId().m_dwId,
3146                  GetFriendlyNameForLogging(), GetThreadEnterCount()));
3147 #if _DEBUG_ADUNLOAD
3148             printf("AppDomain::ThreadExit %x from [%d] (%8.8x) %S count %d\n",
3149                    pThread->GetThreadId(), this, GetId().m_dwId,
3150                    GetFriendlyNameForLogging(), GetThreadEnterCount());
3151 #endif
3152         }
3153     }
3154 #endif // DACCESS_COMPILE
3155
3156     ULONG GetThreadEnterCount()
3157     {
3158         LIMITED_METHOD_CONTRACT;
3159         return m_dwThreadEnterCount;
3160     }
3161
3162     BOOL OnlyOneThreadLeft()
3163     {
3164         LIMITED_METHOD_CONTRACT;
3165         return m_dwThreadEnterCount==1 || m_dwThreadsStillInAppDomain ==1;
3166     }
3167
3168     Context *GetDefaultContext()
3169     {
3170         LIMITED_METHOD_CONTRACT;
3171         return m_pDefaultContext;
3172     }
3173
3174     BOOL CanLoadCode()
3175     {
3176         LIMITED_METHOD_CONTRACT;
3177         return m_Stage >= STAGE_READYFORMANAGEDCODE && m_Stage < STAGE_CLOSED;        
3178     }
3179
3180     void SetAnonymouslyHostedDynamicMethodsAssembly(DomainAssembly * pDomainAssembly)
3181     {
3182         LIMITED_METHOD_CONTRACT;
3183         _ASSERTE(pDomainAssembly != NULL);
3184         _ASSERTE(m_anonymouslyHostedDynamicMethodsAssembly == NULL);
3185         m_anonymouslyHostedDynamicMethodsAssembly = pDomainAssembly;
3186     }
3187
3188     DomainAssembly * GetAnonymouslyHostedDynamicMethodsAssembly()
3189     {
3190         LIMITED_METHOD_CONTRACT;
3191         return m_anonymouslyHostedDynamicMethodsAssembly;
3192     }
3193
3194     BOOL HasUnloadStarted()
3195     {
3196         LIMITED_METHOD_CONTRACT;
3197         return m_Stage>=STAGE_EXITED;
3198     }
3199     static void RefTakerAcquire(AppDomain* pDomain)
3200     {
3201         WRAPPER_NO_CONTRACT;
3202         if(!pDomain)
3203             return;
3204         pDomain->AddRef();
3205 #ifdef _DEBUG
3206         FastInterlockIncrement(&pDomain->m_dwRefTakers);
3207 #endif
3208     }
3209
3210     static void RefTakerRelease(AppDomain* pDomain)
3211     {
3212         WRAPPER_NO_CONTRACT;
3213         if(!pDomain)
3214             return;
3215 #ifdef _DEBUG
3216         _ASSERTE(pDomain->m_dwRefTakers);
3217         FastInterlockDecrement(&pDomain->m_dwRefTakers);
3218 #endif
3219         pDomain->Release();
3220     }
3221
3222 #ifdef _DEBUG 
3223
3224     BOOL IsHeldByIterator()
3225     {
3226         LIMITED_METHOD_CONTRACT;
3227         return m_dwIterHolders>0;
3228     }
3229
3230     BOOL IsHeldByRefTaker()
3231     {
3232         LIMITED_METHOD_CONTRACT;
3233         return m_dwRefTakers>0;
3234     }
3235
3236     void IteratorRelease()
3237     {
3238         LIMITED_METHOD_CONTRACT;
3239         _ASSERTE(m_dwIterHolders);
3240         FastInterlockDecrement(&m_dwIterHolders);
3241     }
3242
3243       
3244     void IteratorAcquire()
3245     {
3246         LIMITED_METHOD_CONTRACT;
3247         FastInterlockIncrement(&m_dwIterHolders);
3248     }
3249     
3250 #endif    
3251     BOOL IsActive()
3252     {
3253         LIMITED_METHOD_DAC_CONTRACT;
3254
3255         return m_Stage >= STAGE_ACTIVE && m_Stage < STAGE_CLOSED;
3256     }
3257     // Range for normal execution of code in the appdomain, currently used for
3258     // appdomain resource monitoring since we don't care to update resource usage
3259     // unless it's in these stages (as fields of AppDomain may not be valid if it's
3260     // not within these stages)
3261     BOOL IsUserActive()
3262     {
3263         LIMITED_METHOD_DAC_CONTRACT;
3264
3265         return m_Stage >= STAGE_ACTIVE && m_Stage <= STAGE_OPEN;
3266     }
3267     BOOL IsValid()
3268     {
3269         LIMITED_METHOD_DAC_CONTRACT;
3270
3271 #ifdef DACCESS_COMPILE
3272         // We want to see all appdomains in SOS, even the about to be destructed ones.
3273         // There is no risk of races under DAC, so we will pretend to be unconditionally valid.
3274         return TRUE;
3275 #else
3276         return m_Stage > STAGE_CREATING && m_Stage < STAGE_CLOSED;
3277 #endif
3278     }
3279
3280 #ifdef _DEBUG
3281     BOOL IsBeingCreated()
3282     {
3283         LIMITED_METHOD_CONTRACT;
3284
3285         return m_dwCreationHolders > 0;
3286     }
3287
3288     void IncCreationCount()
3289     {
3290         LIMITED_METHOD_CONTRACT;
3291
3292         FastInterlockIncrement(&m_dwCreationHolders);
3293         _ASSERTE(m_dwCreationHolders > 0);
3294     }
3295
3296     void DecCreationCount()
3297     {
3298         LIMITED_METHOD_CONTRACT;
3299
3300         FastInterlockDecrement(&m_dwCreationHolders);
3301         _ASSERTE(m_dwCreationHolders > -1);
3302     }
3303 #endif
3304     BOOL IsRunningIn(Thread* pThread);
3305
3306     BOOL IsUnloading()
3307     {
3308         LIMITED_METHOD_CONTRACT;
3309         SUPPORTS_DAC;
3310
3311         return m_Stage > STAGE_UNLOAD_REQUESTED;
3312     }
3313
3314     BOOL NotReadyForManagedCode()
3315     {
3316         LIMITED_METHOD_CONTRACT;
3317
3318         return m_Stage < STAGE_READYFORMANAGEDCODE;
3319     }
3320
3321     void SetFinalized()
3322     {
3323         LIMITED_METHOD_CONTRACT;
3324         SetStage(STAGE_FINALIZED);
3325     }
3326
3327     BOOL IsFinalizing()
3328     {
3329         LIMITED_METHOD_CONTRACT;
3330
3331         return m_Stage >= STAGE_FINALIZING;
3332     }
3333
3334     BOOL IsFinalized()
3335     {
3336         LIMITED_METHOD_CONTRACT;
3337
3338         return m_Stage >= STAGE_FINALIZED;
3339     }
3340
3341     BOOL NoAccessToHandleTable()
3342     {
3343         LIMITED_METHOD_CONTRACT;
3344         SUPPORTS_DAC;
3345
3346         return m_Stage >= STAGE_HANDLETABLE_NOACCESS;
3347     }
3348
3349     // Checks whether the given thread can enter the app domain
3350     BOOL CanThreadEnter(Thread *pThread);
3351
3352     // Following two are needed for the Holder
3353     static void SetUnloadInProgress(AppDomain *pThis) PUB;
3354     static void SetUnloadComplete(AppDomain *pThis) PUB;
3355     // Predicates for GC asserts
3356     BOOL ShouldHaveFinalization()
3357     {
3358         LIMITED_METHOD_CONTRACT;
3359
3360         return ((DWORD) m_Stage) < STAGE_COLLECTED;
3361     }
3362     BOOL ShouldHaveCode()
3363     {
3364         LIMITED_METHOD_CONTRACT;
3365
3366         return ((DWORD) m_Stage) < STAGE_COLLECTED;
3367     }
3368     BOOL ShouldHaveRoots()
3369     {
3370         LIMITED_METHOD_CONTRACT;
3371
3372         return ((DWORD) m_Stage) < STAGE_CLEARED;
3373     }
3374     BOOL ShouldHaveInstances()
3375     {
3376         LIMITED_METHOD_CONTRACT;
3377
3378         return ((DWORD) m_Stage) < STAGE_COLLECTED;
3379     }
3380
3381
3382     static void RaiseExitProcessEvent();
3383     Assembly* RaiseResourceResolveEvent(DomainAssembly* pAssembly, LPCSTR szName);
3384     DomainAssembly* RaiseTypeResolveEventThrowing(DomainAssembly* pAssembly, LPCSTR szName, ASSEMBLYREF *pResultingAssemblyRef);
3385     Assembly* RaiseAssemblyResolveEvent(AssemblySpec *pSpec, BOOL fIntrospection, BOOL fPreBind);
3386
3387 private:
3388     CrstExplicitInit    m_ReflectionCrst;
3389     CrstExplicitInit    m_RefClassFactCrst;
3390
3391
3392     EEClassFactoryInfoHashTable *m_pRefClassFactHash;   // Hash table that maps a class factory info to a COM comp.
3393 #ifdef FEATURE_COMINTEROP
3394     DispIDCache *m_pRefDispIDCache;
3395     COMorRemotingFlag m_COMorRemotingFlag;
3396     OBJECTHANDLE  m_hndMissing;     //Handle points to Missing.Value Object which is used for [Optional] arg scenario during IDispatch CCW Call
3397
3398     PTR_DomainAssembly m_pSystemDll;                            // System.dll loaded into this domain
3399     PTR_DomainAssembly m_pSystemRuntimeWindowsRuntimeDll;       // System.Runtime.WindowsRuntime.dll loaded into this domain
3400     PTR_DomainAssembly m_pSystemRuntimeWindowsRuntimeUIXamlDll; // System.Runtime.WindowsRuntime.UI.Xaml.dll loaded into this domain
3401     PTR_DomainAssembly m_pSystemNumericsVectors;                // System.Numerics.Vectors.dll loaded into this domain
3402 public:
3403     BOOL FindRedirectedAssemblyFromIndexIfLoaded(WinMDAdapter::FrameworkAssemblyIndex index, Assembly** ppAssembly);
3404
3405     BOOL IsSystemDll(Assembly *pAssembly)
3406     {
3407         LIMITED_METHOD_CONTRACT;
3408         return (m_pSystemDll != NULL && m_pSystemDll->GetCurrentAssembly() == pAssembly);
3409     }
3410 private:
3411     
3412     MethodTable* m_rpCLRTypes[WinMDAdapter::RedirectedTypeIndex_Count];
3413
3414     MethodTable* LoadRedirectedType(WinMDAdapter::RedirectedTypeIndex index, WinMDAdapter::FrameworkAssemblyIndex assembly);
3415 #endif // FEATURE_COMINTEROP
3416
3417 public:
3418
3419     CrstBase *GetRefClassFactCrst()
3420     {
3421         LIMITED_METHOD_CONTRACT;
3422
3423         return &m_RefClassFactCrst;
3424     }
3425
3426 #ifndef DACCESS_COMPILE
3427     EEClassFactoryInfoHashTable* GetClassFactHash()
3428     {
3429         STATIC_CONTRACT_THROWS;
3430         STATIC_CONTRACT_GC_TRIGGERS;
3431         STATIC_CONTRACT_FAULT;
3432
3433         if (m_pRefClassFactHash != NULL) {
3434             return m_pRefClassFactHash;
3435         }
3436
3437         return SetupClassFactHash();
3438     }
3439 #endif // DACCESS_COMPILE
3440
3441 #ifdef FEATURE_COMINTEROP
3442     DispIDCache* GetRefDispIDCache()
3443     {
3444         STATIC_CONTRACT_THROWS;
3445         STATIC_CONTRACT_GC_TRIGGERS;
3446         STATIC_CONTRACT_FAULT;
3447
3448         if (m_pRefDispIDCache != NULL) {
3449             return m_pRefDispIDCache;
3450         }
3451
3452         return SetupRefDispIDCache();
3453     }
3454 #endif // FEATURE_COMINTEROP
3455
3456     PTR_LoaderHeap GetStubHeap();
3457     PTR_LoaderHeap GetLowFrequencyHeap();
3458     PTR_LoaderHeap GetHighFrequencyHeap();
3459     virtual PTR_LoaderAllocator GetLoaderAllocator();
3460
3461 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
3462     #define ARM_ETW_ALLOC_THRESHOLD (4 * 1024 * 1024)
3463     // cache line size in ULONGLONG - 128 bytes which are 16 ULONGLONG's
3464     #define ARM_CACHE_LINE_SIZE_ULL 16
3465
3466     inline ULONGLONG GetAllocBytes()
3467     {
3468         LIMITED_METHOD_CONTRACT;
3469         ULONGLONG ullTotalAllocBytes = 0;
3470
3471         // Ensure that m_pullAllocBytes is non-null to avoid an AV in a race between GC and AD unload.
3472         // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullAllocBytes, causing the AD unload.
3473         if(NULL != m_pullAllocBytes)
3474         {
3475             for (DWORD i = 0; i < m_dwNumHeaps; i++)
3476             {
3477                 ullTotalAllocBytes += m_pullAllocBytes[i * ARM_CACHE_LINE_SIZE_ULL];
3478             }
3479         }
3480         return ullTotalAllocBytes;
3481     }
3482
3483     void RecordAllocBytes(size_t allocatedBytes, DWORD dwHeapNumber)
3484     {
3485         LIMITED_METHOD_CONTRACT;
3486         _ASSERTE(dwHeapNumber < m_dwNumHeaps);
3487         
3488         // Ensure that m_pullAllocBytes is non-null to avoid an AV in a race between GC and AD unload.
3489         // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullAllocBytes, causing the AD unload.
3490         if(NULL != m_pullAllocBytes)
3491         {
3492             m_pullAllocBytes[dwHeapNumber * ARM_CACHE_LINE_SIZE_ULL] += allocatedBytes;
3493         }
3494
3495         ULONGLONG ullTotalAllocBytes = GetAllocBytes();
3496
3497         if ((ullTotalAllocBytes - m_ullLastEtwAllocBytes) >= ARM_ETW_ALLOC_THRESHOLD)
3498         {
3499             m_ullLastEtwAllocBytes = ullTotalAllocBytes;
3500             FireEtwAppDomainMemAllocated((ULONGLONG)this, ullTotalAllocBytes, GetClrInstanceId());
3501         }
3502     }
3503
3504     inline ULONGLONG GetSurvivedBytes()
3505     {
3506         LIMITED_METHOD_CONTRACT;
3507         ULONGLONG ullTotalSurvivedBytes = 0;
3508
3509         // Ensure that m_pullSurvivedBytes is non-null to avoid an AV in a race between GC and AD unload.
3510         // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullSurvivedBytes, causing the AD unload.
3511         if(NULL != m_pullSurvivedBytes)
3512         {
3513             for (DWORD i = 0; i < m_dwNumHeaps; i++)
3514             {
3515                 ullTotalSurvivedBytes += m_pullSurvivedBytes[i * ARM_CACHE_LINE_SIZE_ULL];
3516             }
3517         }
3518         return ullTotalSurvivedBytes;
3519     }
3520
3521     void RecordSurvivedBytes(size_t promotedBytes, DWORD dwHeapNumber)
3522     {
3523         WRAPPER_NO_CONTRACT;
3524         _ASSERTE(dwHeapNumber < m_dwNumHeaps);
3525    
3526         // Ensure that m_pullSurvivedBytes is non-null to avoid an AV in a race between GC and AD unload.
3527         // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullSurvivedBytes, causing the AD unload.
3528         if(NULL != m_pullSurvivedBytes)
3529         {
3530             m_pullSurvivedBytes[dwHeapNumber * ARM_CACHE_LINE_SIZE_ULL] += promotedBytes;
3531         }
3532     }
3533
3534     inline void ResetSurvivedBytes()
3535     {
3536         LIMITED_METHOD_CONTRACT;
3537         
3538         // Ensure that m_pullSurvivedBytes is non-null to avoid an AV in a race between GC and AD unload.
3539         // A race can occur when a new appdomain is created, but an OOM is thrown when allocating for m_pullSurvivedBytes, causing the AD unload.
3540         if(NULL != m_pullSurvivedBytes)
3541         {
3542             for (DWORD i = 0; i < m_dwNumHeaps; i++)
3543             {
3544                 m_pullSurvivedBytes[i * ARM_CACHE_LINE_SIZE_ULL] = 0;
3545             }
3546         }
3547     }
3548
3549     // Return the total processor time (user and kernel) used by threads executing in this AppDomain so far.
3550     // The result is in 100ns units.
3551     ULONGLONG QueryProcessorUsage();
3552
3553     // Add to the current count of processor time used by threads within this AppDomain. This API is called by
3554     // threads transitioning between AppDomains.
3555     void UpdateProcessorUsage(ULONGLONG ullAdditionalUsage);
3556 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
3557
3558 private:
3559     static void RaiseOneExitProcessEvent_Wrapper(AppDomainIterator* pi);
3560     static void RaiseOneExitProcessEvent();
3561     size_t EstimateSize();
3562     EEClassFactoryInfoHashTable* SetupClassFactHash();
3563 #ifdef FEATURE_COMINTEROP
3564     DispIDCache* SetupRefDispIDCache();
3565     COMorRemotingFlag GetPreferComInsteadOfManagedRemotingFromConfigFile();
3566 #endif // FEATURE_COMINTEROP
3567
3568     void InitializeDefaultDomainManager ();
3569
3570 #ifdef FEATURE_CLICKONCE
3571     void InitializeDefaultClickOnceDomain();
3572 #endif // FEATURE_CLICKONCE
3573
3574     void InitializeDefaultDomainSecurity();
3575 public:
3576 #ifdef FEATURE_CLICKONCE
3577     BOOL IsClickOnceAppDomain();
3578 #endif // FEATURE_CLICKONCE
3579
3580 protected:
3581     BOOL PostBindResolveAssembly(AssemblySpec  *pPrePolicySpec,
3582                                  AssemblySpec  *pPostPolicySpec,
3583                                  HRESULT        hrBindResult,
3584                                  AssemblySpec **ppFailedSpec);
3585
3586 #ifdef FEATURE_COMINTEROP
3587 public:
3588     void ReleaseRCWs(LPVOID pCtxCookie);
3589     void DetachRCWs();
3590
3591 protected:
3592 #endif // FEATURE_COMINTEROP
3593
3594     LPWSTR m_pwDynamicDir;
3595
3596 private:
3597     void RaiseLoadingAssemblyEvent(DomainAssembly* pAssembly);
3598
3599     friend class DomainAssembly;
3600
3601 public:
3602     static void ProcessUnloadDomainEventOnFinalizeThread();
3603     static BOOL HasWorkForFinalizerThread()
3604     {
3605         LIMITED_METHOD_CONTRACT;
3606         return s_pAppDomainToRaiseUnloadEvent != NULL;
3607     }
3608
3609 private:
3610     static AppDomain* s_pAppDomainToRaiseUnloadEvent;
3611     static BOOL s_fProcessUnloadDomainEvent;
3612
3613     void RaiseUnloadDomainEvent();
3614     static void RaiseUnloadDomainEvent_Wrapper(LPVOID /* AppDomain * */);
3615
3616     BOOL RaiseUnhandledExceptionEvent(OBJECTREF *pSender, OBJECTREF *pThrowable, BOOL isTerminating);
3617     BOOL HasUnhandledExceptionEventHandler();
3618     BOOL RaiseUnhandledExceptionEventNoThrow(OBJECTREF *pSender, OBJECTREF *pThrowable, BOOL isTerminating);
3619     
3620     struct RaiseUnhandled_Args
3621     {
3622         AppDomain *pExceptionDomain;
3623         AppDomain *pTargetDomain;
3624         OBJECTREF *pSender;
3625         OBJECTREF *pThrowable;
3626         BOOL isTerminating;
3627         BOOL *pResult;
3628     };
3629     #ifndef FEATURE_CORECLR 
3630     static void RaiseUnhandledExceptionEvent_Wrapper(LPVOID /* RaiseUnhandled_Args * */);
3631     #endif
3632
3633
3634     static void AllowThreadEntrance(AppDomain *pApp);
3635     static void RestrictThreadEntrance(AppDomain *pApp);
3636
3637     typedef Holder<AppDomain*,DoNothing<AppDomain*>,AppDomain::AllowThreadEntrance,NULL> RestrictEnterHolder;
3638     
3639     enum Stage {
3640         STAGE_CREATING,
3641         STAGE_READYFORMANAGEDCODE,
3642         STAGE_ACTIVE,
3643         STAGE_OPEN,
3644         STAGE_UNLOAD_REQUESTED,
3645         STAGE_EXITING,
3646         STAGE_EXITED,
3647         STAGE_FINALIZING,
3648         STAGE_FINALIZED,
3649         STAGE_HANDLETABLE_NOACCESS,
3650         STAGE_CLEARED,
3651         STAGE_COLLECTED,
3652         STAGE_CLOSED
3653     };
3654     void SetStage(Stage stage)
3655     {
3656         CONTRACTL
3657         {
3658             NOTHROW;
3659             GC_NOTRIGGER;
3660             SO_TOLERANT;
3661             MODE_ANY;
3662         }
3663         CONTRACTL_END;
3664         STRESS_LOG2(LF_APPDOMAIN, LL_INFO100,"Updating AD stage, ADID=%d, stage=%d\n",GetId().m_dwId,stage);
3665         TESTHOOKCALL(AppDomainStageChanged(GetId().m_dwId,m_Stage,stage));
3666         Stage lastStage=m_Stage;
3667         while (lastStage !=stage) 
3668             lastStage = (Stage)FastInterlockCompareExchange((LONG*)&m_Stage,stage,lastStage);
3669     };
3670     void Exit(BOOL fRunFinalizers, BOOL fAsyncExit);
3671     void Close();
3672     void ClearGCRoots();
3673     void ClearGCHandles();
3674     void HandleAsyncPinHandles();
3675     void UnwindThreads();
3676     // Return TRUE if EE is stopped
3677     // Return FALSE if more work is needed
3678     BOOL StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnloadRequestThread);
3679
3680     // Use Rude Abort to unload the domain.
3681     BOOL m_fRudeUnload;
3682
3683     Thread *m_pUnloadRequestThread;
3684     ADUnloadSink*   m_ADUnloadSink;
3685     BOOL  m_bForceGCOnUnload;
3686     BOOL  m_bUnloadingFromUnloadEvent;
3687     AppDomainLoaderAllocator m_LoaderAllocator;
3688
3689     // List of unloaded LoaderAllocators, protected by code:GetLoaderAllocatorReferencesLock (for now)
3690     LoaderAllocator * m_pDelayedLoaderAllocatorUnloadList;
3691     
3692 public:
3693     
3694     // Register the loader allocator for deletion in code:ShutdownFreeLoaderAllocators.
3695     void RegisterLoaderAllocatorForDeletion(LoaderAllocator * pLoaderAllocator);
3696     
3697     AppDomain * m_pNextInDelayedUnloadList;
3698     
3699     void SetForceGCOnUnload(BOOL bSet)
3700     {
3701         m_bForceGCOnUnload=bSet;
3702     }
3703
3704     void SetUnloadingFromUnloadEvent()
3705     {
3706         m_bUnloadingFromUnloadEvent=TRUE;
3707     }
3708
3709     BOOL IsUnloadingFromUnloadEvent()
3710     {
3711         return m_bUnloadingFromUnloadEvent;
3712     }
3713     
3714     void SetRudeUnload()
3715     {
3716         LIMITED_METHOD_CONTRACT;
3717
3718         m_fRudeUnload = TRUE;
3719     }
3720
3721     BOOL IsRudeUnload()
3722     {
3723         LIMITED_METHOD_CONTRACT;
3724
3725         return m_fRudeUnload;
3726     }
3727
3728     ADUnloadSink* GetADUnloadSink();
3729     ADUnloadSink* GetADUnloadSinkForUnload();
3730     void SetUnloadRequestThread(Thread *pThread)
3731     {
3732         LIMITED_METHOD_CONTRACT;
3733
3734         m_pUnloadRequestThread = pThread;
3735     }
3736
3737     Thread *GetUnloadRequestThread()
3738     {
3739         LIMITED_METHOD_CONTRACT;
3740
3741         return m_pUnloadRequestThread;
3742     }
3743
3744 public:
3745     void SetGCRefPoint(int gccounter)
3746     {
3747         LIMITED_METHOD_CONTRACT;
3748         m_LoaderAllocator.SetGCRefPoint(gccounter);
3749     }
3750     int  GetGCRefPoint()
3751     {
3752         LIMITED_METHOD_CONTRACT;
3753         return m_LoaderAllocator.GetGCRefPoint();
3754     }
3755
3756     static USHORT GetOffsetOfId()
3757     {
3758         LIMITED_METHOD_CONTRACT;
3759         size_t ofs = offsetof(class AppDomain, m_dwId);
3760         _ASSERTE(FitsInI2(ofs));
3761         return (USHORT)ofs;
3762     }
3763
3764     
3765     void AddMemoryPressure();
3766     void RemoveMemoryPressure();
3767     void Unload(BOOL fForceUnload);
3768     static HRESULT UnloadById(ADID Id, BOOL fSync, BOOL fExceptionsPassThrough=FALSE);
3769     static HRESULT UnloadWait(ADID Id, ADUnloadSink* pSink);
3770 #ifdef FEATURE_TESTHOOKS        
3771     static HRESULT UnloadWaitNoCatch(ADID Id, ADUnloadSink* pSink);
3772 #endif
3773     static void ResetUnloadRequestThread(ADID Id);
3774
3775     void UnlinkClass(MethodTable *pMT);
3776
3777     typedef Holder<AppDomain *, AppDomain::SetUnloadInProgress, AppDomain::SetUnloadComplete> UnloadHolder;
3778     Assembly *GetRootAssembly()
3779     {
3780         LIMITED_METHOD_CONTRACT;
3781         return m_pRootAssembly;
3782     }
3783
3784 #ifndef DACCESS_COMPILE
3785     void SetRootAssembly(Assembly *pAssembly)
3786     {
3787         LIMITED_METHOD_CONTRACT;
3788         m_pRootAssembly = pAssembly;
3789     }
3790 #endif
3791
3792 private:
3793     SString         m_friendlyName;
3794     PTR_Assembly    m_pRootAssembly;
3795
3796     // General purpose flags.
3797     DWORD           m_dwFlags;
3798
3799     // When an application domain is created the ref count is artifically incremented
3800     // by one. For it to hit zero an explicit close must have happened.
3801     LONG        m_cRef;                    // Ref count.
3802
3803     PTR_IApplicationSecurityDescriptor m_pSecDesc;  // Application Security Descriptor
3804
3805     OBJECTHANDLE    m_ExposedObject;
3806
3807 #ifdef FEATURE_LOADER_OPTIMIZATION
3808     // Indicates where assemblies will be loaded for
3809     // this domain. By default all assemblies are loaded into the domain.
3810     // There are two additional settings, all
3811     // assemblies can be loaded into the shared domain or assemblies
3812     // that are strong named are loaded into the shared area.
3813     SharePolicy m_SharePolicy;
3814 #endif
3815
3816     IUnknown        *m_pComIPForExposedObject;
3817
3818     // Hash table that maps a clsid to a type
3819     PtrHashMap          m_clsidHash;
3820
3821 #ifdef FEATURE_COMINTEROP
3822     // Hash table that maps WinRT class names to MethodTables.
3823     PTR_NameToTypeMapTable m_pNameToTypeMap;
3824     UINT                m_vNameToTypeMapVersion;
3825
3826     UINT                m_nEpoch; // incremented each time m_pNameToTypeMap is enumerated
3827
3828     // Hash table that remembers the last cached WinRT factory object per type per appdomain.
3829     WinRTFactoryCache   *m_pWinRTFactoryCache;
3830
3831     // The wrapper cache for this domain - it has its own CCacheLineAllocator on a per domain basis
3832     // to allow the domain to go away and eventually kill the memory when all refs are gone
3833     ComCallWrapperCache *m_pComCallWrapperCache;
3834     
3835     // this cache stores the RCWs in this domain
3836     RCWCache *m_pRCWCache;
3837
3838     // this cache stores the RCW -> CCW references in this domain
3839     RCWRefCache *m_pRCWRefCache;
3840     
3841     // The method table used for LicenseInteropHelper
3842     MethodTable*    m_pLicenseInteropHelperMT;
3843 #endif // FEATURE_COMINTEROP
3844
3845     AssemblySink*      m_pAsyncPool;  // asynchronous retrival object pool (only one is kept)
3846
3847     // The index of this app domain among existing app domains (starting from 1)
3848     ADIndex m_dwIndex;
3849
3850     // The thread-pool index of this app domain among existing app domains (starting from 1)
3851     TPIndex m_tpIndex;
3852
3853 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
3854     ULONGLONG* m_pullAllocBytes;
3855     ULONGLONG* m_pullSurvivedBytes;
3856     DWORD m_dwNumHeaps;
3857     ULONGLONG m_ullLastEtwAllocBytes;
3858     // Total processor time (user and kernel) utilized by threads running in this AppDomain so far. May not
3859     // account for threads currently executing in the AppDomain until a call to QueryProcessorUsage() is
3860     // made.
3861     Volatile<ULONGLONG> m_ullTotalProcessorUsage;
3862 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
3863
3864 #ifdef _DEBUG
3865     struct ThreadTrackInfo;
3866     typedef CDynArray<ThreadTrackInfo *> ThreadTrackInfoList;
3867     ThreadTrackInfoList *m_pThreadTrackInfoList;
3868     DWORD m_TrackSpinLock;
3869 #endif
3870
3871
3872     // IL stub cache with fabricated MethodTable parented by a random module in this AD.
3873     ILStubCache         m_ILStubCache;
3874
3875     // U->M thunks created in this domain and not associated with a delegate.
3876     // The cache is keyed by MethodDesc pointers.
3877     UMEntryThunkCache *m_pUMEntryThunkCache;
3878
3879     // The number of  times we have entered this AD
3880     ULONG m_dwThreadEnterCount;
3881     // The number of threads that have entered this AD, for ADU only
3882     ULONG m_dwThreadsStillInAppDomain;
3883
3884     Volatile<Stage> m_Stage;
3885
3886     // The default context for this domain
3887     Context *m_pDefaultContext;
3888
3889     SString         m_applicationBase;
3890     SString         m_privateBinPaths;
3891     SString         m_configFile;
3892
3893     ArrayList        m_failedAssemblies;
3894
3895     DomainAssembly * m_anonymouslyHostedDynamicMethodsAssembly;
3896
3897 #ifdef _DEBUG
3898     Volatile<LONG> m_dwIterHolders;
3899     Volatile<LONG> m_dwRefTakers;
3900     Volatile<LONG> m_dwCreationHolders;
3901 #endif
3902
3903     //
3904     // DAC iterator for failed assembly loads
3905     //
3906     class FailedAssemblyIterator
3907     {
3908         ArrayList::Iterator m_i;
3909         
3910       public:
3911         BOOL Next()
3912         {
3913             WRAPPER_NO_CONTRACT;
3914             return m_i.Next();
3915         }
3916         FailedAssembly *GetFailedAssembly()
3917         {
3918             WRAPPER_NO_CONTRACT;
3919             return dac_cast<PTR_FailedAssembly>(m_i.GetElement());
3920         }
3921         SIZE_T GetIndex()
3922         {
3923             WRAPPER_NO_CONTRACT;
3924             return m_i.GetIndex();
3925         }
3926
3927       private:
3928         friend class AppDomain;
3929         // Cannot have constructor so this iterator can be used inside a union
3930         static FailedAssemblyIterator Create(AppDomain *pDomain)
3931         {
3932             WRAPPER_NO_CONTRACT;
3933             FailedAssemblyIterator i;
3934
3935             i.m_i = pDomain->m_failedAssemblies.Iterate();
3936             return i;
3937         }
3938     };
3939     friend class FailedAssemblyIterator;
3940
3941     FailedAssemblyIterator IterateFailedAssembliesEx()
3942     {
3943         WRAPPER_NO_CONTRACT;
3944         return FailedAssemblyIterator::Create(this);
3945     }
3946
3947     //---------------------------------------------------------
3948     // Stub caches for Method stubs
3949     //---------------------------------------------------------
3950
3951 #ifdef FEATURE_FUSION
3952     void TurnOnBindingRedirects();
3953 #endif
3954 public:
3955
3956 #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
3957 private:
3958     Volatile<BOOL> m_fIsBindingModelLocked;
3959 public:
3960     BOOL IsHostAssemblyResolverInUse();
3961     BOOL IsBindingModelLocked();
3962     BOOL LockBindingModel();
3963 #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
3964
3965     UMEntryThunkCache *GetUMEntryThunkCache();
3966
3967     ILStubCache* GetILStubCache()
3968     {
3969         LIMITED_METHOD_CONTRACT;
3970         return &m_ILStubCache;
3971     }
3972
3973     static AppDomain* GetDomain(ILStubCache* pILStubCache)
3974     {
3975         return CONTAINING_RECORD(pILStubCache, AppDomain, m_ILStubCache);
3976     }
3977
3978     enum {
3979         CONTEXT_INITIALIZED =               0x0001,
3980         USER_CREATED_DOMAIN =               0x0002, // created by call to AppDomain.CreateDomain
3981         ALLOCATEDCOM =                      0x0008,
3982         LOAD_SYSTEM_ASSEMBLY_EVENT_SENT =   0x0040,
3983         REMOTING_CONFIGURED_FOR_DOMAIN =    0x0100,
3984         COMPILATION_DOMAIN =                0x0400, // Are we ngenning?
3985         APP_DOMAIN_CAN_BE_UNLOADED =        0x0800, // if need extra bits, can derive this at runtime
3986         ORPHANED_LOCKS =                    0x1000, // Orphaned locks exist in this appdomain.
3987         PASSIVE_DOMAIN =                    0x2000, // Can we execute code in this AppDomain
3988         VERIFICATION_DOMAIN =               0x4000, // This is a verification domain
3989         ILLEGAL_VERIFICATION_DOMAIN =       0x8000, // This can't be a verification domain
3990         IGNORE_UNHANDLED_EXCEPTIONS =      0x10000, // AppDomain was created using the APPDOMAIN_IGNORE_UNHANDLED_EXCEPTIONS flag
3991         ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP    =      0x20000, // AppDomain was created using the APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP flag
3992 #ifdef MDIL
3993         MDIL_COMPILATION_DOMAIN =         0x040000, // Are we generating MDIL?
3994         MINIMAL_MDIL_COMPILATION_DOMAIN = 0x080000, // Are we generating platform MDIL?
3995         NO_MDIL_COMPILATION_DOMAIN      = 0x100000, // Are we generating a file we believe will fail on the Triton code path
3996 #endif
3997 #ifdef FEATURE_CORECLR
3998         ENABLE_SKIP_PLAT_CHECKS         = 0x200000, // Skip various assembly checks (like platform check)
3999         ENABLE_ASSEMBLY_LOADFILE        = 0x400000, // Allow Assembly.LoadFile in CoreCLR
4000 #endif        
4001     };
4002
4003     SecurityContext *m_pSecContext;
4004
4005     AssemblySpecBindingCache  m_AssemblyCache;
4006     DomainAssemblyCache       m_UnmanagedCache;
4007     size_t                    m_MemoryPressure;
4008
4009     SString m_AppDomainManagerAssembly;
4010     SString m_AppDomainManagerType;
4011     BOOL    m_fAppDomainManagerSetInConfig;
4012     EInitializeNewDomainFlags m_dwAppDomainManagerInitializeDomainFlags;
4013
4014 #ifdef FEATURE_CORECLR 
4015     ArrayList m_NativeDllSearchDirectories;
4016 #endif
4017     BOOL m_ReversePInvokeCanEnter;
4018     bool m_ForceTrivialWaitOperations;
4019     // Section to support AD unload due to escalation
4020 public:
4021     static void CreateADUnloadWorker();
4022
4023     static void CreateADUnloadStartEvent();
4024
4025     static DWORD WINAPI ADUnloadThreadStart(void *args);
4026
4027     // Default is safe unload with test hook
4028     void EnableADUnloadWorker();
4029
4030     // If called to handle stack overflow, we can not set event, since the thread has limit stack.
4031     void EnableADUnloadWorker(EEPolicy::AppDomainUnloadTypes type, BOOL fHasStack = TRUE);
4032
4033     static void EnableADUnloadWorkerForThreadAbort();
4034     static void EnableADUnloadWorkerForFinalizer();
4035     static void EnableADUnloadWorkerForCollectedADCleanup();
4036
4037     BOOL IsUnloadRequested()
4038     {
4039         LIMITED_METHOD_CONTRACT;
4040
4041         return (m_Stage == STAGE_UNLOAD_REQUESTED);
4042     }
4043
4044 #ifdef FEATURE_CORECLR
4045     BOOL IsImageFromTrustedPath(PEImage* pImage);
4046     BOOL IsImageFullyTrusted(PEImage* pImage);
4047 #endif
4048
4049 #ifdef FEATURE_TYPEEQUIVALENCE
4050 private:
4051     VolatilePtr<TypeEquivalenceHashTable> m_pTypeEquivalenceTable;
4052     CrstExplicitInit m_TypeEquivalenceCrst;
4053 public:
4054     TypeEquivalenceHashTable * GetTypeEquivalenceCache();
4055 #endif
4056
4057     private:
4058     static void ADUnloadWorkerHelper(AppDomain *pDomain);
4059     static CLREvent * g_pUnloadStartEvent;
4060
4061 #ifdef DACCESS_COMPILE
4062 public:
4063     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
4064                                    bool enumThis);
4065 #endif
4066
4067 #ifdef FEATURE_MULTICOREJIT
4068
4069 private:
4070     MulticoreJitManager m_MulticoreJitManager;
4071
4072 public:
4073     MulticoreJitManager & GetMulticoreJitManager()
4074     {
4075         LIMITED_METHOD_CONTRACT;
4076
4077         return m_MulticoreJitManager;
4078     }
4079
4080 #endif
4081
4082 #ifdef FEATURE_COMINTEROP
4083
4084 private:
4085 #ifdef FEATURE_REFLECTION_ONLY_LOAD
4086     // ReflectionOnly WinRT binder and its TypeCache (only in classic = non-AppX; the scenario is not supported in AppX)
4087     CLRPrivBinderReflectionOnlyWinRT *    m_pReflectionOnlyWinRtBinder;
4088     CLRPrivTypeCacheReflectionOnlyWinRT * m_pReflectionOnlyWinRtTypeCache;
4089 #endif // FEATURE_REFLECTION_ONLY_LOAD
4090
4091 #endif //FEATURE_COMINTEROP
4092
4093 public:
4094 #ifndef FEATURE_CORECLR
4095     BOOL m_bUseOsSorting;
4096     DWORD m_sortVersion;
4097     COMNlsCustomSortLibrary *m_pCustomSortLibrary;
4098 #if _DEBUG
4099     BOOL m_bSortingInitialized;
4100 #endif // _DEBUG
4101     COMNlsHashProvider *m_pNlsHashProvider;
4102 #endif // !FEATURE_CORECLR
4103
4104 #ifdef FEATURE_HOSTED_BINDER
4105 private:
4106     // This is the root-level default load context root binder. If null, then
4107     // the Fusion binder is used; otherwise this binder is used.
4108     ReleaseHolder<ICLRPrivBinder> m_pLoadContextHostBinder;
4109
4110     // -------------------------
4111     // IMPORTANT!
4112     // The shared and designer context binders are ONLY to be used in tool
4113     // scenarios. There are known issues where use of these binders will
4114     // cause application crashes, and interesting behaviors.
4115     // -------------------------
4116     
4117     // This is the default designer shared context root binder.
4118     // This is used as the parent binder for ImmersiveDesignerContextBinders
4119     ReleaseHolder<ICLRPrivBinder> m_pSharedContextHostBinder;
4120
4121     // This is the current context root binder.
4122     // Normally, this variable is immutable for appdomain lifetime, but in designer scenarios
4123     // it may be replaced by designer context binders
4124     Volatile<ICLRPrivBinder *>    m_pCurrentContextHostBinder;
4125
4126 public:
4127     // Returns the current hosted binder, or null if none available.
4128     inline
4129     ICLRPrivBinder * GetCurrentLoadContextHostBinder() const
4130     {
4131         LIMITED_METHOD_CONTRACT;
4132         return m_pCurrentContextHostBinder;
4133     }
4134
4135     // Returns the shared context binder, or null if none available.
4136     inline
4137     ICLRPrivBinder * GetSharedContextHostBinder() const
4138     {
4139         LIMITED_METHOD_CONTRACT;
4140         return m_pSharedContextHostBinder;
4141     }
4142
4143     // Returns the load context binder, or null if none available.
4144     inline
4145     ICLRPrivBinder * GetLoadContextHostBinder() const
4146     {
4147         LIMITED_METHOD_CONTRACT;
4148         return m_pLoadContextHostBinder;
4149     }
4150
4151 #ifndef DACCESS_COMPILE
4152
4153     // This is only called from the ImmersiveDesignerContext code
4154     // It is protected with a managed monitor lock
4155     inline
4156     void SetSharedContextHostBinder(ICLRPrivBinder * pBinder)
4157     {
4158         LIMITED_METHOD_CONTRACT;
4159         pBinder->AddRef();
4160         m_pSharedContextHostBinder = pBinder;
4161     }
4162
4163     // This is called from CorHost2's implementation of ICLRPrivRuntime::CreateAppDomain.
4164     // Should only be called during AppDomain creation.
4165     inline
4166     void SetLoadContextHostBinder(ICLRPrivBinder * pBinder)
4167     {
4168         LIMITED_METHOD_CONTRACT;
4169         pBinder->AddRef();
4170         m_pLoadContextHostBinder = m_pCurrentContextHostBinder = pBinder;
4171     }
4172
4173     inline
4174     void SetCurrentContextHostBinder(ICLRPrivBinder * pBinder)
4175     {
4176         CONTRACTL
4177         {
4178             THROWS;
4179             GC_TRIGGERS;
4180         }
4181         CONTRACTL_END;
4182
4183         LockHolder lh(this);
4184
4185 #ifdef FEATURE_COMINTEROP
4186         if (m_pNameToTypeMap != nullptr)
4187         {
4188             delete m_pNameToTypeMap;
4189             m_pNameToTypeMap = nullptr;
4190         }
4191
4192         m_vNameToTypeMapVersion++;
4193 #endif
4194
4195         m_pCurrentContextHostBinder = pBinder;
4196     }
4197
4198 #endif // DACCESS_COMPILE
4199
4200     // Indicates that a hosted binder is present.
4201     inline
4202     bool HasLoadContextHostBinder()
4203     {
4204         LIMITED_METHOD_CONTRACT;
4205         return m_pLoadContextHostBinder != nullptr;
4206     }
4207
4208     class ComInterfaceReleaseList
4209     {
4210         SArray<IUnknown *> m_objects;
4211     public:
4212         ~ComInterfaceReleaseList()
4213         {
4214             WRAPPER_NO_CONTRACT;
4215
4216             for (COUNT_T i = 0; i < m_objects.GetCount(); i++)
4217             {
4218                 IUnknown *pItf = *(m_objects.GetElements() + i);
4219                 if (pItf != nullptr)
4220                     pItf->Release();
4221             }
4222         }
4223
4224         // Append to the list of object to free. Only use under the AppDomain "LockHolder(pAppDomain)"
4225         void Append(IUnknown *pInterfaceToRelease)
4226         {
4227             WRAPPER_NO_CONTRACT;
4228             m_objects.Append(pInterfaceToRelease);
4229         }
4230     } AppDomainInterfaceReleaseList;
4231
4232 private:
4233     //-----------------------------------------------------------
4234     // Static ICLRPrivAssembly -> DomainAssembly mapping functions.
4235     // This map does not maintain a reference count to either key or value.
4236     // PEFile maintains a reference count on the ICLRPrivAssembly through its code:PEFile::m_pHostAssembly field.
4237     // It is removed from this hash table by code:DomainAssembly::~DomainAssembly.
4238     struct HostAssemblyHashTraits : public DefaultSHashTraits<PTR_DomainAssembly>
4239     {
4240     public:
4241         typedef PTR_ICLRPrivAssembly key_t;
4242         
4243         static key_t GetKey(element_t const & elem)
4244         {
4245             STATIC_CONTRACT_WRAPPER;
4246             return elem->GetFile()->GetHostAssembly();
4247         }
4248         
4249         static BOOL Equals(key_t key1, key_t key2) 
4250         {
4251             LIMITED_METHOD_CONTRACT;
4252             return dac_cast<TADDR>(key1) == dac_cast<TADDR>(key2);
4253         }
4254         
4255         static count_t Hash(key_t key)
4256         {
4257             STATIC_CONTRACT_LIMITED_METHOD;
4258             //return reinterpret_cast<count_t>(dac_cast<TADDR>(key));
4259             return (count_t)(dac_cast<TADDR>(key));
4260         }
4261         
4262         static const element_t Null() { return NULL; }
4263         static const element_t Deleted() { return (element_t)(TADDR)-1; }
4264         static bool IsNull(const element_t & e) { return e == NULL; }
4265         static bool IsDeleted(const element_t & e) { return dac_cast<TADDR>(e) == (TADDR)-1; }
4266     };
4267
4268     struct OriginalFileHostAssemblyHashTraits : public HostAssemblyHashTraits
4269     {
4270     public:
4271         static key_t GetKey(element_t const & elem)
4272         {
4273             STATIC_CONTRACT_WRAPPER;
4274             return elem->GetOriginalFile()->GetHostAssembly();
4275         }
4276     };
4277     
4278     typedef SHash<HostAssemblyHashTraits> HostAssemblyMap;
4279     typedef SHash<OriginalFileHostAssemblyHashTraits> OriginalFileHostAssemblyMap;
4280     HostAssemblyMap   m_hostAssemblyMap;
4281     OriginalFileHostAssemblyMap   m_hostAssemblyMapForOrigFile;
4282     CrstExplicitInit  m_crstHostAssemblyMap;
4283     // Lock to serialize all Add operations (in addition to the "read-lock" above)
4284     CrstExplicitInit  m_crstHostAssemblyMapAdd;
4285
4286 public:
4287     // Returns DomainAssembly.
4288     PTR_DomainAssembly FindAssembly(PTR_ICLRPrivAssembly pHostAssembly);
4289     
4290 #ifndef DACCESS_COMPILE
4291 private:
4292     friend void DomainAssembly::Allocate();
4293     friend DomainAssembly::~DomainAssembly();
4294
4295     // Called from DomainAssembly::Begin.
4296     void PublishHostedAssembly(
4297         DomainAssembly* pAssembly);
4298
4299     // Called from DomainAssembly::UpdatePEFile.
4300     void UpdatePublishHostedAssembly(
4301         DomainAssembly* pAssembly,
4302         PTR_PEFile pFile);
4303
4304     // Called from DomainAssembly::~DomainAssembly
4305     void UnPublishHostedAssembly(
4306         DomainAssembly* pAssembly);
4307 #endif // DACCESS_COMPILE
4308
4309 #endif //FEATURE_HOSTED_BINDER
4310 #ifdef FEATURE_PREJIT
4311     friend void DomainFile::InsertIntoDomainFileWithNativeImageList();
4312     Volatile<DomainFile *> m_pDomainFileWithNativeImageList;
4313 public:
4314     DomainFile *GetDomainFilesWithNativeImagesList()
4315     {
4316         LIMITED_METHOD_CONTRACT;
4317         return m_pDomainFileWithNativeImageList;
4318     }
4319 #endif
4320 };  // class AppDomain
4321
4322
4323 // This holder is to be used to take a reference to make sure AppDomain* is still valid
4324 // Please do not use if you are aleady ADU-safe
4325 typedef Wrapper<AppDomain*,AppDomain::RefTakerAcquire,AppDomain::RefTakerRelease,NULL> AppDomainRefTaker;
4326
4327 // Just a ref holder
4328 typedef ReleaseHolder<AppDomain> AppDomainRefHolder;
4329
4330 // This class provides a way to access AppDomain by ID
4331 // without risking the appdomain getting invalid in the process
4332 class AppDomainFromIDHolder
4333 {
4334 public:
4335     enum SyncType  
4336     {
4337         SyncType_GC,     // Prevents AD from being unloaded by forbidding GC for the lifetime of the object
4338         SyncType_ADLock  // Prevents AD from being unloaded by requiring ownership of DomainLock for the lifetime of the object
4339     };
4340 protected:    
4341     AppDomain* m_pDomain;
4342 #ifdef _DEBUG    
4343     BOOL       m_bAcquired;
4344     BOOL       m_bChecked;
4345     SyncType   m_type;
4346 #endif
4347 public:
4348     DEBUG_NOINLINE AppDomainFromIDHolder(ADID adId, BOOL bUnsafePoint, SyncType synctype=SyncType_GC);
4349     DEBUG_NOINLINE AppDomainFromIDHolder(SyncType synctype=SyncType_GC);
4350     DEBUG_NOINLINE ~AppDomainFromIDHolder();
4351
4352         void* GetAddress() { return m_pDomain; }        // Used to get an identfier for ETW
4353     void Assign(ADID adId, BOOL bUnsafePoint);
4354     void ThrowIfUnloaded();
4355     void Release();
4356     BOOL IsUnloaded() 
4357     {
4358         LIMITED_METHOD_CONTRACT;
4359 #ifdef _DEBUG
4360         m_bChecked=TRUE; 
4361         if (m_pDomain==NULL)
4362         {
4363             // no need to enforce anything
4364             Release(); 
4365         }
4366 #endif
4367         return m_pDomain==NULL;
4368     };
4369     AppDomain* operator->();
4370 };  // class AppDomainFromIDHolder
4371
4372
4373
4374 typedef VPTR(class SystemDomain) PTR_SystemDomain;
4375
4376 class SystemDomain : public BaseDomain
4377 {
4378     friend class AppDomainNative;
4379     friend class AppDomainIterator;
4380     friend class UnsafeAppDomainIterator;
4381     friend class ClrDataAccess;
4382     friend class AppDomainFromIDHolder;
4383     friend Frame *Thread::IsRunningIn(AppDomain* pDomain, int *count);
4384
4385     VPTR_VTABLE_CLASS(SystemDomain, BaseDomain)
4386     VPTR_UNIQUE(VPTR_UNIQUE_SystemDomain)
4387     static AppDomain *GetAppDomainAtId(ADID indx);
4388
4389 public:  
4390     static PTR_LoaderAllocator GetGlobalLoaderAllocator();
4391     virtual PTR_LoaderAllocator GetLoaderAllocator() { WRAPPER_NO_CONTRACT; return GetGlobalLoaderAllocator(); }
4392     static AppDomain* GetAppDomainFromId(ADID indx,DWORD ADValidityKind)
4393     {
4394         CONTRACTL
4395         {
4396             NOTHROW;
4397             GC_NOTRIGGER;
4398             MODE_COOPERATIVE;
4399         }
4400         CONTRACTL_END;
4401         AppDomain* pRetVal;
4402         if (indx.m_dwId==DefaultADID)
4403             pRetVal= SystemDomain::System()->DefaultDomain();
4404         else
4405             pRetVal= GetAppDomainAtId(indx);
4406 #ifdef _DEBUG
4407         // Only call CheckADValidity in DEBUG builds for non-NULL return values
4408         if (pRetVal != NULL)
4409             CheckADValidity(pRetVal, ADValidityKind);
4410 #endif        
4411         return pRetVal;
4412     }
4413     //****************************************************************************************
4414     //
4415     // To be run during the initial start up of the EE. This must be
4416     // performed prior to any class operations.
4417     static void Attach();
4418
4419     //****************************************************************************************
4420     //
4421     // To be run during shutdown. This must be done after all operations
4422     // that require the use of system classes (i.e., exceptions).
4423     // DetachBegin stops all domains, while DetachEnd deallocates domain resources.
4424     static void DetachBegin();
4425
4426     //****************************************************************************************
4427     //
4428     // To be run during shutdown. This must be done after all operations
4429     // that require the use of system classes (i.e., exceptions).
4430     // DetachBegin stops release resources held by systemdomain and the default domain.
4431     static void DetachEnd();
4432
4433     //****************************************************************************************
4434     //
4435     // Initializes and shutdowns the single instance of the SystemDomain
4436     // in the EE
4437 #ifndef DACCESS_COMPILE
4438     void *operator new(size_t size, void *pInPlace);
4439     void operator delete(void *pMem);
4440 #endif
4441     void Init();
4442     void Stop();
4443     void Terminate();
4444     static void LazyInitGlobalStringLiteralMap();
4445
4446     //****************************************************************************************
4447     //
4448     // Load the base system classes, these classes are required before
4449     // any other classes are loaded
4450     void LoadBaseSystemClasses();
4451
4452     AppDomain* DefaultDomain()
4453     {
4454         LIMITED_METHOD_DAC_CONTRACT;
4455
4456         return m_pDefaultDomain;
4457     }
4458
4459     // Notification when an assembly is loaded into the system domain
4460     void OnAssemblyLoad(Assembly *assem);
4461
4462     //****************************************************************************************
4463     //
4464     // Global Static to get the one and only system domain
4465     static SystemDomain * System()
4466     {
4467         LIMITED_METHOD_DAC_CONTRACT;
4468
4469         return m_pSystemDomain;
4470     }
4471
4472     static PEAssembly* SystemFile()
4473     {
4474         WRAPPER_NO_CONTRACT;
4475
4476         _ASSERTE(m_pSystemDomain);
4477         return System()->m_pSystemFile;
4478     }
4479
4480     static Assembly* SystemAssembly()
4481     {
4482         WRAPPER_NO_CONTRACT;
4483
4484         return System()->m_pSystemAssembly;
4485     }
4486
4487     static Module* SystemModule()
4488     {
4489         WRAPPER_NO_CONTRACT;
4490
4491         return SystemAssembly()->GetManifestModule();
4492     }
4493
4494     static BOOL IsSystemLoaded()
4495     {
4496         WRAPPER_NO_CONTRACT;
4497
4498         return System()->m_pSystemAssembly != NULL;
4499     }
4500
4501 #ifndef DACCESS_COMPILE
4502     static GlobalStringLiteralMap *GetGlobalStringLiteralMap()
4503     {
4504         WRAPPER_NO_CONTRACT;
4505
4506         if (m_pGlobalStringLiteralMap == NULL)
4507         {
4508             SystemDomain::LazyInitGlobalStringLiteralMap();
4509         }
4510         _ASSERTE(m_pGlobalStringLiteralMap);
4511         return m_pGlobalStringLiteralMap;
4512     }
4513     static GlobalStringLiteralMap *GetGlobalStringLiteralMapNoCreate()
4514     {
4515         LIMITED_METHOD_CONTRACT;
4516
4517         _ASSERTE(m_pGlobalStringLiteralMap);
4518         return m_pGlobalStringLiteralMap;
4519     }
4520 #endif // DACCESS_COMPILE
4521
4522 #ifndef FEATURE_CORECLR    
4523     static void ExecuteMainMethod(HMODULE hMod, __in_opt LPWSTR path = NULL);
4524 #endif
4525     static void ActivateApplication(int *pReturnValue);
4526
4527     static void InitializeDefaultDomain(
4528         BOOL allowRedirects
4529 #ifdef FEATURE_HOSTED_BINDER
4530         , ICLRPrivBinder * pBinder = NULL
4531 #endif
4532         );
4533     static void SetupDefaultDomain();
4534     static HRESULT SetupDefaultDomainNoThrow();
4535
4536 #if defined(FEATURE_COMINTEROP_APARTMENT_SUPPORT) && !defined(CROSSGEN_COMPILE)
4537     static Thread::ApartmentState GetEntryPointThreadAptState(IMDInternalImport* pScope, mdMethodDef mdMethod);
4538     static void SetThreadAptState(IMDInternalImport* pScope, Thread::ApartmentState state);
4539 #endif
4540     static BOOL SetGlobalSharePolicyUsingAttribute(IMDInternalImport* pScope, mdMethodDef mdMethod);
4541
4542 #ifdef FEATURE_MIXEDMODE
4543     static HRESULT RunDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved);
4544 #endif // FEATURE_MIXEDMODE
4545
4546     //****************************************************************************************
4547     //
4548     // Use an already exising & inited Application Domain (e.g. a subclass).
4549     static void LoadDomain(AppDomain     *pDomain);
4550
4551 #ifndef DACCESS_COMPILE
4552     static void MakeUnloadable(AppDomain* pApp)
4553     {
4554         WRAPPER_NO_CONTRACT;
4555         System()->AddDomain(pApp);
4556         pApp->SetCanUnload();
4557     }
4558 #endif // DACCESS_COMPILE
4559
4560     //****************************************************************************************
4561     // Methods used to get the callers module and hence assembly and app domain.
4562     __declspec(deprecated("This method is deprecated, use the version that takes a StackCrawlMark instead"))
4563     static Module* GetCallersModule(int skip);
4564     static MethodDesc* GetCallersMethod(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
4565     static MethodTable* GetCallersType(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
4566     static Module* GetCallersModule(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
4567     static Assembly* GetCallersAssembly(StackCrawlMark* stackMark, AppDomain **ppAppDomain = NULL);
4568
4569     static bool IsReflectionInvocationMethod(MethodDesc* pMeth);
4570
4571 #ifndef DACCESS_COMPILE
4572     //****************************************************************************************
4573     // Returns the domain associated with the current context. (this can only be a child domain)
4574     static inline AppDomain * GetCurrentDomain()
4575     {
4576         WRAPPER_NO_CONTRACT;
4577         return ::GetAppDomain();
4578     }
4579 #endif //!DACCESS_COMPILE
4580
4581 #ifdef DEBUGGING_SUPPORTED
4582     //****************************************************************************************
4583     // Debugger/Publisher helper function to indicate creation of new app domain to debugger
4584     // and publishing it in the IPC block
4585     static void PublishAppDomainAndInformDebugger (AppDomain *pDomain);
4586 #endif // DEBUGGING_SUPPORTED
4587
4588     //****************************************************************************************
4589     // Helper function to remove a domain from the system
4590     BOOL RemoveDomain(AppDomain* pDomain); // Does not decrement the reference
4591
4592 #ifdef PROFILING_SUPPORTED
4593     //****************************************************************************************
4594     // Tell profiler about system created domains which are created before the profiler is
4595     // actually activated.
4596     static void NotifyProfilerStartup();
4597
4598     //****************************************************************************************
4599     // Tell profiler at shutdown that system created domains are going away.  They are not
4600     // torn down using the normal sequence.
4601     static HRESULT NotifyProfilerShutdown();
4602 #endif // PROFILING_SUPPORTED
4603
4604     IApplicationSecurityDescriptor* GetSecurityDescriptor()
4605     {
4606         LIMITED_METHOD_CONTRACT;
4607
4608         return NULL;
4609     }
4610
4611     //****************************************************************************************
4612     // return the dev path
4613 #ifdef FEATURE_FUSION    
4614     void GetDevpathW(__out_ecount_opt(1) LPWSTR* pPath, DWORD* pSize);
4615 #endif
4616
4617 #ifndef DACCESS_COMPILE
4618     void IncrementNumAppDomains ()
4619     {
4620         LIMITED_METHOD_CONTRACT;
4621
4622         s_dNumAppDomains++;
4623     }
4624
4625     void DecrementNumAppDomains ()
4626     {
4627         LIMITED_METHOD_CONTRACT;
4628
4629         s_dNumAppDomains--;
4630     }
4631
4632     ULONG GetNumAppDomains ()
4633     {
4634         LIMITED_METHOD_CONTRACT;
4635
4636         return s_dNumAppDomains;
4637     }
4638 #endif // DACCESS_COMPILE
4639
4640     //
4641     // AppDomains currently have both an index and an ID.  The
4642     // index is "densely" assigned; indices are reused as domains
4643     // are unloaded.  The Id's on the other hand, are not reclaimed
4644     // so may be sparse.
4645     //
4646     // Another important difference - it's OK to call GetAppDomainAtId for
4647     // an unloaded domain (it will return NULL), while GetAppDomainAtIndex
4648     // will assert if the domain is unloaded.
4649     //<TODO>
4650     // @todo:
4651     // I'm not really happy with this situation, but
4652     //  (a) we need an ID for a domain which will last the process lifetime for the
4653     //      remoting code.
4654     //  (b) we need a dense ID, for the handle table index.
4655     // So for now, I'm leaving both, but hopefully in the future we can come up
4656     // with something better.
4657     //</TODO>
4658
4659     static ADIndex GetNewAppDomainIndex(AppDomain * pAppDomain);
4660     static void ReleaseAppDomainIndex(ADIndex indx);
4661     static PTR_AppDomain GetAppDomainAtIndex(ADIndex indx);
4662     static PTR_AppDomain TestGetAppDomainAtIndex(ADIndex indx);
4663     static DWORD GetCurrentAppDomainMaxIndex()
4664     {
4665         WRAPPER_NO_CONTRACT;
4666
4667         ArrayListStatic* list = (ArrayListStatic *)&m_appDomainIndexList;
4668         PREFIX_ASSUME(list!=NULL);
4669         return list->GetCount();
4670     }
4671
4672     static ADID GetNewAppDomainId(AppDomain *pAppDomain);
4673     static void ReleaseAppDomainId(ADID indx);
4674     
4675 #ifndef DACCESS_COMPILE
4676     static ADID GetCurrentAppDomainMaxId() { ADID id; id.m_dwId=m_appDomainIdList.GetCount(); return id;}
4677 #endif // DACCESS_COMPILE
4678
4679
4680 #ifndef DACCESS_COMPILE
4681     DWORD RequireAppDomainCleanup()
4682     {
4683         LIMITED_METHOD_CONTRACT;
4684         return m_pDelayedUnloadList != 0 || m_pDelayedUnloadListOfLoaderAllocators != 0;
4685     }
4686
4687     void AddToDelayedUnloadList(AppDomain* pDomain, BOOL bAsync)
4688     {
4689         CONTRACTL
4690         {
4691             NOTHROW;
4692             GC_NOTRIGGER;
4693             MODE_COOPERATIVE;
4694         }
4695         CONTRACTL_END;
4696         m_UnloadIsAsync = bAsync;
4697         
4698         CrstHolder lh(&m_DelayedUnloadCrst);
4699         pDomain->m_pNextInDelayedUnloadList=m_pDelayedUnloadList;
4700         m_pDelayedUnloadList=pDomain;
4701         if (m_UnloadIsAsync)
4702         {
4703             pDomain->AddRef();
4704             int iGCRefPoint=GCHeap::GetGCHeap()->CollectionCount(GCHeap::GetGCHeap()->GetMaxGeneration());
4705             if (GCHeap::GetGCHeap()->IsGCInProgress())
4706                 iGCRefPoint++;
4707             pDomain->SetGCRefPoint(iGCRefPoint);
4708         }
4709     }
4710
4711     void AddToDelayedUnloadList(LoaderAllocator * pAllocator)
4712     {
4713         CONTRACTL
4714         {
4715             NOTHROW;
4716             GC_NOTRIGGER;
4717             MODE_COOPERATIVE;
4718         }
4719         CONTRACTL_END;
4720
4721         CrstHolder lh(&m_DelayedUnloadCrst);
4722         pAllocator->m_pLoaderAllocatorDestroyNext=m_pDelayedUnloadListOfLoaderAllocators;
4723         m_pDelayedUnloadListOfLoaderAllocators=pAllocator;
4724
4725         int iGCRefPoint=GCHeap::GetGCHeap()->CollectionCount(GCHeap::GetGCHeap()->GetMaxGeneration());
4726         if (GCHeap::GetGCHeap()->IsGCInProgress())
4727             iGCRefPoint++;
4728         pAllocator->SetGCRefPoint(iGCRefPoint);
4729     }
4730
4731     void ClearCollectedDomains();
4732     void ProcessClearingDomains();
4733     void ProcessDelayedUnloadDomains();
4734     
4735     static void SetUnloadInProgress(AppDomain *pDomain)
4736     {
4737         WRAPPER_NO_CONTRACT;
4738
4739         _ASSERTE(m_pAppDomainBeingUnloaded == NULL);
4740         m_pAppDomainBeingUnloaded = pDomain;
4741         m_dwIndexOfAppDomainBeingUnloaded = pDomain->GetIndex();
4742     }
4743
4744     static void SetUnloadDomainCleared()
4745     {
4746         LIMITED_METHOD_CONTRACT;
4747
4748         // about to delete, so clear this pointer so nobody uses it
4749         m_pAppDomainBeingUnloaded = NULL;
4750     }
4751     static void SetUnloadComplete()
4752     {
4753         LIMITED_METHOD_CONTRACT;
4754
4755         // should have already cleared the AppDomain* prior to delete
4756         // either we succesfully unloaded and cleared or we failed and restored the ID
4757         _ASSERTE(m_pAppDomainBeingUnloaded == NULL && m_dwIndexOfAppDomainBeingUnloaded.m_dwIndex != 0
4758             || m_pAppDomainBeingUnloaded && SystemDomain::GetAppDomainAtId(m_pAppDomainBeingUnloaded->GetId()) != NULL);
4759         m_pAppDomainBeingUnloaded = NULL;
4760         m_pAppDomainUnloadingThread = NULL;
4761     }
4762
4763     static AppDomain *AppDomainBeingUnloaded()
4764     {
4765         LIMITED_METHOD_CONTRACT;
4766         return m_pAppDomainBeingUnloaded;
4767     }
4768
4769     static ADIndex IndexOfAppDomainBeingUnloaded()
4770     {
4771         LIMITED_METHOD_CONTRACT;
4772         return m_dwIndexOfAppDomainBeingUnloaded;
4773     }
4774
4775     static void SetUnloadRequestingThread(Thread *pRequestingThread)
4776     {
4777         LIMITED_METHOD_CONTRACT;
4778         m_pAppDomainUnloadRequestingThread = pRequestingThread;
4779     }
4780
4781     static Thread *GetUnloadRequestingThread()
4782     {
4783         LIMITED_METHOD_CONTRACT;
4784         return m_pAppDomainUnloadRequestingThread;
4785     }
4786
4787     static void SetUnloadingThread(Thread *pUnloadingThread)
4788     {
4789         LIMITED_METHOD_CONTRACT;
4790         m_pAppDomainUnloadingThread = pUnloadingThread;
4791     }
4792
4793     static Thread *GetUnloadingThread()
4794     {
4795         LIMITED_METHOD_CONTRACT;
4796         return m_pAppDomainUnloadingThread;
4797     }
4798
4799     static void EnumAllStaticGCRefs(promote_func* fn, ScanContext* sc);
4800
4801 #endif // DACCESS_COMPILE
4802
4803 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
4804     // The *AD* methods are what we got from tracing through EE roots.
4805     // RecordTotalSurvivedBytes is the total promoted from a GC.
4806     static void ResetADSurvivedBytes();
4807     static ULONGLONG GetADSurvivedBytes();
4808     static void RecordTotalSurvivedBytes(size_t totalSurvivedBytes);
4809     static ULONGLONG GetTotalSurvivedBytes()
4810     {
4811         LIMITED_METHOD_CONTRACT;
4812         return m_totalSurvivedBytes;
4813     }
4814 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
4815
4816     //****************************************************************************************
4817     // Routines to deal with the base library (currently mscorlib.dll)
4818     LPCWSTR BaseLibrary()
4819     {
4820         WRAPPER_NO_CONTRACT;
4821
4822         return m_BaseLibrary;
4823     }
4824
4825 #ifndef DACCESS_COMPILE
4826     BOOL IsBaseLibrary(SString &path)
4827     {
4828         WRAPPER_NO_CONTRACT;
4829
4830         // See if it is the installation path to mscorlib
4831         if (path.EqualsCaseInsensitive(m_BaseLibrary, PEImage::GetFileSystemLocale()))
4832             return TRUE;
4833
4834         // Or, it might be the GAC location of mscorlib
4835         if (System()->SystemAssembly() != NULL
4836             && path.EqualsCaseInsensitive(System()->SystemAssembly()->GetManifestFile()->GetPath(),
4837                                           PEImage::GetFileSystemLocale()))
4838             return TRUE;
4839
4840         return FALSE;
4841     }
4842
4843     BOOL IsBaseLibrarySatellite(SString &path)
4844     {
4845         WRAPPER_NO_CONTRACT;
4846
4847         // See if it is the installation path to mscorlib.resources
4848         SString s(SString::Ascii,g_psBaseLibrarySatelliteAssemblyName);
4849         if (path.EqualsCaseInsensitive(s, PEImage::GetFileSystemLocale()))
4850             return TRUE;
4851
4852         // workaround!  Must implement some code to do this string comparison for
4853         // mscorlib.resources in a culture-specific directory in the GAC.
4854
4855         /*
4856         // Or, it might be the GAC location of mscorlib.resources
4857         if (System()->SystemAssembly() != NULL
4858             && path.EqualsCaseInsensitive(System()->SystemAssembly()->GetManifestFile()->GetPath(),
4859                                           PEImage::GetFileSystemLocale()))
4860             return TRUE;
4861         */
4862
4863         return FALSE;
4864     }
4865 #endif // DACCESS_COMPILE
4866
4867     // Return the system directory
4868     LPCWSTR SystemDirectory()
4869     {
4870         WRAPPER_NO_CONTRACT;
4871
4872         return m_SystemDirectory;
4873     }
4874
4875 private:
4876
4877     //****************************************************************************************
4878     // Helper function to create the single COM domain
4879     void CreateDefaultDomain();
4880
4881     //****************************************************************************************
4882     // Helper function to add a domain to the global list
4883     void AddDomain(AppDomain* pDomain);
4884
4885     void CreatePreallocatedExceptions();
4886
4887     void PreallocateSpecialObjects();
4888
4889     //****************************************************************************************
4890     //
4891     static StackWalkAction CallersMethodCallback(CrawlFrame* pCrawlFrame, VOID* pClientData);
4892     static StackWalkAction CallersMethodCallbackWithStackMark(CrawlFrame* pCrawlFrame, VOID* pClientData);
4893
4894 #ifndef DACCESS_COMPILE
4895     // This class is not to be created through normal allocation.
4896     SystemDomain() 
4897     {
4898         STANDARD_VM_CONTRACT;
4899
4900         m_pDefaultDomain = NULL;
4901         m_pDelayedUnloadList=NULL;
4902         m_pDelayedUnloadListOfLoaderAllocators=NULL;
4903         m_UnloadIsAsync = FALSE;
4904
4905         m_GlobalAllocator.Init(this);
4906     }
4907 #endif
4908
4909     PTR_PEAssembly  m_pSystemFile;      // Single assembly (here for quicker reference);
4910     PTR_Assembly    m_pSystemAssembly;  // Single assembly (here for quicker reference);
4911     PTR_AppDomain   m_pDefaultDomain;   // Default domain for COM+ classes exposed through IClassFactory.
4912
4913     GlobalLoaderAllocator m_GlobalAllocator;
4914
4915
4916     InlineSString<100>  m_BaseLibrary;
4917
4918 #ifdef FEATURE_VERSIONING
4919
4920     InlineSString<100>  m_SystemDirectory;
4921
4922 #else
4923
4924     LPCWSTR             m_SystemDirectory;
4925
4926 #endif
4927
4928     LPWSTR      m_pwDevpath;
4929     DWORD       m_dwDevpath;
4930     BOOL        m_fDevpath;  // have we searched the environment
4931
4932     // <TODO>@TODO: CTS, we can keep the com modules in a single assembly or in different assemblies.
4933     // We are currently using different assemblies but this is potentitially to slow...</TODO>
4934
4935     // Global domain that every one uses
4936     SPTR_DECL(SystemDomain, m_pSystemDomain);
4937
4938     AppDomain* m_pDelayedUnloadList;
4939     BOOL m_UnloadIsAsync;
4940
4941     LoaderAllocator * m_pDelayedUnloadListOfLoaderAllocators;
4942
4943 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
4944     // This is what gets promoted for the whole GC heap.
4945     static size_t m_totalSurvivedBytes;
4946 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
4947
4948     SVAL_DECL(ArrayListStatic, m_appDomainIndexList);
4949 #ifndef DACCESS_COMPILE
4950     static CrstStatic m_DelayedUnloadCrst;
4951     static CrstStatic       m_SystemDomainCrst;
4952
4953
4954     static ArrayListStatic  m_appDomainIdList;
4955
4956     // only one ad can be unloaded at a time
4957     static AppDomain*   m_pAppDomainBeingUnloaded;
4958     // need this so can determine AD being unloaded after it has been deleted
4959     static ADIndex      m_dwIndexOfAppDomainBeingUnloaded;
4960
4961     // if had to spin off a separate thread to do the unload, this is the original thread.
4962     // allows us to delay aborting it until it's the last one so that it can receive
4963     // notification of an unload failure
4964     static Thread *m_pAppDomainUnloadRequestingThread;
4965
4966     // this is the thread doing the actual unload. He's allowed to enter the domain
4967     // even if have started unloading.
4968     static Thread *m_pAppDomainUnloadingThread;
4969
4970     static GlobalStringLiteralMap *m_pGlobalStringLiteralMap;
4971
4972     static ULONG       s_dNumAppDomains;  // Maintain a count of children app domains.
4973
4974     static DWORD        m_dwLowestFreeIndex;
4975 #endif // DACCESS_COMPILE
4976
4977 protected:
4978
4979     // These flags let the correct native image of mscorlib to be loaded.
4980     // This is important for hardbinding to it
4981
4982     SVAL_DECL(BOOL, s_fForceDebug);
4983     SVAL_DECL(BOOL, s_fForceProfiling);
4984     SVAL_DECL(BOOL, s_fForceInstrument);
4985
4986 public:
4987     static void     SetCompilationOverrides(BOOL fForceDebug,
4988                                             BOOL fForceProfiling,
4989                                             BOOL fForceInstrument);
4990
4991     static void     GetCompilationOverrides(BOOL * fForceDebug,
4992                                             BOOL * fForceProfiling,
4993                                             BOOL * fForceInstrument);
4994 public:
4995     //****************************************************************************************
4996     //
4997
4998 #ifndef DACCESS_COMPILE
4999 #ifdef _DEBUG
5000 inline static BOOL IsUnderDomainLock() { LIMITED_METHOD_CONTRACT; return m_SystemDomainCrst.OwnedByCurrentThread();};
5001 #endif
5002
5003     // This lock controls adding and removing domains from the system domain
5004     class LockHolder : public CrstHolder
5005     {
5006     public:
5007         LockHolder()
5008             : CrstHolder(&m_SystemDomainCrst)
5009         {
5010             WRAPPER_NO_CONTRACT;
5011         }
5012     };
5013 #endif // DACCESS_COMPILE
5014
5015 public:
5016     DWORD GetTotalNumSizedRefHandles();
5017
5018 #ifdef DACCESS_COMPILE
5019 public:
5020     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
5021                                    bool enumThis);
5022 #endif
5023
5024 };  // class SystemDomain
5025
5026
5027 //
5028 // an UnsafeAppDomainIterator is used to iterate over all existing domains
5029 //
5030 // The iteration is guaranteed to include all domains that exist at the
5031 // start & end of the iteration. This iterator is considered unsafe because it does not
5032 // reference count the various appdomains, and can only be used when the runtime is stopped,
5033 // or external synchronization is used. (and therefore no other thread may cause the appdomain list to change.)
5034 //
5035 class UnsafeAppDomainIterator
5036 {
5037     friend class SystemDomain;
5038 public:
5039     UnsafeAppDomainIterator(BOOL bOnlyActive)
5040     {
5041         m_bOnlyActive = bOnlyActive;
5042     }
5043
5044     void Init()
5045     {
5046         LIMITED_METHOD_CONTRACT;
5047         SystemDomain* sysDomain = SystemDomain::System();
5048         if (sysDomain)
5049         {
5050             ArrayListStatic* list = &sysDomain->m_appDomainIndexList;
5051             PREFIX_ASSUME(list != NULL);
5052             m_i = list->Iterate();
5053         }
5054         else
5055         {
5056             m_i.SetEmpty();
5057         }
5058
5059         m_pCurrent = NULL;
5060     }
5061
5062     BOOL Next()
5063     {
5064         WRAPPER_NO_CONTRACT;
5065
5066         while (m_i.Next())
5067         {
5068             m_pCurrent = dac_cast<PTR_AppDomain>(m_i.GetElement());
5069             if (m_pCurrent != NULL &&
5070                 (m_bOnlyActive ?
5071                  m_pCurrent->IsActive() : m_pCurrent->IsValid()))
5072             {
5073                 return TRUE;
5074             }
5075         }
5076
5077         m_pCurrent = NULL;
5078         return FALSE;
5079     }
5080
5081     AppDomain * GetDomain()
5082     {
5083         LIMITED_METHOD_DAC_CONTRACT;
5084
5085         return m_pCurrent;
5086     }
5087
5088   private:
5089
5090     ArrayList::Iterator m_i;
5091     AppDomain *         m_pCurrent;
5092     BOOL                m_bOnlyActive;
5093 };  // class UnsafeAppDomainIterator
5094
5095 //
5096 // an AppDomainIterator is used to iterate over all existing domains.
5097 //
5098 // The iteration is guaranteed to include all domains that exist at the
5099 // start & end of the iteration.  Any domains added or deleted during
5100 // iteration may or may not be included.  The iterator also guarantees
5101 // that the current iterated appdomain (GetDomain()) will not be deleted.
5102 //
5103
5104 class AppDomainIterator : public UnsafeAppDomainIterator
5105 {
5106     friend class SystemDomain;
5107
5108   public:
5109     AppDomainIterator(BOOL bOnlyActive) : UnsafeAppDomainIterator(bOnlyActive)
5110     {
5111         WRAPPER_NO_CONTRACT;
5112         Init();
5113     }
5114
5115     ~AppDomainIterator()
5116     {
5117         WRAPPER_NO_CONTRACT;
5118
5119 #ifndef DACCESS_COMPILE
5120         if (GetDomain() != NULL)
5121         {
5122 #ifdef _DEBUG            
5123             GetDomain()->IteratorRelease();
5124 #endif            
5125             GetDomain()->Release();
5126         }
5127 #endif
5128     }
5129
5130     BOOL Next()
5131     {
5132         WRAPPER_NO_CONTRACT;
5133
5134 #ifndef DACCESS_COMPILE
5135         if (GetDomain() != NULL)
5136         {
5137 #ifdef _DEBUG            
5138             GetDomain()->IteratorRelease();
5139 #endif            
5140             GetDomain()->Release();
5141         }
5142
5143         SystemDomain::LockHolder lh;
5144 #endif
5145
5146         if (UnsafeAppDomainIterator::Next())
5147         {
5148 #ifndef DACCESS_COMPILE
5149             GetDomain()->AddRef();
5150 #ifdef _DEBUG            
5151             GetDomain()->IteratorAcquire();
5152 #endif
5153 #endif
5154             return TRUE;
5155         }
5156
5157         return FALSE;
5158     }
5159 };  // class AppDomainIterator
5160
5161 typedef VPTR(class SharedDomain) PTR_SharedDomain;
5162
5163 class SharedDomain : public BaseDomain
5164 {
5165     VPTR_VTABLE_CLASS_AND_CTOR(SharedDomain, BaseDomain)
5166
5167 public:
5168
5169     static void Attach();
5170     static void Detach();
5171
5172     virtual BOOL IsSharedDomain() { LIMITED_METHOD_DAC_CONTRACT; return TRUE; }
5173     virtual PTR_LoaderAllocator GetLoaderAllocator() { WRAPPER_NO_CONTRACT; return SystemDomain::GetGlobalLoaderAllocator(); }
5174
5175     virtual PTR_AppDomain AsAppDomain()
5176     {
5177         LIMITED_METHOD_CONTRACT;
5178         STATIC_CONTRACT_SO_TOLERANT;
5179         _ASSERTE(!"Not an AppDomain");
5180         return NULL;
5181     }
5182
5183     static SharedDomain * GetDomain();
5184
5185     void Init();
5186     void Terminate();
5187
5188     // This will also set the tenured bit if and only if the add was successful,
5189     // and will make sure that the bit appears atomically set to all readers that
5190     // might be accessing the hash on another thread.
5191     MethodTable * FindIndexClass(SIZE_T index);
5192
5193 #ifdef FEATURE_LOADER_OPTIMIZATION
5194     void AddShareableAssembly(Assembly * pAssembly);
5195
5196     class SharedAssemblyIterator
5197     {
5198         PtrHashMap::PtrIterator i;
5199         Assembly * m_pAssembly;
5200
5201       public:
5202         SharedAssemblyIterator() :
5203           i(GetDomain() ? GetDomain()->m_assemblyMap.firstBucket() : NULL)
5204         { LIMITED_METHOD_DAC_CONTRACT; }
5205
5206         BOOL Next()
5207         {
5208             WRAPPER_NO_CONTRACT;
5209             SUPPORTS_DAC;
5210
5211             if (i.end())
5212                 return FALSE;
5213
5214             m_pAssembly = PTR_Assembly(dac_cast<TADDR>(i.GetValue()));
5215             ++i;
5216             return TRUE;
5217         }
5218
5219         Assembly * GetAssembly()
5220         {
5221             LIMITED_METHOD_DAC_CONTRACT;
5222
5223             return m_pAssembly;
5224         }
5225
5226       private:
5227         friend class SharedDomain;
5228     };
5229     
5230     Assembly * FindShareableAssembly(SharedAssemblyLocator * pLocator);
5231     SIZE_T GetShareableAssemblyCount();
5232 #endif //FEATURE_LOADER_OPTIMIZATION
5233
5234 private:
5235     friend class SharedAssemblyIterator;
5236     friend class SharedFileLockHolder;
5237     friend class ClrDataAccess;
5238
5239 #ifndef DACCESS_COMPILE
5240     void *operator new(size_t size, void *pInPlace);
5241     void operator delete(void *pMem);
5242 #endif
5243
5244     SPTR_DECL(SharedDomain, m_pSharedDomain);
5245
5246 #ifdef FEATURE_LOADER_OPTIMIZATION
5247     PEFileListLock          m_FileCreateLock;
5248     SIZE_T                  m_nextClassIndex;
5249     PtrHashMap              m_assemblyMap;
5250 #endif
5251     
5252 public:
5253 #ifdef DACCESS_COMPILE
5254     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
5255                                    bool enumThis);
5256 #endif
5257
5258 #ifdef FEATURE_LOADER_OPTIMIZATION
5259     // Hash map comparison function`
5260     static BOOL CompareSharedAssembly(UPTR u1, UPTR u2);
5261 #endif
5262 };
5263
5264 #ifdef FEATURE_LOADER_OPTIMIZATION
5265 class SharedFileLockHolderBase : protected HolderBase<PEFile *>
5266 {
5267   protected:
5268     PEFileListLock      *m_pLock;
5269     ListLockEntry   *m_pLockElement;
5270
5271     SharedFileLockHolderBase(PEFile *value)
5272       : HolderBase<PEFile *>(value)
5273     {
5274         LIMITED_METHOD_CONTRACT;
5275
5276         m_pLock = NULL;
5277         m_pLockElement = NULL;
5278     }
5279
5280 #ifndef DACCESS_COMPILE
5281     void DoAcquire()
5282     {
5283         STATIC_CONTRACT_THROWS;
5284         STATIC_CONTRACT_GC_TRIGGERS;
5285         STATIC_CONTRACT_FAULT;
5286
5287         PEFileListLockHolder lockHolder(m_pLock);
5288
5289         m_pLockElement = m_pLock->FindFileLock(m_value);
5290         if (m_pLockElement == NULL)
5291         {
5292             m_pLockElement = new ListLockEntry(m_pLock, m_value);
5293             m_pLock->AddElement(m_pLockElement);
5294         }
5295         else
5296             m_pLockElement->AddRef();
5297
5298         lockHolder.Release();
5299
5300         m_pLockElement->Enter();
5301     }
5302
5303     void DoRelease()
5304     {
5305         STATIC_CONTRACT_NOTHROW;
5306         STATIC_CONTRACT_GC_TRIGGERS;
5307         STATIC_CONTRACT_FORBID_FAULT;
5308
5309         m_pLockElement->Leave();
5310         m_pLockElement->Release();
5311         m_pLockElement = NULL;
5312     }
5313 #endif // DACCESS_COMPILE
5314 };
5315
5316 class SharedFileLockHolder : public BaseHolder<PEFile *, SharedFileLockHolderBase>
5317 {
5318   public:
5319     DEBUG_NOINLINE SharedFileLockHolder(SharedDomain *pDomain, PEFile *pFile, BOOL Take = TRUE)
5320       : BaseHolder<PEFile *, SharedFileLockHolderBase>(pFile, FALSE)
5321     {
5322         STATIC_CONTRACT_THROWS;
5323         STATIC_CONTRACT_GC_TRIGGERS;
5324         STATIC_CONTRACT_FAULT;
5325         ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
5326
5327         m_pLock = &pDomain->m_FileCreateLock;
5328         if (Take)
5329             Acquire();
5330     }
5331 };
5332 #endif // FEATURE_LOADER_OPTIMIZATION
5333
5334 inline BOOL BaseDomain::IsDefaultDomain()
5335
5336     LIMITED_METHOD_DAC_CONTRACT; 
5337     return (SystemDomain::System()->DefaultDomain() == this);
5338 }
5339
5340 #include "comreflectioncache.inl"
5341
5342 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
5343 // holds an extra reference so needs special Extract() and should not have SuppressRelease()
5344 // Holders/Wrappers have nonvirtual methods so cannot use them as the base class
5345 template <class AppDomainType>
5346 class AppDomainCreationHolder 
5347 {
5348 private:
5349     // disable the copy ctor
5350     AppDomainCreationHolder(const AppDomainCreationHolder<AppDomainType>&) {}
5351
5352 protected:
5353     AppDomainType* m_pDomain;
5354     BOOL       m_bAcquired;
5355     void ReleaseAppDomainDuringCreation()
5356     {
5357         CONTRACTL
5358         {
5359             NOTHROW;
5360             WRAPPER(GC_TRIGGERS);
5361             PRECONDITION(m_bAcquired);
5362             PRECONDITION(CheckPointer(m_pDomain));
5363         }
5364         CONTRACTL_END;
5365
5366         if (m_pDomain->NotReadyForManagedCode())
5367         {
5368             m_pDomain->Release();
5369         }
5370         else
5371         {
5372             STRESS_LOG2 (LF_APPDOMAIN, LL_INFO100, "Unload domain during creation [%d] %p\n", m_pDomain->GetId().m_dwId, m_pDomain);
5373             SystemDomain::MakeUnloadable(m_pDomain);
5374 #ifdef _DEBUG
5375             DWORD hostTestADUnload = g_pConfig->GetHostTestADUnload();
5376             m_pDomain->EnableADUnloadWorker(hostTestADUnload != 2?EEPolicy::ADU_Safe:EEPolicy::ADU_Rude);
5377 #else
5378             m_pDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
5379 #endif
5380         }
5381     };
5382     
5383 public:
5384     AppDomainCreationHolder() 
5385     {
5386         m_pDomain=NULL;
5387         m_bAcquired=FALSE;
5388     };
5389     ~AppDomainCreationHolder()
5390     {
5391         if (m_bAcquired) 
5392         {
5393             Release();
5394         }
5395     };
5396     void Assign(AppDomainType* pDomain)
5397     {
5398         if(m_bAcquired)
5399             Release();
5400         m_pDomain=pDomain;
5401         if(m_pDomain)
5402         {
5403             AppDomain::RefTakerAcquire(m_pDomain);
5404 #ifdef _DEBUG
5405             m_pDomain->IncCreationCount();
5406 #endif // _DEBUG
5407         }
5408         m_bAcquired=TRUE;
5409     };
5410     
5411     void Release()
5412     {
5413         _ASSERTE(m_bAcquired);
5414         if(m_pDomain)
5415         {
5416 #ifdef _DEBUG
5417             m_pDomain->DecCreationCount();
5418 #endif // _DEBUG
5419             if(!m_pDomain->IsDefaultDomain())
5420                 ReleaseAppDomainDuringCreation();
5421             AppDomain::RefTakerRelease(m_pDomain);
5422         };
5423         m_bAcquired=FALSE;
5424     };
5425
5426     AppDomainType* Extract()
5427     {
5428         _ASSERTE(m_bAcquired);
5429         if(m_pDomain)
5430         {
5431 #ifdef _DEBUG
5432             m_pDomain->DecCreationCount();
5433 #endif // _DEBUG
5434             AppDomain::RefTakerRelease(m_pDomain);
5435         }
5436         m_bAcquired=FALSE;
5437         return m_pDomain;
5438     };
5439
5440     AppDomainType* operator ->()
5441     {
5442         _ASSERTE(m_bAcquired);
5443         return m_pDomain;
5444     }
5445
5446     operator AppDomainType*()
5447     {
5448         _ASSERTE(m_bAcquired);
5449         return m_pDomain;
5450     }
5451
5452     void DoneCreating()
5453     {
5454         Extract();
5455     }
5456 };
5457 #endif // !DACCESS_COMPILE && !CROSSGEN_COMPILE
5458
5459
5460 #endif // !CLR_STANDALONE_BINDER
5461
5462 #endif