Merge pull request #15341 from tannergooding/simd-scalar
[platform/upstream/coreclr.git] / src / vm / appdomain.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5
6 #include "common.h"
7
8 #include "appdomain.hpp"
9 #include "peimagelayout.inl"
10 #include "field.h"
11 #include "strongnameinternal.h"
12 #include "excep.h"
13 #include "eeconfig.h"
14 #include "gcheaputilities.h"
15 #include "eventtrace.h"
16 #include "perfcounters.h"
17 #include "assemblyname.hpp"
18 #include "eeprofinterfaces.h"
19 #include "dbginterface.h"
20 #ifndef DACCESS_COMPILE
21 #include "eedbginterfaceimpl.h"
22 #endif
23 #include "comdynamic.h"
24 #include "mlinfo.h"
25 #include "posterror.h"
26 #include "assemblynative.hpp"
27 #include "shimload.h"
28 #include "stringliteralmap.h"
29 #include "codeman.h"
30 #include "comcallablewrapper.h"
31 #include "apithreadstress.h"
32 #include "eventtrace.h"
33 #include "comdelegate.h"
34 #include "siginfo.hpp"
35 #include "typekey.h"
36
37 #include "caparser.h"
38 #include "ecall.h"
39 #include "finalizerthread.h"
40 #include "threadsuspend.h"
41
42 #ifdef FEATURE_PREJIT
43 #include "corcompile.h"
44 #include "compile.h"
45 #endif // FEATURE_PREJIT
46
47 #ifdef FEATURE_COMINTEROP
48 #include "comtoclrcall.h"
49 #include "runtimecallablewrapper.h"
50 #include "mngstdinterfaces.h"
51 #include "olevariant.h"
52 #include "rcwrefcache.h"
53 #include "olecontexthelpers.h"
54 #endif // FEATURE_COMINTEROP
55 #ifdef FEATURE_TYPEEQUIVALENCE
56 #include "typeequivalencehash.hpp"
57 #endif
58
59 #include "appdomain.inl"
60 #include "typeparse.h"
61 #include "mdaassistants.h"
62 #include "threadpoolrequest.h"
63
64 #include "nativeoverlapped.h"
65
66 #ifndef FEATURE_PAL
67 #include "dwreport.h"
68 #endif // !FEATURE_PAL
69
70 #include "stringarraylist.h"
71
72 #include "../binder/inc/clrprivbindercoreclr.h"
73
74
75 #include "clrprivtypecachewinrt.h"
76
77
78 #pragma warning(push)
79 #pragma warning(disable:4324) 
80 #include "marvin32.h"
81 #pragma warning(pop)
82
83 // this file handles string conversion errors for itself
84 #undef  MAKE_TRANSLATIONFAILED
85
86 // Define these macro's to do strict validation for jit lock and class
87 // init entry leaks.  This defines determine if the asserts that
88 // verify for these leaks are defined or not.  These asserts can
89 // sometimes go off even if no entries have been leaked so this
90 // defines should be used with caution.
91 //
92 // If we are inside a .cctor when the application shut's down then the
93 // class init lock's head will be set and this will cause the assert
94 // to go off.
95 //
96 // If we are jitting a method when the application shut's down then
97 // the jit lock's head will be set causing the assert to go off.
98
99 //#define STRICT_CLSINITLOCK_ENTRY_LEAK_DETECTION
100
101 static const WCHAR DEFAULT_DOMAIN_FRIENDLY_NAME[] = W("DefaultDomain");
102 static const WCHAR OTHER_DOMAIN_FRIENDLY_NAME_PREFIX[] = W("Domain");
103
104 #define STATIC_OBJECT_TABLE_BUCKET_SIZE 1020
105
106 #define MAX_URL_LENGTH                  2084 // same as INTERNET_MAX_URL_LENGTH
107
108 //#define _DEBUG_ADUNLOAD 1
109
110 HRESULT RunDllMain(MethodDesc *pMD, HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved); // clsload.cpp
111
112
113
114
115
116 // Statics
117
118 SPTR_IMPL(SystemDomain, SystemDomain, m_pSystemDomain);
119 SVAL_IMPL(ArrayListStatic, SystemDomain, m_appDomainIndexList);
120 SPTR_IMPL(SharedDomain, SharedDomain, m_pSharedDomain);
121 SVAL_IMPL(BOOL, SystemDomain, s_fForceDebug);
122 SVAL_IMPL(BOOL, SystemDomain, s_fForceProfiling);
123 SVAL_IMPL(BOOL, SystemDomain, s_fForceInstrument);
124
125 #ifndef DACCESS_COMPILE
126
127 // Base Domain Statics
128 CrstStatic          BaseDomain::m_SpecialStaticsCrst;
129
130 int                 BaseDomain::m_iNumberOfProcessors = 0;
131
132 // Shared Domain Statics
133 DECLSPEC_ALIGN(16) 
134 static BYTE         g_pSharedDomainMemory[sizeof(SharedDomain)];
135
136 // System Domain Statics
137 GlobalStringLiteralMap* SystemDomain::m_pGlobalStringLiteralMap = NULL;
138
139 DECLSPEC_ALIGN(16) 
140 static BYTE         g_pSystemDomainMemory[sizeof(SystemDomain)];
141
142 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
143 size_t              SystemDomain::m_totalSurvivedBytes = 0;
144 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
145
146 CrstStatic          SystemDomain::m_SystemDomainCrst;
147 CrstStatic          SystemDomain::m_DelayedUnloadCrst;
148
149 ULONG               SystemDomain::s_dNumAppDomains = 0;
150
151 AppDomain *         SystemDomain::m_pAppDomainBeingUnloaded = NULL;
152 ADIndex             SystemDomain::m_dwIndexOfAppDomainBeingUnloaded;
153 Thread            *SystemDomain::m_pAppDomainUnloadRequestingThread = 0;
154 Thread            *SystemDomain::m_pAppDomainUnloadingThread = 0;
155
156 ArrayListStatic     SystemDomain::m_appDomainIdList;
157
158 DWORD               SystemDomain::m_dwLowestFreeIndex        = 0;
159
160
161
162 // comparison function to be used for matching clsids in our clsid hash table
163 BOOL CompareCLSID(UPTR u1, UPTR u2)
164 {
165     CONTRACTL
166     {
167         THROWS;
168         GC_TRIGGERS;
169         MODE_ANY;
170         SO_INTOLERANT;
171         INJECT_FAULT(COMPlusThrowOM(););
172     }
173     CONTRACTL_END;
174
175     GUID *pguid = (GUID *)(u1 << 1);
176     _ASSERTE(pguid != NULL);
177
178     MethodTable *pMT= (MethodTable *)u2;
179     _ASSERTE(pMT!= NULL);
180
181     GUID guid;
182     pMT->GetGuid(&guid, TRUE);
183     if (!IsEqualIID(guid, *pguid))
184         return FALSE;
185
186     return TRUE;
187 }
188
189 #ifndef CROSSGEN_COMPILE
190 // Constructor for the LargeHeapHandleBucket class.
191 LargeHeapHandleBucket::LargeHeapHandleBucket(LargeHeapHandleBucket *pNext, DWORD Size, BaseDomain *pDomain, BOOL bCrossAD)
192 : m_pNext(pNext)
193 , m_ArraySize(Size)
194 , m_CurrentPos(0)
195 , m_CurrentEmbeddedFreePos(0) // hint for where to start a search for an embedded free item
196 {
197     CONTRACTL
198     {
199         THROWS;
200         GC_TRIGGERS;
201         MODE_COOPERATIVE;
202         PRECONDITION(CheckPointer(pDomain));
203         INJECT_FAULT(COMPlusThrowOM(););
204     }
205     CONTRACTL_END;
206
207     PTRARRAYREF HandleArrayObj;
208
209     // Allocate the array in the large object heap.
210     if (!bCrossAD) 
211     {
212         OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
213         HandleArrayObj = (PTRARRAYREF)AllocateObjectArray(Size, g_pObjectClass, TRUE);
214     }
215     else 
216     {
217         // During AD creation we don't want to assign the handle array to the currently running AD but
218         // to the AD being created.  Ensure that AllocateArrayEx doesn't set the AD and then set it here.
219         AppDomain *pAD = pDomain->AsAppDomain();
220         _ASSERTE(pAD);
221         _ASSERTE(pAD->IsBeingCreated());
222
223         OBJECTREF array;
224         {
225             OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
226             array = AllocateArrayEx(
227                 ClassLoader::LoadArrayTypeThrowing(g_pObjectClass),
228                 (INT32 *)(&Size),
229                 1,
230                 TRUE
231                 DEBUG_ARG(TRUE));
232         }
233
234         array->SetAppDomain(pAD);
235
236         HandleArrayObj = (PTRARRAYREF)array;
237     }
238
239     // Retrieve the pointer to the data inside the array. This is legal since the array
240     // is located in the large object heap and is guaranteed not to move.
241     m_pArrayDataPtr = (OBJECTREF *)HandleArrayObj->GetDataPtr();
242
243     // Store the array in a strong handle to keep it alive.
244     m_hndHandleArray = pDomain->CreatePinningHandle((OBJECTREF)HandleArrayObj);
245 }
246
247
248 // Destructor for the LargeHeapHandleBucket class.
249 LargeHeapHandleBucket::~LargeHeapHandleBucket()
250 {
251     CONTRACTL
252     {
253         NOTHROW;
254         GC_NOTRIGGER;
255     }
256     CONTRACTL_END;
257
258     if (m_hndHandleArray)
259     {
260         DestroyPinningHandle(m_hndHandleArray);
261         m_hndHandleArray = NULL;
262     }
263 }
264
265
266 // Allocate handles from the bucket.
267 OBJECTREF *LargeHeapHandleBucket::AllocateHandles(DWORD nRequested)
268 {
269     CONTRACTL
270     {
271         NOTHROW;
272         GC_NOTRIGGER;
273         MODE_COOPERATIVE;
274     }
275     CONTRACTL_END;
276
277     _ASSERTE(nRequested > 0 && nRequested <= GetNumRemainingHandles());
278     _ASSERTE(m_pArrayDataPtr == (OBJECTREF*)((PTRARRAYREF)ObjectFromHandle(m_hndHandleArray))->GetDataPtr());
279
280     // Store the handles in the buffer that was passed in
281     OBJECTREF* ret = &m_pArrayDataPtr[m_CurrentPos];
282     m_CurrentPos += nRequested;
283
284     return ret;
285 }
286
287 // look for a free item embedded in the table
288 OBJECTREF *LargeHeapHandleBucket::TryAllocateEmbeddedFreeHandle()
289 {
290     CONTRACTL
291     {
292         NOTHROW;
293         GC_NOTRIGGER;
294         MODE_COOPERATIVE;
295     }
296     CONTRACTL_END;
297
298     OBJECTREF pPreallocatedSentinalObject = ObjectFromHandle(g_pPreallocatedSentinelObject);
299     _ASSERTE(pPreallocatedSentinalObject  != NULL);
300
301     for (int  i = m_CurrentEmbeddedFreePos; i < m_CurrentPos; i++)
302     {
303         if (m_pArrayDataPtr[i] == pPreallocatedSentinalObject)
304         {
305             m_CurrentEmbeddedFreePos = i;
306             m_pArrayDataPtr[i] = NULL;
307             return &m_pArrayDataPtr[i];
308         }
309     }
310
311     // didn't find it (we don't bother wrapping around for a full search, it's not worth it to try that hard, we'll get it next time)
312
313     m_CurrentEmbeddedFreePos = 0;
314     return NULL;
315 }
316
317
318 // Maximum bucket size will be 64K on 32-bit and 128K on 64-bit. 
319 // We subtract out a small amount to leave room for the object
320 // header and length of the array.
321
322 #define MAX_BUCKETSIZE (16384 - 4)
323
324 // Constructor for the LargeHeapHandleTable class.
325 LargeHeapHandleTable::LargeHeapHandleTable(BaseDomain *pDomain, DWORD InitialBucketSize)
326 : m_pHead(NULL)
327 , m_pDomain(pDomain)
328 , m_NextBucketSize(InitialBucketSize)
329 , m_pFreeSearchHint(NULL)
330 , m_cEmbeddedFree(0)
331 {
332     CONTRACTL
333     {
334         THROWS;
335         GC_TRIGGERS;
336         MODE_COOPERATIVE;
337         PRECONDITION(CheckPointer(pDomain));
338         INJECT_FAULT(COMPlusThrowOM(););
339     }
340     CONTRACTL_END;
341
342 #ifdef _DEBUG
343     m_pCrstDebug = NULL;
344 #endif
345 }
346
347
348 // Destructor for the LargeHeapHandleTable class.
349 LargeHeapHandleTable::~LargeHeapHandleTable()
350 {
351     CONTRACTL
352     {
353         NOTHROW;
354         GC_NOTRIGGER;
355     }
356     CONTRACTL_END;
357
358     // Delete the buckets.
359     while (m_pHead)
360     {
361         LargeHeapHandleBucket *pOld = m_pHead;
362         m_pHead = pOld->GetNext();
363         delete pOld;
364     }
365 }
366
367 //*****************************************************************************
368 //
369 // LOCKING RULES FOR AllocateHandles() and ReleaseHandles()  12/08/2004
370 //
371 //
372 // These functions are not protected by any locking in this location but rather the callers are
373 // assumed to be doing suitable locking  for the handle table.  The handle table itself is
374 // behaving rather like a thread-agnostic collection class -- it doesn't want to know
375 // much about the outside world and so it is just doing its job with no awareness of
376 // thread notions.
377 //
378 // The instance in question is
379 // There are two locations you can find a LargeHeapHandleTable
380 // 1) there is one in every BaseDomain, it is used to keep track of the static members
381 //     in that domain
382 // 2) there is one in the System Domain that is used for the GlobalStringLiteralMap
383 //
384 // the one in (2) is not the same as the one that is in the BaseDomain object that corresponds
385 // to the SystemDomain -- that one is basically stilborn because the string literals don't go
386 // there and of course the System Domain has no code loaded into it -- only regular
387 // AppDomains (like Domain 0) actually execute code.  As a result handle tables are in
388 // practice used either for string literals or for static members but never for both.
389 // At least not at this writing.
390 //
391 // Now it's useful to consider what the locking discipline is for these classes.
392 //
393 // ---------
394 //
395 // First case: (easiest) is the statics members
396 //
397 // Each BaseDomain has its own critical section
398 //
399 // BaseDomain::AllocateObjRefPtrsInLargeTable takes a lock with
400 //        CrstHolder ch(&m_LargeHeapHandleTableCrst);
401 //
402 // it does this before it calls AllocateHandles which suffices.  It does not call ReleaseHandles
403 // at any time (although ReleaseHandles may be called via AllocateHandles if the request
404 // doesn't fit in the current block, the remaining handles at the end of the block are released
405 // automatically as part of allocation/recycling)
406 //
407 // note: Recycled handles are only used during String Literal allocation because we only try
408 // to recycle handles if the allocation request is for exactly one handle.
409 //
410 // The handles in the BaseDomain handle table are released when the Domain is unloaded
411 // as the GC objects become rootless at that time.
412 //
413 // This dispenses with all of the Handle tables except the one that is used for string literals
414 //
415 // ---------
416 //
417 // Second case:  Allocation for use in a string literal
418 //
419 // AppDomainStringLiteralMap::GetStringLiteral
420 // leads to calls to
421 //     LargeHeapHandleBlockHolder constructor
422 //     leads to calls to
423 //          m_Data = pOwner->AllocateHandles(nCount);
424 //
425 // before doing this  AppDomainStringLiteralMap::GetStringLiteral takes this lock
426 //
427 //    CrstHolder gch(&(SystemDomain::GetGlobalStringLiteralMap()->m_HashTableCrstGlobal));
428 //
429 // which is the lock for the hash table that it owns
430 //
431 // STRINGREF *AppDomainStringLiteralMap::GetInternedString
432 //
433 // has a similar call path and uses the same approach and  the same lock
434 // this covers all the paths which allocate
435 //
436 // ---------
437 //
438 // Third case:  Releases for use in a string literal entry
439 //
440 // CrstHolder gch(&(SystemDomain::GetGlobalStringLiteralMap()->m_HashTableCrstGlobal));
441 // taken in the AppDomainStringLiteralMap functions below protects the 4 ways that this can happen
442 //
443 // case 3a)
444 //
445 // in an appdomain unload case
446 //
447 // AppDomainStringLiteralMap::~AppDomainStringLiteralMap() takes the lock then
448 // leads to calls to
449 //     StringLiteralEntry::Release
450 //    which leads to
451 //        SystemDomain::GetGlobalStringLiteralMapNoCreate()->RemoveStringLiteralEntry(this)
452 //        which leads to
453 //            m_LargeHeapHandleTable.ReleaseHandles((OBJECTREF*)pObjRef, 1);
454 //
455 // case 3b)
456 //
457 // AppDomainStringLiteralMap::GetStringLiteral() can call StringLiteralEntry::Release in some
458 // error cases, leading to the same stack as above
459 //
460 // case 3c)
461 //
462 // AppDomainStringLiteralMap::GetInternedString() can call StringLiteralEntry::Release in some
463 // error cases, leading to the same stack as above
464 //
465 // case 3d)
466 //
467 // The same code paths in 3b and 3c and also end up releasing if an exception is thrown
468 // during their processing.  Both these paths use a StringLiteralEntryHolder to assist in cleanup,
469 // the StaticRelease method of the StringLiteralEntry gets called, which in turn calls the
470 // Release method.
471
472
473 // Allocate handles from the large heap handle table.
474 OBJECTREF* LargeHeapHandleTable::AllocateHandles(DWORD nRequested, BOOL bCrossAD)
475 {
476     CONTRACTL
477     {
478         THROWS;
479         GC_TRIGGERS;
480         MODE_COOPERATIVE;
481         PRECONDITION(nRequested > 0);
482         INJECT_FAULT(COMPlusThrowOM(););
483     }
484     CONTRACTL_END;
485
486     // SEE "LOCKING RULES FOR AllocateHandles() and ReleaseHandles()" above
487
488     // the lock must be registered and already held by the caller per contract
489 #ifdef _DEBUG
490     _ASSERTE(m_pCrstDebug != NULL);
491     _ASSERTE(m_pCrstDebug->OwnedByCurrentThread());
492 #endif
493
494     if (nRequested == 1 && m_cEmbeddedFree != 0)
495     {
496         // special casing singleton requests to look for slots that can be re-used
497
498         // we need to do this because string literals are allocated one at a time and then sometimes
499         // released.  we do not wish for the number of handles consumed by string literals to
500         // increase forever as assemblies are loaded and unloaded
501
502         if (m_pFreeSearchHint == NULL)
503             m_pFreeSearchHint = m_pHead;
504
505         while (m_pFreeSearchHint)
506         {
507             OBJECTREF* pObjRef = m_pFreeSearchHint->TryAllocateEmbeddedFreeHandle();
508             if (pObjRef != NULL)
509             {
510                 // the slot is to have been prepared with a null ready to go
511                 _ASSERTE(*pObjRef == NULL);
512                 m_cEmbeddedFree--;
513                 return pObjRef;
514             }
515             m_pFreeSearchHint = m_pFreeSearchHint->GetNext();
516         }
517
518         // the search doesn't wrap around so it's possible that we might have embedded free items
519         // and not find them but that's ok, we'll get them on the next alloc... all we're trying to do
520         // is to not have big leaks over time.
521     }
522
523
524     // Retrieve the remaining number of handles in the bucket.
525     DWORD NumRemainingHandlesInBucket = (m_pHead != NULL) ? m_pHead->GetNumRemainingHandles() : 0;
526
527     // create a new block if this request doesn't fit in the current block
528     if (nRequested > NumRemainingHandlesInBucket)
529     {
530         if (m_pHead != NULL)
531         {
532             // mark the handles in that remaining region as available for re-use
533             ReleaseHandles(m_pHead->CurrentPos(), NumRemainingHandlesInBucket);
534
535             // mark what's left as having been used
536             m_pHead->ConsumeRemaining();
537         }
538
539         // create a new bucket for this allocation
540
541         // We need a block big enough to hold the requested handles
542         DWORD NewBucketSize = max(m_NextBucketSize, nRequested);
543
544         m_pHead = new LargeHeapHandleBucket(m_pHead, NewBucketSize, m_pDomain, bCrossAD);
545
546         m_NextBucketSize = min(m_NextBucketSize * 2, MAX_BUCKETSIZE);
547     }
548
549     return m_pHead->AllocateHandles(nRequested);
550 }
551
552 //*****************************************************************************
553 // Release object handles allocated using AllocateHandles().
554 void LargeHeapHandleTable::ReleaseHandles(OBJECTREF *pObjRef, DWORD nReleased)
555 {
556     CONTRACTL
557     {
558         NOTHROW;
559         GC_NOTRIGGER;
560         MODE_COOPERATIVE;
561         PRECONDITION(CheckPointer(pObjRef));
562     }
563     CONTRACTL_END;
564
565     // SEE "LOCKING RULES FOR AllocateHandles() and ReleaseHandles()" above
566
567     // the lock must be registered and already held by the caller per contract
568 #ifdef _DEBUG
569     _ASSERTE(m_pCrstDebug != NULL);
570     _ASSERTE(m_pCrstDebug->OwnedByCurrentThread());
571 #endif
572
573     OBJECTREF pPreallocatedSentinalObject = ObjectFromHandle(g_pPreallocatedSentinelObject);
574     _ASSERTE(pPreallocatedSentinalObject  != NULL);
575
576
577     // Add the released handles to the list of available handles.
578     for (DWORD i = 0; i < nReleased; i++)
579     {
580         SetObjectReference(&pObjRef[i], pPreallocatedSentinalObject, NULL);
581     }
582
583     m_cEmbeddedFree += nReleased;
584 }
585
586
587
588
589 // Constructor for the ThreadStaticHandleBucket class.
590 ThreadStaticHandleBucket::ThreadStaticHandleBucket(ThreadStaticHandleBucket *pNext, DWORD Size, BaseDomain *pDomain)
591 : m_pNext(pNext)
592 , m_ArraySize(Size)
593 {
594     CONTRACTL
595     {
596         THROWS;
597         GC_TRIGGERS;
598         MODE_COOPERATIVE;
599         PRECONDITION(CheckPointer(pDomain));
600         INJECT_FAULT(COMPlusThrowOM(););
601     }
602     CONTRACTL_END;
603
604     PTRARRAYREF HandleArrayObj;
605
606     // Allocate the array on the GC heap.
607     OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
608     HandleArrayObj = (PTRARRAYREF)AllocateObjectArray(Size, g_pObjectClass, FALSE);
609
610     // Store the array in a strong handle to keep it alive.
611     m_hndHandleArray = pDomain->CreateStrongHandle((OBJECTREF)HandleArrayObj);
612 }
613
614 // Destructor for the ThreadStaticHandleBucket class.
615 ThreadStaticHandleBucket::~ThreadStaticHandleBucket()
616 {
617     CONTRACTL
618     {
619         NOTHROW;
620         GC_NOTRIGGER;
621         MODE_COOPERATIVE;
622     }
623     CONTRACTL_END;
624
625     if (m_hndHandleArray)
626     {
627         DestroyStrongHandle(m_hndHandleArray);
628         m_hndHandleArray = NULL;
629     }
630 }
631
632 // Allocate handles from the bucket.
633 OBJECTHANDLE ThreadStaticHandleBucket::GetHandles()
634 {
635     CONTRACTL
636     {
637         NOTHROW;
638         GC_NOTRIGGER;
639         MODE_COOPERATIVE;
640     }
641     CONTRACTL_END;
642
643     return m_hndHandleArray;
644 }
645
646 // Constructor for the ThreadStaticHandleTable class.
647 ThreadStaticHandleTable::ThreadStaticHandleTable(BaseDomain *pDomain)
648 : m_pHead(NULL)
649 , m_pDomain(pDomain)
650 {
651     CONTRACTL
652     {
653         NOTHROW;
654         GC_NOTRIGGER;
655         MODE_ANY;
656         PRECONDITION(CheckPointer(pDomain));
657     }
658     CONTRACTL_END;
659 }
660
661 // Destructor for the ThreadStaticHandleTable class.
662 ThreadStaticHandleTable::~ThreadStaticHandleTable()
663 {
664     CONTRACTL
665     {
666         NOTHROW;
667         GC_NOTRIGGER;
668     }
669     CONTRACTL_END;
670
671     // Delete the buckets.
672     while (m_pHead)
673     {
674         ThreadStaticHandleBucket *pOld = m_pHead;
675         m_pHead = pOld->GetNext();
676         delete pOld;
677     }
678 }
679
680 // Allocate handles from the large heap handle table.
681 OBJECTHANDLE ThreadStaticHandleTable::AllocateHandles(DWORD nRequested)
682 {
683     CONTRACTL
684     {
685         THROWS;
686         GC_TRIGGERS;
687         MODE_COOPERATIVE;
688         PRECONDITION(nRequested > 0);
689         INJECT_FAULT(COMPlusThrowOM(););
690     }
691     CONTRACTL_END;
692
693     // create a new bucket for this allocation
694     m_pHead = new ThreadStaticHandleBucket(m_pHead, nRequested, m_pDomain);
695
696     return m_pHead->GetHandles();
697 }
698
699 #endif // CROSSGEN_COMPILE
700
701
702 //*****************************************************************************
703 // BaseDomain
704 //*****************************************************************************
705 void BaseDomain::Attach()
706 {
707     m_SpecialStaticsCrst.Init(CrstSpecialStatics);
708 }
709
710 BaseDomain::BaseDomain()
711 {
712     // initialize fields so the domain can be safely destructed
713     // shouldn't call anything that can fail here - use ::Init instead
714     CONTRACTL
715     {
716         THROWS;
717         GC_TRIGGERS;
718         MODE_ANY;
719         FORBID_FAULT;
720     }
721     CONTRACTL_END;
722
723     m_fDisableInterfaceCache = FALSE;
724
725     m_pFusionContext = NULL;
726     m_pTPABinderContext = NULL;
727
728     // Make sure the container is set to NULL so that it gets loaded when it is used.
729     m_pLargeHeapHandleTable = NULL;
730
731 #ifndef CROSSGEN_COMPILE
732     // Note that m_handleStore is overridden by app domains
733     m_handleStore = GCHandleUtilities::GetGCHandleManager()->GetGlobalHandleStore();
734 #else
735     m_handleStore = NULL;
736 #endif
737
738     m_pMarshalingData = NULL;
739
740     m_dwContextStatics = 0;
741 #ifdef FEATURE_COMINTEROP
742     m_pMngStdInterfacesInfo = NULL;
743     m_pWinRtBinder = NULL;
744 #endif
745     m_FileLoadLock.PreInit();
746     m_JITLock.PreInit();
747     m_ClassInitLock.PreInit();
748     m_ILStubGenLock.PreInit();
749
750 #ifdef FEATURE_CODE_VERSIONING
751     m_codeVersionManager.PreInit(this == (BaseDomain *)g_pSharedDomainMemory);
752 #endif
753
754 } //BaseDomain::BaseDomain
755
756 //*****************************************************************************
757 void BaseDomain::Init()
758 {
759     CONTRACTL
760     {
761         THROWS;
762         GC_TRIGGERS;
763         MODE_ANY;
764         INJECT_FAULT(COMPlusThrowOM(););
765     }
766     CONTRACTL_END;
767
768     //
769     // Initialize the domain locks
770     //
771
772     if (this == reinterpret_cast<BaseDomain*>(&g_pSharedDomainMemory[0]))
773         m_DomainCrst.Init(CrstSharedBaseDomain);
774     else if (this == reinterpret_cast<BaseDomain*>(&g_pSystemDomainMemory[0]))
775         m_DomainCrst.Init(CrstSystemBaseDomain);
776     else
777         m_DomainCrst.Init(CrstBaseDomain);
778
779     m_DomainCacheCrst.Init(CrstAppDomainCache);
780     m_DomainLocalBlockCrst.Init(CrstDomainLocalBlock);
781
782     m_InteropDataCrst.Init(CrstInteropData, CRST_REENTRANCY);
783
784     m_WinRTFactoryCacheCrst.Init(CrstWinRTFactoryCache, CRST_UNSAFE_COOPGC);
785
786     // NOTE: CRST_UNSAFE_COOPGC prevents a GC mode switch to preemptive when entering this crst.
787     // If you remove this flag, we will switch to preemptive mode when entering
788     // m_FileLoadLock, which means all functions that enter it will become
789     // GC_TRIGGERS.  (This includes all uses of PEFileListLockHolder, LoadLockHolder, etc.)  So be sure
790     // to update the contracts if you remove this flag.
791     m_FileLoadLock.Init(CrstAssemblyLoader,
792                         CrstFlags(CRST_HOST_BREAKABLE), TRUE);
793
794     //
795     //   The JIT lock and the CCtor locks are at the same level (and marked as
796     //   UNSAFE_SAME_LEVEL) because they are all part of the same deadlock detection mechanism. We
797     //   see through cycles of JITting and .cctor execution and then explicitly allow the cycle to
798     //   be broken by giving access to uninitialized classes.  If there is no cycle or if the cycle
799     //   involves other locks that arent part of this special deadlock-breaking semantics, then
800     //   we continue to block.
801     //
802     m_JITLock.Init(CrstJit, CrstFlags(CRST_REENTRANCY | CRST_UNSAFE_SAMELEVEL), TRUE);
803     m_ClassInitLock.Init(CrstClassInit, CrstFlags(CRST_REENTRANCY | CRST_UNSAFE_SAMELEVEL), TRUE);
804
805     m_ILStubGenLock.Init(CrstILStubGen, CrstFlags(CRST_REENTRANCY), TRUE);
806
807     // Large heap handle table CRST.
808     m_LargeHeapHandleTableCrst.Init(CrstAppDomainHandleTable);
809
810     m_crstLoaderAllocatorReferences.Init(CrstLoaderAllocatorReferences);
811     // Has to switch thread to GC_NOTRIGGER while being held (see code:BaseDomain#AssemblyListLock)
812     m_crstAssemblyList.Init(CrstAssemblyList, CrstFlags(
813         CRST_GC_NOTRIGGER_WHEN_TAKEN | CRST_DEBUGGER_THREAD | CRST_TAKEN_DURING_SHUTDOWN));
814
815     // Initialize the EE marshaling data to NULL.
816     m_pMarshalingData = NULL;
817
818 #ifdef FEATURE_COMINTEROP
819     // Allocate the managed standard interfaces information.
820     m_pMngStdInterfacesInfo = new MngStdInterfacesInfo();
821     
822     {
823         CLRPrivBinderWinRT::NamespaceResolutionKind fNamespaceResolutionKind = CLRPrivBinderWinRT::NamespaceResolutionKind_WindowsAPI;
824         if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_DesignerNamespaceResolutionEnabled) != FALSE)
825         {
826             fNamespaceResolutionKind = CLRPrivBinderWinRT::NamespaceResolutionKind_DesignerResolveEvent;
827         }
828         CLRPrivTypeCacheWinRT * pWinRtTypeCache = CLRPrivTypeCacheWinRT::GetOrCreateTypeCache();
829         m_pWinRtBinder = CLRPrivBinderWinRT::GetOrCreateBinder(pWinRtTypeCache, fNamespaceResolutionKind);
830     }
831 #endif // FEATURE_COMINTEROP
832
833     // Init the COM Interop data hash
834     {
835         LockOwner lock = {&m_InteropDataCrst, IsOwnerOfCrst};
836         m_interopDataHash.Init(0, NULL, false, &lock);
837     }
838
839     m_dwSizedRefHandles = 0;
840     if (!m_iNumberOfProcessors)
841     {
842         m_iNumberOfProcessors = GetCurrentProcessCpuCount();
843     }
844 }
845
846 #undef LOADERHEAP_PROFILE_COUNTER
847
848 #ifndef CROSSGEN_COMPILE
849 //*****************************************************************************
850 void BaseDomain::Terminate()
851 {
852     CONTRACTL
853     {
854         NOTHROW;
855         GC_TRIGGERS;
856         MODE_ANY;
857     }
858     CONTRACTL_END;
859
860     m_crstLoaderAllocatorReferences.Destroy();
861     m_DomainCrst.Destroy();
862     m_DomainCacheCrst.Destroy();
863     m_DomainLocalBlockCrst.Destroy();
864     m_InteropDataCrst.Destroy();
865
866     JitListLockEntry* pJitElement;
867     ListLockEntry* pElement;
868
869     // All the threads that are in this domain had better be stopped by this
870     // point.
871     //
872     // We might be jitting or running a .cctor so we need to empty that queue.
873     pJitElement = m_JITLock.Pop(TRUE);
874     while (pJitElement)
875     {
876 #ifdef STRICT_JITLOCK_ENTRY_LEAK_DETECTION
877         _ASSERTE ((m_JITLock.m_pHead->m_dwRefCount == 1
878             && m_JITLock.m_pHead->m_hrResultCode == E_FAIL) ||
879             dbg_fDrasticShutdown || g_fInControlC);
880 #endif // STRICT_JITLOCK_ENTRY_LEAK_DETECTION
881         delete(pJitElement);
882         pJitElement = m_JITLock.Pop(TRUE);
883
884     }
885     m_JITLock.Destroy();
886
887     pElement = m_ClassInitLock.Pop(TRUE);
888     while (pElement)
889     {
890 #ifdef STRICT_CLSINITLOCK_ENTRY_LEAK_DETECTION
891         _ASSERTE (dbg_fDrasticShutdown || g_fInControlC);
892 #endif
893         delete(pElement);
894         pElement = m_ClassInitLock.Pop(TRUE);
895     }
896     m_ClassInitLock.Destroy();
897
898     FileLoadLock* pFileElement;
899     pFileElement = (FileLoadLock*) m_FileLoadLock.Pop(TRUE);
900     while (pFileElement)
901     {
902 #ifdef STRICT_CLSINITLOCK_ENTRY_LEAK_DETECTION
903         _ASSERTE (dbg_fDrasticShutdown || g_fInControlC);
904 #endif
905         pFileElement->Release();
906         pFileElement = (FileLoadLock*) m_FileLoadLock.Pop(TRUE);
907     }
908     m_FileLoadLock.Destroy();
909
910     pElement = m_ILStubGenLock.Pop(TRUE);
911     while (pElement)
912     {
913 #ifdef STRICT_JITLOCK_ENTRY_LEAK_DETECTION
914         _ASSERTE ((m_ILStubGenLock.m_pHead->m_dwRefCount == 1
915             && m_ILStubGenLock.m_pHead->m_hrResultCode == E_FAIL) ||
916             dbg_fDrasticShutdown || g_fInControlC);
917 #endif // STRICT_JITLOCK_ENTRY_LEAK_DETECTION
918         delete(pElement);
919         pElement = m_ILStubGenLock.Pop(TRUE);
920     }
921     m_ILStubGenLock.Destroy();
922
923     m_LargeHeapHandleTableCrst.Destroy();
924
925     if (m_pLargeHeapHandleTable != NULL)
926     {
927         delete m_pLargeHeapHandleTable;
928         m_pLargeHeapHandleTable = NULL;
929     }
930
931     if (!IsAppDomain())
932     {
933         // Kind of a workaround - during unloading, we need to have an EE halt
934         // around deleting this stuff. So it gets deleted in AppDomain::Terminate()
935         // for those things (because there is a convenient place there.)
936         GetLoaderAllocator()->CleanupStringLiteralMap();
937     }
938
939 #ifdef FEATURE_COMINTEROP
940     if (m_pMngStdInterfacesInfo)
941     {
942         delete m_pMngStdInterfacesInfo;
943         m_pMngStdInterfacesInfo = NULL;
944     }
945     
946     if (m_pWinRtBinder != NULL)
947     {
948         m_pWinRtBinder->Release();
949     }
950 #endif // FEATURE_COMINTEROP
951
952     ClearFusionContext();
953
954     m_dwSizedRefHandles = 0;
955 }
956 #endif // CROSSGEN_COMPILE
957
958 void BaseDomain::InitVSD()
959 {
960     STANDARD_VM_CONTRACT;
961
962     // This is a workaround for gcc, since it fails to successfully resolve
963     // "TypeIDMap::STARTING_SHARED_DOMAIN_ID" when used within the ?: operator.
964     UINT32 startingId;
965     if (IsSharedDomain())
966     {
967         startingId = TypeIDMap::STARTING_SHARED_DOMAIN_ID;
968     }
969     else
970     {
971         startingId = TypeIDMap::STARTING_UNSHARED_DOMAIN_ID;
972     }
973
974     // By passing false as the last parameter, interfaces loaded in the
975     // shared domain will not be given fat type ids if RequiresFatDispatchTokens
976     // is set. This is correct, as the fat dispatch tokens are only needed to solve
977     // uniqueness problems involving domain specific types.
978     m_typeIDMap.Init(startingId, 2, !IsSharedDomain());
979
980 #ifndef CROSSGEN_COMPILE
981     GetLoaderAllocator()->InitVirtualCallStubManager(this);
982 #endif
983 }
984
985 #ifndef CROSSGEN_COMPILE
986
987 DWORD BaseDomain::AllocateContextStaticsOffset(DWORD* pOffsetSlot)
988 {
989     CONTRACTL
990     {
991         THROWS;
992         GC_TRIGGERS;
993     }
994     CONTRACTL_END;
995
996     CrstHolder ch(&m_SpecialStaticsCrst);
997
998     DWORD dwOffset = *pOffsetSlot;
999
1000     if (dwOffset == (DWORD)-1)
1001     {
1002         // Allocate the slot
1003         dwOffset = m_dwContextStatics++;
1004         *pOffsetSlot = dwOffset;
1005     }
1006
1007     return dwOffset;
1008 }
1009
1010 void BaseDomain::ClearFusionContext()
1011 {
1012     CONTRACTL
1013     {
1014         NOTHROW;
1015         GC_TRIGGERS;
1016         MODE_PREEMPTIVE;
1017     }
1018     CONTRACTL_END;
1019
1020     if(m_pFusionContext) {
1021         m_pFusionContext->Release();
1022         m_pFusionContext = NULL;
1023     }
1024     if (m_pTPABinderContext) {
1025         m_pTPABinderContext->Release();
1026         m_pTPABinderContext = NULL;
1027     }
1028 }
1029
1030 #ifdef  FEATURE_PREJIT
1031 void AppDomain::DeleteNativeCodeRanges()
1032 {
1033     CONTRACTL
1034     {
1035         NOTHROW;
1036         GC_NOTRIGGER;
1037         MODE_PREEMPTIVE;
1038         FORBID_FAULT;
1039     }
1040     CONTRACTL_END;
1041
1042     // Fast path to skip using the assembly iterator when the appdomain has not yet completely been initialized 
1043     // and yet we are destroying it.  (This is the case if we OOM during AppDomain creation.)
1044     if (m_Assemblies.IsEmpty())
1045         return;
1046
1047     // Shutdown assemblies
1048     AssemblyIterator i = IterateAssembliesEx( (AssemblyIterationFlags)(kIncludeLoaded | kIncludeLoading | kIncludeExecution | kIncludeIntrospection | kIncludeFailedToLoad) );
1049     CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
1050
1051     while (i.Next(pDomainAssembly.This()))
1052     {
1053         Assembly * assembly = pDomainAssembly->m_pAssembly;
1054         if ((assembly != NULL) && !assembly->IsDomainNeutral())
1055             assembly->DeleteNativeCodeRanges();
1056     }
1057 }
1058 #endif
1059
1060 void AppDomain::ShutdownAssemblies()
1061 {
1062     CONTRACTL
1063     {
1064         NOTHROW;
1065         GC_TRIGGERS;
1066         MODE_ANY;
1067     }
1068     CONTRACTL_END;
1069
1070     // Fast path to skip using the assembly iterator when the appdomain has not yet completely been initialized 
1071     // and yet we are destroying it.  (This is the case if we OOM during AppDomain creation.)
1072     if (m_Assemblies.IsEmpty())
1073         return;
1074
1075     // Shutdown assemblies
1076     // has two stages because Terminate needs info from the Assembly's dependencies
1077
1078     // Stage 1: call code:Assembly::Terminate
1079     AssemblyIterator i = IterateAssembliesEx((AssemblyIterationFlags)(
1080         kIncludeLoaded | kIncludeLoading | kIncludeExecution | kIncludeIntrospection | kIncludeFailedToLoad | kIncludeCollected));
1081     DomainAssembly * pDomainAssembly = NULL;
1082
1083     while (i.Next_UnsafeNoAddRef(&pDomainAssembly))
1084     {
1085         // Note: cannot use DomainAssembly::GetAssembly() here as it asserts that the assembly has been
1086         // loaded to at least the FILE_LOAD_ALLOCATE level. Since domain shutdown can take place
1087         // asynchronously this property cannot be guaranteed. Access the m_pAssembly field directly instead.
1088         Assembly * assembly = pDomainAssembly->m_pAssembly;
1089         if (assembly && !assembly->IsDomainNeutral())
1090             assembly->Terminate();
1091     }
1092     
1093     // Stage 2: Clear the list of assemblies
1094     i = IterateAssembliesEx((AssemblyIterationFlags)(
1095         kIncludeLoaded | kIncludeLoading | kIncludeExecution | kIncludeIntrospection | kIncludeFailedToLoad | kIncludeCollected));
1096     while (i.Next_UnsafeNoAddRef(&pDomainAssembly))
1097     {
1098         // We are in shutdown path, no one else can get to the list anymore
1099         delete pDomainAssembly;
1100     }
1101     m_Assemblies.Clear(this);
1102     
1103     // Stage 2: Clear the loader allocators registered for deletion from code:Assembly:Terminate calls in 
1104     // stage 1
1105     // Note: It is not clear to me why we cannot delete the loader allocator from within 
1106     // code:DomainAssembly::~DomainAssembly
1107     ShutdownFreeLoaderAllocators(FALSE);
1108 } // AppDomain::ShutdownAssemblies
1109
1110 void AppDomain::ShutdownFreeLoaderAllocators(BOOL bFromManagedCode)
1111 {
1112     // If we're called from managed code (i.e. the finalizer thread) we take a lock in
1113     // LoaderAllocator::CleanupFailedTypeInit, which may throw. Otherwise we're called
1114     // from the app-domain shutdown path in which we can avoid taking the lock.
1115     CONTRACTL
1116     {
1117         GC_TRIGGERS;
1118         if (bFromManagedCode) THROWS; else NOTHROW;
1119         MODE_ANY;
1120         CAN_TAKE_LOCK;
1121     }
1122     CONTRACTL_END;
1123
1124     CrstHolder ch(GetLoaderAllocatorReferencesLock());
1125     
1126     // Shutdown the LoaderAllocators associated with collectible assemblies
1127     while (m_pDelayedLoaderAllocatorUnloadList != NULL)
1128     {
1129         LoaderAllocator * pCurrentLoaderAllocator = m_pDelayedLoaderAllocatorUnloadList;
1130         // Remove next loader allocator from the list
1131         m_pDelayedLoaderAllocatorUnloadList = m_pDelayedLoaderAllocatorUnloadList->m_pLoaderAllocatorDestroyNext;
1132
1133         if (bFromManagedCode)
1134         {
1135             // For loader allocator finalization, we need to be careful about cleaning up per-appdomain allocations
1136             // and synchronizing with GC using delay unload list. We need to wait for next Gen2 GC to finish to ensure
1137             // that GC heap does not have any references to the MethodTables being unloaded.
1138
1139             pCurrentLoaderAllocator->CleanupFailedTypeInit();
1140
1141             pCurrentLoaderAllocator->CleanupHandles();
1142
1143             GCX_COOP();
1144             SystemDomain::System()->AddToDelayedUnloadList(pCurrentLoaderAllocator);
1145         }
1146         else
1147         {
1148             // For appdomain unload, delete the loader allocator right away
1149             delete pCurrentLoaderAllocator;
1150         }
1151     }
1152 } // AppDomain::ShutdownFreeLoaderAllocators
1153
1154 //---------------------------------------------------------------------------------------
1155 // 
1156 // Register the loader allocator for deletion in code:AppDomain::ShutdownFreeLoaderAllocators.
1157 // 
1158 void AppDomain::RegisterLoaderAllocatorForDeletion(LoaderAllocator * pLoaderAllocator)
1159 {
1160     CONTRACTL
1161     {
1162         GC_TRIGGERS;
1163         NOTHROW;
1164         MODE_ANY;
1165         CAN_TAKE_LOCK;
1166     }
1167     CONTRACTL_END;
1168     
1169     CrstHolder ch(GetLoaderAllocatorReferencesLock());
1170     
1171     pLoaderAllocator->m_pLoaderAllocatorDestroyNext = m_pDelayedLoaderAllocatorUnloadList;
1172     m_pDelayedLoaderAllocatorUnloadList = pLoaderAllocator;
1173 }
1174
1175 void AppDomain::ShutdownNativeDllSearchDirectories()
1176 {
1177     LIMITED_METHOD_CONTRACT;
1178     // Shutdown assemblies
1179     PathIterator i = IterateNativeDllSearchDirectories();
1180
1181     while (i.Next())
1182     {
1183         delete i.GetPath();
1184     }
1185
1186     m_NativeDllSearchDirectories.Clear();
1187 }
1188
1189 void AppDomain::ReleaseDomainBoundInfo()
1190 {
1191     CONTRACTL
1192     {
1193         NOTHROW;
1194         GC_TRIGGERS;
1195         MODE_ANY;
1196     }
1197     CONTRACTL_END;;
1198     // Shutdown assemblies
1199     m_AssemblyCache.OnAppDomainUnload();
1200
1201     AssemblyIterator i = IterateAssembliesEx( (AssemblyIterationFlags)(kIncludeFailedToLoad) );
1202     CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
1203     
1204     while (i.Next(pDomainAssembly.This()))
1205     {
1206        pDomainAssembly->ReleaseManagedData();
1207     }
1208 }
1209
1210 void AppDomain::ReleaseFiles()
1211 {
1212     STANDARD_VM_CONTRACT;
1213
1214     // Shutdown assemblies
1215     AssemblyIterator i = IterateAssembliesEx((AssemblyIterationFlags)(
1216         kIncludeLoaded  | kIncludeExecution | kIncludeIntrospection | kIncludeFailedToLoad | kIncludeLoading));
1217     CollectibleAssemblyHolder<DomainAssembly *> pAsm;
1218
1219     while (i.Next(pAsm.This()))
1220     {
1221         if (pAsm->GetCurrentAssembly() == NULL)
1222         {
1223             // Might be domain neutral or not, but should have no live objects as it has not been
1224             // really loaded yet. Just reset it.
1225             _ASSERTE(FitsIn<DWORD>(i.GetIndex()));
1226             m_Assemblies.Set(this, static_cast<DWORD>(i.GetIndex()), NULL);
1227             delete pAsm.Extract();
1228         }
1229         else
1230         {
1231             if (!pAsm->GetCurrentAssembly()->IsDomainNeutral())
1232                 pAsm->ReleaseFiles();
1233         }
1234     }
1235 } // AppDomain::ReleaseFiles
1236
1237
1238 OBJECTREF* BaseDomain::AllocateObjRefPtrsInLargeTable(int nRequested, OBJECTREF** ppLazyAllocate, BOOL bCrossAD)
1239 {
1240     CONTRACTL
1241     {
1242         THROWS;
1243         GC_TRIGGERS;
1244         MODE_ANY;
1245         PRECONDITION((nRequested > 0));
1246         INJECT_FAULT(COMPlusThrowOM(););
1247     }
1248     CONTRACTL_END;
1249
1250     if (ppLazyAllocate && *ppLazyAllocate)
1251     {
1252         // Allocation already happened
1253         return *ppLazyAllocate;
1254     }
1255
1256     // Enter preemptive state, take the lock and go back to cooperative mode.
1257     {
1258         CrstHolder ch(&m_LargeHeapHandleTableCrst);
1259         GCX_COOP();
1260
1261         if (ppLazyAllocate && *ppLazyAllocate)
1262         {
1263             // Allocation already happened
1264             return *ppLazyAllocate;
1265         }
1266
1267         // Make sure the large heap handle table is initialized.
1268         if (!m_pLargeHeapHandleTable)
1269             InitLargeHeapHandleTable();
1270
1271         // Allocate the handles.
1272         OBJECTREF* result = m_pLargeHeapHandleTable->AllocateHandles(nRequested, bCrossAD);
1273
1274         if (ppLazyAllocate)
1275         {
1276             *ppLazyAllocate = result;
1277         }
1278
1279         return result;
1280     }
1281 }
1282 #endif // CROSSGEN_COMPILE
1283
1284 #endif // !DACCESS_COMPILE
1285
1286 /*static*/
1287 PTR_BaseDomain BaseDomain::ComputeBaseDomain(
1288     BaseDomain * pGenericDefinitionDomain,   // the domain that owns the generic type or method
1289     Instantiation classInst,                // the type arguments to the type (if any)
1290     Instantiation methodInst)               // the type arguments to the method (if any)
1291 {
1292     CONTRACT(PTR_BaseDomain)
1293     {
1294         NOTHROW;
1295         GC_NOTRIGGER;
1296         FORBID_FAULT;
1297         MODE_ANY;
1298         POSTCONDITION(CheckPointer(RETVAL));
1299         SUPPORTS_DAC;
1300         SO_TOLERANT;
1301     }
1302     CONTRACT_END
1303
1304     if (pGenericDefinitionDomain && pGenericDefinitionDomain->IsAppDomain())
1305         RETURN PTR_BaseDomain(pGenericDefinitionDomain);
1306
1307     for (DWORD i = 0; i < classInst.GetNumArgs(); i++)
1308     {
1309         PTR_BaseDomain pArgDomain = classInst[i].GetDomain();
1310         if (pArgDomain->IsAppDomain())
1311             RETURN pArgDomain;
1312     }
1313
1314     for (DWORD i = 0; i < methodInst.GetNumArgs(); i++)
1315     {
1316         PTR_BaseDomain pArgDomain = methodInst[i].GetDomain();
1317         if (pArgDomain->IsAppDomain())
1318             RETURN pArgDomain;
1319     }
1320     RETURN (pGenericDefinitionDomain ? 
1321             PTR_BaseDomain(pGenericDefinitionDomain) : 
1322             PTR_BaseDomain(SystemDomain::System()));
1323 }
1324
1325 PTR_BaseDomain BaseDomain::ComputeBaseDomain(TypeKey * pKey)
1326 {
1327     CONTRACTL
1328     {
1329         NOTHROW;
1330         GC_NOTRIGGER;
1331         MODE_ANY;
1332         SUPPORTS_DAC;
1333     }
1334     CONTRACTL_END;
1335
1336
1337     if (pKey->GetKind() == ELEMENT_TYPE_CLASS)
1338         return BaseDomain::ComputeBaseDomain(pKey->GetModule()->GetDomain(),
1339                                              pKey->GetInstantiation());
1340     else if (pKey->GetKind() != ELEMENT_TYPE_FNPTR)
1341         return pKey->GetElementType().GetDomain();
1342     else
1343         return BaseDomain::ComputeBaseDomain(NULL,Instantiation(pKey->GetRetAndArgTypes(), pKey->GetNumArgs()+1));
1344 }
1345
1346
1347
1348
1349
1350 #ifndef DACCESS_COMPILE
1351
1352 // Insert class in the hash table
1353 void AppDomain::InsertClassForCLSID(MethodTable* pMT, BOOL fForceInsert /*=FALSE*/)
1354 {
1355     CONTRACTL
1356     {
1357         GC_TRIGGERS;
1358         MODE_ANY;
1359         THROWS;
1360         INJECT_FAULT(COMPlusThrowOM(););
1361     }
1362     CONTRACTL_END;
1363
1364     CVID cvid;
1365
1366     // Ensure that registered classes are activated for allocation
1367     pMT->EnsureInstanceActive();
1368
1369     // Note that it is possible for multiple classes to claim the same CLSID, and in such a
1370     // case it is arbitrary which one we will return for a future query for a given app domain.
1371
1372     pMT->GetGuid(&cvid, fForceInsert);
1373
1374     if (!IsEqualIID(cvid, GUID_NULL))
1375     {
1376         //<TODO>@todo get a better key</TODO>
1377         LPVOID val = (LPVOID)pMT;
1378         {
1379             LockHolder lh(this);
1380
1381             if (LookupClass(cvid) != pMT)
1382             {
1383                 m_clsidHash.InsertValue(GetKeyFromGUID(&cvid), val);
1384             }
1385         }
1386     }
1387 }
1388
1389 void AppDomain::InsertClassForCLSID(MethodTable* pMT, GUID *pGuid)
1390 {
1391     CONTRACT_VOID
1392     {
1393         NOTHROW;
1394         PRECONDITION(CheckPointer(pMT));
1395         PRECONDITION(CheckPointer(pGuid));
1396     }
1397     CONTRACT_END;
1398
1399     LPVOID val = (LPVOID)pMT;
1400     {
1401         LockHolder lh(this);
1402
1403         CVID* cvid = pGuid;
1404         if (LookupClass(*cvid) != pMT)
1405         {
1406             m_clsidHash.InsertValue(GetKeyFromGUID(pGuid), val);
1407         }
1408     }
1409
1410     RETURN;
1411 }
1412 #endif // DACCESS_COMPILE
1413
1414 #ifdef FEATURE_COMINTEROP
1415
1416 #ifndef DACCESS_COMPILE
1417 void AppDomain::CacheTypeByName(const SString &ssClassName, const UINT vCacheVersion, TypeHandle typeHandle, BYTE bFlags, BOOL bReplaceExisting /*= FALSE*/)
1418 {
1419     WRAPPER_NO_CONTRACT;
1420     LockHolder lh(this);
1421     CacheTypeByNameWorker(ssClassName, vCacheVersion, typeHandle, bFlags, bReplaceExisting);
1422 }
1423
1424 void AppDomain::CacheTypeByNameWorker(const SString &ssClassName, const UINT vCacheVersion, TypeHandle typeHandle, BYTE bFlags, BOOL bReplaceExisting /*= FALSE*/)
1425 {
1426     CONTRACTL
1427     {
1428         THROWS;
1429         GC_TRIGGERS;
1430         PRECONDITION(!typeHandle.IsNull());
1431     }
1432     CONTRACTL_END;
1433
1434     NewArrayHolder<WCHAR> wzClassName(DuplicateStringThrowing(ssClassName.GetUnicode()));
1435
1436     if (m_vNameToTypeMapVersion != vCacheVersion)
1437         return;
1438
1439     if (m_pNameToTypeMap == nullptr)
1440     {
1441         m_pNameToTypeMap = new NameToTypeMapTable();
1442     }
1443
1444     NameToTypeMapEntry e;
1445     e.m_key.m_wzName = wzClassName;
1446     e.m_key.m_cchName = ssClassName.GetCount();
1447     e.m_typeHandle = typeHandle;
1448     e.m_nEpoch = this->m_nEpoch;
1449     e.m_bFlags = bFlags;
1450     if (!bReplaceExisting)
1451         m_pNameToTypeMap->Add(e);
1452     else
1453         m_pNameToTypeMap->AddOrReplace(e);
1454
1455     wzClassName.SuppressRelease();
1456 }
1457 #endif // DACCESS_COMPILE
1458
1459 TypeHandle AppDomain::LookupTypeByName(const SString &ssClassName, UINT* pvCacheVersion, BYTE *pbFlags)
1460 {
1461     WRAPPER_NO_CONTRACT;
1462     LockHolder lh(this);
1463     return LookupTypeByNameWorker(ssClassName, pvCacheVersion, pbFlags);
1464 }
1465
1466 TypeHandle AppDomain::LookupTypeByNameWorker(const SString &ssClassName, UINT* pvCacheVersion, BYTE *pbFlags)
1467 {
1468     CONTRACTL
1469     {
1470         THROWS;
1471         GC_TRIGGERS;
1472         SUPPORTS_DAC;
1473         PRECONDITION(CheckPointer(pbFlags, NULL_OK));
1474     }
1475     CONTRACTL_END;
1476
1477     *pvCacheVersion = m_vNameToTypeMapVersion;
1478
1479     if (m_pNameToTypeMap == nullptr)
1480         return TypeHandle();  // a null TypeHandle
1481
1482     NameToTypeMapEntry::Key key;
1483     key.m_cchName = ssClassName.GetCount();
1484     key.m_wzName  = ssClassName.GetUnicode();
1485
1486     const NameToTypeMapEntry * pEntry = m_pNameToTypeMap->LookupPtr(key);
1487     if (pEntry == NULL)
1488         return TypeHandle();  // a null TypeHandle
1489
1490     if (pbFlags != NULL)
1491         *pbFlags = pEntry->m_bFlags;
1492
1493     return pEntry->m_typeHandle;
1494 }
1495
1496 PTR_MethodTable AppDomain::LookupTypeByGuid(const GUID & guid)
1497 {
1498     CONTRACTL
1499     {
1500         THROWS;
1501         GC_TRIGGERS;
1502         MODE_ANY;
1503         SUPPORTS_DAC;
1504     }
1505     CONTRACTL_END;
1506
1507     SString sGuid;
1508     {
1509         WCHAR wszGuid[64];
1510         GuidToLPWSTR(guid, wszGuid, _countof(wszGuid));
1511         sGuid.Append(wszGuid);
1512     }
1513     UINT ver;
1514     TypeHandle th = LookupTypeByName(sGuid, &ver, NULL);
1515
1516     if (!th.IsNull())
1517     {
1518         _ASSERTE(!th.IsTypeDesc());
1519         return th.AsMethodTable();
1520     }
1521
1522 #ifdef FEATURE_PREJIT
1523     else
1524     {
1525         // Next look in each ngen'ed image in turn
1526         AssemblyIterator assemblyIterator = IterateAssembliesEx((AssemblyIterationFlags)(
1527             kIncludeLoaded | kIncludeExecution));
1528         CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
1529         while (assemblyIterator.Next(pDomainAssembly.This()))
1530         {
1531             CollectibleAssemblyHolder<Assembly *> pAssembly = pDomainAssembly->GetLoadedAssembly();
1532
1533             DomainAssembly::ModuleIterator i = pDomainAssembly->IterateModules(kModIterIncludeLoaded);
1534             while (i.Next())
1535             {
1536                 Module * pModule = i.GetLoadedModule();
1537                 if (!pModule->HasNativeImage())
1538                     continue;
1539                 _ASSERTE(!pModule->IsCollectible());
1540                 PTR_MethodTable pMT = pModule->LookupTypeByGuid(guid);
1541                 if (pMT != NULL)
1542                 {
1543                     return pMT;
1544                 }
1545             }
1546         }
1547     }
1548 #endif // FEATURE_PREJIT
1549     return NULL;
1550 }
1551
1552 #ifndef DACCESS_COMPILE
1553 void AppDomain::CacheWinRTTypeByGuid(TypeHandle typeHandle)
1554 {
1555     CONTRACTL
1556     {
1557         THROWS;
1558         GC_TRIGGERS;
1559         MODE_ANY;
1560         PRECONDITION(!typeHandle.IsTypeDesc());
1561         PRECONDITION(CanCacheWinRTTypeByGuid(typeHandle));
1562     }
1563     CONTRACTL_END;
1564
1565     PTR_MethodTable pMT = typeHandle.AsMethodTable();
1566
1567     GUID guid;
1568     if (pMT->GetGuidForWinRT(&guid))
1569     {
1570         SString sGuid;
1571
1572         {
1573             WCHAR wszGuid[64];
1574             GuidToLPWSTR(guid, wszGuid, _countof(wszGuid));
1575             sGuid.Append(wszGuid);
1576         }
1577
1578         BYTE bFlags = 0x80;
1579         TypeHandle th;
1580         UINT vCacheVersion;
1581         {
1582             LockHolder lh(this);
1583             th = LookupTypeByNameWorker(sGuid, &vCacheVersion, &bFlags);
1584
1585             if (th.IsNull())
1586             {
1587                 // no other entry with the same GUID exists in the cache
1588                 CacheTypeByNameWorker(sGuid, vCacheVersion, typeHandle, bFlags);
1589             }
1590             else if (typeHandle.AsMethodTable() != th.AsMethodTable() && th.IsProjectedFromWinRT())
1591             {
1592                 // If we found a native WinRT type cached with the same GUID, replace it.
1593                 // Otherwise simply add the new mapping to the cache.
1594                 CacheTypeByNameWorker(sGuid, vCacheVersion, typeHandle, bFlags, TRUE);
1595             }
1596         }
1597     }
1598 }
1599 #endif // DACCESS_COMPILE
1600
1601 void AppDomain::GetCachedWinRTTypes(
1602                         SArray<PTR_MethodTable> * pTypes, 
1603                         SArray<GUID> * pGuids, 
1604                         UINT minEpoch, 
1605                         UINT * pCurEpoch)
1606 {
1607     CONTRACTL
1608     {
1609         THROWS;
1610         GC_TRIGGERS;
1611         MODE_ANY;
1612         SUPPORTS_DAC;
1613     }
1614     CONTRACTL_END;
1615
1616     LockHolder lh(this);
1617
1618     for (auto it = m_pNameToTypeMap->Begin(), end = m_pNameToTypeMap->End(); 
1619             it != end; 
1620             ++it)
1621     {
1622         NameToTypeMapEntry entry = (NameToTypeMapEntry)(*it);
1623         TypeHandle th = entry.m_typeHandle;
1624         if (th.AsMethodTable() != NULL && 
1625             entry.m_key.m_wzName[0] == W('{') &&
1626             entry.m_nEpoch >= minEpoch)
1627         {
1628             _ASSERTE(!th.IsTypeDesc());
1629             PTR_MethodTable pMT = th.AsMethodTable();
1630             // we're parsing the GUID value from the cache, because projected types do not cache the 
1631             // COM GUID in their GetGuid() but rather the legacy GUID
1632             GUID iid;
1633             if (LPWSTRToGuid(&iid, entry.m_key.m_wzName, 38) && iid != GUID_NULL)
1634             {
1635                 pTypes->Append(pMT);
1636                 pGuids->Append(iid);
1637             }
1638         }
1639     }
1640
1641 #ifdef FEATURE_PREJIT
1642     // Next look in each ngen'ed image in turn
1643     AssemblyIterator assemblyIterator = IterateAssembliesEx((AssemblyIterationFlags)(
1644         kIncludeLoaded | kIncludeExecution));
1645     CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
1646     while (assemblyIterator.Next(pDomainAssembly.This()))
1647     {
1648         CollectibleAssemblyHolder<Assembly *> pAssembly = pDomainAssembly->GetLoadedAssembly();
1649
1650         DomainAssembly::ModuleIterator i = pDomainAssembly->IterateModules(kModIterIncludeLoaded);
1651         while (i.Next())
1652         {
1653             Module * pModule = i.GetLoadedModule();
1654             if (!pModule->HasNativeImage())
1655                 continue;
1656             _ASSERTE(!pModule->IsCollectible());
1657
1658             pModule->GetCachedWinRTTypes(pTypes, pGuids);
1659         }
1660     }
1661 #endif // FEATURE_PREJIT
1662
1663     if (pCurEpoch != NULL)
1664         *pCurEpoch = m_nEpoch;
1665     ++m_nEpoch;
1666 }
1667
1668 #ifndef CROSSGEN_COMPILE
1669 #ifndef DACCESS_COMPILE
1670 // static
1671 void WinRTFactoryCacheTraits::OnDestructPerEntryCleanupAction(const WinRTFactoryCacheEntry& e)
1672 {
1673     WRAPPER_NO_CONTRACT;
1674     if (e.m_pCtxEntry != NULL)
1675     {
1676         e.m_pCtxEntry->Release();
1677     }
1678     // the AD is going away, no need to destroy the OBJECTHANDLE
1679 }
1680
1681 void AppDomain::CacheWinRTFactoryObject(MethodTable *pClassMT, OBJECTREF *refFactory, LPVOID lpCtxCookie)
1682 {
1683     CONTRACTL
1684     {
1685         THROWS;
1686         GC_TRIGGERS;
1687         MODE_COOPERATIVE;
1688         PRECONDITION(CheckPointer(pClassMT));
1689     }
1690     CONTRACTL_END;
1691
1692     CtxEntryHolder pNewCtxEntry;
1693     if (lpCtxCookie != NULL)
1694     {
1695         // We don't want to insert the context cookie in the cache because it's just an address
1696         // of an internal COM data structure which will be freed when the apartment is torn down.
1697         // What's worse, if another apartment is later created, its context cookie may have exactly
1698         // the same value leading to incorrect cache hits. We'll use our CtxEntry instead which
1699         // is ref-counted and keeps the COM data structure alive even after the apartment ceases
1700         // to exist.
1701         pNewCtxEntry = CtxEntryCache::GetCtxEntryCache()->FindCtxEntry(lpCtxCookie, GetThread());
1702     }
1703
1704     WinRTFactoryCacheLockHolder lh(this);
1705
1706     if (m_pWinRTFactoryCache == nullptr)
1707     {
1708         m_pWinRTFactoryCache = new WinRTFactoryCache();
1709     }
1710
1711     WinRTFactoryCacheEntry *pEntry = const_cast<WinRTFactoryCacheEntry*>(m_pWinRTFactoryCache->LookupPtr(pClassMT));
1712     if (!pEntry)
1713     {
1714         //
1715         // No existing entry for this cache
1716         // Create a new one
1717         //
1718         WinRTFactoryCacheEntry e;
1719
1720         OBJECTHANDLEHolder ohNewHandle(CreateHandle(*refFactory));
1721
1722         e.key               = pClassMT;
1723         e.m_pCtxEntry       = pNewCtxEntry;
1724         e.m_ohFactoryObject = ohNewHandle;
1725
1726         m_pWinRTFactoryCache->Add(e);
1727      
1728         // suppress release of the CtxEntry and handle after we successfully inserted the new entry
1729         pNewCtxEntry.SuppressRelease();
1730         ohNewHandle.SuppressRelease();
1731     }
1732     else
1733     {
1734         //
1735         // Existing entry
1736         //
1737         // release the old CtxEntry and update the entry
1738         CtxEntry *pTemp = pNewCtxEntry.Extract();
1739         pNewCtxEntry = pEntry->m_pCtxEntry;
1740         pEntry->m_pCtxEntry = pTemp;
1741
1742         IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager();
1743         mgr->StoreObjectInHandle(pEntry->m_ohFactoryObject, OBJECTREFToObject(*refFactory));
1744     }
1745 }
1746
1747 OBJECTREF AppDomain::LookupWinRTFactoryObject(MethodTable *pClassMT, LPVOID lpCtxCookie)
1748 {
1749     CONTRACTL
1750     {
1751         THROWS;
1752         GC_NOTRIGGER;
1753         MODE_COOPERATIVE;
1754         PRECONDITION(CheckPointer(pClassMT));
1755         PRECONDITION(CheckPointer(m_pWinRTFactoryCache, NULL_OK));
1756     }
1757     CONTRACTL_END;
1758
1759
1760     if (m_pWinRTFactoryCache == nullptr)
1761         return NULL;
1762             
1763     //
1764     // Retrieve cached factory
1765     //
1766     WinRTFactoryCacheLockHolder lh(this);
1767
1768     const WinRTFactoryCacheEntry *pEntry = m_pWinRTFactoryCache->LookupPtr(pClassMT);
1769     if (pEntry == NULL)
1770         return NULL;
1771     
1772     //
1773     // Ignore factories from a different context, unless lpCtxCookie == NULL, 
1774     // which means the factory is free-threaded
1775     // Note that we cannot touch the RCW to retrieve cookie at this point
1776     // because the RCW might belong to a STA thread and that STA thread might die
1777     // and take the RCW with it. Therefore we have to save cookie in this cache    
1778     //
1779     if (pEntry->m_pCtxEntry == NULL || pEntry->m_pCtxEntry->GetCtxCookie() == lpCtxCookie)
1780         return ObjectFromHandle(pEntry->m_ohFactoryObject);
1781     
1782     return NULL;
1783 }
1784
1785 void AppDomain::RemoveWinRTFactoryObjects(LPVOID pCtxCookie)
1786 {
1787     CONTRACTL
1788     {
1789         THROWS;
1790         GC_TRIGGERS;
1791         MODE_ANY;
1792     }
1793     CONTRACTL_END;
1794
1795     if (m_pWinRTFactoryCache == nullptr)
1796         return;
1797
1798     // helper class for delayed CtxEntry cleanup
1799     class CtxEntryListReleaseHolder
1800     {
1801     public:
1802         CQuickArrayList<CtxEntry *> m_list;
1803
1804         ~CtxEntryListReleaseHolder()
1805         {
1806             CONTRACTL
1807             {
1808                 NOTHROW;
1809                 GC_TRIGGERS;
1810                 MODE_ANY;
1811             }
1812             CONTRACTL_END;
1813
1814             for (SIZE_T i = 0; i < m_list.Size(); i++)
1815             {
1816                 m_list[i]->Release();
1817             }
1818         }
1819     } ctxEntryListReleaseHolder;
1820
1821     GCX_COOP();
1822     {
1823         WinRTFactoryCacheLockHolder lh(this);
1824
1825         // Go through the hash table and remove items in the given context
1826         for (WinRTFactoryCache::Iterator it = m_pWinRTFactoryCache->Begin(); it != m_pWinRTFactoryCache->End(); it++)
1827         {
1828             if (it->m_pCtxEntry != NULL && it->m_pCtxEntry->GetCtxCookie() == pCtxCookie)
1829             {
1830                 // Releasing the CtxEntry may trigger GC which we can't do under the lock so we push
1831                 // it on our local list and release them all after we're done iterating the hashtable.
1832                 ctxEntryListReleaseHolder.m_list.Push(it->m_pCtxEntry);
1833
1834                 DestroyHandle(it->m_ohFactoryObject);
1835                 m_pWinRTFactoryCache->Remove(it);
1836             }
1837         }
1838     }
1839 }
1840
1841 OBJECTREF AppDomain::GetMissingObject()
1842 {
1843     CONTRACTL
1844     {
1845         THROWS;
1846         GC_TRIGGERS;
1847         MODE_COOPERATIVE;
1848     }
1849     CONTRACTL_END;
1850
1851     if (!m_hndMissing)
1852     {
1853         // Get the field
1854         FieldDesc *pValueFD = MscorlibBinder::GetField(FIELD__MISSING__VALUE);
1855
1856         pValueFD->CheckRunClassInitThrowing();
1857
1858         // Retrieve the value static field and store it.
1859         OBJECTHANDLE hndMissing = CreateHandle(pValueFD->GetStaticOBJECTREF());
1860
1861         if (FastInterlockCompareExchangePointer(&m_hndMissing, hndMissing, NULL) != NULL)
1862         {
1863             // Exchanged failed. The m_hndMissing did not equal NULL and was returned.
1864             DestroyHandle(hndMissing);
1865         }
1866     }
1867
1868     return ObjectFromHandle(m_hndMissing);
1869 }
1870
1871 #endif // DACCESS_COMPILE
1872 #endif //CROSSGEN_COMPILE
1873 #endif // FEATURE_COMINTEROP
1874
1875 #ifndef DACCESS_COMPILE
1876
1877 EEMarshalingData *BaseDomain::GetMarshalingData()
1878 {
1879     CONTRACT (EEMarshalingData*)
1880     {
1881         THROWS;
1882         GC_TRIGGERS;
1883         MODE_ANY;
1884         INJECT_FAULT(COMPlusThrowOM());
1885         POSTCONDITION(CheckPointer(m_pMarshalingData));
1886     }
1887     CONTRACT_END;
1888
1889     if (!m_pMarshalingData)
1890     {
1891         // Take the lock
1892         CrstHolder holder(&m_InteropDataCrst);
1893
1894         if (!m_pMarshalingData)
1895         {
1896             LoaderHeap* pHeap = GetLoaderAllocator()->GetLowFrequencyHeap();
1897             m_pMarshalingData = new (pHeap) EEMarshalingData(this, pHeap, &m_DomainCrst);
1898         }
1899     }
1900
1901     RETURN m_pMarshalingData;
1902 }
1903
1904 void BaseDomain::DeleteMarshalingData()
1905 {
1906     CONTRACTL
1907     {
1908         NOTHROW;
1909         GC_TRIGGERS;
1910         MODE_ANY;
1911     }
1912     CONTRACTL_END;
1913
1914     // We are in shutdown - no need to take any lock
1915     if (m_pMarshalingData)
1916     {
1917         delete m_pMarshalingData;
1918         m_pMarshalingData = NULL;
1919     }
1920 }
1921
1922 #ifndef CROSSGEN_COMPILE
1923
1924 STRINGREF *BaseDomain::IsStringInterned(STRINGREF *pString)
1925 {
1926     CONTRACTL
1927     {
1928         GC_TRIGGERS;
1929         THROWS;
1930         MODE_COOPERATIVE;
1931         PRECONDITION(CheckPointer(pString));
1932         INJECT_FAULT(COMPlusThrowOM(););
1933     }
1934     CONTRACTL_END;
1935
1936     return GetLoaderAllocator()->IsStringInterned(pString);
1937 }
1938
1939 STRINGREF *BaseDomain::GetOrInternString(STRINGREF *pString)
1940 {
1941     CONTRACTL
1942     {
1943         GC_TRIGGERS;
1944         THROWS;
1945         MODE_COOPERATIVE;
1946         PRECONDITION(CheckPointer(pString));
1947         INJECT_FAULT(COMPlusThrowOM(););
1948     }
1949     CONTRACTL_END;
1950
1951     return GetLoaderAllocator()->GetOrInternString(pString);
1952 }
1953
1954 void BaseDomain::InitLargeHeapHandleTable()
1955 {
1956     CONTRACTL
1957     {
1958         THROWS;
1959         GC_TRIGGERS;
1960         MODE_ANY;
1961         PRECONDITION(m_pLargeHeapHandleTable==NULL);
1962         INJECT_FAULT(COMPlusThrowOM(););
1963     }
1964     CONTRACTL_END;
1965
1966     m_pLargeHeapHandleTable = new LargeHeapHandleTable(this, STATIC_OBJECT_TABLE_BUCKET_SIZE);
1967
1968 #ifdef _DEBUG
1969     m_pLargeHeapHandleTable->RegisterCrstDebug(&m_LargeHeapHandleTableCrst);
1970 #endif
1971 }
1972
1973 #ifdef FEATURE_COMINTEROP
1974 MethodTable* AppDomain::GetLicenseInteropHelperMethodTable()
1975 {
1976     CONTRACTL
1977     {
1978         THROWS;
1979         GC_TRIGGERS;
1980     }
1981     CONTRACTL_END;
1982
1983     if(m_pLicenseInteropHelperMT == NULL)
1984     {
1985         // Do this work outside of the lock so we don't have an unbreakable lock condition
1986
1987         TypeHandle licenseMgrTypeHnd;
1988         MethodDescCallSite  loadLM(METHOD__MARSHAL__LOAD_LICENSE_MANAGER);
1989
1990         licenseMgrTypeHnd = (MethodTable*) loadLM.Call_RetLPVOID((ARG_SLOT*)NULL);
1991
1992         //
1993         // Look up this method by name, because the type is actually declared in System.dll.  <TODO>@todo: why?</TODO>
1994         //
1995
1996         MethodDesc *pGetLIHMD = MemberLoader::FindMethod(licenseMgrTypeHnd.AsMethodTable(),
1997                 "GetLicenseInteropHelperType", &gsig_SM_Void_RetIntPtr);
1998         _ASSERTE(pGetLIHMD);
1999
2000         TypeHandle lihTypeHnd;
2001
2002         MethodDescCallSite getLIH(pGetLIHMD);
2003         lihTypeHnd = (MethodTable*) getLIH.Call_RetLPVOID((ARG_SLOT*)NULL);
2004
2005         BaseDomain::LockHolder lh(this);
2006
2007         if(m_pLicenseInteropHelperMT == NULL)
2008             m_pLicenseInteropHelperMT = lihTypeHnd.AsMethodTable();
2009     }
2010     return m_pLicenseInteropHelperMT;
2011 }
2012
2013 COMorRemotingFlag AppDomain::GetComOrRemotingFlag()
2014 {
2015     CONTRACTL
2016     {
2017         NOTHROW;
2018         GC_TRIGGERS;
2019         MODE_ANY;
2020     }
2021     CONTRACTL_END;
2022
2023     // 0. check if the value is already been set
2024     if (m_COMorRemotingFlag != COMorRemoting_NotInitialized)
2025         return m_COMorRemotingFlag;
2026
2027     // 1. check whether the process is AppX
2028     if (AppX::IsAppXProcess())
2029     {
2030         // do not use Remoting in AppX
2031         m_COMorRemotingFlag = COMorRemoting_COM;
2032         return m_COMorRemotingFlag;
2033     }
2034
2035     // 2. check the xml file
2036     m_COMorRemotingFlag = GetPreferComInsteadOfManagedRemotingFromConfigFile();
2037     if (m_COMorRemotingFlag != COMorRemoting_NotInitialized)
2038     {
2039         return m_COMorRemotingFlag;
2040     }
2041
2042     // 3. check the global setting
2043     if (NULL != g_pConfig && g_pConfig->ComInsteadOfManagedRemoting())
2044     {
2045         m_COMorRemotingFlag = COMorRemoting_COM;
2046     }
2047     else
2048     {
2049         m_COMorRemotingFlag = COMorRemoting_Remoting;
2050     }
2051
2052     return m_COMorRemotingFlag;
2053 }
2054
2055 BOOL AppDomain::GetPreferComInsteadOfManagedRemoting()
2056 {
2057     WRAPPER_NO_CONTRACT;
2058
2059     return (GetComOrRemotingFlag() == COMorRemoting_COM);
2060 }
2061
2062 COMorRemotingFlag AppDomain::GetPreferComInsteadOfManagedRemotingFromConfigFile()
2063 {
2064     CONTRACTL
2065     {
2066         NOTHROW;
2067         GC_TRIGGERS;
2068         MODE_ANY;
2069     }
2070     CONTRACTL_END;
2071
2072     return COMorRemoting_COM;
2073 }
2074 #endif // FEATURE_COMINTEROP
2075
2076 #endif // CROSSGEN_COMPILE
2077
2078 //*****************************************************************************
2079 //*****************************************************************************
2080 //*****************************************************************************
2081
2082 void *SystemDomain::operator new(size_t size, void *pInPlace)
2083 {
2084     LIMITED_METHOD_CONTRACT;
2085     return pInPlace;
2086 }
2087
2088
2089 void SystemDomain::operator delete(void *pMem)
2090 {
2091     LIMITED_METHOD_CONTRACT;
2092     // Do nothing - new() was in-place
2093 }
2094
2095
2096 void    SystemDomain::SetCompilationOverrides(BOOL fForceDebug,
2097                                               BOOL fForceProfiling,
2098                                               BOOL fForceInstrument)
2099 {
2100     LIMITED_METHOD_CONTRACT;
2101     s_fForceDebug = fForceDebug;
2102     s_fForceProfiling = fForceProfiling;
2103     s_fForceInstrument = fForceInstrument;
2104 }
2105
2106 #endif //!DACCESS_COMPILE
2107
2108 void    SystemDomain::GetCompilationOverrides(BOOL * fForceDebug,
2109                                               BOOL * fForceProfiling,
2110                                               BOOL * fForceInstrument)
2111 {
2112     LIMITED_METHOD_DAC_CONTRACT;
2113     *fForceDebug = s_fForceDebug;
2114     *fForceProfiling = s_fForceProfiling;
2115     *fForceInstrument = s_fForceInstrument;
2116 }
2117
2118 #ifndef DACCESS_COMPILE
2119
2120 void SystemDomain::Attach()
2121 {
2122     CONTRACTL
2123     {
2124         THROWS;
2125         GC_TRIGGERS;
2126         MODE_ANY;
2127         PRECONDITION(m_pSystemDomain == NULL);
2128         INJECT_FAULT(COMPlusThrowOM(););
2129     }
2130     CONTRACTL_END;
2131
2132 #ifndef CROSSGEN_COMPILE
2133     // Initialize stub managers
2134     PrecodeStubManager::Init();
2135     DelegateInvokeStubManager::Init();
2136     JumpStubStubManager::Init();
2137     RangeSectionStubManager::Init();
2138     ILStubManager::Init();
2139     InteropDispatchStubManager::Init();
2140     StubLinkStubManager::Init();
2141
2142     ThunkHeapStubManager::Init();
2143
2144     TailCallStubManager::Init();
2145
2146     PerAppDomainTPCountList::InitAppDomainIndexList();
2147 #endif // CROSSGEN_COMPILE
2148
2149     m_appDomainIndexList.Init();
2150     m_appDomainIdList.Init();
2151
2152     m_SystemDomainCrst.Init(CrstSystemDomain, (CrstFlags)(CRST_REENTRANCY | CRST_TAKEN_DURING_SHUTDOWN));
2153     m_DelayedUnloadCrst.Init(CrstSystemDomainDelayedUnloadList, CRST_UNSAFE_COOPGC);
2154
2155     // Initialize the ID dispenser that is used for domain neutral module IDs
2156     g_pModuleIndexDispenser = new IdDispenser();
2157
2158     // Create the global SystemDomain and initialize it.
2159     m_pSystemDomain = new (&g_pSystemDomainMemory[0]) SystemDomain();
2160     // No way it can fail since g_pSystemDomainMemory is a static array.
2161     CONSISTENCY_CHECK(CheckPointer(m_pSystemDomain));
2162
2163     LOG((LF_CLASSLOADER,
2164          LL_INFO10,
2165          "Created system domain at %p\n",
2166          m_pSystemDomain));
2167
2168     // We need to initialize the memory pools etc. for the system domain.
2169     m_pSystemDomain->BaseDomain::Init(); // Setup the memory heaps
2170
2171     // Create the default domain
2172     m_pSystemDomain->CreateDefaultDomain();
2173     SharedDomain::Attach();
2174
2175     // Each domain gets its own ReJitManager, and ReJitManager has its own static
2176     // initialization to run
2177     ReJitManager::InitStatic();
2178 }
2179
2180 #ifndef CROSSGEN_COMPILE
2181
2182 void SystemDomain::DetachBegin()
2183 {
2184     WRAPPER_NO_CONTRACT;
2185     // Shut down the domain and its children (but don't deallocate anything just
2186     // yet).
2187
2188     // TODO: we should really not running managed DLLMain during process detach.
2189     if (GetThread() == NULL)
2190     {
2191         return;
2192     }
2193
2194     if(m_pSystemDomain)
2195         m_pSystemDomain->Stop();
2196 }
2197
2198 void SystemDomain::DetachEnd()
2199 {
2200     CONTRACTL
2201     {
2202         NOTHROW;
2203         GC_TRIGGERS;
2204         MODE_ANY;
2205     }
2206     CONTRACTL_END;
2207     // Shut down the domain and its children (but don't deallocate anything just
2208     // yet).
2209     if(m_pSystemDomain)
2210     {
2211         GCX_PREEMP();
2212         m_pSystemDomain->ClearFusionContext();
2213         if (m_pSystemDomain->m_pDefaultDomain)
2214             m_pSystemDomain->m_pDefaultDomain->ClearFusionContext();
2215     }
2216 }
2217
2218 void SystemDomain::Stop()
2219 {
2220     WRAPPER_NO_CONTRACT;
2221     AppDomainIterator i(TRUE);
2222
2223     while (i.Next())
2224         if (i.GetDomain()->m_Stage < AppDomain::STAGE_CLEARED)
2225             i.GetDomain()->Stop();
2226 }
2227
2228
2229 void SystemDomain::Terminate() // bNotifyProfiler is ignored
2230 {
2231     CONTRACTL
2232     {
2233         NOTHROW;
2234         GC_TRIGGERS;
2235         MODE_ANY;
2236     }
2237     CONTRACTL_END;
2238
2239     // This ignores the refences and terminates the appdomains
2240     AppDomainIterator i(FALSE);
2241
2242     while (i.Next())
2243     {
2244         delete i.GetDomain();
2245         // Keep the iterator from Releasing the current domain
2246         i.m_pCurrent = NULL;
2247     }
2248
2249     if (m_pSystemFile != NULL) {
2250         m_pSystemFile->Release();
2251         m_pSystemFile = NULL;
2252     }
2253
2254     m_pSystemAssembly = NULL;
2255
2256     if(m_pwDevpath) {
2257         delete[] m_pwDevpath;
2258         m_pwDevpath = NULL;
2259     }
2260     m_dwDevpath = 0;
2261     m_fDevpath = FALSE;
2262
2263     if (m_pGlobalStringLiteralMap) {
2264         delete m_pGlobalStringLiteralMap;
2265         m_pGlobalStringLiteralMap = NULL;
2266     }
2267
2268
2269     SharedDomain::Detach();
2270
2271     BaseDomain::Terminate();
2272
2273 #ifdef FEATURE_COMINTEROP
2274     if (g_pRCWCleanupList != NULL)
2275         delete g_pRCWCleanupList;
2276 #endif // FEATURE_COMINTEROP
2277     m_GlobalAllocator.Terminate();
2278 }
2279
2280
2281 void SystemDomain::PreallocateSpecialObjects()
2282 {
2283     CONTRACTL
2284     {
2285         THROWS;
2286         GC_TRIGGERS;
2287         MODE_COOPERATIVE;
2288         INJECT_FAULT(COMPlusThrowOM(););
2289     }
2290     CONTRACTL_END;
2291
2292     _ASSERTE(g_pPreallocatedSentinelObject == NULL);
2293
2294     OBJECTREF pPreallocatedSentinalObject = AllocateObject(g_pObjectClass);
2295 #if CHECK_APP_DOMAIN_LEAKS
2296     pPreallocatedSentinalObject->SetSyncBlockAppDomainAgile();
2297 #endif
2298     g_pPreallocatedSentinelObject = CreatePinningHandle( pPreallocatedSentinalObject );
2299
2300 #ifdef FEATURE_PREJIT
2301     if (SystemModule()->HasNativeImage())
2302     {
2303         CORCOMPILE_EE_INFO_TABLE *pEEInfo = SystemModule()->GetNativeImage()->GetNativeEEInfoTable();
2304         pEEInfo->emptyString = (CORINFO_Object **)StringObject::GetEmptyStringRefPtr();
2305     }
2306 #endif
2307 }
2308
2309 void SystemDomain::CreatePreallocatedExceptions()
2310 {
2311     CONTRACTL
2312     {
2313         THROWS;
2314         GC_TRIGGERS;
2315         MODE_COOPERATIVE;
2316         INJECT_FAULT(COMPlusThrowOM(););
2317     }
2318     CONTRACTL_END;
2319
2320     EXCEPTIONREF pBaseException = (EXCEPTIONREF)AllocateObject(g_pExceptionClass);
2321     pBaseException->SetHResult(COR_E_EXCEPTION);
2322     pBaseException->SetXCode(EXCEPTION_COMPLUS);
2323     _ASSERTE(g_pPreallocatedBaseException == NULL);
2324     g_pPreallocatedBaseException = CreateHandle(pBaseException);
2325
2326
2327     EXCEPTIONREF pOutOfMemory = (EXCEPTIONREF)AllocateObject(g_pOutOfMemoryExceptionClass);
2328     pOutOfMemory->SetHResult(COR_E_OUTOFMEMORY);
2329     pOutOfMemory->SetXCode(EXCEPTION_COMPLUS);
2330     _ASSERTE(g_pPreallocatedOutOfMemoryException == NULL);
2331     g_pPreallocatedOutOfMemoryException = CreateHandle(pOutOfMemory);
2332
2333
2334     EXCEPTIONREF pStackOverflow = (EXCEPTIONREF)AllocateObject(g_pStackOverflowExceptionClass);
2335     pStackOverflow->SetHResult(COR_E_STACKOVERFLOW);
2336     pStackOverflow->SetXCode(EXCEPTION_COMPLUS);
2337     _ASSERTE(g_pPreallocatedStackOverflowException == NULL);
2338     g_pPreallocatedStackOverflowException = CreateHandle(pStackOverflow);
2339
2340
2341     EXCEPTIONREF pExecutionEngine = (EXCEPTIONREF)AllocateObject(g_pExecutionEngineExceptionClass);
2342     pExecutionEngine->SetHResult(COR_E_EXECUTIONENGINE);
2343     pExecutionEngine->SetXCode(EXCEPTION_COMPLUS);
2344     _ASSERTE(g_pPreallocatedExecutionEngineException == NULL);
2345     g_pPreallocatedExecutionEngineException = CreateHandle(pExecutionEngine);
2346
2347
2348     EXCEPTIONREF pRudeAbortException = (EXCEPTIONREF)AllocateObject(g_pThreadAbortExceptionClass);
2349 #if CHECK_APP_DOMAIN_LEAKS
2350     pRudeAbortException->SetSyncBlockAppDomainAgile();
2351 #endif
2352     pRudeAbortException->SetHResult(COR_E_THREADABORTED);
2353     pRudeAbortException->SetXCode(EXCEPTION_COMPLUS);
2354     _ASSERTE(g_pPreallocatedRudeThreadAbortException == NULL);
2355     g_pPreallocatedRudeThreadAbortException = CreateHandle(pRudeAbortException);
2356
2357
2358     EXCEPTIONREF pAbortException = (EXCEPTIONREF)AllocateObject(g_pThreadAbortExceptionClass);
2359 #if CHECK_APP_DOMAIN_LEAKS
2360     pAbortException->SetSyncBlockAppDomainAgile();
2361 #endif
2362     pAbortException->SetHResult(COR_E_THREADABORTED);
2363     pAbortException->SetXCode(EXCEPTION_COMPLUS);
2364     _ASSERTE(g_pPreallocatedThreadAbortException == NULL);
2365     g_pPreallocatedThreadAbortException = CreateHandle( pAbortException );
2366 }
2367 #endif // CROSSGEN_COMPILE
2368
2369 void SystemDomain::Init()
2370 {
2371     STANDARD_VM_CONTRACT;
2372
2373     HRESULT hr = S_OK;
2374
2375 #ifdef _DEBUG
2376     LOG((
2377         LF_EEMEM,
2378         LL_INFO10,
2379         "sizeof(EEClass)     = %d\n"
2380         "sizeof(MethodTable) = %d\n"
2381         "sizeof(MethodDesc)= %d\n"
2382         "sizeof(FieldDesc)   = %d\n"
2383         "sizeof(Module)      = %d\n",
2384         sizeof(EEClass),
2385         sizeof(MethodTable),
2386         sizeof(MethodDesc),
2387         sizeof(FieldDesc),
2388         sizeof(Module)
2389     ));
2390 #endif // _DEBUG
2391
2392     // The base domain is initialized in SystemDomain::Attach()
2393     // to allow stub caches to use the memory pool. Do not
2394     // initialze it here!
2395
2396 #ifndef CROSSGEN_COMPILE
2397 #ifdef _DEBUG
2398     Context     *curCtx = GetCurrentContext();
2399 #endif
2400     _ASSERTE(curCtx);
2401     _ASSERTE(curCtx->GetDomain() != NULL);
2402 #endif
2403
2404 #ifdef FEATURE_PREJIT
2405     if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_ZapDisable) != 0)
2406         g_fAllowNativeImages = false;
2407 #endif
2408
2409     m_pSystemFile = NULL;
2410     m_pSystemAssembly = NULL;
2411
2412     DWORD size = 0;
2413
2414
2415     // Get the install directory so we can find mscorlib
2416     hr = GetInternalSystemDirectory(NULL, &size);
2417     if (hr != HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
2418         ThrowHR(hr);
2419
2420     // GetInternalSystemDirectory returns a size, including the null!
2421     WCHAR *buffer = m_SystemDirectory.OpenUnicodeBuffer(size-1);
2422     IfFailThrow(GetInternalSystemDirectory(buffer, &size));
2423     m_SystemDirectory.CloseBuffer();
2424     m_SystemDirectory.Normalize();
2425
2426     // At this point m_SystemDirectory should already be canonicalized
2427
2428
2429     m_BaseLibrary.Append(m_SystemDirectory);
2430     if (!m_BaseLibrary.EndsWith(DIRECTORY_SEPARATOR_CHAR_W))
2431     {
2432         m_BaseLibrary.Append(DIRECTORY_SEPARATOR_CHAR_W);
2433     }
2434     m_BaseLibrary.Append(g_pwBaseLibrary);
2435     m_BaseLibrary.Normalize();
2436
2437     LoadBaseSystemClasses();
2438
2439     {
2440         // We are about to start allocating objects, so we must be in cooperative mode.
2441         // However, many of the entrypoints to the system (DllGetClassObject and all
2442         // N/Direct exports) get called multiple times.  Sometimes they initialize the EE,
2443         // but generally they remain in preemptive mode.  So we really want to push/pop
2444         // the state here:
2445         GCX_COOP();
2446
2447 #ifndef CROSSGEN_COMPILE
2448         if (!NingenEnabled())
2449         {
2450             CreatePreallocatedExceptions();
2451
2452             PreallocateSpecialObjects();
2453         }
2454 #endif
2455
2456         // Finish loading mscorlib now.
2457         m_pSystemAssembly->GetDomainAssembly()->EnsureActive();
2458     }
2459
2460 #ifdef _DEBUG
2461     BOOL fPause = EEConfig::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_PauseOnLoad, FALSE);
2462
2463     while(fPause)
2464     {
2465         ClrSleepEx(20, TRUE);
2466     }
2467 #endif // _DEBUG
2468 }
2469
2470 #ifndef CROSSGEN_COMPILE
2471 void SystemDomain::LazyInitGlobalStringLiteralMap()
2472 {
2473     CONTRACTL
2474     {
2475         THROWS;
2476         GC_TRIGGERS;
2477         MODE_ANY;
2478         INJECT_FAULT(COMPlusThrowOM(););
2479     }
2480     CONTRACTL_END;
2481
2482     // Allocate the global string literal map.
2483     NewHolder<GlobalStringLiteralMap> pGlobalStringLiteralMap(new GlobalStringLiteralMap());
2484
2485     // Initialize the global string literal map.
2486     pGlobalStringLiteralMap->Init();
2487
2488     if (InterlockedCompareExchangeT<GlobalStringLiteralMap *>(&m_pGlobalStringLiteralMap, pGlobalStringLiteralMap, NULL) == NULL)
2489     {
2490         pGlobalStringLiteralMap.SuppressRelease();
2491     }
2492 }
2493
2494 void AppDomain::CreateADUnloadStartEvent()
2495 {
2496     CONTRACTL
2497     {
2498         THROWS;
2499         GC_NOTRIGGER;
2500         SO_TOLERANT;
2501         MODE_ANY;
2502     }
2503     CONTRACTL_END;
2504
2505     g_pUnloadStartEvent = new CLREvent();
2506     g_pUnloadStartEvent->CreateAutoEvent(FALSE);
2507 }
2508
2509 /*static*/ void SystemDomain::EnumAllStaticGCRefs(promote_func* fn, ScanContext* sc)
2510 {
2511     CONTRACT_VOID
2512     {
2513         NOTHROW;
2514         GC_NOTRIGGER;
2515         MODE_COOPERATIVE;
2516     }
2517     CONTRACT_END;
2518
2519     // We don't do a normal AppDomainIterator because we can't take the SystemDomain lock from
2520     // here.
2521     // We're only supposed to call this from a Server GC. We're walking here m_appDomainIdList
2522     // m_appDomainIdList will have an AppDomain* or will be NULL. So the only danger is if we
2523     // Fetch an AppDomain and then in some other thread the AppDomain is deleted.
2524     //
2525     // If the thread deleting the AppDomain (AppDomain::~AppDomain)was in Preemptive mode
2526     // while doing SystemDomain::EnumAllStaticGCRefs we will issue a GCX_COOP(), which will wait
2527     // for the GC to finish, so we are safe
2528     //
2529     // If the thread is in cooperative mode, it must have been suspended for the GC so a delete
2530     // can't happen.
2531
2532     _ASSERTE(GCHeapUtilities::IsGCInProgress() &&
2533              GCHeapUtilities::IsServerHeap()   &&
2534              IsGCSpecialThread());
2535
2536     SystemDomain* sysDomain = SystemDomain::System();
2537     if (sysDomain)
2538     {
2539         DWORD i;
2540         DWORD count = (DWORD) m_appDomainIdList.GetCount();
2541         for (i = 0 ; i < count ; i++)
2542         {
2543             AppDomain* pAppDomain = (AppDomain *)m_appDomainIdList.Get(i);
2544             if (pAppDomain && pAppDomain->IsActive() && !pAppDomain->IsUnloading())
2545             {
2546 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
2547                 if (g_fEnableARM)
2548                 {
2549                     sc->pCurrentDomain = pAppDomain;
2550                 }
2551 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
2552                 pAppDomain->EnumStaticGCRefs(fn, sc);
2553             }
2554         }
2555     }
2556
2557     RETURN;
2558 }
2559
2560 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
2561 void SystemDomain::ResetADSurvivedBytes()
2562 {
2563     CONTRACT_VOID
2564     {
2565         NOTHROW;
2566         GC_NOTRIGGER;
2567         MODE_ANY;
2568     }
2569     CONTRACT_END;
2570
2571     _ASSERTE(GCHeapUtilities::IsGCInProgress());
2572
2573     SystemDomain* sysDomain = SystemDomain::System();
2574     if (sysDomain)
2575     {
2576         DWORD i;
2577         DWORD count = (DWORD) m_appDomainIdList.GetCount();
2578         for (i = 0 ; i < count ; i++)
2579         {
2580             AppDomain* pAppDomain = (AppDomain *)m_appDomainIdList.Get(i);
2581             if (pAppDomain && pAppDomain->IsUserActive())
2582             {
2583                 pAppDomain->ResetSurvivedBytes();
2584             }
2585         }
2586     }
2587
2588     RETURN;
2589 }
2590
2591 ULONGLONG SystemDomain::GetADSurvivedBytes()
2592 {
2593     CONTRACTL
2594     {
2595         NOTHROW;
2596         GC_NOTRIGGER;
2597         MODE_ANY;
2598     }
2599     CONTRACTL_END;
2600
2601     SystemDomain* sysDomain = SystemDomain::System();
2602     ULONGLONG ullTotalADSurvived = 0;
2603     if (sysDomain)
2604     {
2605         DWORD i;
2606         DWORD count = (DWORD) m_appDomainIdList.GetCount();
2607         for (i = 0 ; i < count ; i++)
2608         {
2609             AppDomain* pAppDomain = (AppDomain *)m_appDomainIdList.Get(i);
2610             if (pAppDomain && pAppDomain->IsUserActive())
2611             {
2612                 ULONGLONG ullSurvived = pAppDomain->GetSurvivedBytes();
2613                 ullTotalADSurvived += ullSurvived;
2614             }
2615         }
2616     }
2617
2618     return ullTotalADSurvived;
2619 }
2620
2621 void SystemDomain::RecordTotalSurvivedBytes(size_t totalSurvivedBytes)
2622 {
2623     CONTRACT_VOID
2624     {
2625         NOTHROW;
2626         GC_NOTRIGGER;
2627         MODE_ANY;
2628     }
2629     CONTRACT_END;
2630
2631     m_totalSurvivedBytes = totalSurvivedBytes;
2632
2633     SystemDomain* sysDomain = SystemDomain::System();
2634     if (sysDomain)
2635     {
2636         DWORD i;
2637         DWORD count = (DWORD) m_appDomainIdList.GetCount();
2638         for (i = 0 ; i < count ; i++)
2639         {
2640             AppDomain* pAppDomain = (AppDomain *)m_appDomainIdList.Get(i);
2641             if (pAppDomain && pAppDomain->IsUserActive())
2642             {
2643                 FireEtwAppDomainMemSurvived((ULONGLONG)pAppDomain, pAppDomain->GetSurvivedBytes(), totalSurvivedBytes, GetClrInstanceId());
2644             }
2645         }
2646     }
2647
2648     RETURN;
2649 }
2650 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
2651
2652 // Only called when EE is suspended.
2653 DWORD SystemDomain::GetTotalNumSizedRefHandles()
2654 {
2655     CONTRACTL
2656     {
2657         NOTHROW;
2658         GC_NOTRIGGER;
2659         MODE_ANY;
2660     }
2661     CONTRACTL_END;
2662
2663     SystemDomain* sysDomain = SystemDomain::System();
2664     DWORD dwTotalNumSizedRefHandles = 0;
2665     if (sysDomain)
2666     {
2667         DWORD i;
2668         DWORD count = (DWORD) m_appDomainIdList.GetCount();
2669         for (i = 0 ; i < count ; i++)
2670         {
2671             AppDomain* pAppDomain = (AppDomain *)m_appDomainIdList.Get(i);
2672             if (pAppDomain && pAppDomain->IsActive() && !pAppDomain->IsUnloading())
2673             {
2674                 dwTotalNumSizedRefHandles += pAppDomain->GetNumSizedRefHandles();
2675             }
2676         }
2677     }
2678
2679     return dwTotalNumSizedRefHandles;
2680 }
2681 #endif // CROSSGEN_COMPILE
2682
2683 void SystemDomain::LoadBaseSystemClasses()
2684 {
2685     STANDARD_VM_CONTRACT;
2686
2687     ETWOnStartup(LdSysBases_V1, LdSysBasesEnd_V1);
2688
2689     {
2690         m_pSystemFile = PEAssembly::OpenSystem(NULL);
2691     }
2692     // Only partially load the system assembly. Other parts of the code will want to access
2693     // the globals in this function before finishing the load.
2694     m_pSystemAssembly = DefaultDomain()->LoadDomainAssembly(NULL, m_pSystemFile, FILE_LOAD_POST_LOADLIBRARY)->GetCurrentAssembly();
2695
2696     // Set up binder for mscorlib
2697     MscorlibBinder::AttachModule(m_pSystemAssembly->GetManifestModule());
2698
2699     // Load Object
2700     g_pObjectClass = MscorlibBinder::GetClass(CLASS__OBJECT);
2701
2702     // Now that ObjectClass is loaded, we can set up
2703     // the system for finalizers.  There is no point in deferring this, since we need
2704     // to know this before we allocate our first object.
2705     g_pObjectFinalizerMD = MscorlibBinder::GetMethod(METHOD__OBJECT__FINALIZE);
2706
2707
2708     g_pCanonMethodTableClass = MscorlibBinder::GetClass(CLASS____CANON);
2709
2710     // NOTE: !!!IMPORTANT!!! ValueType and Enum MUST be loaded one immediately after
2711     //                       the other, because we have coded MethodTable::IsChildValueType
2712     //                       in such a way that it depends on this behaviour.
2713     // Load the ValueType class
2714     g_pValueTypeClass = MscorlibBinder::GetClass(CLASS__VALUE_TYPE);
2715
2716     // Load the enum class
2717     g_pEnumClass = MscorlibBinder::GetClass(CLASS__ENUM);
2718     _ASSERTE(!g_pEnumClass->IsValueType());
2719
2720     // Load System.RuntimeType
2721     g_pRuntimeTypeClass = MscorlibBinder::GetClass(CLASS__CLASS);
2722     _ASSERTE(g_pRuntimeTypeClass->IsFullyLoaded());
2723
2724     // Load Array class
2725     g_pArrayClass = MscorlibBinder::GetClass(CLASS__ARRAY);
2726
2727     // Calling a method on IList<T> for an array requires redirection to a method on
2728     // the SZArrayHelper class. Retrieving such methods means calling
2729     // GetActualImplementationForArrayGenericIListMethod, which calls FetchMethod for
2730     // the corresponding method on SZArrayHelper. This basically results in a class
2731     // load due to a method call, which the debugger cannot handle, so we pre-load
2732     // the SZArrayHelper class here.
2733     g_pSZArrayHelperClass = MscorlibBinder::GetClass(CLASS__SZARRAYHELPER);
2734
2735     // Load ByReference class
2736     //
2737     // NOTE: ByReference<T> must be the first by-ref-like system type to be loaded,
2738     //       because MethodTable::ClassifyEightBytesWithManagedLayout depends on it.
2739     g_pByReferenceClass = MscorlibBinder::GetClass(CLASS__BYREFERENCE);
2740
2741     // Load Nullable class
2742     g_pNullableClass = MscorlibBinder::GetClass(CLASS__NULLABLE);
2743
2744     // Load the Object array class.
2745     g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT] = ClassLoader::LoadArrayTypeThrowing(TypeHandle(g_pObjectClass)).AsArray();
2746
2747     // We have delayed allocation of mscorlib's static handles until we load the object class
2748     MscorlibBinder::GetModule()->AllocateRegularStaticHandles(DefaultDomain());
2749
2750     g_TypedReferenceMT = MscorlibBinder::GetClass(CLASS__TYPED_REFERENCE);
2751
2752     // Make sure all primitive types are loaded
2753     for (int et = ELEMENT_TYPE_VOID; et <= ELEMENT_TYPE_R8; et++)
2754         MscorlibBinder::LoadPrimitiveType((CorElementType)et);
2755
2756     MscorlibBinder::LoadPrimitiveType(ELEMENT_TYPE_I);
2757     MscorlibBinder::LoadPrimitiveType(ELEMENT_TYPE_U);
2758
2759     // unfortunately, the following cannot be delay loaded since the jit
2760     // uses it to compute method attributes within a function that cannot
2761     // handle Complus exception and the following call goes through a path
2762     // where a complus exception can be thrown. It is unfortunate, because
2763     // we know that the delegate class and multidelegate class are always
2764     // guaranteed to be found.
2765     g_pDelegateClass = MscorlibBinder::GetClass(CLASS__DELEGATE);
2766     g_pMulticastDelegateClass = MscorlibBinder::GetClass(CLASS__MULTICAST_DELEGATE);
2767
2768     // used by IsImplicitInterfaceOfSZArray
2769     MscorlibBinder::GetClass(CLASS__IENUMERABLEGENERIC);
2770     MscorlibBinder::GetClass(CLASS__ICOLLECTIONGENERIC);
2771     MscorlibBinder::GetClass(CLASS__ILISTGENERIC);
2772     MscorlibBinder::GetClass(CLASS__IREADONLYCOLLECTIONGENERIC);
2773     MscorlibBinder::GetClass(CLASS__IREADONLYLISTGENERIC);
2774
2775     // Load String
2776     g_pStringClass = MscorlibBinder::LoadPrimitiveType(ELEMENT_TYPE_STRING);
2777     _ASSERTE(g_pStringClass->GetBaseSize() == ObjSizeOf(StringObject)+sizeof(WCHAR));
2778     _ASSERTE(g_pStringClass->GetComponentSize() == 2);
2779
2780     // Used by Buffer::BlockCopy
2781     g_pByteArrayMT = ClassLoader::LoadArrayTypeThrowing(
2782         TypeHandle(MscorlibBinder::GetElementType(ELEMENT_TYPE_U1))).AsArray()->GetMethodTable();
2783
2784 #ifndef CROSSGEN_COMPILE
2785     ECall::PopulateManagedStringConstructors();
2786 #endif // CROSSGEN_COMPILE
2787
2788     g_pExceptionClass = MscorlibBinder::GetClass(CLASS__EXCEPTION);
2789     g_pOutOfMemoryExceptionClass = MscorlibBinder::GetException(kOutOfMemoryException);
2790     g_pStackOverflowExceptionClass = MscorlibBinder::GetException(kStackOverflowException);
2791     g_pExecutionEngineExceptionClass = MscorlibBinder::GetException(kExecutionEngineException);
2792     g_pThreadAbortExceptionClass = MscorlibBinder::GetException(kThreadAbortException);
2793
2794
2795     // used by gc to handle predefined agility checking
2796     g_pThreadClass = MscorlibBinder::GetClass(CLASS__THREAD);
2797
2798 #ifdef FEATURE_COMINTEROP
2799     g_pBaseCOMObject = MscorlibBinder::GetClass(CLASS__COM_OBJECT);
2800     g_pBaseRuntimeClass = MscorlibBinder::GetClass(CLASS__RUNTIME_CLASS);
2801     
2802     MscorlibBinder::GetClass(CLASS__IDICTIONARYGENERIC);
2803     MscorlibBinder::GetClass(CLASS__IREADONLYDICTIONARYGENERIC);
2804     MscorlibBinder::GetClass(CLASS__ATTRIBUTE);
2805     MscorlibBinder::GetClass(CLASS__EVENT_HANDLERGENERIC);
2806
2807     MscorlibBinder::GetClass(CLASS__IENUMERABLE);
2808     MscorlibBinder::GetClass(CLASS__ICOLLECTION);
2809     MscorlibBinder::GetClass(CLASS__ILIST);
2810     MscorlibBinder::GetClass(CLASS__IDISPOSABLE);
2811
2812 #ifdef _DEBUG
2813     WinRTInterfaceRedirector::VerifyRedirectedInterfaceStubs();
2814 #endif // _DEBUG
2815 #endif
2816
2817 #ifdef FEATURE_ICASTABLE
2818     g_pICastableInterface = MscorlibBinder::GetClass(CLASS__ICASTABLE);
2819 #endif // FEATURE_ICASTABLE
2820
2821     // Load a special marker method used to detect Constrained Execution Regions
2822     // at jit time.
2823     g_pExecuteBackoutCodeHelperMethod = MscorlibBinder::GetMethod(METHOD__RUNTIME_HELPERS__EXECUTE_BACKOUT_CODE_HELPER);
2824
2825     // Make sure that FCall mapping for Monitor.Enter is initialized. We need it in case Monitor.Enter is used only as JIT helper. 
2826     // For more details, see comment in code:JITutil_MonEnterWorker around "__me = GetEEFuncEntryPointMacro(JIT_MonEnter)".
2827     ECall::GetFCallImpl(MscorlibBinder::GetMethod(METHOD__MONITOR__ENTER));
2828
2829 #ifdef PROFILING_SUPPORTED
2830     // Note that g_profControlBlock.fBaseSystemClassesLoaded must be set to TRUE only after
2831     // all base system classes are loaded.  Profilers are not allowed to call any type-loading
2832     // APIs until g_profControlBlock.fBaseSystemClassesLoaded is TRUE.  It is important that
2833     // all base system classes need to be loaded before profilers can trigger the type loading.
2834     g_profControlBlock.fBaseSystemClassesLoaded = TRUE;
2835 #endif // PROFILING_SUPPORTED
2836
2837 #if defined(_DEBUG) && !defined(CROSSGEN_COMPILE)
2838     if (!NingenEnabled())
2839     {
2840         g_Mscorlib.Check();
2841     }
2842 #endif
2843
2844 #if defined(HAVE_GCCOVER) && defined(FEATURE_PREJIT)
2845     if (GCStress<cfg_instr_ngen>::IsEnabled())
2846     {
2847         // Setting up gc coverage requires the base system classes
2848         //  to be initialized. So we have deferred it until now for mscorlib.
2849         Module *pModule = MscorlibBinder::GetModule();
2850         _ASSERTE(pModule->IsSystem());
2851         if(pModule->HasNativeImage())
2852         {
2853             SetupGcCoverageForNativeImage(pModule);
2854         }
2855     }
2856 #endif // defined(HAVE_GCCOVER) && !defined(FEATURE_PREJIT)
2857 }
2858
2859 /*static*/
2860 void SystemDomain::LoadDomain(AppDomain *pDomain)
2861 {
2862     CONTRACTL
2863     {
2864         THROWS;
2865         GC_TRIGGERS;
2866         MODE_ANY;
2867         PRECONDITION(CheckPointer(System()));
2868         INJECT_FAULT(COMPlusThrowOM(););
2869     }
2870     CONTRACTL_END;
2871
2872     pDomain->SetCanUnload();    // by default can unload any domain
2873     SystemDomain::System()->AddDomain(pDomain);
2874 }
2875
2876 ADIndex SystemDomain::GetNewAppDomainIndex(AppDomain *pAppDomain)
2877 {
2878     STANDARD_VM_CONTRACT;
2879
2880     DWORD count = m_appDomainIndexList.GetCount();
2881     DWORD i;
2882
2883 #ifdef _DEBUG
2884     if (count < 2000)
2885     {
2886         // So that we can keep AD index inside object header.
2887         // We do not want to create syncblock unless needed.
2888         i = count;
2889     }
2890     else
2891     {
2892 #endif // _DEBUG
2893         //
2894         // Look for an unused index.  Note that in a checked build,
2895         // we never reuse indexes - this makes it easier to tell
2896         // when we are looking at a stale app domain.
2897         //
2898
2899         i = m_appDomainIndexList.FindElement(m_dwLowestFreeIndex, NULL);
2900         if (i == (DWORD) ArrayList::NOT_FOUND)
2901             i = count;
2902         m_dwLowestFreeIndex = i+1;
2903 #ifdef _DEBUG
2904         if (m_dwLowestFreeIndex >= 2000)
2905         {
2906             m_dwLowestFreeIndex = 0;
2907         }
2908     }
2909 #endif // _DEBUG
2910
2911     if (i == count)
2912         IfFailThrow(m_appDomainIndexList.Append(pAppDomain));
2913     else
2914         m_appDomainIndexList.Set(i, pAppDomain);
2915
2916     _ASSERTE(i < m_appDomainIndexList.GetCount());
2917
2918     // Note that index 0 means domain agile.
2919     return ADIndex(i+1);
2920 }
2921
2922 void SystemDomain::ReleaseAppDomainIndex(ADIndex index)
2923 {
2924     WRAPPER_NO_CONTRACT;
2925     SystemDomain::LockHolder lh;
2926     // Note that index 0 means domain agile.
2927     index.m_dwIndex--;
2928
2929     _ASSERTE(m_appDomainIndexList.Get(index.m_dwIndex) != NULL);
2930
2931     m_appDomainIndexList.Set(index.m_dwIndex, NULL);
2932
2933 #ifndef _DEBUG
2934     if (index.m_dwIndex < m_dwLowestFreeIndex)
2935         m_dwLowestFreeIndex = index.m_dwIndex;
2936 #endif // !_DEBUG
2937 }
2938
2939 #endif // !DACCESS_COMPILE
2940
2941 PTR_AppDomain SystemDomain::GetAppDomainAtIndex(ADIndex index)
2942 {
2943     LIMITED_METHOD_CONTRACT;
2944     SUPPORTS_DAC;
2945     _ASSERTE(index.m_dwIndex != 0);
2946
2947     PTR_AppDomain pAppDomain = TestGetAppDomainAtIndex(index);
2948
2949     _ASSERTE(pAppDomain || !"Attempt to access unloaded app domain");
2950
2951     return pAppDomain;
2952 }
2953
2954 PTR_AppDomain SystemDomain::TestGetAppDomainAtIndex(ADIndex index)
2955 {
2956     LIMITED_METHOD_CONTRACT;
2957     SUPPORTS_DAC;
2958     _ASSERTE(index.m_dwIndex != 0);
2959     index.m_dwIndex--;
2960
2961 #ifndef DACCESS_COMPILE
2962     _ASSERTE(index.m_dwIndex < (DWORD)m_appDomainIndexList.GetCount());
2963     AppDomain *pAppDomain = (AppDomain*) m_appDomainIndexList.Get(index.m_dwIndex);
2964 #else // DACCESS_COMPILE
2965     PTR_ArrayListStatic pList = &m_appDomainIndexList;
2966     AppDomain *pAppDomain = dac_cast<PTR_AppDomain>(pList->Get(index.m_dwIndex));
2967 #endif // DACCESS_COMPILE
2968     return PTR_AppDomain(pAppDomain);
2969 }
2970
2971 #ifndef DACCESS_COMPILE
2972
2973 // See also code:SystemDomain::ReleaseAppDomainId
2974 ADID SystemDomain::GetNewAppDomainId(AppDomain *pAppDomain)
2975 {
2976     CONTRACTL
2977     {
2978         THROWS;
2979         GC_TRIGGERS;
2980         MODE_ANY;
2981         INJECT_FAULT(COMPlusThrowOM(););
2982     }
2983     CONTRACTL_END;
2984
2985     DWORD i = m_appDomainIdList.GetCount();
2986
2987     IfFailThrow(m_appDomainIdList.Append(pAppDomain));
2988
2989     _ASSERTE(i < m_appDomainIdList.GetCount());
2990
2991     return ADID(i+1);
2992 }
2993
2994 AppDomain *SystemDomain::GetAppDomainAtId(ADID index)
2995 {
2996     CONTRACTL
2997     {
2998 #ifdef _DEBUG
2999         if (!SystemDomain::IsUnderDomainLock() && !IsGCThread()) { MODE_COOPERATIVE;} else { DISABLED(MODE_ANY);}
3000 #endif
3001         GC_NOTRIGGER;
3002         SO_TOLERANT;
3003         NOTHROW;
3004     }
3005     CONTRACTL_END;
3006
3007     if(index.m_dwId == 0)
3008         return NULL;
3009     DWORD requestedID = index.m_dwId - 1;
3010
3011     if(requestedID  >= (DWORD)m_appDomainIdList.GetCount())
3012         return NULL;
3013
3014     AppDomain * result = (AppDomain *)m_appDomainIdList.Get(requestedID);
3015
3016 #ifndef CROSSGEN_COMPILE
3017     if(result==NULL && GetThread() == FinalizerThread::GetFinalizerThread() &&
3018         SystemDomain::System()->AppDomainBeingUnloaded()!=NULL &&
3019         SystemDomain::System()->AppDomainBeingUnloaded()->GetId()==index)
3020         result=SystemDomain::System()->AppDomainBeingUnloaded();
3021     // If the current thread can't enter the AppDomain, then don't return it.
3022     if (!result || !result->CanThreadEnter(GetThread()))
3023         return NULL;
3024 #endif // CROSSGEN_COMPILE
3025
3026     return result;
3027 }
3028
3029 // Releases an appdomain index.   Note that today we have code that depends on these
3030 // indexes not being recycled, so we don't actually shrink m_appDomainIdList, but 
3031 // simply zero out an entry.   THus we 'leak' the memory associated the slot in
3032 // m_appDomainIdList.  
3033 // 
3034 // TODO make this a sparse structure so that we avoid that leak.  
3035 //
3036 void SystemDomain::ReleaseAppDomainId(ADID index)
3037 {
3038     LIMITED_METHOD_CONTRACT;
3039     index.m_dwId--;
3040
3041     _ASSERTE(index.m_dwId < (DWORD)m_appDomainIdList.GetCount());
3042
3043     m_appDomainIdList.Set(index.m_dwId, NULL);
3044 }
3045
3046 #if defined(FEATURE_COMINTEROP_APARTMENT_SUPPORT) && !defined(CROSSGEN_COMPILE)
3047
3048 #ifdef _DEBUG
3049 int g_fMainThreadApartmentStateSet = 0;
3050 #endif
3051
3052 Thread::ApartmentState SystemDomain::GetEntryPointThreadAptState(IMDInternalImport* pScope, mdMethodDef mdMethod)
3053 {
3054     STANDARD_VM_CONTRACT;
3055
3056     HRESULT hr;
3057     IfFailThrow(hr = pScope->GetCustomAttributeByName(mdMethod,
3058                                                       DEFAULTDOMAIN_MTA_TYPE,
3059                                                       NULL,
3060                                                       NULL));
3061     BOOL fIsMTA = FALSE;
3062     if(hr == S_OK)
3063         fIsMTA = TRUE;
3064
3065     IfFailThrow(hr = pScope->GetCustomAttributeByName(mdMethod,
3066                                                       DEFAULTDOMAIN_STA_TYPE,
3067                                                       NULL,
3068                                                       NULL));
3069     BOOL fIsSTA = FALSE;
3070     if (hr == S_OK)
3071         fIsSTA = TRUE;
3072
3073     if (fIsSTA && fIsMTA)
3074         COMPlusThrowHR(COR_E_CUSTOMATTRIBUTEFORMAT);
3075
3076     if (fIsSTA)
3077         return Thread::AS_InSTA;
3078     else if (fIsMTA)
3079         return Thread::AS_InMTA;
3080
3081     return Thread::AS_Unknown;
3082 }
3083
3084 void SystemDomain::SetThreadAptState (Thread::ApartmentState state)
3085 {
3086     STANDARD_VM_CONTRACT;
3087
3088     Thread* pThread = GetThread();
3089     _ASSERTE(pThread);
3090
3091     if(state == Thread::AS_InSTA)
3092     {
3093         Thread::ApartmentState pState = pThread->SetApartment(Thread::AS_InSTA, TRUE);
3094         _ASSERTE(pState == Thread::AS_InSTA);
3095     }
3096     else if (state == Thread::AS_InMTA)
3097     {
3098         Thread::ApartmentState pState = pThread->SetApartment(Thread::AS_InMTA, TRUE);
3099         _ASSERTE(pState == Thread::AS_InMTA);
3100     }
3101
3102 #ifdef _DEBUG
3103     g_fMainThreadApartmentStateSet++;
3104 #endif
3105 }
3106 #endif // defined(FEATURE_COMINTEROP_APARTMENT_SUPPORT) && !defined(CROSSGEN_COMPILE)
3107
3108 // Looks in all the modules for the DefaultDomain attribute
3109 // The order is assembly and then the modules. It is first
3110 // come, first serve.
3111 BOOL SystemDomain::SetGlobalSharePolicyUsingAttribute(IMDInternalImport* pScope, mdMethodDef mdMethod)
3112 {
3113     STANDARD_VM_CONTRACT;
3114
3115
3116     return FALSE;
3117 }
3118
3119 void SystemDomain::SetupDefaultDomain()
3120 {
3121     CONTRACT_VOID
3122     {
3123         THROWS;
3124         GC_TRIGGERS;
3125         MODE_ANY;
3126         INJECT_FAULT(COMPlusThrowOM(););
3127     }
3128     CONTRACT_END;
3129
3130
3131     Thread *pThread = GetThread();
3132     _ASSERTE(pThread);
3133
3134     AppDomain *pDomain;
3135     pDomain = pThread->GetDomain();
3136     _ASSERTE(pDomain);
3137
3138     GCX_COOP();
3139
3140     ENTER_DOMAIN_PTR(SystemDomain::System()->DefaultDomain(),ADV_DEFAULTAD)
3141     {
3142         // Push this frame around loading the main assembly to ensure the
3143         // debugger can properly recgonize any managed code that gets run
3144         // as "class initializaion" code.
3145         FrameWithCookie<DebuggerClassInitMarkFrame> __dcimf;
3146
3147         {
3148             GCX_PREEMP();
3149             InitializeDefaultDomain(TRUE);
3150         }
3151
3152         __dcimf.Pop();
3153     }
3154     END_DOMAIN_TRANSITION;
3155
3156     RETURN;
3157 }
3158
3159 HRESULT SystemDomain::SetupDefaultDomainNoThrow()
3160 {
3161     CONTRACTL
3162     {
3163         NOTHROW;
3164         MODE_ANY;
3165     }
3166     CONTRACTL_END;
3167
3168     HRESULT hr = S_OK;
3169
3170     EX_TRY
3171     {
3172         SystemDomain::SetupDefaultDomain();
3173     }
3174     EX_CATCH_HRESULT(hr);
3175
3176     return hr;
3177 }
3178
3179 #ifdef _DEBUG
3180 int g_fInitializingInitialAD = 0;
3181 #endif
3182
3183 // This routine completes the initialization of the default domaine.
3184 // After this call mananged code can be executed.
3185 void SystemDomain::InitializeDefaultDomain(
3186     BOOL allowRedirects,
3187     ICLRPrivBinder * pBinder)
3188 {
3189     STANDARD_VM_CONTRACT;
3190
3191     WCHAR* pwsConfig = NULL;
3192     WCHAR* pwsPath = NULL;
3193
3194     ETWOnStartup (InitDefaultDomain_V1, InitDefaultDomainEnd_V1);
3195
3196
3197     // Setup the default AppDomain.
3198
3199 #ifdef _DEBUG
3200     g_fInitializingInitialAD++;
3201 #endif
3202
3203     AppDomain* pDefaultDomain = SystemDomain::System()->DefaultDomain();
3204
3205     if (pBinder != nullptr)
3206     {
3207         pDefaultDomain->SetLoadContextHostBinder(pBinder);
3208     }
3209
3210     {
3211         GCX_COOP();
3212
3213         pDefaultDomain->InitializeDomainContext(allowRedirects, pwsPath, pwsConfig);
3214
3215 #ifndef CROSSGEN_COMPILE
3216         if (!NingenEnabled())
3217         {
3218     
3219             if (!IsSingleAppDomain())
3220             {
3221                 pDefaultDomain->InitializeDefaultDomainManager();
3222             }
3223         }
3224 #endif // CROSSGEN_COMPILE
3225     }
3226
3227     // DefaultDomain Load event
3228     ETW::LoaderLog::DomainLoad(pDefaultDomain);
3229
3230 #ifdef _DEBUG
3231     g_fInitializingInitialAD--;
3232 #endif
3233
3234     TESTHOOKCALL(RuntimeStarted(RTS_DEFAULTADREADY));
3235 }
3236
3237
3238
3239 #ifndef CROSSGEN_COMPILE
3240
3241 #ifdef _DEBUG
3242 Volatile<LONG> g_fInExecuteMainMethod = 0;
3243 #endif
3244
3245
3246
3247
3248 #endif // CROSSGEN_COMPILE
3249
3250
3251
3252 // Helper function to load an assembly. This is called from LoadCOMClass.
3253 /* static */
3254
3255 Assembly *AppDomain::LoadAssemblyHelper(LPCWSTR wszAssembly,
3256                                         LPCWSTR wszCodeBase)
3257 {
3258     CONTRACT(Assembly *)
3259     {
3260         THROWS;
3261         POSTCONDITION(CheckPointer(RETVAL));
3262         PRECONDITION(wszAssembly || wszCodeBase);
3263         INJECT_FAULT(COMPlusThrowOM(););
3264     }
3265     CONTRACT_END;
3266
3267     AssemblySpec spec;
3268     if(wszAssembly) {
3269         #define MAKE_TRANSLATIONFAILED  { ThrowOutOfMemory(); }
3270         MAKE_UTF8PTR_FROMWIDE(szAssembly,wszAssembly);
3271         #undef  MAKE_TRANSLATIONFAILED
3272        
3273         IfFailThrow(spec.Init(szAssembly));
3274     }
3275
3276     if (wszCodeBase) {
3277         spec.SetCodeBase(wszCodeBase);
3278     }
3279     RETURN spec.LoadAssembly(FILE_LOADED);
3280 }
3281
3282 #if defined(FEATURE_CLASSIC_COMINTEROP) && !defined(CROSSGEN_COMPILE)
3283
3284 MethodTable *AppDomain::LoadCOMClass(GUID clsid,
3285                                      BOOL bLoadRecord/*=FALSE*/,
3286                                      BOOL* pfAssemblyInReg/*=NULL*/)
3287 {
3288     // @CORESYSTODO: what to do here?
3289     return NULL;
3290 }
3291
3292 #endif // FEATURE_CLASSIC_COMINTEROP && !CROSSGEN_COMPILE
3293
3294
3295 /*static*/
3296 bool SystemDomain::IsReflectionInvocationMethod(MethodDesc* pMeth)
3297 {
3298     CONTRACTL
3299     {
3300         THROWS;
3301         GC_TRIGGERS;
3302         MODE_ANY;
3303     }
3304     CONTRACTL_END;
3305
3306     MethodTable* pCaller = pMeth->GetMethodTable();
3307
3308     // All Reflection Invocation methods are defined in mscorlib.dll
3309     if (!pCaller->GetModule()->IsSystem())
3310         return false;
3311
3312     /* List of types that should be skipped to identify true caller */
3313     static const BinderClassID reflectionInvocationTypes[] = {
3314         CLASS__METHOD,
3315         CLASS__METHOD_BASE,
3316         CLASS__METHOD_INFO,
3317         CLASS__CONSTRUCTOR,
3318         CLASS__CONSTRUCTOR_INFO,
3319         CLASS__CLASS,
3320         CLASS__TYPE_HANDLE,
3321         CLASS__METHOD_HANDLE,
3322         CLASS__FIELD_HANDLE,
3323         CLASS__TYPE,
3324         CLASS__FIELD,
3325         CLASS__RT_FIELD_INFO,
3326         CLASS__FIELD_INFO,
3327         CLASS__EVENT,
3328         CLASS__EVENT_INFO,
3329         CLASS__PROPERTY,
3330         CLASS__PROPERTY_INFO,
3331         CLASS__ACTIVATOR,
3332         CLASS__ARRAY,
3333         CLASS__ASSEMBLYBASE,
3334         CLASS__ASSEMBLY,
3335         CLASS__TYPE_DELEGATOR,
3336         CLASS__RUNTIME_HELPERS,
3337         CLASS__LAZY_INITIALIZER,
3338         CLASS__DYNAMICMETHOD,
3339         CLASS__DELEGATE,
3340         CLASS__MULTICAST_DELEGATE,
3341         CLASS__APP_DOMAIN
3342     };
3343
3344     static const BinderClassID genericReflectionInvocationTypes[] = {
3345         CLASS__LAZY
3346     };
3347
3348     static mdTypeDef genericReflectionInvocationTypeDefs[NumItems(genericReflectionInvocationTypes)];
3349
3350     static bool fInited = false;
3351
3352     if (!VolatileLoad(&fInited))
3353     {
3354         // Make sure all types are loaded so that we can use faster GetExistingClass()
3355         for (unsigned i = 0; i < NumItems(reflectionInvocationTypes); i++)
3356         {
3357             MscorlibBinder::GetClass(reflectionInvocationTypes[i]);
3358         }
3359
3360         // Make sure all types are loaded so that we can use faster GetExistingClass()
3361         for (unsigned i = 0; i < NumItems(genericReflectionInvocationTypes); i++)
3362         {
3363             genericReflectionInvocationTypeDefs[i] = MscorlibBinder::GetClass(genericReflectionInvocationTypes[i])->GetCl();
3364         }
3365
3366         MscorlibBinder::GetClass(CLASS__APP_DOMAIN);
3367
3368         VolatileStore(&fInited, true);
3369     }
3370
3371     if (pCaller->HasInstantiation())
3372     {
3373         // For generic types, pCaller will be an instantiated type and never equal to the type definition.
3374         // So we compare their TypeDef tokens instead.
3375         for (unsigned i = 0; i < NumItems(genericReflectionInvocationTypeDefs); i++)
3376         {
3377             if (pCaller->GetCl() == genericReflectionInvocationTypeDefs[i])
3378                 return true;
3379         }
3380     }
3381     else
3382     {
3383         for (unsigned i = 0; i < NumItems(reflectionInvocationTypes); i++)
3384         {
3385             if (MscorlibBinder::GetExistingClass(reflectionInvocationTypes[i]) == pCaller)
3386                 return true;
3387         }
3388     }
3389
3390     return false;
3391 }
3392
3393 #ifndef CROSSGEN_COMPILE
3394 struct CallersDataWithStackMark
3395 {
3396     StackCrawlMark* stackMark;
3397     BOOL foundMe;
3398     MethodDesc* pFoundMethod;
3399     MethodDesc* pPrevMethod;
3400     AppDomain*  pAppDomain;
3401 };
3402
3403 /*static*/
3404 MethodDesc* SystemDomain::GetCallersMethod(StackCrawlMark* stackMark,
3405                                            AppDomain **ppAppDomain/*=NULL*/)
3406
3407 {
3408     CONTRACTL
3409     {
3410         THROWS;
3411         GC_TRIGGERS;
3412         MODE_ANY;
3413         INJECT_FAULT(COMPlusThrowOM(););
3414     }
3415     CONTRACTL_END;
3416
3417     GCX_COOP();
3418
3419     CallersDataWithStackMark cdata;
3420     ZeroMemory(&cdata, sizeof(CallersDataWithStackMark));
3421     cdata.stackMark = stackMark;
3422
3423     GetThread()->StackWalkFrames(CallersMethodCallbackWithStackMark, &cdata, FUNCTIONSONLY | LIGHTUNWIND);
3424
3425     if(cdata.pFoundMethod) {
3426         if (ppAppDomain)
3427             *ppAppDomain = cdata.pAppDomain;
3428         return cdata.pFoundMethod;
3429     } else
3430         return NULL;
3431 }
3432
3433 /*static*/
3434 MethodTable* SystemDomain::GetCallersType(StackCrawlMark* stackMark,
3435                                           AppDomain **ppAppDomain/*=NULL*/)
3436
3437 {
3438     CONTRACTL
3439     {
3440         THROWS;
3441         GC_TRIGGERS;
3442         MODE_COOPERATIVE;
3443         INJECT_FAULT(COMPlusThrowOM(););
3444     }
3445     CONTRACTL_END;
3446
3447     CallersDataWithStackMark cdata;
3448     ZeroMemory(&cdata, sizeof(CallersDataWithStackMark));
3449     cdata.stackMark = stackMark;
3450
3451     GetThread()->StackWalkFrames(CallersMethodCallbackWithStackMark, &cdata, FUNCTIONSONLY | LIGHTUNWIND);
3452
3453     if(cdata.pFoundMethod) {
3454         if (ppAppDomain)
3455             *ppAppDomain = cdata.pAppDomain;
3456         return cdata.pFoundMethod->GetMethodTable();
3457     } else
3458         return NULL;
3459 }
3460
3461 /*static*/
3462 Module* SystemDomain::GetCallersModule(StackCrawlMark* stackMark,
3463                                        AppDomain **ppAppDomain/*=NULL*/)
3464
3465 {
3466     CONTRACTL
3467     {
3468         THROWS;
3469         GC_TRIGGERS;
3470         MODE_ANY;
3471         INJECT_FAULT(COMPlusThrowOM(););
3472     }
3473     CONTRACTL_END;
3474
3475     GCX_COOP();
3476
3477     CallersDataWithStackMark cdata;
3478     ZeroMemory(&cdata, sizeof(CallersDataWithStackMark));
3479     cdata.stackMark = stackMark;
3480
3481     GetThread()->StackWalkFrames(CallersMethodCallbackWithStackMark, &cdata, FUNCTIONSONLY | LIGHTUNWIND);
3482
3483     if(cdata.pFoundMethod) {
3484         if (ppAppDomain)
3485             *ppAppDomain = cdata.pAppDomain;
3486         return cdata.pFoundMethod->GetModule();
3487     } else
3488         return NULL;
3489 }
3490
3491 struct CallersData
3492 {
3493     int skip;
3494     MethodDesc* pMethod;
3495 };
3496
3497 /*static*/
3498 Assembly* SystemDomain::GetCallersAssembly(StackCrawlMark *stackMark,
3499                                            AppDomain **ppAppDomain/*=NULL*/)
3500 {
3501     WRAPPER_NO_CONTRACT;
3502     Module* mod = GetCallersModule(stackMark, ppAppDomain);
3503     if (mod)
3504         return mod->GetAssembly();
3505     return NULL;
3506 }
3507
3508 /*static*/
3509 Module* SystemDomain::GetCallersModule(int skip)
3510 {
3511     CONTRACTL
3512     {
3513         THROWS;
3514         GC_TRIGGERS;
3515         MODE_ANY;
3516         INJECT_FAULT(COMPlusThrowOM(););
3517     }
3518     CONTRACTL_END;
3519
3520     GCX_COOP();
3521
3522     CallersData cdata;
3523     ZeroMemory(&cdata, sizeof(CallersData));
3524     cdata.skip = skip;
3525
3526     StackWalkFunctions(GetThread(), CallersMethodCallback, &cdata);
3527
3528     if(cdata.pMethod)
3529         return cdata.pMethod->GetModule();
3530     else
3531         return NULL;
3532 }
3533
3534 /*private static*/
3535 StackWalkAction SystemDomain::CallersMethodCallbackWithStackMark(CrawlFrame* pCf, VOID* data)
3536 {
3537     CONTRACTL
3538     {
3539         THROWS;
3540         GC_TRIGGERS;
3541         MODE_COOPERATIVE;
3542         SO_INTOLERANT;
3543         INJECT_FAULT(COMPlusThrowOM(););
3544     }
3545     CONTRACTL_END;
3546
3547
3548     MethodDesc *pFunc = pCf->GetFunction();
3549
3550     /* We asked to be called back only for functions */
3551     _ASSERTE(pFunc);
3552
3553     CallersDataWithStackMark* pCaller = (CallersDataWithStackMark*) data;
3554     if (pCaller->stackMark)
3555     {
3556         if (!pCf->IsInCalleesFrames(pCaller->stackMark))
3557         {
3558             // save the current in case it is the one we want
3559             pCaller->pPrevMethod = pFunc;
3560             pCaller->pAppDomain = pCf->GetAppDomain();
3561             return SWA_CONTINUE;
3562         }
3563
3564         // LookForMe stack crawl marks needn't worry about reflection or
3565         // remoting frames on the stack. Each frame above (newer than) the
3566         // target will be captured by the logic above. Once we transition to
3567         // finding the stack mark below the AofRA, we know that we hit the
3568         // target last time round and immediately exit with the cached result.
3569
3570         if (*(pCaller->stackMark) == LookForMe)
3571         {
3572             pCaller->pFoundMethod = pCaller->pPrevMethod;
3573             return SWA_ABORT;
3574         }
3575     }
3576
3577     // Skip reflection and remoting frames that could lie between a stack marked
3578     // method and its true caller (or that caller and its own caller). These
3579     // frames are infrastructure and logically transparent to the stack crawling
3580     // algorithm.
3581
3582     // Skipping remoting frames. We always skip entire client to server spans
3583     // (though we see them in the order server then client during a stack crawl
3584     // obviously).
3585
3586     // We spot the server dispatcher end because all calls are dispatched
3587     // through a single method: StackBuilderSink._PrivateProcessMessage.
3588
3589     Frame* frame = pCf->GetFrame();
3590     _ASSERTE(pCf->IsFrameless() || frame);
3591
3592
3593
3594     // Skipping reflection frames. We don't need to be quite as exhaustive here
3595     // as the security or reflection stack walking code since we know this logic
3596     // is only invoked for selected methods in mscorlib itself. So we're
3597     // reasonably sure we won't have any sensitive methods late bound invoked on
3598     // constructors, properties or events. This leaves being invoked via
3599     // MethodInfo, Type or Delegate (and depending on which invoke overload is
3600     // being used, several different reflection classes may be involved).
3601
3602     g_IBCLogger.LogMethodDescAccess(pFunc);
3603
3604     if (SystemDomain::IsReflectionInvocationMethod(pFunc))
3605         return SWA_CONTINUE;
3606
3607     if (frame && frame->GetFrameType() == Frame::TYPE_MULTICAST)
3608     {
3609         // This must be either a secure delegate frame or a true multicast delegate invocation.
3610
3611         _ASSERTE(pFunc->GetMethodTable()->IsDelegate());
3612
3613         DELEGATEREF del = (DELEGATEREF)((SecureDelegateFrame*)frame)->GetThis(); // This can throw.
3614
3615         if (COMDelegate::IsSecureDelegate(del))
3616         {
3617             if (del->IsWrapperDelegate())
3618             {
3619                 // On ARM, we use secure delegate infrastructure to preserve R4 register.
3620                 return SWA_CONTINUE;
3621             }
3622             // For a secure delegate frame, we should return the delegate creator instead
3623             // of the delegate method itself.
3624             pFunc = (MethodDesc*) del->GetMethodPtrAux();
3625         }
3626         else
3627         {
3628             _ASSERTE(COMDelegate::IsTrueMulticastDelegate(del));
3629             return SWA_CONTINUE;
3630         }
3631     }
3632
3633     // Return the first non-reflection/remoting frame if no stack mark was
3634     // supplied.
3635     if (!pCaller->stackMark)
3636     {
3637         pCaller->pFoundMethod = pFunc;
3638         pCaller->pAppDomain = pCf->GetAppDomain();
3639         return SWA_ABORT;
3640     }
3641
3642     // If we got here, we must already be in the frame containing the stack mark and we are not looking for "me".
3643     _ASSERTE(pCaller->stackMark &&
3644              pCf->IsInCalleesFrames(pCaller->stackMark) &&
3645              *(pCaller->stackMark) != LookForMe);
3646
3647     // When looking for caller's caller, we delay returning results for another
3648     // round (the way this is structured, we will still be able to skip
3649     // reflection and remoting frames between the caller and the caller's
3650     // caller).
3651
3652     if ((*(pCaller->stackMark) == LookForMyCallersCaller) &&
3653         (pCaller->pFoundMethod == NULL))
3654     {
3655         pCaller->pFoundMethod = pFunc;
3656         return SWA_CONTINUE;
3657     }
3658
3659     // If remoting is not available, we only set the caller if the crawlframe is from the same domain.
3660     // Why? Because if the callerdomain is different from current domain,
3661     // there have to be interop/native frames in between.
3662     // For example, in the CORECLR, if we find the caller to be in a different domain, then the 
3663     // call into reflection is due to an unmanaged call into mscorlib. For that
3664     // case, the caller really is an INTEROP method.
3665     // In general, if the caller is INTEROP, we set the caller/callerdomain to be NULL 
3666     // (To be precise: they are already NULL and we don't change them).
3667     if (pCf->GetAppDomain() == GetAppDomain())
3668     // We must either be looking for the caller, or the caller's caller when
3669     // we've already found the caller (we used a non-null value in pFoundMethod
3670     // simply as a flag, the correct method to return in both case is the
3671     // current method).
3672     {
3673         pCaller->pFoundMethod = pFunc;
3674         pCaller->pAppDomain = pCf->GetAppDomain();
3675     }
3676
3677     return SWA_ABORT;
3678 }
3679
3680 /*private static*/
3681 StackWalkAction SystemDomain::CallersMethodCallback(CrawlFrame* pCf, VOID* data)
3682 {
3683     LIMITED_METHOD_CONTRACT;
3684     STATIC_CONTRACT_SO_TOLERANT;
3685     MethodDesc *pFunc = pCf->GetFunction();
3686
3687     /* We asked to be called back only for functions */
3688     _ASSERTE(pFunc);
3689
3690     CallersData* pCaller = (CallersData*) data;
3691     if(pCaller->skip == 0) {
3692         pCaller->pMethod = pFunc;
3693         return SWA_ABORT;
3694     }
3695     else {
3696         pCaller->skip--;
3697         return SWA_CONTINUE;
3698     }
3699
3700 }
3701 #endif // CROSSGEN_COMPILE
3702
3703 #ifdef CROSSGEN_COMPILE
3704 // defined in compile.cpp
3705 extern CompilationDomain * theDomain;
3706 #endif
3707
3708 void SystemDomain::CreateDefaultDomain()
3709 {
3710     STANDARD_VM_CONTRACT;
3711
3712 #ifdef CROSSGEN_COMPILE
3713     AppDomainRefHolder pDomain(theDomain);
3714 #else
3715     AppDomainRefHolder pDomain(new AppDomain());
3716 #endif
3717
3718     SystemDomain::LockHolder lh;
3719     pDomain->Init();
3720
3721     // need to make this assignment here since we'll be releasing
3722     // the lock before calling AddDomain. So any other thread
3723     // grabbing this lock after we release it will find that
3724     // the COM Domain has already been created
3725     m_pDefaultDomain = pDomain;
3726     _ASSERTE (pDomain->GetId().m_dwId == DefaultADID);
3727
3728     // allocate a Virtual Call Stub Manager for the default domain
3729     m_pDefaultDomain->InitVSD();
3730
3731     pDomain->SetStage(AppDomain::STAGE_OPEN);
3732     pDomain.SuppressRelease();
3733
3734     LOG((LF_CLASSLOADER | LF_CORDB,
3735          LL_INFO10,
3736          "Created default domain at %p\n", m_pDefaultDomain));
3737 }
3738
3739 #ifdef DEBUGGING_SUPPORTED
3740
3741 void SystemDomain::PublishAppDomainAndInformDebugger (AppDomain *pDomain)
3742 {
3743     CONTRACTL
3744     {
3745         if(!g_fEEInit) {THROWS;} else {DISABLED(NOTHROW);};
3746         if(!g_fEEInit) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);};
3747         MODE_ANY;
3748     }
3749     CONTRACTL_END;
3750
3751     LOG((LF_CORDB, LL_INFO100, "SD::PADAID: Adding 0x%x\n", pDomain));
3752
3753     // Call the publisher API to add this appdomain entry to the list
3754     // The publisher will handle failures, so we don't care if this succeeds or fails.
3755     if (g_pDebugInterface != NULL)
3756     {
3757         g_pDebugInterface->AddAppDomainToIPC(pDomain);
3758     }
3759 }
3760
3761 #endif // DEBUGGING_SUPPORTED
3762
3763 void SystemDomain::AddDomain(AppDomain* pDomain)
3764 {
3765     CONTRACTL
3766     {
3767         NOTHROW;
3768         MODE_ANY;
3769         GC_TRIGGERS;
3770         PRECONDITION(CheckPointer((pDomain)));
3771     }
3772     CONTRACTL_END;
3773
3774     {
3775         LockHolder lh;
3776
3777         _ASSERTE (pDomain->m_Stage != AppDomain::STAGE_CREATING);
3778         if (pDomain->m_Stage == AppDomain::STAGE_READYFORMANAGEDCODE ||
3779             pDomain->m_Stage == AppDomain::STAGE_ACTIVE)
3780         {
3781             pDomain->SetStage(AppDomain::STAGE_OPEN);
3782             IncrementNumAppDomains(); // Maintain a count of app domains added to the list.
3783         }
3784     }
3785
3786     // Note that if you add another path that can reach here without calling
3787     // PublishAppDomainAndInformDebugger, then you should go back & make sure
3788     // that PADAID gets called.  Right after this call, if not sooner.
3789     LOG((LF_CORDB, LL_INFO1000, "SD::AD:Would have added domain here! 0x%x\n",
3790         pDomain));
3791 }
3792
3793 BOOL SystemDomain::RemoveDomain(AppDomain* pDomain)
3794 {
3795     CONTRACTL
3796     {
3797         NOTHROW;
3798         GC_TRIGGERS;
3799         MODE_ANY;
3800         PRECONDITION(CheckPointer(pDomain));
3801         PRECONDITION(!pDomain->IsDefaultDomain());    
3802     }
3803     CONTRACTL_END;
3804
3805     // You can not remove the default domain.
3806
3807
3808     if (!pDomain->IsActive())
3809         return FALSE;
3810
3811     pDomain->Release();
3812
3813     return TRUE;
3814 }
3815
3816
3817 #ifdef PROFILING_SUPPORTED
3818 void SystemDomain::NotifyProfilerStartup()
3819 {
3820     CONTRACTL
3821     {
3822         NOTHROW;
3823         GC_TRIGGERS;
3824         MODE_PREEMPTIVE;
3825     }
3826     CONTRACTL_END;
3827
3828     {
3829         BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
3830         _ASSERTE(System());
3831         g_profControlBlock.pProfInterface->AppDomainCreationStarted((AppDomainID) System());
3832         END_PIN_PROFILER();
3833     }
3834
3835     {
3836         BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
3837         _ASSERTE(System());
3838         g_profControlBlock.pProfInterface->AppDomainCreationFinished((AppDomainID) System(), S_OK);
3839         END_PIN_PROFILER();
3840     }
3841
3842     {
3843         BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
3844         _ASSERTE(System()->DefaultDomain());
3845         g_profControlBlock.pProfInterface->AppDomainCreationStarted((AppDomainID) System()->DefaultDomain());
3846         END_PIN_PROFILER();
3847     }
3848
3849     {
3850         BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
3851         _ASSERTE(System()->DefaultDomain());
3852         g_profControlBlock.pProfInterface->AppDomainCreationFinished((AppDomainID) System()->DefaultDomain(), S_OK);
3853         END_PIN_PROFILER();
3854     }
3855
3856     {
3857         BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
3858         _ASSERTE(SharedDomain::GetDomain());
3859         g_profControlBlock.pProfInterface->AppDomainCreationStarted((AppDomainID) SharedDomain::GetDomain());
3860         END_PIN_PROFILER();
3861     }
3862
3863     {
3864         BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
3865         _ASSERTE(SharedDomain::GetDomain());
3866         g_profControlBlock.pProfInterface->AppDomainCreationFinished((AppDomainID) SharedDomain::GetDomain(), S_OK);
3867         END_PIN_PROFILER();
3868     }
3869 }
3870
3871 HRESULT SystemDomain::NotifyProfilerShutdown()
3872 {
3873     CONTRACTL
3874     {
3875         NOTHROW;
3876         GC_TRIGGERS;
3877         MODE_PREEMPTIVE;
3878     }
3879     CONTRACTL_END;
3880
3881     {
3882         BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
3883         _ASSERTE(System());
3884         g_profControlBlock.pProfInterface->AppDomainShutdownStarted((AppDomainID) System());
3885         END_PIN_PROFILER();
3886     }
3887
3888     {
3889         BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
3890         _ASSERTE(System());
3891         g_profControlBlock.pProfInterface->AppDomainShutdownFinished((AppDomainID) System(), S_OK);
3892         END_PIN_PROFILER();
3893     }
3894
3895     {
3896         BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
3897         _ASSERTE(System()->DefaultDomain());
3898         g_profControlBlock.pProfInterface->AppDomainShutdownStarted((AppDomainID) System()->DefaultDomain());
3899         END_PIN_PROFILER();
3900     }
3901
3902     {
3903         BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
3904         _ASSERTE(System()->DefaultDomain());
3905         g_profControlBlock.pProfInterface->AppDomainShutdownFinished((AppDomainID) System()->DefaultDomain(), S_OK);
3906         END_PIN_PROFILER();
3907     }
3908     return (S_OK);
3909 }
3910 #endif // PROFILING_SUPPORTED
3911
3912
3913 #ifdef _DEBUG
3914 struct AppDomain::ThreadTrackInfo {
3915     Thread *pThread;
3916     CDynArray<Frame *> frameStack;
3917 };
3918 #endif // _DEBUG
3919
3920 AppDomain::AppDomain()
3921 {
3922     // initialize fields so the appdomain can be safely destructed
3923     // shouldn't call anything that can fail here - use ::Init instead
3924     CONTRACTL
3925     {
3926         THROWS;
3927         GC_TRIGGERS;
3928         MODE_ANY;
3929         FORBID_FAULT;
3930     }
3931     CONTRACTL_END;
3932
3933     m_cRef=1;
3934     m_pNextInDelayedUnloadList = NULL;
3935     m_fRudeUnload = FALSE;
3936     m_pUnloadRequestThread = NULL;
3937     m_ADUnloadSink=NULL;
3938
3939
3940     // Initialize Shared state. Assemblies are loaded
3941     // into each domain by default.
3942 #ifdef FEATURE_LOADER_OPTIMIZATION    
3943     m_SharePolicy = SHARE_POLICY_UNSPECIFIED;
3944 #endif
3945
3946     m_pRootAssembly = NULL;
3947
3948     m_pwDynamicDir = NULL;
3949
3950     m_dwFlags = 0;
3951     m_pDefaultContext = NULL;
3952 #ifdef FEATURE_COMINTEROP
3953     m_pComCallWrapperCache = NULL;
3954     m_pRCWCache = NULL;
3955     m_pRCWRefCache = NULL;
3956     m_pLicenseInteropHelperMT = NULL;
3957     m_COMorRemotingFlag = COMorRemoting_NotInitialized;
3958     memset(m_rpCLRTypes, 0, sizeof(m_rpCLRTypes));
3959 #endif // FEATURE_COMINTEROP
3960
3961     m_pUMEntryThunkCache = NULL;
3962
3963     m_pAsyncPool = NULL;
3964     m_handleStore = NULL;
3965
3966     m_ExposedObject = NULL;
3967     m_pComIPForExposedObject = NULL;
3968
3969  #ifdef _DEBUG
3970     m_pThreadTrackInfoList = NULL;
3971     m_TrackSpinLock = 0;
3972     m_Assemblies.Debug_SetAppDomain(this);
3973 #endif // _DEBUG
3974
3975     m_dwThreadEnterCount = 0;
3976     m_dwThreadsStillInAppDomain = (ULONG)-1;
3977
3978 #ifdef FEATURE_COMINTEROP
3979     m_pRefDispIDCache = NULL;
3980     m_hndMissing = NULL;
3981 #endif
3982
3983     m_pRefClassFactHash = NULL;
3984     m_anonymouslyHostedDynamicMethodsAssembly = NULL;
3985
3986     m_ReversePInvokeCanEnter=TRUE;
3987     m_ForceTrivialWaitOperations = false;
3988     m_Stage=STAGE_CREATING;
3989
3990     m_bForceGCOnUnload=FALSE;
3991     m_bUnloadingFromUnloadEvent=FALSE;
3992 #ifdef _DEBUG
3993     m_dwIterHolders=0;
3994     m_dwRefTakers=0;
3995     m_dwCreationHolders=0;
3996 #endif
3997
3998 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
3999     m_ullTotalProcessorUsage = 0;
4000     m_pullAllocBytes = NULL;
4001     m_pullSurvivedBytes = NULL;
4002 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
4003
4004 #ifdef FEATURE_TYPEEQUIVALENCE
4005     m_pTypeEquivalenceTable = NULL;
4006 #endif // FEATURE_TYPEEQUIVALENCE
4007
4008 #ifdef FEATURE_COMINTEROP
4009     m_pNameToTypeMap = NULL;
4010     m_vNameToTypeMapVersion = 0;
4011     m_nEpoch = 0;
4012     m_pWinRTFactoryCache = NULL;
4013 #endif // FEATURE_COMINTEROP
4014
4015 #ifdef FEATURE_PREJIT
4016     m_pDomainFileWithNativeImageList = NULL;
4017 #endif
4018
4019     m_fIsBindingModelLocked.Store(FALSE);
4020
4021 } // AppDomain::AppDomain
4022
4023 AppDomain::~AppDomain()
4024 {
4025     CONTRACTL
4026     {
4027         NOTHROW;
4028         GC_TRIGGERS;
4029         MODE_ANY;
4030     }
4031     CONTRACTL_END;
4032
4033 #ifndef CROSSGEN_COMPILE
4034
4035     _ASSERTE(m_dwCreationHolders == 0);
4036
4037     // release the TPIndex.  note that since TPIndex values are recycled the TPIndex
4038     // can only be released once all threads in the AppDomain have exited.
4039     if (GetTPIndex().m_dwIndex != 0)
4040         PerAppDomainTPCountList::ResetAppDomainIndex(GetTPIndex());
4041
4042     if (m_dwId.m_dwId!=0)
4043         SystemDomain::ReleaseAppDomainId(m_dwId);
4044
4045     m_AssemblyCache.Clear();
4046
4047     if (m_ADUnloadSink)
4048         m_ADUnloadSink->Release();
4049
4050     if(!g_fEEInit)
4051         Terminate();
4052
4053
4054
4055
4056 #ifdef FEATURE_COMINTEROP
4057     if (m_pNameToTypeMap != nullptr)
4058     {
4059         delete m_pNameToTypeMap;
4060         m_pNameToTypeMap = nullptr;
4061     }
4062     if (m_pWinRTFactoryCache != nullptr)
4063     {
4064         delete m_pWinRTFactoryCache;
4065         m_pWinRTFactoryCache = nullptr;
4066     }
4067 #endif //FEATURE_COMINTEROP
4068     
4069 #ifdef _DEBUG
4070     // If we were tracking thread AD transitions, cleanup the list on shutdown
4071     if (m_pThreadTrackInfoList)
4072     {
4073         while (m_pThreadTrackInfoList->Count() > 0)
4074         {
4075             // Get the very last element
4076             ThreadTrackInfo *pElem = *(m_pThreadTrackInfoList->Get(m_pThreadTrackInfoList->Count() - 1));
4077             _ASSERTE(pElem);
4078
4079             // Free the memory
4080             delete pElem;
4081
4082             // Remove pointer entry from the list
4083             m_pThreadTrackInfoList->Delete(m_pThreadTrackInfoList->Count() - 1);
4084         }
4085
4086         // Now delete the list itself
4087         delete m_pThreadTrackInfoList;
4088         m_pThreadTrackInfoList = NULL;
4089     }
4090 #endif // _DEBUG
4091
4092 #endif // CROSSGEN_COMPILE
4093 }
4094
4095 //*****************************************************************************
4096 //*****************************************************************************
4097 //*****************************************************************************
4098 void AppDomain::Init()
4099 {
4100     CONTRACTL
4101     {
4102         STANDARD_VM_CHECK;
4103         PRECONDITION(SystemDomain::IsUnderDomainLock());
4104     }
4105     CONTRACTL_END;
4106
4107     m_pDelayedLoaderAllocatorUnloadList = NULL;
4108
4109     SetStage( STAGE_CREATING);
4110
4111
4112     // The lock is taken also during stack walking (GC or profiler)
4113     //  - To prevent deadlock with GC thread, we cannot trigger GC while holding the lock
4114     //  - To prevent deadlock with profiler thread, we cannot allow thread suspension
4115     m_crstHostAssemblyMap.Init(
4116         CrstHostAssemblyMap, 
4117         (CrstFlags)(CRST_GC_NOTRIGGER_WHEN_TAKEN 
4118                     | CRST_DEBUGGER_THREAD 
4119                     INDEBUG(| CRST_DEBUG_ONLY_CHECK_FORBID_SUSPEND_THREAD)));
4120     m_crstHostAssemblyMapAdd.Init(CrstHostAssemblyMapAdd);
4121
4122     m_dwId = SystemDomain::GetNewAppDomainId(this);
4123
4124     m_LoaderAllocator.Init(this);
4125
4126 #ifndef CROSSGEN_COMPILE
4127     //Allocate the threadpool entry before the appdomin id list. Otherwise,
4128     //the thread pool list will be out of sync if insertion of id in 
4129     //the appdomain fails. 
4130     m_tpIndex = PerAppDomainTPCountList::AddNewTPIndex();    
4131 #endif // CROSSGEN_COMPILE
4132
4133     m_dwIndex = SystemDomain::GetNewAppDomainIndex(this);
4134
4135 #ifndef CROSSGEN_COMPILE
4136     PerAppDomainTPCountList::SetAppDomainId(m_tpIndex, m_dwId);
4137
4138     m_ADUnloadSink=new ADUnloadSink();
4139 #endif
4140
4141     BaseDomain::Init();
4142
4143     // Set up the IL stub cache
4144     m_ILStubCache.Init(GetLoaderAllocator()->GetHighFrequencyHeap());
4145
4146 // Set up the binding caches
4147     m_AssemblyCache.Init(&m_DomainCacheCrst, GetHighFrequencyHeap());
4148     m_UnmanagedCache.InitializeTable(this, &m_DomainCacheCrst);
4149
4150     m_MemoryPressure = 0;
4151
4152     m_sDomainLocalBlock.Init(this);
4153
4154 #ifndef CROSSGEN_COMPILE
4155
4156 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
4157     // NOTE: it's important that we initialize ARM data structures before calling
4158     // Ref_CreateHandleTableBucket, this is because AD::Init() can race with GC
4159     // and once we add ourselves to the handle table map the GC can start walking
4160     // our handles and calling AD::RecordSurvivedBytes() which touches ARM data.
4161     if (GCHeapUtilities::IsServerHeap())
4162         m_dwNumHeaps = CPUGroupInfo::CanEnableGCCPUGroups() ?
4163                            CPUGroupInfo::GetNumActiveProcessors() :
4164                            GetCurrentProcessCpuCount();
4165     else
4166         m_dwNumHeaps = 1;
4167     m_pullAllocBytes = new ULONGLONG [m_dwNumHeaps * ARM_CACHE_LINE_SIZE_ULL];
4168     m_pullSurvivedBytes = new ULONGLONG [m_dwNumHeaps * ARM_CACHE_LINE_SIZE_ULL];
4169     for (DWORD i = 0; i < m_dwNumHeaps; i++)
4170     {
4171         m_pullAllocBytes[i * ARM_CACHE_LINE_SIZE_ULL] = 0;
4172         m_pullSurvivedBytes[i * ARM_CACHE_LINE_SIZE_ULL] = 0;
4173     }
4174     m_ullLastEtwAllocBytes = 0;
4175 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
4176
4177     // Default domain reuses the handletablemap that was created during EEStartup since
4178     // default domain cannot be unloaded.
4179     if (GetId().m_dwId == DefaultADID)
4180     {
4181         m_handleStore = GCHandleUtilities::GetGCHandleManager()->GetGlobalHandleStore();
4182     }
4183     else
4184     {
4185         m_handleStore = GCHandleUtilities::GetGCHandleManager()->CreateHandleStore((void*)(uintptr_t)m_dwIndex.m_dwIndex);
4186     }
4187
4188     if (!m_handleStore)
4189     {
4190         COMPlusThrowOM();
4191     }
4192
4193 #endif // CROSSGEN_COMPILE
4194
4195 #ifdef FEATURE_TYPEEQUIVALENCE
4196     m_TypeEquivalenceCrst.Init(CrstTypeEquivalenceMap);
4197 #endif
4198
4199     m_ReflectionCrst.Init(CrstReflection, CRST_UNSAFE_ANYMODE);
4200     m_RefClassFactCrst.Init(CrstClassFactInfoHash);
4201
4202     {
4203         LockOwner lock = {&m_DomainCrst, IsOwnerOfCrst};
4204         m_clsidHash.Init(0,&CompareCLSID,true, &lock); // init hash table
4205     }
4206
4207     SetStage(STAGE_READYFORMANAGEDCODE);
4208
4209 #ifndef CROSSGEN_COMPILE
4210     m_pDefaultContext = new Context(this);
4211
4212     m_ExposedObject = CreateHandle(NULL);
4213
4214     // Create the Application Security Descriptor
4215
4216     COUNTER_ONLY(GetPerfCounters().m_Loading.cAppDomains++);
4217
4218 #ifdef FEATURE_COMINTEROP
4219     if (!AppX::IsAppXProcess())
4220     {
4221     }
4222 #endif //FEATURE_COMINTEROP
4223
4224 #ifdef FEATURE_TIERED_COMPILATION
4225     m_tieredCompilationManager.Init(GetId());
4226 #endif
4227 #endif // CROSSGEN_COMPILE
4228 } // AppDomain::Init
4229
4230
4231 /*********************************************************************/
4232
4233 BOOL AppDomain::IsCompilationDomain()
4234 {
4235     LIMITED_METHOD_CONTRACT;
4236
4237     BOOL isCompilationDomain = (m_dwFlags & COMPILATION_DOMAIN) != 0;
4238 #ifdef FEATURE_PREJIT
4239     _ASSERTE(!isCompilationDomain ||
4240              (IsCompilationProcess() && IsPassiveDomain()));
4241 #endif // FEATURE_PREJIT
4242     return isCompilationDomain;
4243 }
4244
4245 #ifndef CROSSGEN_COMPILE
4246
4247 extern int g_fADUnloadWorkerOK;
4248
4249 // Notes:
4250 //   This helper will send the AppDomain creation notifications for profiler / debugger.
4251 //   If it throws, its backout code will also send a notification.
4252 //   If it succeeds, then we still need to send a AppDomainCreateFinished notification.
4253 void AppDomain::CreateUnmanagedObject(AppDomainCreationHolder<AppDomain>& pDomain)
4254 {
4255     CONTRACTL
4256     {
4257         THROWS;
4258         MODE_COOPERATIVE;
4259         GC_TRIGGERS;
4260         INJECT_FAULT(COMPlusThrowOM(););
4261     }
4262     CONTRACTL_END;
4263
4264     GCX_PREEMP();
4265
4266     pDomain.Assign(new AppDomain());
4267     if (g_fADUnloadWorkerOK<0)
4268     {
4269         AppDomain::CreateADUnloadWorker();
4270     }
4271
4272     //@todo: B#25921
4273     // We addref Appdomain object here and notify a profiler that appdomain 
4274     // creation has started, then return to managed code which will  call 
4275     // the function that releases the appdomain and notifies a profiler that we finished
4276     // creating the appdomain. If an exception is raised while we're in that managed code
4277     // we will leak memory and the profiler will not be notified about the failure
4278
4279 #ifdef PROFILING_SUPPORTED
4280     // Signal profile if present.
4281     {
4282         BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
4283         g_profControlBlock.pProfInterface->AppDomainCreationStarted((AppDomainID) (AppDomain*) pDomain);
4284         END_PIN_PROFILER();
4285     }
4286     EX_TRY
4287 #endif // PROFILING_SUPPORTED
4288     {
4289         {
4290             SystemDomain::LockHolder lh;
4291             pDomain->Init(); 
4292             // allocate a Virtual Call Stub Manager for this domain
4293             pDomain->InitVSD();
4294         }
4295
4296         pDomain->SetCanUnload();    // by default can unload any domain
4297         
4298         #ifdef DEBUGGING_SUPPORTED    
4299         // Notify the debugger here, before the thread transitions into the 
4300         // AD to finish the setup, and before any assemblies are loaded into it.
4301         SystemDomain::PublishAppDomainAndInformDebugger(pDomain);
4302         #endif // DEBUGGING_SUPPORTED
4303
4304         STRESS_LOG2 (LF_APPDOMAIN, LL_INFO100, "Create domain [%d] %p\n", pDomain->GetId().m_dwId, (AppDomain*)pDomain);
4305         pDomain->LoadSystemAssemblies();
4306         pDomain->SetupSharedStatics();
4307
4308         pDomain->SetStage(AppDomain::STAGE_ACTIVE);    
4309     }        
4310 #ifdef PROFILING_SUPPORTED
4311     EX_HOOK
4312     {
4313         // Need the first assembly loaded in to get any data on an app domain.
4314         {
4315             BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
4316             g_profControlBlock.pProfInterface->AppDomainCreationFinished((AppDomainID)(AppDomain*) pDomain, GET_EXCEPTION()->GetHR());
4317             END_PIN_PROFILER();
4318         }
4319     }
4320     EX_END_HOOK;
4321
4322     // On success, caller must still send the AppDomainCreationFinished notification.
4323 #endif // PROFILING_SUPPORTED
4324 }
4325
4326 void AppDomain::Stop()
4327 {
4328     CONTRACTL
4329     {
4330         NOTHROW;
4331         MODE_ANY;
4332         GC_TRIGGERS;
4333     }
4334     CONTRACTL_END;
4335
4336 #ifdef FEATURE_MULTICOREJIT
4337     GetMulticoreJitManager().StopProfile(true);
4338 #endif
4339
4340     // Set the unloaded flag before notifying the debugger
4341     GetLoaderAllocator()->SetIsUnloaded();
4342
4343 #ifdef DEBUGGING_SUPPORTED
4344     if (IsDebuggerAttached())
4345         NotifyDebuggerUnload();
4346 #endif // DEBUGGING_SUPPORTED
4347
4348     m_pRootAssembly = NULL; // This assembly is in the assembly list;
4349
4350 #ifdef DEBUGGING_SUPPORTED
4351     if (NULL != g_pDebugInterface)
4352     {
4353         // Call the publisher API to delete this appdomain entry from the list
4354         CONTRACT_VIOLATION(ThrowsViolation);
4355         g_pDebugInterface->RemoveAppDomainFromIPC (this);
4356     }
4357 #endif // DEBUGGING_SUPPORTED
4358 }
4359
4360 void AppDomain::Terminate()
4361 {
4362     CONTRACTL
4363     {
4364         NOTHROW;
4365         GC_TRIGGERS;
4366         MODE_ANY;
4367     }
4368     CONTRACTL_END;
4369
4370     GCX_PREEMP();
4371
4372
4373     _ASSERTE(m_dwThreadEnterCount == 0 || IsDefaultDomain());
4374
4375     if (m_pComIPForExposedObject)
4376     {
4377         m_pComIPForExposedObject->Release();
4378         m_pComIPForExposedObject = NULL;
4379     }
4380
4381     delete m_pDefaultContext;
4382     m_pDefaultContext = NULL;
4383
4384     if (m_pUMEntryThunkCache)
4385     {
4386         delete m_pUMEntryThunkCache;
4387         m_pUMEntryThunkCache = NULL;
4388     }
4389
4390 #ifdef FEATURE_COMINTEROP
4391     if (m_pRCWCache)
4392     {
4393         delete m_pRCWCache;
4394         m_pRCWCache = NULL;
4395     }
4396
4397     if (m_pRCWRefCache)
4398     {
4399         delete m_pRCWRefCache;
4400         m_pRCWRefCache = NULL;
4401     }
4402     
4403     if (m_pComCallWrapperCache)
4404     {
4405         m_pComCallWrapperCache->Neuter();
4406         m_pComCallWrapperCache->Release();
4407     }
4408
4409     // if the above released the wrapper cache, then it will call back and reset our
4410     // m_pComCallWrapperCache to null. If not null, then need to set it's domain pointer to
4411     // null.
4412     if (! m_pComCallWrapperCache)
4413     {
4414         LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::Terminate ComCallWrapperCache released\n"));
4415     }
4416 #ifdef _DEBUG
4417     else
4418     {
4419         m_pComCallWrapperCache = NULL;
4420         LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::Terminate ComCallWrapperCache not released\n"));
4421     }
4422 #endif // _DEBUG
4423
4424 #endif // FEATURE_COMINTEROP
4425
4426
4427     if (!IsAtProcessExit())
4428     {
4429         // if we're not shutting down everything then clean up the string literals associated
4430         // with this appdomain -- note that is no longer needs to happen while suspended
4431         // because the appropriate locks are taken in the GlobalStringLiteralMap
4432         // this is important as this locks have a higher lock number than does the
4433         // thread-store lock which is taken when we suspend.
4434         GetLoaderAllocator()->CleanupStringLiteralMap();
4435
4436         // Suspend the EE to do some clean up that can only occur
4437         // while no threads are running.
4438         GCX_COOP (); // SuspendEE may require current thread to be in Coop mode
4439         ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_APPDOMAIN_SHUTDOWN);
4440     }
4441
4442     // Note that this must be performed before restarting the EE. It will clean
4443     // the cache and prevent others from using stale cache entries.
4444     //@TODO: Would be nice to get this back to BaseDomain, but need larger fix for that.
4445     // NOTE: Must have the runtime suspended to unlink managers
4446     // NOTE: May be NULL due to OOM during initialization. Can skip in that case.
4447     GetLoaderAllocator()->UninitVirtualCallStubManager();
4448     MethodTable::ClearMethodDataCache();
4449     ClearJitGenericHandleCache(this);
4450
4451     // @TODO s_TPMethodTableCrst prevents us from from keeping the whole
4452     // assembly shutdown logic here. See if we can do better in the next milestone
4453 #ifdef  FEATURE_PREJIT
4454     DeleteNativeCodeRanges();
4455 #endif
4456
4457     if (!IsAtProcessExit())
4458     {
4459         // Resume the EE.
4460         ThreadSuspend::RestartEE(FALSE, TRUE);
4461     }
4462
4463     ShutdownAssemblies();
4464     ShutdownNativeDllSearchDirectories();
4465
4466     if (m_pRefClassFactHash)
4467     {
4468         m_pRefClassFactHash->Destroy();
4469         // storage for m_pRefClassFactHash itself is allocated on the loader heap
4470     }
4471
4472 #ifdef FEATURE_TYPEEQUIVALENCE
4473     m_TypeEquivalenceCrst.Destroy();
4474 #endif
4475
4476     m_ReflectionCrst.Destroy();
4477     m_RefClassFactCrst.Destroy();
4478
4479     m_LoaderAllocator.Terminate();
4480
4481     BaseDomain::Terminate();
4482
4483     if (m_handleStore)
4484     {
4485         GCHandleUtilities::GetGCHandleManager()->DestroyHandleStore(m_handleStore);
4486         m_handleStore = NULL;
4487     }
4488
4489 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
4490     if (m_pullAllocBytes)
4491     {
4492         delete [] m_pullAllocBytes;
4493     }
4494     if (m_pullSurvivedBytes)
4495     {
4496         delete [] m_pullSurvivedBytes;
4497     }
4498 #endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
4499
4500     if(m_dwIndex.m_dwIndex != 0)
4501         SystemDomain::ReleaseAppDomainIndex(m_dwIndex);
4502 } // AppDomain::Terminate
4503
4504 void AppDomain::CloseDomain()
4505 {
4506     CONTRACTL
4507     {
4508         NOTHROW;
4509         GC_TRIGGERS;
4510         MODE_ANY;
4511     }
4512     CONTRACTL_END;
4513
4514
4515     BOOL bADRemoved=FALSE;;
4516
4517     AddRef();  // Hold a reference
4518     AppDomainRefHolder AdHolder(this);
4519     {
4520         SystemDomain::LockHolder lh;
4521
4522         SystemDomain::System()->DecrementNumAppDomains(); // Maintain a count of app domains added to the list.
4523         bADRemoved = SystemDomain::System()->RemoveDomain(this);
4524     }
4525
4526     if(bADRemoved)
4527         Stop();
4528 }
4529
4530 /*********************************************************************/
4531
4532 struct GetExposedObject_Args
4533 {
4534     AppDomain *pDomain;
4535     OBJECTREF *ref;
4536 };
4537
4538 static void GetExposedObject_Wrapper(LPVOID ptr)
4539 {
4540     CONTRACTL
4541     {
4542         THROWS;
4543         GC_TRIGGERS;
4544         MODE_COOPERATIVE;
4545     }
4546     CONTRACTL_END;
4547     GetExposedObject_Args *args = (GetExposedObject_Args *) ptr;
4548     *(args->ref) = args->pDomain->GetExposedObject();
4549 }
4550
4551
4552 OBJECTREF AppDomain::GetExposedObject()
4553 {
4554     CONTRACTL
4555     {
4556         MODE_COOPERATIVE;
4557         THROWS;
4558         GC_TRIGGERS;
4559         INJECT_FAULT(COMPlusThrowOM(););
4560     }
4561     CONTRACTL_END;
4562
4563     OBJECTREF ref = GetRawExposedObject();
4564     if (ref == NULL)
4565     {
4566         APPDOMAINREF obj = NULL;
4567
4568         Thread *pThread = GetThread();
4569         if (pThread->GetDomain() != this)
4570         {
4571             GCPROTECT_BEGIN(ref);
4572             GetExposedObject_Args args = {this, &ref};
4573             // call through DoCallBack with a domain transition
4574             pThread->DoADCallBack(this,GetExposedObject_Wrapper, &args,ADV_CREATING|ADV_RUNNINGIN);
4575             GCPROTECT_END();
4576             return ref;
4577         }
4578         MethodTable *pMT = MscorlibBinder::GetClass(CLASS__APP_DOMAIN);
4579
4580         // Create the module object
4581         obj = (APPDOMAINREF) AllocateObject(pMT);
4582         obj->SetDomain(this);
4583
4584         if (!StoreFirstObjectInHandle(m_ExposedObject, (OBJECTREF) obj))
4585         {
4586             obj = (APPDOMAINREF) GetRawExposedObject();
4587             _ASSERTE(obj);
4588         }
4589
4590         return (OBJECTREF) obj;
4591     }
4592
4593     return ref;
4594 }
4595
4596
4597
4598 OBJECTREF AppDomain::DoSetup(OBJECTREF* setupInfo)
4599 {
4600     CONTRACTL
4601     {
4602         MODE_COOPERATIVE;
4603         THROWS;
4604         GC_TRIGGERS;
4605         INJECT_FAULT(COMPlusThrowOM(););
4606     }
4607     CONTRACTL_END;
4608
4609     ADID adid=GetAppDomain()->GetId();
4610
4611     OBJECTREF retval=NULL;
4612     GCPROTECT_BEGIN(retval);    
4613
4614     ENTER_DOMAIN_PTR(this,ADV_CREATING);
4615
4616     MethodDescCallSite setup(METHOD__APP_DOMAIN__SETUP);
4617
4618     ARG_SLOT args[1];
4619
4620     args[0]=ObjToArgSlot(*setupInfo);
4621
4622     OBJECTREF activator;
4623     activator=setup.Call_RetOBJECTREF(args);
4624     _ASSERTE(activator==NULL);
4625     
4626 #if defined(FEATURE_MULTICOREJIT)
4627     // Disable AutoStartProfile in default domain from this code path.
4628     // It's called from SystemDomain::ExecuteMainMethod for normal program, not needed for SL and Asp.Net
4629     if (! IsDefaultDomain())
4630     {
4631         GCX_PREEMP();
4632
4633         GetMulticoreJitManager().AutoStartProfile(this);
4634     }
4635 #endif
4636
4637     END_DOMAIN_TRANSITION;
4638     GCPROTECT_END();
4639     return retval;
4640 }
4641
4642 #endif // !CROSSGEN_COMPILE
4643
4644 #ifdef FEATURE_COMINTEROP
4645 #ifndef CROSSGEN_COMPILE
4646 HRESULT AppDomain::GetComIPForExposedObject(IUnknown **pComIP)
4647 {
4648     // Assumption: This function is called for AppDomain's that the current
4649     //             thread is in or has entered, or the AppDomain is kept alive.
4650     //
4651     // Assumption: This function can now throw.  The caller is responsible for any
4652     //             BEGIN_EXTERNAL_ENTRYPOINT, EX_TRY, or other
4653     //             techniques to convert to a COM HRESULT protocol.
4654     CONTRACTL
4655     {
4656         THROWS;
4657         GC_TRIGGERS;
4658         MODE_ANY;
4659     }
4660     CONTRACTL_END;
4661
4662     HRESULT hr = S_OK;
4663     Thread *pThread = GetThread();
4664     if (m_pComIPForExposedObject)
4665     {
4666         GCX_PREEMP_THREAD_EXISTS(pThread);
4667         m_pComIPForExposedObject->AddRef();
4668         *pComIP = m_pComIPForExposedObject;
4669         return S_OK;
4670     }
4671
4672     IUnknown* punk = NULL;
4673
4674     OBJECTREF ref = NULL;
4675     GCPROTECT_BEGIN(ref);
4676
4677     EnsureComStarted();
4678
4679     ENTER_DOMAIN_PTR(this,ADV_DEFAULTAD)
4680     {
4681         ref = GetExposedObject();
4682         punk = GetComIPFromObjectRef(&ref);
4683         if (FastInterlockCompareExchangePointer(&m_pComIPForExposedObject, punk, NULL) == NULL)
4684         {
4685             GCX_PREEMP_THREAD_EXISTS(pThread);
4686             m_pComIPForExposedObject->AddRef();
4687         }
4688     }
4689     END_DOMAIN_TRANSITION;
4690
4691     GCPROTECT_END();
4692
4693     if(SUCCEEDED(hr))
4694     {
4695         *pComIP = m_pComIPForExposedObject;
4696     }
4697
4698     return hr;
4699 }
4700 #endif //#ifndef CROSSGEN_COMPILE
4701
4702 MethodTable *AppDomain::GetRedirectedType(WinMDAdapter::RedirectedTypeIndex index)
4703 {
4704     CONTRACTL
4705     {
4706         THROWS;
4707         GC_TRIGGERS;
4708         MODE_ANY;
4709     }
4710     CONTRACTL_END;
4711
4712     // If we have the type loaded already, use that
4713     if (m_rpCLRTypes[index] != nullptr)
4714     {
4715         return m_rpCLRTypes[index];
4716     }
4717
4718     WinMDAdapter::FrameworkAssemblyIndex frameworkAssemblyIndex;
4719     WinMDAdapter::GetRedirectedTypeInfo(index, nullptr, nullptr, nullptr, &frameworkAssemblyIndex, nullptr, nullptr);
4720     MethodTable * pMT = LoadRedirectedType(index, frameworkAssemblyIndex);
4721     m_rpCLRTypes[index] = pMT;
4722     return pMT;
4723 }
4724
4725 MethodTable* AppDomain::LoadRedirectedType(WinMDAdapter::RedirectedTypeIndex index, WinMDAdapter::FrameworkAssemblyIndex assembly)
4726 {
4727     CONTRACTL
4728     {
4729         THROWS;
4730         GC_TRIGGERS;
4731         MODE_ANY;
4732         PRECONDITION(index < WinMDAdapter::RedirectedTypeIndex_Count);
4733     }
4734     CONTRACTL_END;
4735
4736     LPCSTR szClrNamespace;
4737     LPCSTR szClrName;
4738     LPCSTR szFullWinRTName;
4739     WinMDAdapter::FrameworkAssemblyIndex nFrameworkAssemblyIndex;
4740
4741     WinMDAdapter::GetRedirectedTypeInfo(index, &szClrNamespace, &szClrName, &szFullWinRTName, &nFrameworkAssemblyIndex, nullptr, nullptr);
4742
4743     _ASSERTE(nFrameworkAssemblyIndex >= WinMDAdapter::FrameworkAssembly_Mscorlib &&
4744              nFrameworkAssemblyIndex < WinMDAdapter::FrameworkAssembly_Count);
4745
4746     if (assembly != nFrameworkAssemblyIndex)
4747     {
4748         // The framework type does not live in the assembly we were requested to load redirected types from
4749         return nullptr;
4750     }
4751     else if (nFrameworkAssemblyIndex == WinMDAdapter::FrameworkAssembly_Mscorlib)
4752     {
4753         return ClassLoader::LoadTypeByNameThrowing(MscorlibBinder::GetModule()->GetAssembly(),
4754                                                    szClrNamespace,
4755                                                    szClrName,
4756                                                    ClassLoader::ThrowIfNotFound,
4757                                                    ClassLoader::LoadTypes,
4758                                                    CLASS_LOAD_EXACTPARENTS).GetMethodTable();
4759     }
4760     else
4761     {
4762         LPCSTR pSimpleName;
4763         AssemblyMetaDataInternal context;
4764         const BYTE * pbKeyToken;
4765         DWORD cbKeyTokenLength;
4766         DWORD dwFlags;
4767
4768         WinMDAdapter::GetExtraAssemblyRefProps(nFrameworkAssemblyIndex,
4769                                                &pSimpleName,
4770                                                &context,
4771                                                &pbKeyToken,
4772                                                &cbKeyTokenLength,
4773                                                &dwFlags);
4774
4775         Assembly* pAssembly = AssemblySpec::LoadAssembly(pSimpleName,
4776                                                          &context,
4777                                                          pbKeyToken,
4778                                                          cbKeyTokenLength,
4779                                                          dwFlags);
4780
4781         return ClassLoader::LoadTypeByNameThrowing(
4782             pAssembly,
4783             szClrNamespace,
4784             szClrName,
4785             ClassLoader::ThrowIfNotFound,
4786             ClassLoader::LoadTypes,
4787             CLASS_LOAD_EXACTPARENTS).GetMethodTable();
4788     }
4789 }
4790 #endif //FEATURE_COMINTEROP
4791
4792 #endif //!DACCESS_COMPILE
4793
4794 #ifndef DACCESS_COMPILE
4795
4796 bool IsPlatformAssembly(LPCSTR szName, DomainAssembly *pDomainAssembly)
4797 {
4798     CONTRACTL
4799     {
4800         THROWS;
4801         GC_TRIGGERS;
4802         MODE_ANY;
4803         PRECONDITION(CheckPointer(szName));
4804         PRECONDITION(CheckPointer(pDomainAssembly));
4805     }
4806     CONTRACTL_END;
4807
4808     PEAssembly *pPEAssembly = pDomainAssembly->GetFile();
4809
4810     if (strcmp(szName, pPEAssembly->GetSimpleName()) != 0)
4811     {
4812         return false;
4813     }
4814     
4815     DWORD cbPublicKey;
4816     const BYTE *pbPublicKey = static_cast<const BYTE *>(pPEAssembly->GetPublicKey(&cbPublicKey));
4817     if (pbPublicKey == nullptr)
4818     {
4819         return false;
4820     }
4821
4822     return StrongNameIsSilverlightPlatformKey(pbPublicKey, cbPublicKey);
4823 }
4824
4825 void AppDomain::AddAssembly(DomainAssembly * assem)
4826 {
4827     CONTRACTL
4828     {
4829         THROWS;
4830         GC_TRIGGERS;
4831         MODE_ANY;
4832         INJECT_FAULT(COMPlusThrowOM(););
4833     }
4834     CONTRACTL_END;
4835     
4836     {
4837         CrstHolder ch(GetAssemblyListLock());
4838     
4839         // Attempt to find empty space in assemblies list
4840         DWORD asmCount = m_Assemblies.GetCount_Unlocked();
4841         for (DWORD i = 0; i < asmCount; ++i)
4842         {
4843             if (m_Assemblies.Get_UnlockedNoReference(i) == NULL)
4844             {
4845                 m_Assemblies.Set_Unlocked(i, assem);
4846                 return;
4847             }
4848         }
4849
4850         // If empty space not found, simply add to end of list
4851         IfFailThrow(m_Assemblies.Append_Unlocked(assem));
4852     }
4853 }
4854
4855 void AppDomain::RemoveAssembly_Unlocked(DomainAssembly * pAsm)
4856 {
4857     CONTRACTL
4858     {
4859         NOTHROW;
4860         GC_NOTRIGGER;
4861     }
4862     CONTRACTL_END;
4863     
4864     _ASSERTE(GetAssemblyListLock()->OwnedByCurrentThread());
4865     
4866     DWORD asmCount = m_Assemblies.GetCount_Unlocked();
4867     for (DWORD i = 0; i < asmCount; ++i)
4868     {
4869         if (m_Assemblies.Get_UnlockedNoReference(i) == pAsm)
4870         {
4871             m_Assemblies.Set_Unlocked(i, NULL);
4872             return;
4873         }
4874     }
4875     
4876     _ASSERTE(!"Unreachable");
4877 }
4878
4879 BOOL AppDomain::ContainsAssembly(Assembly * assem)
4880 {
4881     WRAPPER_NO_CONTRACT;
4882     AssemblyIterator i = IterateAssembliesEx((AssemblyIterationFlags)(
4883         kIncludeLoaded | 
4884         (assem->IsIntrospectionOnly() ? kIncludeIntrospection : kIncludeExecution)));
4885     CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
4886
4887     while (i.Next(pDomainAssembly.This()))
4888     {
4889         CollectibleAssemblyHolder<Assembly *> pAssembly = pDomainAssembly->GetLoadedAssembly();
4890         if (pAssembly == assem)
4891             return TRUE;
4892     }
4893
4894     return FALSE;
4895 }
4896
4897 EEClassFactoryInfoHashTable* AppDomain::SetupClassFactHash()
4898 {
4899     CONTRACTL
4900     {
4901         THROWS;
4902         GC_TRIGGERS;
4903         MODE_ANY;
4904         INJECT_FAULT(COMPlusThrowOM(););
4905     }
4906     CONTRACTL_END;
4907
4908     CrstHolder ch(&m_ReflectionCrst);
4909
4910     if (m_pRefClassFactHash == NULL)
4911     {
4912         AllocMemHolder<void> pCache(GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof (EEClassFactoryInfoHashTable))));
4913         EEClassFactoryInfoHashTable *tmp = new (pCache) EEClassFactoryInfoHashTable;
4914         LockOwner lock = {&m_RefClassFactCrst,IsOwnerOfCrst};
4915         if (!tmp->Init(20, &lock))
4916             COMPlusThrowOM();
4917         pCache.SuppressRelease();
4918         m_pRefClassFactHash = tmp;
4919     }
4920
4921     return m_pRefClassFactHash;
4922 }
4923
4924 #ifdef FEATURE_COMINTEROP
4925 DispIDCache* AppDomain::SetupRefDispIDCache()
4926 {
4927     CONTRACTL
4928     {
4929         THROWS;
4930         GC_TRIGGERS;
4931         MODE_ANY;
4932         INJECT_FAULT(COMPlusThrowOM(););
4933     }
4934     CONTRACTL_END;
4935
4936     CrstHolder ch(&m_ReflectionCrst);
4937
4938     if (m_pRefDispIDCache == NULL)
4939     {
4940         AllocMemHolder<void> pCache = GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof (DispIDCache)));
4941
4942         DispIDCache *tmp = new (pCache) DispIDCache;
4943         tmp->Init();
4944
4945         pCache.SuppressRelease();
4946         m_pRefDispIDCache = tmp;
4947     }
4948
4949     return m_pRefDispIDCache;
4950 }
4951
4952 #endif // FEATURE_COMINTEROP
4953
4954 FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile)
4955 {
4956     CONTRACTL
4957     {
4958         THROWS;
4959         GC_TRIGGERS;
4960         MODE_ANY;
4961         PRECONDITION(pLock->HasLock());
4962         PRECONDITION(pLock->FindFileLock(pFile) == NULL);
4963         INJECT_FAULT(COMPlusThrowOM(););
4964     }
4965     CONTRACTL_END;
4966
4967     NewHolder<FileLoadLock> result(new FileLoadLock(pLock, pFile, pDomainFile));
4968
4969     pLock->AddElement(result);
4970     result->AddRef(); // Add one ref on behalf of the ListLock's reference. The corresponding Release() happens in FileLoadLock::CompleteLoadLevel.
4971     return result.Extract();
4972 }
4973
4974 FileLoadLock::~FileLoadLock()
4975 {
4976     CONTRACTL
4977     {
4978         DESTRUCTOR_CHECK;
4979         NOTHROW;
4980         GC_TRIGGERS;
4981         MODE_ANY;
4982     }
4983     CONTRACTL_END;
4984     ((PEFile *) m_data)->Release();
4985 }
4986
4987 DomainFile *FileLoadLock::GetDomainFile()
4988 {
4989     LIMITED_METHOD_CONTRACT;
4990     return m_pDomainFile;
4991 }
4992
4993 FileLoadLevel FileLoadLock::GetLoadLevel()
4994 {
4995     LIMITED_METHOD_CONTRACT;
4996     return m_level;
4997 }
4998
4999 ADID FileLoadLock::GetAppDomainId()
5000 {
5001     LIMITED_METHOD_CONTRACT;
5002     return m_AppDomainId;
5003 }
5004
5005 // Acquire will return FALSE and not take the lock if the file
5006 // has already been loaded to the target level.  Otherwise,
5007 // it will return TRUE and take the lock.
5008 //
5009 // Note that the taker must release the lock via IncrementLoadLevel.
5010
5011 BOOL FileLoadLock::Acquire(FileLoadLevel targetLevel)
5012 {
5013     WRAPPER_NO_CONTRACT;
5014
5015     // If we are already loaded to the desired level, the lock is "free".
5016     if (m_level >= targetLevel)
5017         return FALSE;
5018
5019     if (!DeadlockAwareEnter())
5020     {
5021         // We failed to get the lock due to a deadlock.
5022         return FALSE;
5023     }
5024
5025     if (m_level >= targetLevel)
5026     {
5027         Leave();
5028         return FALSE;
5029     }
5030
5031     return TRUE;
5032 }
5033
5034 BOOL FileLoadLock::CanAcquire(FileLoadLevel targetLevel)
5035 {
5036     // If we are already loaded to the desired level, the lock is "free".
5037     if (m_level >= targetLevel)
5038         return FALSE;
5039
5040     return CanDeadlockAwareEnter();
5041 }
5042
5043 #if !defined(DACCESS_COMPILE) && (defined(LOGGING) || defined(STRESS_LOG))
5044 static const char *fileLoadLevelName[] =
5045 {
5046     "CREATE",                             // FILE_LOAD_CREATE
5047     "BEGIN",                              // FILE_LOAD_BEGIN
5048     "FIND_NATIVE_IMAGE",                  // FILE_LOAD_FIND_NATIVE_IMAGE
5049     "VERIFY_NATIVE_IMAGE_DEPENDENCIES",   // FILE_LOAD_VERIFY_NATIVE_IMAGE_DEPENDENCIES
5050     "ALLOCATE",                           // FILE_LOAD_ALLOCATE
5051     "ADD_DEPENDENCIES",                   // FILE_LOAD_ADD_DEPENDENCIES
5052     "PRE_LOADLIBRARY",                    // FILE_LOAD_PRE_LOADLIBRARY
5053     "LOADLIBRARY",                        // FILE_LOAD_LOADLIBRARY
5054     "POST_LOADLIBRARY",                   // FILE_LOAD_POST_LOADLIBRARY                
5055     "EAGER_FIXUPS",                       // FILE_LOAD_EAGER_FIXUPS
5056     "VTABLE FIXUPS",                      // FILE_LOAD_VTABLE_FIXUPS
5057     "DELIVER_EVENTS",                     // FILE_LOAD_DELIVER_EVENTS
5058     "LOADED",                             // FILE_LOADED
5059     "VERIFY_EXECUTION",                   // FILE_LOAD_VERIFY_EXECUTION
5060     "ACTIVE",                             // FILE_ACTIVE
5061 };
5062 #endif // !DACCESS_COMPILE && (LOGGING || STRESS_LOG)
5063
5064 BOOL FileLoadLock::CompleteLoadLevel(FileLoadLevel level, BOOL success)
5065 {
5066     CONTRACTL
5067     {
5068         MODE_ANY;
5069         GC_TRIGGERS;
5070         THROWS;
5071         PRECONDITION(HasLock());
5072     }
5073     CONTRACTL_END;
5074
5075     // Increment may happen more than once if reentrancy occurs (e.g. LoadLibrary)
5076     if (level > m_level)
5077     {
5078         // Must complete each level in turn, unless we have an error
5079         CONSISTENCY_CHECK(m_pDomainFile->IsError() || (level == (m_level+1)));
5080         // Remove the lock from the list if the load is completed
5081         if (level >= FILE_ACTIVE)
5082         {
5083             {
5084                 GCX_COOP();
5085                 PEFileListLockHolder lock((PEFileListLock*)m_pList);
5086
5087 #if _DEBUG
5088                 BOOL fDbgOnly_SuccessfulUnlink =
5089 #endif                
5090                     m_pList->Unlink(this);
5091                 _ASSERTE(fDbgOnly_SuccessfulUnlink);
5092
5093                 m_pDomainFile->ClearLoading();
5094
5095                 CONSISTENCY_CHECK(m_dwRefCount >= 2); // Caller (LoadDomainFile) should have 1 refcount and m_pList should have another which was acquired in FileLoadLock::Create.
5096
5097                 m_level = (FileLoadLevel)level;
5098
5099                 // Dev11 bug 236344
5100                 // In AppDomain::IsLoading, if the lock is taken on m_pList and then FindFileLock returns NULL,
5101                 // we depend on the DomainFile's load level being up to date. Hence we must update the load
5102                 // level while the m_pList lock is held.
5103                 if (success)
5104                     m_pDomainFile->SetLoadLevel(level);
5105             }
5106
5107
5108             Release(); // Release m_pList's refcount on this lock, which was acquired in FileLoadLock::Create
5109
5110         }
5111         else
5112         {
5113             m_level = (FileLoadLevel)level;
5114
5115             if (success)
5116                 m_pDomainFile->SetLoadLevel(level);
5117         }
5118
5119 #ifndef DACCESS_COMPILE
5120         switch(level)
5121         {
5122             case FILE_LOAD_ALLOCATE:
5123             case FILE_LOAD_ADD_DEPENDENCIES:
5124             case FILE_LOAD_DELIVER_EVENTS:
5125             case FILE_LOADED:
5126             case FILE_ACTIVE: // The timing of stress logs is not critical, so even for the FILE_ACTIVE stage we need not do it while the m_pList lock is held.
5127                 STRESS_LOG4(LF_CLASSLOADER, LL_INFO100, "Completed Load Level %s for DomainFile %p in AD %i - success = %i\n", fileLoadLevelName[level], m_pDomainFile, m_AppDomainId.m_dwId, success);
5128                 break;
5129             default:
5130                 break;
5131         }
5132 #endif
5133
5134         return TRUE;
5135     }
5136     else
5137         return FALSE;
5138 }
5139
5140 void FileLoadLock::SetError(Exception *ex)
5141 {
5142     CONTRACTL
5143     {
5144         MODE_ANY;
5145         GC_TRIGGERS;
5146         THROWS;
5147         PRECONDITION(CheckPointer(ex));
5148         PRECONDITION(HasLock());
5149         INJECT_FAULT(COMPlusThrowOM(););
5150     }
5151     CONTRACTL_END;
5152
5153     m_cachedHR = ex->GetHR();
5154
5155     LOG((LF_LOADER, LL_WARNING, "LOADER: %x:***%s*\t!!!Non-transient error 0x%x\n",
5156          m_pDomainFile->GetAppDomain(), m_pDomainFile->GetSimpleName(), m_cachedHR));
5157
5158     m_pDomainFile->SetError(ex);
5159
5160     CompleteLoadLevel(FILE_ACTIVE, FALSE);
5161 }
5162
5163 void FileLoadLock::AddRef()
5164 {
5165     LIMITED_METHOD_CONTRACT;
5166     FastInterlockIncrement((LONG *) &m_dwRefCount);
5167 }
5168
5169 UINT32 FileLoadLock::Release()
5170 {
5171     CONTRACTL
5172     {
5173         NOTHROW;
5174         GC_TRIGGERS;
5175         MODE_ANY;
5176     }
5177     CONTRACTL_END;
5178
5179     LONG count = FastInterlockDecrement((LONG *) &m_dwRefCount);
5180     if (count == 0)
5181         delete this;
5182
5183     return count;
5184 }
5185
5186 FileLoadLock::FileLoadLock(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile)
5187   : ListLockEntry(pLock, pFile, "File load lock"),
5188     m_level((FileLoadLevel) (FILE_LOAD_CREATE)),
5189     m_pDomainFile(pDomainFile),
5190     m_cachedHR(S_OK),
5191     m_AppDomainId(pDomainFile->GetAppDomain()->GetId())
5192 {
5193     WRAPPER_NO_CONTRACT;
5194     pFile->AddRef();
5195 }
5196
5197 void FileLoadLock::HolderLeave(FileLoadLock *pThis)
5198 {
5199     LIMITED_METHOD_CONTRACT;
5200     pThis->Leave();
5201 }
5202
5203
5204
5205
5206
5207
5208 //
5209 // Assembly loading:
5210 //
5211 // Assembly loading is carefully layered to avoid deadlocks in the
5212 // presence of circular loading dependencies.
5213 // A LoadLevel is associated with each assembly as it is being loaded.  During the
5214 // act of loading (abstractly, increasing its load level), its lock is
5215 // held, and the current load level is stored on the thread.  Any
5216 // recursive loads during that period are automatically restricted to
5217 // only partially load the dependent assembly to the same level as the
5218 // caller (or to one short of that level in the presence of a deadlock
5219 // loop.)
5220 //
5221 // Each loading stage must be carfully constructed so that
5222 // this constraint is expected and can be dealt with.
5223 //
5224 // Note that there is one case where this still doesn't handle recursion, and that is the
5225 // security subsytem. The security system runs managed code, and thus must typically fully
5226 // initialize assemblies of permission sets it is trying to use. (And of course, these may be used
5227 // while those assemblies are initializing.)  This is dealt with in the historical manner - namely
5228 // the security system passes in a special flag which says that it will deal with null return values
5229 // in the case where a load cannot be safely completed due to such issues.
5230 //
5231
5232 void AppDomain::LoadSystemAssemblies()
5233 {
5234     STANDARD_VM_CONTRACT;
5235
5236     // The only reason to make an assembly a "system assembly" is if the EE is caching
5237     // pointers to stuff in the assembly.  Because this is going on, we need to preserve
5238     // the invariant that the assembly is loaded into every app domain.
5239     //
5240     // Right now we have only one system assembly. We shouldn't need to add any more.
5241
5242     LoadAssembly(NULL, SystemDomain::System()->SystemFile(), FILE_ACTIVE);
5243 }
5244
5245 FileLoadLevel AppDomain::GetDomainFileLoadLevel(DomainFile *pFile)
5246 {
5247     CONTRACTL
5248     {
5249         THROWS;
5250         GC_TRIGGERS;
5251         MODE_ANY;
5252     }
5253     CONTRACTL_END
5254
5255     LoadLockHolder lock(this);
5256
5257     FileLoadLock* pLockEntry = (FileLoadLock *) lock->FindFileLock(pFile->GetFile());
5258
5259     if (pLockEntry == NULL)
5260         return pFile->GetLoadLevel();
5261     else
5262         return pLockEntry->GetLoadLevel();
5263 }
5264
5265 // This checks if the thread has initiated (or completed) loading at the given level.  A false guarantees that
5266 // (a) The current thread (or a thread blocking on the current thread) has not started loading the file
5267 //      at the given level, and
5268 // (b) No other thread had started loading the file at this level at the start of this function call.
5269
5270 // Note that another thread may start loading the file at that level in a race with the completion of
5271 // this function.  However, the caller still has the guarantee that such a load started after this
5272 // function was called (and e.g. any state in place before the function call will be seen by the other thread.)
5273 //
5274 // Conversely, a true guarantees that either the current thread has started the load step, or another
5275 // thread has completed the load step.
5276 //
5277
5278 BOOL AppDomain::IsLoading(DomainFile *pFile, FileLoadLevel level)
5279 {
5280     // Cheap out
5281     if (pFile->GetLoadLevel() < level)
5282     {
5283         FileLoadLock *pLock = NULL;
5284         {
5285             LoadLockHolder lock(this);
5286
5287             pLock = (FileLoadLock *) lock->FindFileLock(pFile->GetFile());
5288
5289             if (pLock == NULL)
5290             {
5291                 // No thread involved with loading
5292                 return pFile->GetLoadLevel() >= level;
5293             }
5294
5295             pLock->AddRef();
5296         }
5297
5298         FileLoadLockRefHolder lockRef(pLock);
5299
5300         if (pLock->Acquire(level))
5301         {
5302             // We got the lock - therefore no other thread has started this loading step yet.
5303             pLock->Leave();
5304             return FALSE;
5305         }
5306
5307         // We didn't get the lock - either this thread is already doing the load,
5308         // or else the load has already finished.
5309     }
5310     return TRUE;
5311 }
5312
5313 // CheckLoading is a weaker form of IsLoading, which will not block on
5314 // other threads waiting for their status.  This is appropriate for asserts.
5315 CHECK AppDomain::CheckLoading(DomainFile *pFile, FileLoadLevel level)
5316 {
5317     // Cheap out
5318     if (pFile->GetLoadLevel() < level)
5319     {
5320         FileLoadLock *pLock = NULL;
5321
5322         LoadLockHolder lock(this);
5323
5324         pLock = (FileLoadLock *) lock->FindFileLock(pFile->GetFile());
5325
5326         if (pLock != NULL
5327             && pLock->CanAcquire(level))
5328         {
5329             // We can get the lock - therefore no other thread has started this loading step yet.
5330             CHECK_FAILF(("Loading step %d has not been initiated yet", level));
5331         }
5332
5333         // We didn't get the lock - either this thread is already doing the load,
5334         // or else the load has already finished.
5335     }
5336
5337     CHECK_OK;
5338 }
5339
5340 CHECK AppDomain::CheckCanLoadTypes(Assembly *pAssembly)
5341 {
5342     CONTRACTL
5343     {
5344         THROWS;
5345         GC_TRIGGERS;
5346         MODE_ANY;
5347     }
5348     CONTRACTL_END;
5349     CHECK_MSG(CheckValidModule(pAssembly->GetManifestModule()),
5350               "Type loading can occur only when executing in the assembly's app domain");
5351     CHECK_OK;
5352 }
5353
5354 CHECK AppDomain::CheckCanExecuteManagedCode(MethodDesc* pMD)
5355 {
5356     CONTRACTL
5357     {
5358         THROWS;
5359         GC_TRIGGERS;
5360         MODE_ANY;
5361     }
5362     CONTRACTL_END;
5363
5364     Module* pModule=pMD->GetModule();
5365
5366     CHECK_MSG(CheckValidModule(pModule),
5367               "Managed code can only run when executing in the module's app domain");
5368
5369     if (!pMD->IsInterface() || pMD->IsStatic()) //interfaces require no activation for instance methods
5370     {
5371         //cctor could have been interupted by ADU
5372         CHECK_MSG(HasUnloadStarted() || pModule->CheckActivated(),
5373               "Managed code can only run when its module has been activated in the current app domain");
5374     }
5375
5376     CHECK_MSG(!IsPassiveDomain() || pModule->CanExecuteCode(),
5377               "Executing managed code from an unsafe assembly in a Passive AppDomain");
5378
5379     CHECK_OK;
5380 }
5381
5382 #endif // !DACCESS_COMPILE
5383
5384 void AppDomain::LoadDomainFile(DomainFile *pFile,
5385                                FileLoadLevel targetLevel)
5386 {
5387     CONTRACTL
5388     {
5389         if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS;
5390         if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS;
5391         if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM();); }
5392         INJECT_FAULT(COMPlusThrowOM(););
5393     }
5394     CONTRACTL_END;
5395
5396     // Quick exit if finished
5397     if (pFile->GetLoadLevel() >= targetLevel)
5398         return;
5399
5400     // Handle the error case
5401     pFile->ThrowIfError(targetLevel);
5402
5403
5404 #ifndef DACCESS_COMPILE
5405
5406     if (pFile->IsLoading())
5407     {
5408         GCX_PREEMP();
5409
5410         // Load some more if appropriate
5411         LoadLockHolder lock(this);
5412
5413         FileLoadLock* pLockEntry = (FileLoadLock *) lock->FindFileLock(pFile->GetFile());
5414         if (pLockEntry == NULL)
5415         {
5416             _ASSERTE (!pFile->IsLoading());
5417             return;
5418         }
5419
5420         pLockEntry->AddRef();
5421
5422         lock.Release();
5423
5424         LoadDomainFile(pLockEntry, targetLevel);
5425     }
5426
5427 #else // DACCESS_COMPILE
5428     DacNotImpl();
5429 #endif // DACCESS_COMPILE
5430 }
5431
5432 #ifndef DACCESS_COMPILE
5433
5434 FileLoadLevel AppDomain::GetThreadFileLoadLevel()
5435 {
5436     WRAPPER_NO_CONTRACT;
5437     if (GetThread()->GetLoadLevelLimiter() == NULL)
5438         return FILE_ACTIVE;
5439     else
5440         return (FileLoadLevel)(GetThread()->GetLoadLevelLimiter()->GetLoadLevel()-1);
5441 }
5442
5443
5444 Assembly *AppDomain::LoadAssembly(AssemblySpec* pIdentity,
5445                                   PEAssembly *pFile,
5446                                   FileLoadLevel targetLevel)
5447 {
5448     CONTRACT(Assembly *)
5449     {
5450         GC_TRIGGERS;
5451         THROWS;
5452         MODE_ANY;
5453         PRECONDITION(CheckPointer(pFile));
5454         POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); // May be NULL in recursive load case
5455         INJECT_FAULT(COMPlusThrowOM(););
5456     }
5457     CONTRACT_END;
5458
5459     DomainAssembly *pAssembly = LoadDomainAssembly(pIdentity, pFile, targetLevel);
5460     PREFIX_ASSUME(pAssembly != NULL);
5461
5462     RETURN pAssembly->GetAssembly();
5463 }
5464
5465 #ifndef CROSSGEN_COMPILE
5466 // Thread stress
5467 class LoadDomainAssemblyStress : APIThreadStress
5468 {
5469 public:
5470     AppDomain *pThis;
5471     AssemblySpec* pSpec;
5472     PEAssembly *pFile;
5473     FileLoadLevel targetLevel;
5474
5475     LoadDomainAssemblyStress(AppDomain *pThis, AssemblySpec* pSpec, PEAssembly *pFile, FileLoadLevel targetLevel)
5476         : pThis(pThis), pSpec(pSpec), pFile(pFile), targetLevel(targetLevel) {LIMITED_METHOD_CONTRACT;}
5477
5478     void Invoke()
5479     {
5480         WRAPPER_NO_CONTRACT;
5481         STATIC_CONTRACT_SO_INTOLERANT;
5482         SetupThread();
5483         pThis->LoadDomainAssembly(pSpec, pFile, targetLevel);
5484     }
5485 };
5486 #endif // CROSSGEN_COMPILE
5487
5488 extern BOOL AreSameBinderInstance(ICLRPrivBinder *pBinderA, ICLRPrivBinder *pBinderB);
5489
5490 DomainAssembly* AppDomain::LoadDomainAssembly( AssemblySpec* pSpec,
5491                                                 PEAssembly *pFile, 
5492                                                 FileLoadLevel targetLevel)
5493 {
5494     STATIC_CONTRACT_THROWS;
5495
5496     if (pSpec == nullptr)
5497     {
5498         // skip caching, since we don't have anything to base it on
5499         return LoadDomainAssemblyInternal(pSpec, pFile, targetLevel);
5500     }
5501
5502     DomainAssembly* pRetVal = NULL;
5503     EX_TRY
5504     {
5505         pRetVal = LoadDomainAssemblyInternal(pSpec, pFile, targetLevel);
5506     }
5507     EX_HOOK
5508     {
5509         Exception* pEx=GET_EXCEPTION();
5510         if (!pEx->IsTransient())
5511         {
5512             // Setup the binder reference in AssemblySpec from the PEAssembly if one is not already set.
5513             ICLRPrivBinder* pCurrentBindingContext = pSpec->GetBindingContext();
5514             ICLRPrivBinder* pBindingContextFromPEAssembly = pFile->GetBindingContext();
5515             
5516             if (pCurrentBindingContext == NULL)
5517             {
5518                 // Set the binding context we got from the PEAssembly if AssemblySpec does not
5519                 // have that information
5520                 _ASSERTE(pBindingContextFromPEAssembly != NULL);
5521                 pSpec->SetBindingContext(pBindingContextFromPEAssembly);
5522             }
5523 #if defined(_DEBUG)            
5524             else
5525             {
5526                 // Binding context in the spec should be the same as the binding context in the PEAssembly
5527                 _ASSERTE(AreSameBinderInstance(pCurrentBindingContext, pBindingContextFromPEAssembly));
5528             }
5529 #endif // _DEBUG            
5530
5531             if (!EEFileLoadException::CheckType(pEx))
5532             {
5533                 StackSString name;
5534                 pSpec->GetFileOrDisplayName(0, name);
5535                 pEx=new EEFileLoadException(name, pEx->GetHR(), NULL, pEx);
5536                 AddExceptionToCache(pSpec, pEx);
5537                 PAL_CPP_THROW(Exception *, pEx);
5538             }
5539             else
5540                 AddExceptionToCache(pSpec, pEx);
5541         }
5542     }
5543     EX_END_HOOK;
5544
5545     return pRetVal;
5546 }
5547
5548
5549 DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity,
5550                                               PEAssembly *pFile,
5551                                               FileLoadLevel targetLevel)
5552 {
5553     CONTRACT(DomainAssembly *)
5554     {
5555         GC_TRIGGERS;
5556         THROWS;
5557         MODE_ANY;
5558         PRECONDITION(CheckPointer(pFile));
5559         PRECONDITION(pFile->IsSystem() || ::GetAppDomain()==this);
5560         POSTCONDITION(CheckPointer(RETVAL));
5561         POSTCONDITION(RETVAL->GetLoadLevel() >= GetThreadFileLoadLevel()
5562                       || RETVAL->GetLoadLevel() >= targetLevel);
5563         POSTCONDITION(RETVAL->CheckNoError(targetLevel));
5564         INJECT_FAULT(COMPlusThrowOM(););
5565     }
5566     CONTRACT_END;
5567
5568
5569     DomainAssembly * result;
5570
5571 #ifndef CROSSGEN_COMPILE
5572     LoadDomainAssemblyStress ts (this, pIdentity, pFile, targetLevel);
5573 #endif
5574
5575     // Go into preemptive mode since this may take a while.
5576     GCX_PREEMP();
5577
5578     // Check for existing fully loaded assembly, or for an assembly which has failed during the loading process.
5579     result = FindAssembly(pFile, FindAssemblyOptions_IncludeFailedToLoad);
5580     
5581     if (result == NULL)
5582     {
5583         // Allocate the DomainAssembly a bit early to avoid GC mode problems. We could potentially avoid
5584         // a rare redundant allocation by moving this closer to FileLoadLock::Create, but it's not worth it.
5585
5586         NewHolder<DomainAssembly> pDomainAssembly;
5587         pDomainAssembly = new DomainAssembly(this, pFile, this->GetLoaderAllocator());
5588
5589         LoadLockHolder lock(this);
5590
5591         // Find the list lock entry
5592         FileLoadLock * fileLock = (FileLoadLock *)lock->FindFileLock(pFile);
5593         if (fileLock == NULL)
5594         {
5595             // Check again in case we were racing
5596             result = FindAssembly(pFile, FindAssemblyOptions_IncludeFailedToLoad);
5597             if (result == NULL)
5598             {
5599                 // We are the first one in - create the DomainAssembly
5600                 fileLock = FileLoadLock::Create(lock, pFile, pDomainAssembly);
5601                 pDomainAssembly.SuppressRelease();
5602             }
5603         }
5604         else
5605         {
5606             fileLock->AddRef();
5607         }
5608
5609         lock.Release();
5610
5611         if (result == NULL)
5612         {
5613             // We pass our ref on fileLock to LoadDomainFile to release.
5614
5615             // Note that if we throw here, we will poison fileLock with an error condition,
5616             // so it will not be removed until app domain unload.  So there is no need
5617             // to release our ref count.
5618             result = (DomainAssembly *)LoadDomainFile(fileLock, targetLevel);
5619         }
5620         else
5621         {
5622             result->EnsureLoadLevel(targetLevel);
5623         }
5624     }
5625     else
5626         result->EnsureLoadLevel(targetLevel);
5627
5628     // Malformed metadata may contain a Module reference to what is actually
5629     // an Assembly. In this case we need to throw an exception, since returning
5630     // a DomainModule as a DomainAssembly is a type safety violation.
5631     if (!result->IsAssembly())
5632     {
5633         ThrowHR(COR_E_ASSEMBLYEXPECTED);
5634     }
5635
5636     // Cache result in all cases, since found pFile could be from a different AssemblyRef than pIdentity
5637     // Do not cache WindowsRuntime assemblies, they are cached in code:CLRPrivTypeCacheWinRT
5638     if ((pIdentity != NULL) && (pIdentity->CanUseWithBindingCache()) && (result->CanUseWithBindingCache()))
5639         GetAppDomain()->AddAssemblyToCache(pIdentity, result);
5640     
5641     RETURN result;
5642 } // AppDomain::LoadDomainAssembly
5643
5644
5645 struct LoadFileArgs
5646 {
5647     FileLoadLock *pLock;
5648     FileLoadLevel targetLevel;
5649     DomainFile *result;
5650 };
5651
5652 #ifndef CROSSGEN_COMPILE
5653 static void LoadDomainFile_Wrapper(void *ptr)
5654 {
5655     WRAPPER_NO_CONTRACT;
5656     STATIC_CONTRACT_SO_INTOLERANT;
5657     GCX_PREEMP();
5658     LoadFileArgs *args = (LoadFileArgs *) ptr;
5659     args->result = GetAppDomain()->LoadDomainFile(args->pLock, args->targetLevel);
5660 }
5661 #endif // !CROSSGEN_COMPILE
5662
5663 DomainFile *AppDomain::LoadDomainFile(FileLoadLock *pLock, FileLoadLevel targetLevel)
5664 {
5665     CONTRACT(DomainFile *)
5666     {
5667         STANDARD_VM_CHECK;
5668         PRECONDITION(CheckPointer(pLock));
5669         PRECONDITION(pLock->GetDomainFile()->GetAppDomain() == this);
5670         POSTCONDITION(RETVAL->GetLoadLevel() >= GetThreadFileLoadLevel()
5671                       || RETVAL->GetLoadLevel() >= targetLevel);
5672         POSTCONDITION(RETVAL->CheckNoError(targetLevel));
5673     }
5674     CONTRACT_END;
5675
5676
5677     if(!CanLoadCode())
5678         COMPlusThrow(kAppDomainUnloadedException);
5679
5680     // Thread stress
5681     APIThreadStress::SyncThreadStress();
5682
5683     DomainFile *pFile = pLock->GetDomainFile();
5684
5685     // Make sure we release the lock on exit
5686     FileLoadLockRefHolder lockRef(pLock);
5687
5688     // We need to perform the early steps of loading mscorlib without a domain transition.  This is
5689     // important for bootstrapping purposes - we need to get mscorlib at least partially loaded
5690     // into a domain before we can run serialization code to do the transition.
5691     //
5692     // Note that we cannot do this in general for all assemblies, because some of the security computations
5693     // require the managed exposed object, which must be created in the correct app domain.
5694
5695     if (this != GetAppDomain()
5696         && pFile->GetFile()->IsSystem()
5697         && targetLevel > FILE_LOAD_ALLOCATE)
5698     {
5699         // Re-call the routine with a limited load level. This will cause the first part of the load to
5700         // get performed in the current app domain.
5701
5702         pLock->AddRef();
5703         LoadDomainFile(pLock, targetLevel > FILE_LOAD_ALLOCATE ? FILE_LOAD_ALLOCATE : targetLevel);
5704
5705         // Now continue on to complete the rest of the load, if any.
5706     }
5707
5708     // Do a quick out check for the already loaded case.
5709     if (pLock->GetLoadLevel() >= targetLevel)
5710     {
5711         pFile->ThrowIfError(targetLevel);
5712
5713         RETURN pFile;
5714     }
5715
5716 #ifndef CROSSGEN_COMPILE
5717     // Make sure we are in the right domain.  Many of the load operations require the target domain
5718     // to be the current app domain, most notably anything involving managed code or managed object
5719     // creation.
5720     if (this != GetAppDomain()
5721         && (!pFile->GetFile()->IsSystem() || targetLevel > FILE_LOAD_ALLOCATE))
5722     {
5723         // Transition to the correct app domain and perform the load there.
5724         GCX_COOP();
5725
5726         // we will release the lock in the other app domain
5727         lockRef.SuppressRelease();
5728
5729         if(!CanLoadCode() || GetDefaultContext() ==NULL)
5730             COMPlusThrow(kAppDomainUnloadedException);
5731         LoadFileArgs args = {pLock, targetLevel, NULL};
5732         GetThread()->DoADCallBack(this, LoadDomainFile_Wrapper, (void *) &args, ADV_CREATING);
5733
5734         RETURN args.result;
5735     }
5736 #endif // CROSSGEN_COMPILE
5737
5738     // Initialize a loading queue.  This will hold any loads which are triggered recursively but
5739     // which cannot be immediately satisfied due to anti-deadlock constraints.
5740
5741     // PendingLoadQueues are allocated on the stack during a load, and
5742     // shared with all nested loads on the same thread. (Note that we won't use
5743     // "candidate" if we are in a recursive load; that's OK since they are cheap to
5744     // construct.)
5745     FileLoadLevel immediateTargetLevel = targetLevel;
5746     {
5747         LoadLevelLimiter limit;
5748         limit.Activate();
5749
5750         // We cannot set a target level higher than that allowed by the limiter currently.
5751         // This is because of anti-deadlock constraints.
5752         if (immediateTargetLevel > limit.GetLoadLevel())
5753             immediateTargetLevel = limit.GetLoadLevel();
5754
5755         LOG((LF_LOADER, LL_INFO100, "LOADER: %x:***%s*\t>>>Load initiated, %s/%s\n",
5756              pFile->GetAppDomain(), pFile->GetSimpleName(),
5757              fileLoadLevelName[immediateTargetLevel], fileLoadLevelName[targetLevel]));
5758
5759         // Now loop and do the load incrementally to the target level.
5760         if (pLock->GetLoadLevel() < immediateTargetLevel)
5761         {
5762             // Thread stress
5763             APIThreadStress::SyncThreadStress();
5764
5765             while (pLock->Acquire(immediateTargetLevel))
5766             {
5767                 FileLoadLevel workLevel;
5768                 {
5769                     FileLoadLockHolder fileLock(pLock);
5770
5771                     // Work level is next step to do
5772                     workLevel = (FileLoadLevel)(fileLock->GetLoadLevel()+1);
5773
5774                     // Set up the anti-deadlock constraint: we cannot safely recursively load any assemblies
5775                     // on this thread to a higher level than this assembly is being loaded now.
5776                     // Note that we do allow work at a parallel level; any deadlocks caused here will
5777                     // be resolved by the deadlock detection in the FileLoadLocks.
5778                     limit.SetLoadLevel(workLevel);
5779
5780                     LOG((LF_LOADER,
5781                          (workLevel == FILE_LOAD_BEGIN
5782                           || workLevel == FILE_LOADED
5783                           || workLevel == FILE_ACTIVE)
5784                          ? LL_INFO10 : LL_INFO1000,
5785                          "LOADER: %p:***%s*\t   loading at level %s\n",
5786                          this, pFile->GetSimpleName(), fileLoadLevelName[workLevel]));
5787
5788                     TryIncrementalLoad(pFile, workLevel, fileLock);
5789                 }
5790                 TESTHOOKCALL(CompletedFileLoadLevel(GetId().m_dwId,pFile,workLevel));
5791             }
5792
5793             if (pLock->GetLoadLevel() == immediateTargetLevel-1)
5794             {
5795                 LOG((LF_LOADER, LL_INFO100, "LOADER: %x:***%s*\t<<<Load limited due to detected deadlock, %s\n",
5796                      pFile->GetAppDomain(), pFile->GetSimpleName(),
5797                      fileLoadLevelName[immediateTargetLevel-1]));
5798             }
5799         }
5800
5801         LOG((LF_LOADER, LL_INFO100, "LOADER: %x:***%s*\t<<<Load completed, %s\n",
5802              pFile->GetAppDomain(), pFile->GetSimpleName(),
5803              fileLoadLevelName[pLock->GetLoadLevel()]));
5804
5805     }
5806
5807     // There may have been an error stored on the domain file by another thread, or from a previous load
5808     pFile->ThrowIfError(targetLevel);
5809
5810     // There are two normal results from the above loop.
5811     //
5812     // 1. We succeeded in loading the file to the current thread's load level.
5813     // 2. We succeeded in loading the file to the current thread's load level - 1, due
5814     //      to deadlock condition with another thread loading the same assembly.
5815     //
5816     // Either of these are considered satisfactory results, as code inside a load must expect
5817     // a parial load result.
5818     //
5819     // However, if load level elevation has occurred, then it is possible for a deadlock to
5820     // prevent us from loading an assembly which was loading before the elevation at a radically
5821     // lower level.  In such a case, we throw an exception which transiently fails the current
5822     // load, since it is likely we have not satisfied the caller.
5823     // (An alternate, and possibly preferable, strategy here would be for all callers to explicitly
5824     // identify the minimum load level acceptable via CheckLoadDomainFile and throw from there.)
5825
5826     pFile->RequireLoadLevel((FileLoadLevel)(immediateTargetLevel-1));
5827
5828
5829     RETURN pFile;
5830 }
5831
5832 void AppDomain::TryIncrementalLoad(DomainFile *pFile, FileLoadLevel workLevel, FileLoadLockHolder &lockHolder)
5833 {
5834     STANDARD_VM_CONTRACT;
5835
5836     // This is factored out so we don't call EX_TRY in a loop (EX_TRY can _alloca)
5837
5838     BOOL released = FALSE;
5839     FileLoadLock* pLoadLock = lockHolder.GetValue();
5840
5841     EX_TRY
5842     {
5843
5844         // Special case: for LoadLibrary, we cannot hold the lock during the
5845         // actual LoadLibrary call, because we might get a callback from _CorDllMain on any
5846         // other thread.  (Note that this requires DomainFile's LoadLibrary to be independently threadsafe.)
5847
5848         if (workLevel == FILE_LOAD_LOADLIBRARY)
5849         {
5850             lockHolder.Release();
5851             released = TRUE;
5852         }
5853
5854         // Do the work
5855         TESTHOOKCALL(NextFileLoadLevel(GetId().m_dwId,pFile,workLevel));
5856         BOOL success = pFile->DoIncrementalLoad(workLevel);
5857         TESTHOOKCALL(CompletingFileLoadLevel(GetId().m_dwId,pFile,workLevel));
5858         if (released)
5859         {
5860             // Reobtain lock to increment level. (Note that another thread may
5861             // have already done it which is OK.
5862             if (pLoadLock->Acquire(workLevel))
5863             {
5864                 // note lockHolder.Acquire isn't wired up to actually take the lock
5865                 lockHolder = pLoadLock;
5866                 released = FALSE;
5867             }
5868         }
5869
5870         if (!released)
5871         {
5872             // Complete the level.
5873             if (pLoadLock->CompleteLoadLevel(workLevel, success) &&
5874                 pLoadLock->GetLoadLevel()==FILE_LOAD_DELIVER_EVENTS)
5875             {
5876                 lockHolder.Release();
5877                 released = TRUE;
5878                 pFile->DeliverAsyncEvents();
5879             };
5880         }
5881     }
5882     EX_HOOK
5883     {
5884         Exception *pEx = GET_EXCEPTION();
5885
5886
5887         //We will cache this error and wire this load to forever fail,
5888         // unless the exception is transient or the file is loaded OK but just cannot execute
5889         if (!pEx->IsTransient() && !pFile->IsLoaded())
5890         {
5891
5892             if (released)
5893             {
5894                 // Reobtain lock to increment level. (Note that another thread may
5895                 // have already done it which is OK.
5896                 if (pLoadLock->Acquire(workLevel)) // note pLockHolder->Acquire isn't wired up to actually take the lock
5897                 {
5898                     // note lockHolder.Acquire isn't wired up to actually take the lock
5899                     lockHolder = pLoadLock;
5900                     released = FALSE;
5901                 }
5902             }
5903
5904             if (!released)
5905             {
5906                 // Report the error in the lock
5907                 pLoadLock->SetError(pEx);
5908             }
5909
5910             if (!EEFileLoadException::CheckType(pEx))
5911                 EEFileLoadException::Throw(pFile->GetFile(), pEx->GetHR(), pEx);
5912         }
5913
5914         // Otherwise, we simply abort this load, and can retry later on.
5915         // @todo cleanup: make sure that each level is restartable after an exception, and
5916         // leaves no bad side effects
5917     }
5918     EX_END_HOOK;
5919 }
5920
5921 // Checks whether the module is valid to be in the given app domain (need not be yet loaded)
5922 CHECK AppDomain::CheckValidModule(Module * pModule)
5923 {
5924     CONTRACTL
5925     {
5926         THROWS;
5927         GC_TRIGGERS;
5928         MODE_ANY;
5929     }
5930     CONTRACTL_END;
5931
5932     if (pModule->FindDomainFile(this) != NULL)
5933         CHECK_OK;
5934
5935     CCHECK_START
5936     {
5937         Assembly * pAssembly = pModule->GetAssembly();
5938
5939         CCHECK(pAssembly->IsDomainNeutral());
5940 #ifdef FEATURE_LOADER_OPTIMIZATION        
5941         Assembly * pSharedAssembly = NULL;
5942         _ASSERTE(this == ::GetAppDomain());
5943         {
5944             SharedAssemblyLocator locator(pAssembly->GetManifestFile());
5945             pSharedAssembly = SharedDomain::GetDomain()->FindShareableAssembly(&locator);
5946         }
5947
5948         CCHECK(pAssembly == pSharedAssembly);
5949 #endif         
5950     }
5951     CCHECK_END;
5952
5953     CHECK_OK;
5954 }
5955
5956 #ifdef FEATURE_LOADER_OPTIMIZATION
5957 // Loads an existing Module into an AppDomain
5958 // WARNING: this can only be done in a very limited scenario - the Module must be an unloaded domain neutral
5959 // dependency in the app domain in question.  Normal code should not call this!
5960 DomainFile *AppDomain::LoadDomainNeutralModuleDependency(Module *pModule, FileLoadLevel targetLevel)
5961 {
5962     CONTRACT(DomainFile *)
5963     {
5964         THROWS;
5965         GC_TRIGGERS;
5966         MODE_ANY;
5967         PRECONDITION(::GetAppDomain()==this);
5968         PRECONDITION(CheckPointer(pModule));
5969         POSTCONDITION(CheckValidModule(pModule));
5970         POSTCONDITION(CheckPointer(RETVAL));
5971         POSTCONDITION(RETVAL->GetModule() == pModule);
5972     }
5973     CONTRACT_END;
5974
5975     DomainFile *pDomainFile = pModule->FindDomainFile(this);
5976
5977     STRESS_LOG3(LF_CLASSLOADER, LL_INFO100,"LDNMD: DomainFile %p for module %p in AppDomain %i\n",pDomainFile,pModule,GetId().m_dwId);
5978
5979     if (pDomainFile == NULL)
5980     {
5981         GCX_PREEMP();
5982
5983         Assembly *pAssembly = pModule->GetAssembly();
5984
5985         DomainAssembly *pDomainAssembly = pAssembly->FindDomainAssembly(this);
5986         if (pDomainAssembly == NULL)
5987         {
5988             AssemblySpec spec(this);
5989             spec.InitializeSpec(pAssembly->GetManifestFile());
5990
5991             pDomainAssembly = spec.LoadDomainAssembly(targetLevel);
5992         }
5993         else
5994         {
5995             //if the domain assembly already exists, we need to load it to the target level
5996             pDomainAssembly->EnsureLoadLevel (targetLevel);
5997         }
5998
5999         if(pAssembly != pDomainAssembly->GetAssembly())
6000         {
6001             ThrowHR(SECURITY_E_INCOMPATIBLE_SHARE);
6002         }
6003
6004         _ASSERTE (pModule == pAssembly->GetManifestModule());
6005         pDomainFile = pDomainAssembly;
6006     }
6007     else
6008     {
6009         // If the DomainFile already exists, we need to load it to the target level.
6010         pDomainFile->EnsureLoadLevel (targetLevel);
6011     }
6012
6013     RETURN pDomainFile;
6014 }
6015
6016 AppDomain::SharePolicy AppDomain::GetSharePolicy()
6017 {
6018     LIMITED_METHOD_CONTRACT;
6019
6020     return SHARE_POLICY_NEVER;
6021 }
6022 #endif // FEATURE_LOADER_OPTIMIZATION
6023
6024
6025 void AppDomain::CheckForMismatchedNativeImages(AssemblySpec * pSpec, const GUID * pGuid)
6026 {
6027     STANDARD_VM_CONTRACT;
6028
6029     //
6030     // The native images are ever used only for trusted images in CoreCLR.
6031     // We don't wish to open the IL file at runtime so we just forgo any
6032     // eager consistency checking. But we still want to prevent mistmatched 
6033     // NGen images from being used. We record all mappings between assembly 
6034     // names and MVID, and fail once we detect mismatch.
6035     //
6036
6037     if (pSpec->IsStrongNamed() && pSpec->HasPublicKey())
6038     {
6039         pSpec->ConvertPublicKeyToToken();
6040     }
6041
6042     //
6043     // CoreCLR binder unifies assembly versions. Ignore assembly version here to 
6044     // detect more types of potential mismatches.
6045     //
6046     AssemblyMetaDataInternal * pContext = pSpec->GetContext();
6047     pContext->usMajorVersion = (USHORT)-1;
6048     pContext->usMinorVersion = (USHORT)-1;
6049     pContext->usBuildNumber = (USHORT)-1;
6050     pContext->usRevisionNumber = (USHORT)-1;
6051
6052     // Ignore the WinRT type while considering if two assemblies have the same identity.
6053     pSpec->SetWindowsRuntimeType(NULL, NULL);
6054
6055     CrstHolder ch(&m_DomainCrst);
6056
6057     const NativeImageDependenciesEntry * pEntry = m_NativeImageDependencies.Lookup(pSpec);
6058
6059     if (pEntry != NULL)
6060     {
6061         if (*pGuid != pEntry->m_guidMVID)
6062         {
6063             SString msg;
6064             msg.Printf("ERROR: Native images generated against multiple versions of assembly %s. ", pSpec->GetName());
6065             WszOutputDebugString(msg.GetUnicode());
6066             COMPlusThrowNonLocalized(kFileLoadException, msg.GetUnicode());
6067         }
6068     }
6069     else
6070     {
6071         //
6072         // No entry yet - create one
6073         //
6074         AllocMemTracker amTracker;
6075         AllocMemTracker *pamTracker = &amTracker;
6076
6077         NativeImageDependenciesEntry * pNewEntry = 
6078             new (pamTracker->Track(GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(NativeImageDependenciesEntry)))))
6079                 NativeImageDependenciesEntry();
6080
6081         pNewEntry->m_AssemblySpec.CopyFrom(pSpec);
6082         pNewEntry->m_AssemblySpec.CloneFieldsToLoaderHeap(AssemblySpec::ALL_OWNED, GetLowFrequencyHeap(), pamTracker);
6083
6084         pNewEntry->m_guidMVID = *pGuid;
6085
6086         m_NativeImageDependencies.Add(pNewEntry);
6087         amTracker.SuppressRelease();
6088     }
6089 }
6090
6091
6092 void AppDomain::SetupSharedStatics()
6093 {
6094     CONTRACTL
6095     {
6096         THROWS;
6097         GC_TRIGGERS;
6098         MODE_ANY;
6099         INJECT_FAULT(COMPlusThrowOM(););
6100     }
6101     CONTRACTL_END;
6102
6103 #ifndef CROSSGEN_COMPILE
6104     if (NingenEnabled())
6105         return;
6106
6107     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: SetupSharedStatics()"));
6108
6109     // don't do any work in init stage. If not init only do work in non-shared case if are default domain
6110     _ASSERTE(!g_fEEInit);
6111
6112     // Because we are allocating/referencing objects, need to be in cooperative mode
6113     GCX_COOP();
6114
6115     static OBJECTHANDLE hSharedStaticsHandle = NULL;
6116
6117     if (hSharedStaticsHandle == NULL) {
6118         // Note that there is no race here since the default domain is always set up first
6119         _ASSERTE(IsDefaultDomain());
6120
6121         MethodTable *pMT = MscorlibBinder::GetClass(CLASS__SHARED_STATICS);
6122         _ASSERTE(pMT->IsClassPreInited());
6123
6124         hSharedStaticsHandle = CreateGlobalHandle(AllocateObject(pMT));
6125     }
6126
6127     DomainLocalModule *pLocalModule;
6128
6129     if (IsSingleAppDomain())
6130     {
6131         pLocalModule = MscorlibBinder::GetModule()->GetDomainLocalModule();
6132     }
6133     else
6134     {
6135         pLocalModule = GetDomainLocalBlock()->GetModuleSlot(
6136             MscorlibBinder::GetModule()->GetModuleIndex());
6137     }
6138
6139     FieldDesc *pFD = MscorlibBinder::GetField(FIELD__SHARED_STATICS__SHARED_STATICS);
6140
6141     OBJECTREF* pHandle = (OBJECTREF*)
6142         ((TADDR)pLocalModule->GetPrecomputedGCStaticsBasePointer()+pFD->GetOffset());
6143     SetObjectReference( pHandle, ObjectFromHandle(hSharedStaticsHandle), this );
6144
6145     // This is a convenient place to initialize String.Empty.
6146     // It is treated as intrinsic by the JIT as so the static constructor would never run.
6147     // Leaving it uninitialized would confuse debuggers.
6148
6149     // String should not have any static constructors.
6150     _ASSERTE(g_pStringClass->IsClassPreInited());
6151
6152     FieldDesc * pEmptyStringFD = MscorlibBinder::GetField(FIELD__STRING__EMPTY);
6153     OBJECTREF* pEmptyStringHandle = (OBJECTREF*)
6154         ((TADDR)pLocalModule->GetPrecomputedGCStaticsBasePointer()+pEmptyStringFD->GetOffset());
6155     SetObjectReference( pEmptyStringHandle, StringObject::GetEmptyString(), this );
6156 #endif // CROSSGEN_COMPILE
6157 }
6158
6159 DomainAssembly * AppDomain::FindAssembly(PEAssembly * pFile, FindAssemblyOptions options/* = FindAssemblyOptions_None*/)
6160 {
6161     CONTRACTL
6162     {
6163         THROWS;
6164         GC_TRIGGERS;
6165         MODE_ANY;
6166         INJECT_FAULT(COMPlusThrowOM(););
6167     }
6168     CONTRACTL_END;
6169
6170     const bool includeFailedToLoad = (options & FindAssemblyOptions_IncludeFailedToLoad) != 0;
6171
6172     if (pFile->HasHostAssembly())
6173     {
6174         DomainAssembly * pDA = FindAssembly(pFile->GetHostAssembly());
6175         if (pDA != nullptr && (pDA->IsLoaded() || (includeFailedToLoad && pDA->IsError())))
6176         {
6177             return pDA;
6178         }
6179         return nullptr;
6180     }
6181
6182     AssemblyIterator i = IterateAssembliesEx((AssemblyIterationFlags)(
6183         kIncludeLoaded | 
6184         (includeFailedToLoad ? kIncludeFailedToLoad : 0) |
6185         (pFile->IsIntrospectionOnly() ? kIncludeIntrospection : kIncludeExecution)));
6186     CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
6187
6188     while (i.Next(pDomainAssembly.This()))
6189     {
6190         PEFile * pManifestFile = pDomainAssembly->GetFile();
6191         if (pManifestFile && 
6192             !pManifestFile->IsResource() && 
6193             pManifestFile->Equals(pFile))
6194         {
6195             // Caller already has PEAssembly, so we can give DomainAssembly away freely without AddRef
6196             return pDomainAssembly.Extract();
6197         }
6198     }
6199     return NULL;
6200 }
6201
6202 static const AssemblyIterationFlags STANDARD_IJW_ITERATOR_FLAGS = 
6203     (AssemblyIterationFlags)(kIncludeLoaded | kIncludeLoading | kIncludeExecution | kExcludeCollectible);
6204
6205
6206 void AppDomain::SetFriendlyName(LPCWSTR pwzFriendlyName, BOOL fDebuggerCares/*=TRUE*/)
6207 {
6208     CONTRACTL
6209     {
6210         THROWS;
6211         if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
6212         MODE_ANY;
6213         INJECT_FAULT(COMPlusThrowOM(););
6214     }
6215     CONTRACTL_END;
6216
6217     // Do all computations into a temporary until we're ensured of success
6218     SString tmpFriendlyName;
6219
6220
6221     if (pwzFriendlyName)
6222         tmpFriendlyName.Set(pwzFriendlyName);
6223     else
6224     {
6225         // If there is an assembly, try to get the name from it.
6226         // If no assembly, but if it's the DefaultDomain, then give it a name
6227
6228         if (m_pRootAssembly)
6229         {
6230             tmpFriendlyName.SetUTF8(m_pRootAssembly->GetSimpleName());
6231
6232             SString::Iterator i = tmpFriendlyName.End();
6233             if (tmpFriendlyName.FindBack(i, '.'))
6234                 tmpFriendlyName.Truncate(i);
6235         }
6236         else
6237         {
6238             if (IsDefaultDomain())
6239                 tmpFriendlyName.Set(DEFAULT_DOMAIN_FRIENDLY_NAME);
6240
6241             // This is for the profiler - if they call GetFriendlyName on an AppdomainCreateStarted
6242             // event, then we want to give them a temporary name they can use.
6243             else if (GetId().m_dwId != 0)
6244             {
6245                 tmpFriendlyName.Clear();
6246                 tmpFriendlyName.Printf(W("%s %d"), OTHER_DOMAIN_FRIENDLY_NAME_PREFIX, GetId().m_dwId);
6247             }
6248         }
6249
6250     }
6251
6252     tmpFriendlyName.Normalize();
6253
6254
6255     m_friendlyName = tmpFriendlyName;
6256     m_friendlyName.Normalize();
6257
6258     if(g_pDebugInterface) 
6259     {
6260         // update the name in the IPC publishing block
6261         if (SUCCEEDED(g_pDebugInterface->UpdateAppDomainEntryInIPC(this)))
6262         {
6263             // inform the attached debugger that the name of this appdomain has changed.
6264             if (IsDebuggerAttached() && fDebuggerCares)
6265                 g_pDebugInterface->NameChangeEvent(this, NULL);
6266         }
6267     }
6268 }
6269
6270 void AppDomain::ResetFriendlyName(BOOL fDebuggerCares/*=TRUE*/)
6271 {
6272     WRAPPER_NO_CONTRACT;
6273     SetFriendlyName(NULL, fDebuggerCares);
6274 }
6275
6276 LPCWSTR AppDomain::GetFriendlyName(BOOL fDebuggerCares/*=TRUE*/)
6277 {
6278     CONTRACT (LPCWSTR)
6279     {
6280         THROWS;
6281         if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
6282         MODE_ANY;
6283         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
6284         INJECT_FAULT(COMPlusThrowOM(););
6285     }
6286     CONTRACT_END;
6287
6288 #if _DEBUG
6289     // Handle NULL this pointer - this happens sometimes when printing log messages
6290     // but in general shouldn't occur in real code
6291     if (this == NULL)
6292         RETURN NULL;
6293 #endif // _DEBUG
6294
6295     if (m_friendlyName.IsEmpty())
6296         SetFriendlyName(NULL, fDebuggerCares);
6297
6298     RETURN m_friendlyName;
6299 }
6300
6301 LPCWSTR AppDomain::GetFriendlyNameForLogging()
6302 {
6303     CONTRACT(LPWSTR)
6304     {
6305         NOTHROW;
6306         GC_NOTRIGGER;
6307         MODE_ANY;
6308         POSTCONDITION(CheckPointer(RETVAL,NULL_OK));
6309     }
6310     CONTRACT_END;
6311 #if _DEBUG
6312     // Handle NULL this pointer - this happens sometimes when printing log messages
6313     // but in general shouldn't occur in real code
6314     if (this == NULL)
6315         RETURN NULL;
6316 #endif // _DEBUG
6317     RETURN (m_friendlyName.IsEmpty() ?W(""):(LPCWSTR)m_friendlyName);
6318 }
6319
6320 LPCWSTR AppDomain::GetFriendlyNameForDebugger()
6321 {
6322     CONTRACT (LPCWSTR)
6323     {
6324         NOTHROW;
6325         if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_NOTRIGGER);}
6326         MODE_ANY;
6327         POSTCONDITION(CheckPointer(RETVAL));
6328     }
6329     CONTRACT_END;
6330
6331
6332     if (m_friendlyName.IsEmpty())
6333     {
6334         BOOL fSuccess = FALSE;
6335
6336         EX_TRY
6337         {
6338             SetFriendlyName(NULL);
6339
6340             fSuccess = TRUE;
6341         }
6342         EX_CATCH
6343         {
6344             // Gobble all exceptions.
6345         }
6346         EX_END_CATCH(SwallowAllExceptions);
6347
6348         if (!fSuccess)
6349         {
6350             RETURN W("");
6351         }
6352     }
6353
6354     RETURN m_friendlyName;
6355 }
6356
6357
6358 #endif // !DACCESS_COMPILE
6359
6360 #ifdef DACCESS_COMPILE
6361
6362 PVOID AppDomain::GetFriendlyNameNoSet(bool* isUtf8)
6363 {
6364     SUPPORTS_DAC;
6365
6366     if (!m_friendlyName.IsEmpty())
6367     {
6368         *isUtf8 = false;
6369         return m_friendlyName.DacGetRawContent();
6370     }
6371     else if (m_pRootAssembly)
6372     {
6373         *isUtf8 = true;
6374         return (PVOID)m_pRootAssembly->GetSimpleName();
6375     }
6376     else if (dac_cast<TADDR>(this) ==
6377              dac_cast<TADDR>(SystemDomain::System()->DefaultDomain()))
6378     {
6379         *isUtf8 = false;
6380         return (PVOID)DEFAULT_DOMAIN_FRIENDLY_NAME;
6381     }
6382     else
6383     {
6384         return NULL;
6385     }
6386 }
6387
6388 #endif // DACCESS_COMPILE
6389
6390 #ifndef DACCESS_COMPILE
6391
6392 BOOL AppDomain::AddFileToCache(AssemblySpec* pSpec, PEAssembly *pFile, BOOL fAllowFailure)
6393 {
6394     CONTRACTL
6395     {
6396         THROWS;
6397         GC_TRIGGERS;
6398         MODE_ANY;
6399         PRECONDITION(CheckPointer(pSpec));
6400         // Hosted fusion binder makes an exception here, so we cannot assert.
6401         //PRECONDITION(pSpec->CanUseWithBindingCache());
6402         //PRECONDITION(pFile->CanUseWithBindingCache());
6403         INJECT_FAULT(COMPlusThrowOM(););
6404     }
6405     CONTRACTL_END;
6406
6407     CrstHolder holder(&m_DomainCacheCrst);
6408     // !!! suppress exceptions
6409     if(!m_AssemblyCache.StoreFile(pSpec, pFile) && !fAllowFailure)
6410     {
6411         // TODO: Disabling the below assertion as currently we experience
6412         // inconsistency on resolving the Microsoft.Office.Interop.MSProject.dll
6413         // This causes below assertion to fire and crashes the VS. This issue
6414         // is being tracked with Dev10 Bug 658555. Brought back it when this bug 
6415         // is fixed.
6416         // _ASSERTE(FALSE);
6417
6418         EEFileLoadException::Throw(pSpec, FUSION_E_CACHEFILE_FAILED, NULL);
6419     }
6420
6421     return TRUE;
6422 }
6423
6424 BOOL AppDomain::AddAssemblyToCache(AssemblySpec* pSpec, DomainAssembly *pAssembly)
6425 {
6426     CONTRACTL
6427     {
6428         THROWS;
6429         GC_TRIGGERS;
6430         MODE_ANY;
6431         PRECONDITION(CheckPointer(pSpec));
6432         PRECONDITION(CheckPointer(pAssembly));
6433         PRECONDITION(pSpec->CanUseWithBindingCache());
6434         PRECONDITION(pAssembly->CanUseWithBindingCache());
6435         INJECT_FAULT(COMPlusThrowOM(););
6436     }
6437     CONTRACTL_END;
6438     
6439     CrstHolder holder(&m_DomainCacheCrst);
6440     // !!! suppress exceptions
6441     BOOL bRetVal = m_AssemblyCache.StoreAssembly(pSpec, pAssembly);
6442     return bRetVal;
6443 }
6444
6445 BOOL AppDomain::AddExceptionToCache(AssemblySpec* pSpec, Exception *ex)
6446 {
6447     CONTRACTL
6448     {
6449         THROWS;
6450         GC_TRIGGERS;
6451         MODE_ANY;
6452         PRECONDITION(CheckPointer(pSpec));
6453         PRECONDITION(pSpec->CanUseWithBindingCache());
6454         INJECT_FAULT(COMPlusThrowOM(););
6455     }
6456     CONTRACTL_END;
6457     
6458     if (ex->IsTransient())
6459         return TRUE;
6460
6461     CrstHolder holder(&m_DomainCacheCrst);
6462     // !!! suppress exceptions
6463     return m_AssemblyCache.StoreException(pSpec, ex);
6464 }
6465
6466 void AppDomain::AddUnmanagedImageToCache(LPCWSTR libraryName, HMODULE hMod)
6467 {
6468     CONTRACTL
6469     {
6470         THROWS;
6471         GC_TRIGGERS;
6472         MODE_ANY;
6473         PRECONDITION(CheckPointer(libraryName));
6474         INJECT_FAULT(COMPlusThrowOM(););
6475     }
6476     CONTRACTL_END;
6477     if (libraryName)
6478     {
6479         AssemblySpec spec;
6480         spec.SetCodeBase(libraryName);
6481         m_UnmanagedCache.InsertEntry(&spec, hMod);
6482     }
6483     return ;
6484 }
6485
6486
6487 HMODULE AppDomain::FindUnmanagedImageInCache(LPCWSTR libraryName)
6488 {
6489     CONTRACT(HMODULE)
6490     {
6491         THROWS;
6492         GC_TRIGGERS;
6493         MODE_ANY;
6494         PRECONDITION(CheckPointer(libraryName,NULL_OK));
6495         POSTCONDITION(CheckPointer(RETVAL,NULL_OK));
6496         INJECT_FAULT(COMPlusThrowOM(););
6497     }
6498     CONTRACT_END;
6499     if(libraryName == NULL) RETURN NULL;
6500
6501     AssemblySpec spec;
6502     spec.SetCodeBase(libraryName);
6503     RETURN (HMODULE) m_UnmanagedCache.LookupEntry(&spec, 0);
6504 }
6505
6506
6507 BOOL AppDomain::IsCached(AssemblySpec *pSpec)
6508 {
6509     WRAPPER_NO_CONTRACT;
6510
6511     // Check to see if this fits our rather loose idea of a reference to mscorlib.
6512     // If so, don't use fusion to bind it - do it ourselves.
6513     if (pSpec->IsMscorlib())
6514         return TRUE;
6515
6516     return m_AssemblyCache.Contains(pSpec);
6517 }
6518
6519 void AppDomain::GetCacheAssemblyList(SetSHash<PTR_DomainAssembly>& assemblyList)
6520 {
6521     CrstHolder holder(&m_DomainCacheCrst);
6522     m_AssemblyCache.GetAllAssemblies(assemblyList);
6523 }
6524
6525 PEAssembly* AppDomain::FindCachedFile(AssemblySpec* pSpec, BOOL fThrow /*=TRUE*/)
6526 {
6527     CONTRACTL
6528     {
6529         if (fThrow) {
6530             GC_TRIGGERS;
6531             THROWS;
6532         }
6533         else {
6534             GC_NOTRIGGER;
6535             NOTHROW;
6536         }
6537         MODE_ANY;
6538     }
6539     CONTRACTL_END;
6540
6541     // Check to see if this fits our rather loose idea of a reference to mscorlib.
6542     // If so, don't use fusion to bind it - do it ourselves.
6543     if (fThrow && pSpec->IsMscorlib())
6544     {
6545         CONSISTENCY_CHECK(SystemDomain::System()->SystemAssembly() != NULL);
6546         PEAssembly *pFile = SystemDomain::System()->SystemFile();
6547         pFile->AddRef();
6548         return pFile;
6549     }
6550
6551     return m_AssemblyCache.LookupFile(pSpec, fThrow);
6552 }
6553
6554
6555 BOOL AppDomain::PostBindResolveAssembly(AssemblySpec  *pPrePolicySpec,
6556                                         AssemblySpec  *pPostPolicySpec,
6557                                         HRESULT        hrBindResult,
6558                                         AssemblySpec **ppFailedSpec)
6559 {
6560     STATIC_CONTRACT_THROWS;
6561     STATIC_CONTRACT_GC_TRIGGERS;
6562     PRECONDITION(CheckPointer(pPrePolicySpec));
6563     PRECONDITION(CheckPointer(pPostPolicySpec));
6564     PRECONDITION(CheckPointer(ppFailedSpec));
6565
6566     BOOL fFailure = TRUE;
6567     *ppFailedSpec = pPrePolicySpec;
6568
6569
6570     PEAssemblyHolder result;
6571
6572     if ((EEFileLoadException::GetFileLoadKind(hrBindResult) == kFileNotFoundException) ||
6573         (hrBindResult == FUSION_E_REF_DEF_MISMATCH) ||
6574         (hrBindResult == FUSION_E_INVALID_NAME))
6575     {
6576         result = TryResolveAssembly(*ppFailedSpec, FALSE /* fPreBind */);
6577
6578         if (result != NULL && pPrePolicySpec->CanUseWithBindingCache() && result->CanUseWithBindingCache())
6579         {
6580             fFailure = FALSE;
6581
6582             // Given the post-policy resolve event construction of the CLR binder,
6583             // chained managed resolve events can race with each other, therefore we do allow
6584             // the adding of the result to fail. Checking for already chached specs
6585             // is not an option as it would introduce another race window.
6586             // The binder does a re-fetch of the
6587             // orignal binding spec and therefore will not cause inconsistency here.
6588             // For the purposes of the resolve event, failure to add to the cache still is a success.
6589             AddFileToCache(pPrePolicySpec, result, TRUE /* fAllowFailure */);
6590             if (*ppFailedSpec != pPrePolicySpec && pPostPolicySpec->CanUseWithBindingCache())
6591             {
6592                 AddFileToCache(pPostPolicySpec, result, TRUE /* fAllowFailure */ );
6593             }
6594         }
6595     }
6596
6597     return fFailure;
6598 }
6599
6600 //----------------------------------------------------------------------------------------
6601 // Helper class for hosted binder
6602
6603 class PEAssemblyAsPrivAssemblyInfo : public IUnknownCommon<ICLRPrivAssemblyInfo>
6604 {
6605 public:
6606     //------------------------------------------------------------------------------------
6607     // Ctor
6608
6609     PEAssemblyAsPrivAssemblyInfo(PEAssembly *pPEAssembly)
6610     {
6611         LIMITED_METHOD_CONTRACT;
6612         STATIC_CONTRACT_THROWS;
6613
6614         if (pPEAssembly == nullptr)
6615             ThrowHR(E_UNEXPECTED);
6616
6617         pPEAssembly->AddRef();
6618         m_pPEAssembly = pPEAssembly;
6619     }
6620
6621     //------------------------------------------------------------------------------------
6622     // ICLRPrivAssemblyInfo methods
6623
6624     //------------------------------------------------------------------------------------
6625     STDMETHOD(GetAssemblyName)(
6626         __in  DWORD cchBuffer,
6627         __out_opt LPDWORD pcchBuffer,
6628         __out_ecount_part_opt(cchBuffer, *pcchBuffer) LPWSTR wzBuffer)
6629     {
6630         CONTRACTL
6631         {
6632             NOTHROW;
6633             GC_TRIGGERS;
6634             MODE_ANY;
6635         }
6636         CONTRACTL_END;
6637
6638         HRESULT hr = S_OK;
6639
6640         if ((cchBuffer == 0) != (wzBuffer == nullptr))
6641         {
6642             return E_INVALIDARG;
6643         }
6644
6645         LPCUTF8 szName = m_pPEAssembly->GetSimpleName();
6646
6647         bool bIsAscii;
6648         DWORD cchName;
6649         IfFailRet(FString::Utf8_Unicode_Length(szName, &bIsAscii, &cchName));
6650
6651         if (cchBuffer < cchName + 1)
6652         {
6653             if (pcchBuffer != nullptr)
6654             {
6655                 *pcchBuffer = cchName + 1;
6656             }
6657             return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
6658         }
6659         else
6660         {
6661             IfFailRet(FString::Utf8_Unicode(szName, bIsAscii, wzBuffer, cchName));
6662             if (pcchBuffer != nullptr)
6663             {
6664                 *pcchBuffer = cchName;
6665             }
6666             return S_OK;
6667         }
6668     }
6669
6670     //------------------------------------------------------------------------------------
6671     STDMETHOD(GetAssemblyVersion)(
6672         USHORT *pMajor,
6673         USHORT *pMinor,
6674         USHORT *pBuild,
6675         USHORT *pRevision)
6676     {
6677         WRAPPER_NO_CONTRACT;
6678         return m_pPEAssembly->GetVersion(pMajor, pMinor, pBuild, pRevision);
6679     }
6680
6681     //------------------------------------------------------------------------------------
6682     STDMETHOD(GetAssemblyPublicKey)(
6683         DWORD cbBuffer,
6684         LPDWORD pcbBuffer,
6685         BYTE *pbBuffer)
6686     {
6687         STATIC_CONTRACT_LIMITED_METHOD;
6688         STATIC_CONTRACT_CAN_TAKE_LOCK;
6689
6690         VALIDATE_PTR_RET(pcbBuffer);
6691         VALIDATE_CONDITION((pbBuffer == nullptr) == (cbBuffer == 0), return E_INVALIDARG);
6692
6693         HRESULT hr = S_OK;
6694
6695         EX_TRY
6696         {
6697             // Note: PEAssembly::GetPublicKey will return bogus data pointer when *pcbBuffer == 0
6698             LPCVOID pbKey = m_pPEAssembly->GetPublicKey(pcbBuffer);
6699
6700             if (*pcbBuffer != 0)
6701             {
6702                 if (pbBuffer != nullptr && cbBuffer >= *pcbBuffer)
6703                 {
6704                     memcpy(pbBuffer, pbKey, *pcbBuffer);
6705                     hr = S_OK;
6706                 }
6707                 else
6708                 {
6709                     hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
6710                 }
6711             }
6712             else
6713             {
6714                 hr = S_FALSE; // ==> No public key
6715             }
6716         }
6717         EX_CATCH_HRESULT(hr);
6718
6719         return hr;
6720     }
6721
6722 private:
6723     ReleaseHolder<PEAssembly> m_pPEAssembly;
6724 };
6725
6726 //-----------------------------------------------------------------------------------------------------------------
6727 static HRESULT VerifyBindHelper(
6728     ICLRPrivAssembly *pPrivAssembly,
6729     IAssemblyName *pAssemblyName,
6730     PEAssembly *pPEAssembly)
6731 {
6732     STATIC_CONTRACT_THROWS;
6733     STATIC_CONTRACT_GC_TRIGGERS;
6734
6735     HRESULT hr = S_OK;
6736     // Create an ICLRPrivAssemblyInfo to call to ICLRPrivAssembly::VerifyBind
6737     NewHolder<PEAssemblyAsPrivAssemblyInfo> pPrivAssemblyInfoImpl = new PEAssemblyAsPrivAssemblyInfo(pPEAssembly);
6738     ReleaseHolder<ICLRPrivAssemblyInfo> pPrivAssemblyInfo;
6739     IfFailRet(pPrivAssemblyInfoImpl->QueryInterface(__uuidof(ICLRPrivAssemblyInfo), (LPVOID *)&pPrivAssemblyInfo));
6740     pPrivAssemblyInfoImpl.SuppressRelease();
6741
6742     // Call VerifyBind to give the host a chance to reject the bind based on assembly image contents.
6743     IfFailRet(pPrivAssembly->VerifyBind(pAssemblyName, pPrivAssembly, pPrivAssemblyInfo));
6744
6745     return hr;
6746 }
6747
6748 //-----------------------------------------------------------------------------------------------------------------
6749 HRESULT AppDomain::BindAssemblySpecForHostedBinder(
6750     AssemblySpec *   pSpec, 
6751     IAssemblyName *  pAssemblyName, 
6752     ICLRPrivBinder * pBinder, 
6753     PEAssembly **    ppAssembly)
6754 {
6755     STANDARD_VM_CONTRACT;
6756     
6757     PRECONDITION(CheckPointer(pSpec));
6758     PRECONDITION(pSpec->GetAppDomain() == this);
6759     PRECONDITION(CheckPointer(ppAssembly));
6760     PRECONDITION(pSpec->GetCodeBase() == nullptr);
6761
6762     HRESULT hr = S_OK;
6763
6764
6765     // The Fusion binder can throw (to preserve compat, since it will actually perform an assembly
6766     // load as part of it's bind), so we need to be careful here to catch any FileNotFoundException
6767     // objects if fThrowIfNotFound is false.
6768     ReleaseHolder<ICLRPrivAssembly> pPrivAssembly;
6769
6770     // We return HRESULTs here on failure instead of throwing as failures here are not necessarily indicative
6771     // of an actual application problem. Returning an error code is substantially faster than throwing, and
6772     // should be used when possible.
6773     IfFailRet(pBinder->BindAssemblyByName(pAssemblyName, &pPrivAssembly));
6774
6775     IfFailRet(BindHostedPrivAssembly(nullptr, pPrivAssembly, pAssemblyName, ppAssembly));
6776
6777
6778     return S_OK;
6779 }
6780
6781 //-----------------------------------------------------------------------------------------------------------------
6782 HRESULT 
6783 AppDomain::BindHostedPrivAssembly(
6784     PEAssembly *       pParentAssembly,
6785     ICLRPrivAssembly * pPrivAssembly, 
6786     IAssemblyName *    pAssemblyName, 
6787     PEAssembly **      ppAssembly, 
6788     BOOL               fIsIntrospectionOnly) // = FALSE
6789 {
6790     STANDARD_VM_CONTRACT;
6791
6792     PRECONDITION(CheckPointer(pPrivAssembly));
6793     PRECONDITION(CheckPointer(ppAssembly));
6794     
6795     HRESULT hr = S_OK;
6796     
6797     *ppAssembly = nullptr;
6798     
6799     // See if result has been previously loaded.
6800     {
6801         DomainAssembly* pDomainAssembly = FindAssembly(pPrivAssembly);
6802         if (pDomainAssembly != nullptr)
6803         {
6804             *ppAssembly = clr::SafeAddRef(pDomainAssembly->GetFile());
6805         }
6806     }
6807
6808     if (*ppAssembly != nullptr)
6809     {   // Already exists: ask the binder to verify and return the assembly.
6810         return VerifyBindHelper(pPrivAssembly, pAssemblyName, *ppAssembly);
6811     }
6812
6813     // Get the IL PEFile.
6814     PEImageHolder pPEImageIL;
6815     {
6816         // Does not already exist, so get the resource for the assembly and load it.
6817         DWORD dwImageType;
6818         ReleaseHolder<ICLRPrivResource> pIResourceIL;
6819
6820         IfFailRet(pPrivAssembly->GetImageResource(ASSEMBLY_IMAGE_TYPE_IL, &dwImageType, &pIResourceIL));
6821         _ASSERTE(dwImageType == ASSEMBLY_IMAGE_TYPE_IL);
6822
6823         pPEImageIL = PEImage::OpenImage(pIResourceIL, MDInternalImport_Default);
6824     }
6825
6826     // See if an NI is available.
6827     DWORD dwAvailableImages;
6828     IfFailRet(pPrivAssembly->GetAvailableImageTypes(&dwAvailableImages));
6829     _ASSERTE(dwAvailableImages & ASSEMBLY_IMAGE_TYPE_IL); // Just double checking that IL bit is always set.
6830
6831     // Get the NI PEFile if available.
6832     PEImageHolder pPEImageNI;
6833     if (dwAvailableImages & ASSEMBLY_IMAGE_TYPE_NATIVE)
6834     {
6835         DWORD dwImageType;
6836         ReleaseHolder<ICLRPrivResource> pIResourceNI;
6837
6838         IfFailRet(pPrivAssembly->GetImageResource(ASSEMBLY_IMAGE_TYPE_NATIVE, &dwImageType, &pIResourceNI));
6839         _ASSERTE(dwImageType == ASSEMBLY_IMAGE_TYPE_NATIVE || FAILED(hr));
6840
6841         pPEImageNI = PEImage::OpenImage(pIResourceNI, MDInternalImport_TrustedNativeImage);
6842     }
6843     _ASSERTE(pPEImageIL != nullptr);
6844     
6845     // Create a PEAssembly using the IL and NI images.
6846     PEAssemblyHolder pPEAssembly = PEAssembly::Open(pParentAssembly, pPEImageIL, pPEImageNI, pPrivAssembly, fIsIntrospectionOnly);
6847
6848
6849     // Ask the binder to verify.
6850     IfFailRet(VerifyBindHelper(pPrivAssembly, pAssemblyName, pPEAssembly));
6851
6852     // The result.    
6853     *ppAssembly = pPEAssembly.Extract();
6854
6855     return S_OK;
6856 } // AppDomain::BindHostedPrivAssembly
6857
6858 //---------------------------------------------------------------------------------------------------------------------
6859 PEAssembly * AppDomain::BindAssemblySpec(
6860     AssemblySpec *         pSpec, 
6861     BOOL                   fThrowOnFileNotFound, 
6862     BOOL                   fRaisePrebindEvents, 
6863     StackCrawlMark *       pCallerStackMark, 
6864     BOOL                   fUseHostBinderIfAvailable)
6865 {
6866     STATIC_CONTRACT_THROWS;
6867     STATIC_CONTRACT_GC_TRIGGERS;
6868     PRECONDITION(CheckPointer(pSpec));
6869     PRECONDITION(pSpec->GetAppDomain() == this);
6870     PRECONDITION(this==::GetAppDomain());
6871
6872     GCX_PREEMP();
6873
6874     BOOL fForceReThrow = FALSE;
6875
6876 #if defined(FEATURE_COMINTEROP)
6877     // Handle WinRT assemblies in the classic/hybrid scenario. If this is an AppX process,
6878     // then this case will be handled by the previous block as part of the full set of
6879     // available binding hosts.
6880     if (pSpec->IsContentType_WindowsRuntime())
6881     {
6882         HRESULT hr = S_OK;
6883
6884         // Get the assembly display name.
6885         ReleaseHolder<IAssemblyName> pAssemblyName;
6886
6887         IfFailThrow(pSpec->CreateFusionName(&pAssemblyName, TRUE, TRUE));
6888
6889
6890         PEAssemblyHolder pAssembly;
6891
6892         EX_TRY
6893         {
6894             hr = BindAssemblySpecForHostedBinder(pSpec, pAssemblyName, m_pWinRtBinder, &pAssembly);
6895             if (FAILED(hr))
6896                 goto EndTry2; // Goto end of try block.
6897 EndTry2:;
6898         }
6899         // The combination of this conditional catch/ the following if statement which will throw reduces the count of exceptions 
6900         // thrown in scenarios where the exception does not escape the method. We cannot get rid of the try/catch block, as
6901         // there are cases within some of the clrpriv binder's which throw.
6902         // Note: In theory, FileNotFound should always come here as HRESULT, never as exception.
6903         EX_CATCH_HRESULT_IF(hr,
6904             !fThrowOnFileNotFound && Assembly::FileNotFound(hr))
6905
6906         if (FAILED(hr) && (fThrowOnFileNotFound || !Assembly::FileNotFound(hr)))
6907         {
6908             if (Assembly::FileNotFound(hr))
6909             {
6910                 _ASSERTE(fThrowOnFileNotFound);
6911                 // Uses defaultScope
6912                 EEFileLoadException::Throw(pSpec, hr);
6913             }
6914
6915             // WinRT type bind failures
6916             _ASSERTE(pSpec->IsContentType_WindowsRuntime());
6917             if (hr == HRESULT_FROM_WIN32(APPMODEL_ERROR_NO_PACKAGE)) // Returned by RoResolveNamespace when using 3rd party WinRT types in classic process
6918             {
6919                 if (fThrowOnFileNotFound)
6920                 {   // Throw NotSupportedException (with custom message) wrapped by TypeLoadException to give user type name for diagnostics
6921                     // Note: TypeLoadException is equivalent of FileNotFound in WinRT world
6922                     EEMessageException ex(kNotSupportedException, IDS_EE_WINRT_THIRDPARTY_NOTSUPPORTED);
6923                     EX_THROW_WITH_INNER(EETypeLoadException, (pSpec->GetWinRtTypeNamespace(), pSpec->GetWinRtTypeClassName(), nullptr, nullptr, IDS_EE_WINRT_LOADFAILURE), &ex);
6924                 }
6925             }
6926             else if ((hr == CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT) || // Returned e.g. for WinRT type name without namespace
6927                      (hr == COR_E_PLATFORMNOTSUPPORTED)) // Using WinRT on pre-Win8 OS
6928             {
6929                 if (fThrowOnFileNotFound)
6930                 {   // Throw ArgumentException/PlatformNotSupportedException wrapped by TypeLoadException to give user type name for diagnostics
6931                     // Note: TypeLoadException is equivalent of FileNotFound in WinRT world
6932                     EEMessageException ex(hr);
6933                     EX_THROW_WITH_INNER(EETypeLoadException, (pSpec->GetWinRtTypeNamespace(), pSpec->GetWinRtTypeClassName(), nullptr, nullptr, IDS_EE_WINRT_LOADFAILURE), &ex);
6934                 }
6935             }
6936             else
6937             {
6938                 IfFailThrow(hr);
6939             }
6940         }
6941         _ASSERTE((FAILED(hr) && !fThrowOnFileNotFound) || pAssembly != nullptr);
6942
6943         return pAssembly.Extract();
6944     }
6945     else
6946 #endif // FEATURE_COMINTEROP
6947     if (pSpec->HasUniqueIdentity())
6948     {
6949         HRESULT hrBindResult = S_OK;
6950         PEAssemblyHolder result;
6951         
6952
6953         EX_TRY
6954         {
6955             if (!IsCached(pSpec))
6956             {
6957
6958                 {
6959                     bool fAddFileToCache = false;
6960
6961                     BOOL fIsWellKnown = FALSE;
6962
6963                     // Use CoreClr's fusion alternative
6964                     CoreBindResult bindResult;
6965
6966                     pSpec->Bind(this, fThrowOnFileNotFound, &bindResult, FALSE /* fNgenExplicitBind */, FALSE /* fExplicitBindToNativeImage */, pCallerStackMark);
6967                     hrBindResult = bindResult.GetHRBindResult();
6968
6969                     if (bindResult.Found()) 
6970                     {
6971                         if (SystemDomain::SystemFile() && bindResult.IsMscorlib())
6972                         {
6973                             // Avoid rebinding to another copy of mscorlib
6974                             result = SystemDomain::SystemFile();
6975                             result.SuppressRelease(); // Didn't get a refcount
6976                         }
6977                         else
6978                         {
6979                             // IsSystem on the PEFile should be false, even for mscorlib satellites
6980                             result = PEAssembly::Open(&bindResult,
6981                                                       FALSE, pSpec->IsIntrospectionOnly());
6982                         }
6983                         fAddFileToCache = true;
6984                         
6985                         // Setup the reference to the binder, which performed the bind, into the AssemblySpec
6986                         ICLRPrivBinder* pBinder = result->GetBindingContext();
6987                         _ASSERTE(pBinder != NULL);
6988                         pSpec->SetBindingContext(pBinder);
6989                     }
6990
6991
6992                     if (fAddFileToCache)
6993                     {
6994
6995
6996                         if (pSpec->CanUseWithBindingCache() && result->CanUseWithBindingCache())
6997                         {
6998                             // Failure to add simply means someone else beat us to it. In that case
6999                             // the FindCachedFile call below (after catch block) will update result
7000                             // to the cached value.
7001                             AddFileToCache(pSpec, result, TRUE /*fAllowFailure*/);
7002                         }
7003                     }
7004                     else if (!fIsWellKnown)
7005                     {
7006                         _ASSERTE(fThrowOnFileNotFound == FALSE);
7007
7008                         // Don't trigger the resolve event for the CoreLib satellite assembly. A misbehaving resolve event may
7009                         // return an assembly that does not match, and this can cause recursive resource lookups during error
7010                         // reporting. The CoreLib satellite assembly is loaded from relative locations based on the culture, see
7011                         // AssemblySpec::Bind().
7012                         if (!pSpec->IsMscorlibSatellite())
7013                         {
7014                             // Trigger the resolve event also for non-throw situation.
7015                             // However, this code path will behave as if the resolve handler has thrown,
7016                             // that is, not trigger an MDA.
7017
7018                             AssemblySpec NewSpec(this);
7019                             AssemblySpec *pFailedSpec = NULL;
7020
7021                             fForceReThrow = TRUE; // Managed resolve event handler can throw
7022
7023                             // Purposly ignore return value
7024                             PostBindResolveAssembly(pSpec, &NewSpec, hrBindResult, &pFailedSpec);
7025                         }
7026                     }
7027                 }
7028             }
7029         }
7030         EX_CATCH
7031         {
7032             Exception *ex = GET_EXCEPTION();
7033
7034             AssemblySpec NewSpec(this);
7035             AssemblySpec *pFailedSpec = NULL;
7036
7037             // Let transient exceptions or managed resolve event handler exceptions propagate
7038             if (ex->IsTransient() || fForceReThrow)
7039             {
7040                 EX_RETHROW;
7041             }
7042
7043             {
7044                 // This is not executed for SO exceptions so we need to disable the backout
7045                 // stack validation to prevent false violations from being reported.
7046                 DISABLE_BACKOUT_STACK_VALIDATION;
7047
7048                 BOOL fFailure = PostBindResolveAssembly(pSpec, &NewSpec, ex->GetHR(), &pFailedSpec);
7049                 if (fFailure)
7050                 {
7051                     BOOL bFileNotFoundException =
7052                         (EEFileLoadException::GetFileLoadKind(ex->GetHR()) == kFileNotFoundException);
7053                 
7054                     if (!bFileNotFoundException)
7055                     {
7056                         fFailure = AddExceptionToCache(pFailedSpec, ex);
7057                     } // else, fFailure stays TRUE
7058                     // Effectively, fFailure == bFileNotFoundException || AddExceptionToCache(pFailedSpec, ex)
7059
7060                     // Only throw this exception if we are the first in the cache
7061                     if (fFailure)
7062                     {
7063                         //
7064                         // If the BindingFailure MDA is enabled, trigger one for this failure
7065                         // Note: TryResolveAssembly() can also throw if an AssemblyResolve event subscriber throws
7066                         //       and the MDA isn't sent in this case (or for transient failure cases)
7067                         //
7068 #ifdef MDA_SUPPORTED
7069                         MdaBindingFailure* pProbe = MDA_GET_ASSISTANT(BindingFailure);
7070                         if (pProbe)
7071                         {
7072                             // Transition to cooperative GC mode before using any OBJECTREFs.
7073                             GCX_COOP();
7074
7075                             OBJECTREF exceptionObj = GET_THROWABLE();
7076                             GCPROTECT_BEGIN(exceptionObj)
7077                             {
7078                                 pProbe->BindFailed(pFailedSpec, &exceptionObj);
7079                             }
7080                             GCPROTECT_END();
7081                         }
7082 #endif
7083
7084                         // In the same cases as for the MDA, store the failure information for DAC to read
7085                         if (IsDebuggerAttached()) {
7086                             FailedAssembly *pFailed = new FailedAssembly();
7087                             pFailed->Initialize(pFailedSpec, ex);
7088                             IfFailThrow(m_failedAssemblies.Append(pFailed));
7089                         }
7090
7091                         if (!bFileNotFoundException || fThrowOnFileNotFound)
7092                         {
7093
7094                             // V1.1 App-compatibility workaround. See VSW530166 if you want to whine about it.
7095                             //
7096                             // In Everett, if we failed to download an assembly because of a broken network cable,
7097                             // we returned a FileNotFoundException with a COR_E_FILENOTFOUND hr embedded inside
7098                             // (which would be exposed when marshaled to native.)
7099                             //
7100                             // In Whidbey, we now set the more appropriate INET_E_RESOURCE_NOT_FOUND hr. But
7101                             // the online/offline switch code in VSTO for Everett hardcoded a check for
7102                             // COR_E_FILENOTFOUND. 
7103                             //
7104                             // So now, to keep that code from breaking, we have to remap INET_E_RESOURCE_NOT_FOUND
7105                             // back to COR_E_FILENOTFOUND. We're doing it here rather down in Fusion so as to affect
7106                             // the least number of callers.
7107                             
7108                             if (ex->GetHR() == INET_E_RESOURCE_NOT_FOUND)
7109                             {
7110                                 EEFileLoadException::Throw(pFailedSpec, COR_E_FILENOTFOUND, ex);
7111                             }
7112
7113                             if (EEFileLoadException::CheckType(ex))
7114                             {
7115                                 if (pFailedSpec == pSpec)
7116                                 {
7117                                     EX_RETHROW; //preserve the information
7118                                 }
7119                                 else
7120                                 {
7121                                     StackSString exceptionDisplayName, failedSpecDisplayName;
7122
7123                                     ((EEFileLoadException*)ex)->GetName(exceptionDisplayName);
7124                                     pFailedSpec->GetFileOrDisplayName(0, failedSpecDisplayName);
7125
7126                                     if (exceptionDisplayName.CompareCaseInsensitive(failedSpecDisplayName) == 0)
7127                                     {
7128                                         EX_RETHROW; // Throw the original exception. Otherwise, we'd throw an exception that contains the same message twice.
7129                                     }
7130                                 }
7131                             }
7132                             
7133                             EEFileLoadException::Throw(pFailedSpec, ex->GetHR(), ex);
7134                         }
7135
7136                     }
7137                 }
7138             }
7139         }
7140         EX_END_CATCH(RethrowTerminalExceptions);
7141
7142         // Now, if it's a cacheable bind we need to re-fetch the result from the cache, as we may have been racing with another
7143         // thread to store our result.  Note that we may throw from here, if there is a cached exception.
7144         // This will release the refcount of the current result holder (if any), and will replace
7145         // it with a non-addref'ed result
7146         if (pSpec->CanUseWithBindingCache() && (result== NULL || result->CanUseWithBindingCache()))
7147         {
7148             result = FindCachedFile(pSpec);
7149
7150             if (result != NULL)
7151                 result->AddRef();
7152         }
7153
7154         return result.Extract();
7155     }
7156     else
7157     {
7158         // Unsupported content type
7159         if (fThrowOnFileNotFound)
7160         {
7161             ThrowHR(COR_E_BADIMAGEFORMAT);
7162         }
7163         return nullptr;
7164     }
7165 } // AppDomain::BindAssemblySpec
7166
7167
7168
7169 PEAssembly *AppDomain::TryResolveAssembly(AssemblySpec *pSpec, BOOL fPreBind)
7170 {
7171     STATIC_CONTRACT_THROWS;
7172     STATIC_CONTRACT_GC_TRIGGERS;
7173     STATIC_CONTRACT_MODE_ANY;
7174
7175     PEAssembly *result = NULL;
7176
7177     EX_TRY
7178     {
7179         result = pSpec->ResolveAssemblyFile(this, fPreBind);
7180     }
7181     EX_HOOK
7182     {
7183         Exception *pEx = GET_EXCEPTION();
7184
7185         if (!pEx->IsTransient())
7186         {
7187             AddExceptionToCache(pSpec, pEx);
7188             if (!EEFileLoadException::CheckType(pEx))
7189                 EEFileLoadException::Throw(pSpec, pEx->GetHR(), pEx);
7190         }
7191     }
7192     EX_END_HOOK;
7193
7194     return result;
7195 }
7196
7197
7198 ULONG AppDomain::AddRef()
7199 {
7200     LIMITED_METHOD_CONTRACT;
7201     return InterlockedIncrement(&m_cRef);
7202 }
7203
7204 ULONG AppDomain::Release()
7205 {
7206     CONTRACTL
7207     {
7208         NOTHROW;
7209         GC_TRIGGERS;
7210         MODE_ANY;
7211         PRECONDITION(m_cRef > 0);
7212     }
7213     CONTRACTL_END;
7214
7215     ULONG   cRef = InterlockedDecrement(&m_cRef);
7216     if (!cRef)
7217     {
7218         _ASSERTE (m_Stage == STAGE_CREATING || m_Stage == STAGE_CLOSED);
7219         ADID adid=GetId();
7220         delete this;
7221         TESTHOOKCALL(AppDomainDestroyed(adid.m_dwId));
7222     }
7223     return (cRef);
7224 }
7225
7226
7227 AppDomain* AppDomain::s_pAppDomainToRaiseUnloadEvent;
7228 BOOL AppDomain::s_fProcessUnloadDomainEvent = FALSE;
7229
7230 #ifndef CROSSGEN_COMPILE
7231
7232 void AppDomain::RaiseUnloadDomainEvent_Wrapper(LPVOID ptr)
7233 {
7234     CONTRACTL
7235     {
7236         THROWS;
7237         MODE_COOPERATIVE;
7238         GC_TRIGGERS;
7239         INJECT_FAULT(COMPlusThrowOM(););
7240         SO_INTOLERANT;
7241     }
7242     CONTRACTL_END;
7243
7244     AppDomain* pDomain = (AppDomain *) ptr;
7245     pDomain->RaiseUnloadDomainEvent();
7246 }
7247
7248 void AppDomain::ProcessUnloadDomainEventOnFinalizeThread()
7249 {
7250     CONTRACTL
7251     {
7252         THROWS;
7253         GC_TRIGGERS;
7254         MODE_COOPERATIVE;
7255     }
7256     CONTRACTL_END;
7257     Thread *pThread = GetThread();
7258     _ASSERTE (pThread && IsFinalizerThread());
7259
7260     // if we are not unloading domain now, do not process the event
7261     if (SystemDomain::AppDomainBeingUnloaded() == NULL)
7262     {
7263         s_pAppDomainToRaiseUnloadEvent->SetStage(STAGE_UNLOAD_REQUESTED);
7264         s_pAppDomainToRaiseUnloadEvent->EnableADUnloadWorker(
7265             s_pAppDomainToRaiseUnloadEvent->IsRudeUnload()?EEPolicy::ADU_Rude:EEPolicy::ADU_Safe);
7266         FastInterlockExchangePointer(&s_pAppDomainToRaiseUnloadEvent, NULL);
7267         return;
7268     }
7269     FastInterlockExchange((LONG*)&s_fProcessUnloadDomainEvent, TRUE);
7270     AppDomain::EnableADUnloadWorkerForFinalizer();
7271     pThread->SetThreadStateNC(Thread::TSNC_RaiseUnloadEvent);
7272     s_pAppDomainToRaiseUnloadEvent->RaiseUnloadDomainEvent();
7273     pThread->ResetThreadStateNC(Thread::TSNC_RaiseUnloadEvent);
7274     s_pAppDomainToRaiseUnloadEvent->EnableADUnloadWorker(
7275         s_pAppDomainToRaiseUnloadEvent->IsRudeUnload()?EEPolicy::ADU_Rude:EEPolicy::ADU_Safe);
7276     FastInterlockExchangePointer(&s_pAppDomainToRaiseUnloadEvent, NULL);
7277     FastInterlockExchange((LONG*)&s_fProcessUnloadDomainEvent, FALSE);
7278
7279     if (pThread->IsAbortRequested())
7280     {
7281         pThread->UnmarkThreadForAbort(Thread::TAR_Thread);
7282     }
7283 }
7284
7285 void AppDomain::RaiseUnloadDomainEvent()
7286 {
7287     CONTRACTL
7288     {
7289         THROWS;
7290         MODE_COOPERATIVE;
7291         GC_TRIGGERS;
7292         SO_INTOLERANT;
7293     }
7294     CONTRACTL_END;
7295
7296     Thread *pThread = GetThread();
7297     if (this != pThread->GetDomain())
7298     {
7299         pThread->DoADCallBack(this, AppDomain::RaiseUnloadDomainEvent_Wrapper, this,ADV_FINALIZER|ADV_COMPILATION);
7300     }
7301     else
7302     {
7303         struct _gc
7304         {
7305             APPDOMAINREF Domain;
7306             OBJECTREF    Delegate;
7307         } gc;
7308         ZeroMemory(&gc, sizeof(gc));
7309
7310         GCPROTECT_BEGIN(gc);
7311         gc.Domain = (APPDOMAINREF) GetRawExposedObject();
7312         if (gc.Domain != NULL)
7313         {
7314             gc.Delegate = gc.Domain->m_pDomainUnloadEventHandler;
7315             if (gc.Delegate != NULL)
7316                 DistributeEvent(&gc.Delegate, (OBJECTREF *) &gc.Domain);
7317         }
7318         GCPROTECT_END();
7319     }
7320 }
7321
7322 void AppDomain::RaiseLoadingAssemblyEvent(DomainAssembly *pAssembly)
7323 {
7324     CONTRACTL
7325     {
7326         NOTHROW;
7327         GC_TRIGGERS;
7328         PRECONDITION(this == GetAppDomain());
7329         MODE_ANY;
7330     }
7331     CONTRACTL_END;
7332
7333     GCX_COOP();
7334     FAULT_NOT_FATAL();
7335     OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
7336
7337     EX_TRY
7338     {
7339         struct _gc {
7340             APPDOMAINREF AppDomainRef;
7341             OBJECTREF    orThis;
7342         } gc;
7343         ZeroMemory(&gc, sizeof(gc));
7344
7345         if ((gc.AppDomainRef = (APPDOMAINREF) GetRawExposedObject()) != NULL) {
7346             if (gc.AppDomainRef->m_pAssemblyEventHandler != NULL)
7347             {
7348                 ARG_SLOT args[2];
7349                 GCPROTECT_BEGIN(gc);
7350
7351                 gc.orThis = pAssembly->GetExposedAssemblyObject();
7352
7353                 MethodDescCallSite  onAssemblyLoad(METHOD__APP_DOMAIN__ON_ASSEMBLY_LOAD, &gc.orThis);
7354
7355                 // GetExposedAssemblyObject may cause a gc, so call this before filling args[0]
7356                 args[1] = ObjToArgSlot(gc.orThis);
7357                 args[0] = ObjToArgSlot(gc.AppDomainRef);
7358
7359                 onAssemblyLoad.Call(args);
7360
7361                 GCPROTECT_END();
7362             }
7363         }
7364     }
7365     EX_CATCH
7366     {
7367     }
7368     EX_END_CATCH(SwallowAllExceptions);
7369 }
7370
7371
7372 BOOL AppDomain::OnUnhandledException(OBJECTREF *pThrowable, BOOL isTerminating/*=TRUE*/) 
7373 {
7374     STATIC_CONTRACT_NOTHROW;
7375     STATIC_CONTRACT_GC_TRIGGERS;
7376     STATIC_CONTRACT_MODE_ANY;
7377
7378     BOOL retVal= FALSE;
7379
7380     GCX_COOP();
7381
7382     // The Everett behavior was to send the unhandled exception event only to the Default
7383     // AppDomain (since that's the only place that exceptions actually went unhandled).
7384     //
7385     // During Whidbey development, we broadcast the event to all AppDomains in the process.
7386     //
7387     // But the official shipping Whidbey behavior is that the unhandled exception event is
7388     // sent to the Default AppDomain and to whatever AppDomain the exception went unhandled
7389     // in.  To achieve this, we declare the exception to be unhandled *BEFORE* we marshal
7390     // it back to the Default AppDomain at the base of the Finalizer, threadpool and managed
7391     // threads.
7392     //
7393     // The rationale for sending the event to the Default AppDomain as well as the one the
7394     // exception went unhandled in is:
7395     //
7396     // 1)  This is compatible with the pre-Whidbey behavior, where only the Default AppDomain
7397     //     received the notification.
7398     //
7399     // 2)  This is convenient for hosts, which don't want to bother injecting listeners into
7400     //     every single AppDomain.
7401
7402     AppDomain *pAppDomain = GetAppDomain();
7403     OBJECTREF orSender = 0;
7404
7405     GCPROTECT_BEGIN(orSender);
7406
7407     orSender = pAppDomain->GetRawExposedObject();
7408
7409     retVal = pAppDomain->RaiseUnhandledExceptionEventNoThrow(&orSender, pThrowable, isTerminating);
7410
7411     GCPROTECT_END();
7412
7413     return retVal;
7414 }
7415
7416
7417 // Move outside of the AppDomain iteration, to avoid issues with the GC Frames being outside
7418 // the domain transition.  This is a chronic issue that causes us to report roots for an AppDomain
7419 // after we have left it.  This causes problems with AppDomain unloading that we only find
7420 // with stress coverage..
7421 void AppDomain::RaiseOneExitProcessEvent()
7422 {
7423     CONTRACTL
7424     {
7425         THROWS;
7426         GC_TRIGGERS;
7427         MODE_COOPERATIVE;
7428     }
7429     CONTRACTL_END;
7430
7431     struct _gc
7432     {
7433         APPDOMAINREF Domain;
7434         OBJECTREF    Delegate;
7435     } gc;
7436     ZeroMemory(&gc, sizeof(gc));
7437
7438     GCPROTECT_BEGIN(gc);
7439     gc.Domain = (APPDOMAINREF) SystemDomain::GetCurrentDomain()->GetRawExposedObject();
7440     if (gc.Domain != NULL)
7441     {
7442         gc.Delegate = gc.Domain->m_pProcessExitEventHandler;
7443         if (gc.Delegate != NULL)
7444             DistributeEvent(&gc.Delegate, (OBJECTREF *) &gc.Domain);
7445     }
7446     GCPROTECT_END();
7447 }
7448
7449 // Local wrapper used in AppDomain::RaiseExitProcessEvent,
7450 // introduced solely to avoid stack overflow because of _alloca in the loop.
7451 // It's just factored out body of the loop, but it has to be a member method of AppDomain,
7452 // because it calls private RaiseOneExitProcessEvent
7453 /*static*/ void AppDomain::RaiseOneExitProcessEvent_Wrapper(AppDomainIterator* pi)
7454 {
7455     STATIC_CONTRACT_MODE_COOPERATIVE;
7456     STATIC_CONTRACT_THROWS;
7457     STATIC_CONTRACT_GC_TRIGGERS;
7458
7459     ENTER_DOMAIN_PTR(pi->GetDomain(), ADV_ITERATOR)
7460     AppDomain::RaiseOneExitProcessEvent();
7461     END_DOMAIN_TRANSITION;
7462 }
7463
7464 static LONG s_ProcessedExitProcessEventCount = 0;
7465
7466 LONG GetProcessedExitProcessEventCount()
7467 {
7468     LIMITED_METHOD_CONTRACT;
7469     return s_ProcessedExitProcessEventCount;
7470 }
7471
7472 void AppDomain::RaiseExitProcessEvent()
7473 {
7474     if (!g_fEEStarted)
7475         return;
7476
7477     STATIC_CONTRACT_MODE_COOPERATIVE;
7478     STATIC_CONTRACT_THROWS;
7479     STATIC_CONTRACT_GC_TRIGGERS;
7480
7481     // Only finalizer thread during shutdown can call this function.
7482     _ASSERTE ((g_fEEShutDown&ShutDown_Finalize1) && GetThread() == FinalizerThread::GetFinalizerThread());
7483
7484     _ASSERTE (GetThread()->PreemptiveGCDisabled());
7485
7486     _ASSERTE (GetThread()->GetDomain()->IsDefaultDomain());
7487
7488     AppDomainIterator i(TRUE);
7489     while (i.Next())
7490     {
7491         RaiseOneExitProcessEvent_Wrapper(&i);
7492         FastInterlockIncrement(&s_ProcessedExitProcessEventCount);
7493     }
7494 }
7495
7496
7497 BOOL
7498 AppDomain::RaiseUnhandledExceptionEventNoThrow(OBJECTREF *pSender, OBJECTREF *pThrowable, BOOL isTerminating)
7499 {
7500     CONTRACTL
7501     {
7502         NOTHROW;
7503         GC_TRIGGERS;
7504         MODE_COOPERATIVE;
7505     }
7506     CONTRACTL_END;
7507     BOOL bRetVal=FALSE;
7508
7509     EX_TRY
7510     {
7511         bRetVal = RaiseUnhandledExceptionEvent(pSender, pThrowable, isTerminating);
7512     }
7513     EX_CATCH
7514     {
7515     }
7516     EX_END_CATCH(SwallowAllExceptions)  // Swallow any errors.
7517     return bRetVal;
7518
7519 }
7520
7521 BOOL
7522 AppDomain::HasUnhandledExceptionEventHandler()
7523 {
7524     CONTRACTL
7525     {
7526         MODE_COOPERATIVE;
7527         GC_NOTRIGGER; //essential
7528         NOTHROW;
7529     }
7530     CONTRACTL_END;
7531     if (!CanThreadEnter(GetThread()))
7532         return FALSE;
7533     if (GetRawExposedObject()==NULL)
7534         return FALSE;
7535     return (((APPDOMAINREF)GetRawExposedObject())->m_pUnhandledExceptionEventHandler!=NULL);
7536 }
7537
7538 BOOL
7539 AppDomain::RaiseUnhandledExceptionEvent(OBJECTREF *pSender, OBJECTREF *pThrowable, BOOL isTerminating)
7540 {
7541     CONTRACTL
7542     {
7543         THROWS;
7544         GC_TRIGGERS;
7545         MODE_COOPERATIVE;
7546         INJECT_FAULT(COMPlusThrowOM(););
7547     }
7548     CONTRACTL_END;
7549
7550     if (!HasUnhandledExceptionEventHandler())
7551         return FALSE;
7552
7553     BOOL result = FALSE;
7554
7555     _ASSERTE(pThrowable != NULL && IsProtectedByGCFrame(pThrowable));
7556     _ASSERTE(pSender    != NULL && IsProtectedByGCFrame(pSender));
7557
7558     _ASSERTE(this == GetThread()->GetDomain());
7559
7560
7561     OBJECTREF orDelegate = NULL;
7562
7563     GCPROTECT_BEGIN(orDelegate);
7564
7565     APPDOMAINREF orAD = (APPDOMAINREF) GetAppDomain()->GetRawExposedObject();
7566
7567     if (orAD != NULL)
7568     {
7569         orDelegate = orAD->m_pUnhandledExceptionEventHandler;
7570         if (orDelegate != NULL)
7571         {
7572             result = TRUE;
7573             DistributeUnhandledExceptionReliably(&orDelegate, pSender, pThrowable, isTerminating);
7574         }
7575     }
7576     GCPROTECT_END();
7577     return result;
7578 }
7579
7580
7581
7582 #endif // CROSSGEN_COMPILE
7583
7584 // You must be in the correct context before calling this
7585 // routine. Therefore, it is only good for initializing the
7586 // default domain.
7587 void AppDomain::InitializeDomainContext(BOOL allowRedirects,
7588                                         LPCWSTR pwszPath,
7589                                         LPCWSTR pwszConfig)
7590 {
7591     CONTRACTL
7592     {
7593         MODE_COOPERATIVE;
7594         GC_TRIGGERS;
7595         THROWS;
7596         INJECT_FAULT(COMPlusThrowOM(););
7597     }
7598     CONTRACTL_END;
7599
7600     if (NingenEnabled())
7601     {
7602
7603         CreateFusionContext();
7604
7605         return;
7606     }
7607
7608 #ifndef CROSSGEN_COMPILE
7609     struct _gc {
7610         STRINGREF pFilePath;
7611         STRINGREF pConfig;
7612         OBJECTREF ref;
7613         PTRARRAYREF propertyNames;
7614         PTRARRAYREF propertyValues;
7615     } gc;
7616     ZeroMemory(&gc, sizeof(gc));
7617
7618     GCPROTECT_BEGIN(gc);
7619     if(pwszPath)
7620     {
7621         gc.pFilePath = StringObject::NewString(pwszPath);
7622     }
7623
7624     if(pwszConfig)
7625     {
7626         gc.pConfig = StringObject::NewString(pwszConfig);
7627     }
7628
7629
7630     if ((gc.ref = GetExposedObject()) != NULL)
7631     {
7632         MethodDescCallSite setupDomain(METHOD__APP_DOMAIN__SETUP_DOMAIN);
7633
7634         ARG_SLOT args[] =
7635         {
7636             ObjToArgSlot(gc.ref),
7637             BoolToArgSlot(allowRedirects),
7638             ObjToArgSlot(gc.pFilePath),
7639             ObjToArgSlot(gc.pConfig),
7640             ObjToArgSlot(gc.propertyNames),
7641             ObjToArgSlot(gc.propertyValues)
7642         };
7643         setupDomain.Call(args);
7644     }
7645     GCPROTECT_END();
7646 #endif // CROSSGEN_COMPILE
7647 }
7648
7649
7650 IUnknown *AppDomain::CreateFusionContext()
7651 {
7652     CONTRACT(IUnknown *)
7653     {
7654         GC_TRIGGERS;
7655         THROWS;
7656         MODE_ANY;
7657         POSTCONDITION(CheckPointer(RETVAL));
7658         INJECT_FAULT(COMPlusThrowOM(););
7659     }
7660     CONTRACT_END;
7661
7662     if (!m_pFusionContext)
7663     {
7664         ETWOnStartup (FusionAppCtx_V1, FusionAppCtxEnd_V1);
7665         CLRPrivBinderCoreCLR *pTPABinder = NULL;
7666
7667         GCX_PREEMP();
7668
7669         // Initialize the assembly binder for the default context loads for CoreCLR.
7670         IfFailThrow(CCoreCLRBinderHelper::DefaultBinderSetupContext(GetId().m_dwId, &pTPABinder));
7671         m_pFusionContext = reinterpret_cast<IUnknown *>(pTPABinder);
7672         
7673         // By default, initial binding context setup for CoreCLR is also the TPABinding context
7674         (m_pTPABinderContext = pTPABinder)->AddRef();
7675
7676     }
7677
7678     RETURN m_pFusionContext;
7679 }
7680
7681
7682
7683 //---------------------------------------------------------------------------------------
7684 //
7685 // AppDomain::IsDebuggerAttached - is a debugger attached to this process
7686 //
7687 // Arguments:
7688 //    None
7689 //
7690 // Return Value:
7691 //    TRUE if a debugger is attached to this process, FALSE otherwise.
7692 //
7693 // Notes:
7694 //    This is identical to CORDebuggerAttached.  This exists idependantly for legacy reasons - we used to
7695 //    support attaching to individual AppDomains.  This should probably go away eventually.
7696 //
7697
7698 BOOL AppDomain::IsDebuggerAttached()
7699 {
7700     LIMITED_METHOD_CONTRACT;
7701
7702     if (CORDebuggerAttached())
7703     {
7704         return TRUE;
7705     }
7706     else
7707     {
7708         return FALSE;
7709     }
7710 }
7711
7712 #ifdef DEBUGGING_SUPPORTED
7713
7714 // This is called from the debugger to request notification events from
7715 // Assemblies, Modules, Types in this appdomain.
7716 BOOL AppDomain::NotifyDebuggerLoad(int flags, BOOL attaching)
7717 {
7718     WRAPPER_NO_CONTRACT;
7719     BOOL result = FALSE;
7720
7721     if (!attaching && !IsDebuggerAttached())
7722         return FALSE;
7723
7724     AssemblyIterator i;
7725
7726     // Attach to our assemblies
7727     LOG((LF_CORDB, LL_INFO100, "AD::NDA: Iterating assemblies\n"));
7728     i = IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoaded | kIncludeLoading | kIncludeExecution));
7729     CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
7730     while (i.Next(pDomainAssembly.This()))
7731     {
7732         result = (pDomainAssembly->NotifyDebuggerLoad(flags, attaching) || 
7733                   result);
7734     }
7735
7736     return result;
7737 }
7738
7739 void AppDomain::NotifyDebuggerUnload()
7740 {
7741     WRAPPER_NO_CONTRACT;    
7742     if (!IsDebuggerAttached())
7743         return;
7744
7745     LOG((LF_CORDB, LL_INFO10, "AD::NDD domain [%d] %#08x %ls\n",
7746          GetId().m_dwId, this, GetFriendlyNameForLogging()));
7747
7748     LOG((LF_CORDB, LL_INFO100, "AD::NDD: Interating domain bound assemblies\n"));
7749     AssemblyIterator i = IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoaded |  kIncludeLoading  | kIncludeExecution));
7750     CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
7751
7752     // Detach from our assemblies
7753     while (i.Next(pDomainAssembly.This()))
7754     {
7755         LOG((LF_CORDB, LL_INFO100, "AD::NDD: Iterating assemblies\n"));
7756         pDomainAssembly->NotifyDebuggerUnload();
7757     }
7758 }
7759 #endif // DEBUGGING_SUPPORTED
7760
7761 void AppDomain::SetSystemAssemblyLoadEventSent(BOOL fFlag)
7762 {
7763     LIMITED_METHOD_CONTRACT;
7764     if (fFlag == TRUE)
7765         m_dwFlags |= LOAD_SYSTEM_ASSEMBLY_EVENT_SENT;
7766     else
7767         m_dwFlags &= ~LOAD_SYSTEM_ASSEMBLY_EVENT_SENT;
7768 }
7769
7770 BOOL AppDomain::WasSystemAssemblyLoadEventSent(void)
7771 {
7772     LIMITED_METHOD_CONTRACT;
7773     return ((m_dwFlags & LOAD_SYSTEM_ASSEMBLY_EVENT_SENT) == 0) ? FALSE : TRUE;
7774 }
7775
7776 #ifndef CROSSGEN_COMPILE
7777 // U->M thunks created in this domain and not associated with a delegate.
7778 UMEntryThunkCache *AppDomain::GetUMEntryThunkCache()
7779 {
7780     CONTRACTL
7781     {
7782         THROWS;
7783         GC_TRIGGERS;
7784         MODE_ANY;
7785         INJECT_FAULT(COMPlusThrowOM(););
7786     }
7787     CONTRACTL_END;
7788
7789     if (!m_pUMEntryThunkCache)
7790     {
7791         UMEntryThunkCache *pUMEntryThunkCache = new UMEntryThunkCache(this);
7792
7793         if (FastInterlockCompareExchangePointer(&m_pUMEntryThunkCache, pUMEntryThunkCache, NULL) != NULL)
7794         {
7795             // some thread swooped in and set the field
7796             delete pUMEntryThunkCache;
7797         }
7798     }
7799     _ASSERTE(m_pUMEntryThunkCache);
7800     return m_pUMEntryThunkCache;
7801 }
7802
7803 #ifdef FEATURE_COMINTEROP
7804
7805 ComCallWrapperCache *AppDomain::GetComCallWrapperCache()
7806 {
7807     CONTRACTL
7808     {
7809         THROWS;
7810         GC_TRIGGERS;
7811         MODE_ANY;
7812         INJECT_FAULT(COMPlusThrowOM(););
7813     }
7814     CONTRACTL_END;
7815
7816     if (! m_pComCallWrapperCache)
7817     {
7818         BaseDomain::LockHolder lh(this);
7819
7820         if (! m_pComCallWrapperCache)
7821             m_pComCallWrapperCache = ComCallWrapperCache::Create(this);
7822     }
7823     _ASSERTE(m_pComCallWrapperCache);
7824     return m_pComCallWrapperCache;
7825 }
7826
7827 RCWRefCache *AppDomain::GetRCWRefCache()
7828 {
7829     CONTRACT(RCWRefCache*)
7830     {
7831         THROWS;
7832         GC_NOTRIGGER;
7833         MODE_ANY;
7834         POSTCONDITION(CheckPointer(RETVAL));
7835     }
7836     CONTRACT_END;
7837
7838     if (!m_pRCWRefCache) {
7839         NewHolder<RCWRefCache> pRCWRefCache = new RCWRefCache(this);
7840         if (FastInterlockCompareExchangePointer(&m_pRCWRefCache, (RCWRefCache *)pRCWRefCache, NULL) == NULL)
7841         {
7842             pRCWRefCache.SuppressRelease();    
7843         }        
7844     }
7845     RETURN m_pRCWRefCache;
7846 }
7847
7848 RCWCache *AppDomain::CreateRCWCache()
7849 {
7850     CONTRACT(RCWCache*)
7851     {
7852         THROWS;
7853         GC_TRIGGERS;
7854         MODE_ANY;
7855         INJECT_FAULT(COMPlusThrowOM(););
7856         POSTCONDITION(CheckPointer(RETVAL));
7857     }
7858     CONTRACT_END;
7859
7860     // Initialize the global RCW cleanup list here as well. This is so that it
7861     // it guaranteed to exist if any RCW's are created, but it is not created
7862     // unconditionally.
7863     if (!g_pRCWCleanupList)
7864     {
7865         SystemDomain::LockHolder lh;
7866
7867         if (!g_pRCWCleanupList)
7868             g_pRCWCleanupList = new RCWCleanupList();
7869     }
7870     _ASSERTE(g_pRCWCleanupList);
7871
7872     {
7873         BaseDomain::LockHolder lh(this);
7874
7875         if (!m_pRCWCache)
7876             m_pRCWCache = new RCWCache(this);
7877     }
7878
7879     RETURN m_pRCWCache;
7880 }
7881
7882 void AppDomain::ReleaseRCWs(LPVOID pCtxCookie)
7883 {
7884     WRAPPER_NO_CONTRACT;
7885     if (m_pRCWCache)
7886         m_pRCWCache->ReleaseWrappersWorker(pCtxCookie);
7887
7888     RemoveWinRTFactoryObjects(pCtxCookie);
7889 }
7890
7891 void AppDomain::DetachRCWs()
7892 {
7893     WRAPPER_NO_CONTRACT;
7894     if (m_pRCWCache)
7895         m_pRCWCache->DetachWrappersWorker();
7896 }
7897
7898 #endif // FEATURE_COMINTEROP
7899
7900 BOOL AppDomain::CanThreadEnter(Thread *pThread)
7901 {
7902     WRAPPER_NO_CONTRACT;
7903
7904     if (m_Stage < STAGE_EXITED)
7905         return TRUE;
7906
7907     if (pThread == SystemDomain::System()->GetUnloadingThread())
7908         return m_Stage < STAGE_FINALIZING;
7909     if (pThread == FinalizerThread::GetFinalizerThread())
7910         return m_Stage < STAGE_FINALIZED;
7911
7912     return FALSE;
7913 }
7914
7915 void AppDomain::AllowThreadEntrance(AppDomain * pApp)
7916 {
7917     CONTRACTL
7918     {
7919         NOTHROW;
7920         GC_TRIGGERS;
7921         MODE_ANY;
7922         FORBID_FAULT;
7923         PRECONDITION(CheckPointer(pApp));
7924     }
7925     CONTRACTL_END;
7926
7927     if (pApp->GetUnloadRequestThread() == NULL)
7928     {
7929         // This is asynchonous unload, either by a host, or by AppDomain.Unload from AD unload event.
7930         if (!pApp->IsUnloadingFromUnloadEvent())
7931         {
7932             pApp->SetStage(STAGE_UNLOAD_REQUESTED);
7933             pApp->EnableADUnloadWorker(
7934                  pApp->IsRudeUnload()?EEPolicy::ADU_Rude:EEPolicy::ADU_Safe);
7935             return;
7936         }
7937     }
7938
7939     SystemDomain::LockHolder lh; // we don't want to reopen appdomain if other thread can be preparing to unload it
7940
7941 #ifdef FEATURE_COMINTEROP
7942     if (pApp->m_pComCallWrapperCache)
7943         pApp->m_pComCallWrapperCache->ResetDomainIsUnloading();
7944 #endif // FEATURE_COMINTEROP
7945
7946     pApp->SetStage(STAGE_OPEN);
7947 }
7948
7949 void AppDomain::RestrictThreadEntrance(AppDomain * pApp)
7950 {
7951     CONTRACTL
7952     {
7953         DISABLED(NOTHROW);
7954         DISABLED(GC_TRIGGERS);
7955         MODE_ANY;
7956         DISABLED(FORBID_FAULT);
7957         PRECONDITION(CheckPointer(pApp));
7958     }
7959     CONTRACTL_END;
7960
7961 #ifdef FEATURE_COMINTEROP
7962     // Set the flag on our CCW cache so stubs won't enter
7963     if (pApp->m_pComCallWrapperCache)
7964         pApp->m_pComCallWrapperCache->SetDomainIsUnloading();
7965 #endif // FEATURE_COMINTEROP
7966
7967     SystemDomain::LockHolder lh; // we don't want to reopen appdomain if other thread can be preparing to unload it
7968     // Release our ID so remoting and thread pool won't enter
7969     pApp->SetStage(STAGE_EXITED);
7970 };
7971
7972 void AppDomain::Exit(BOOL fRunFinalizers, BOOL fAsyncExit)
7973 {
7974     CONTRACTL
7975     {
7976         THROWS;
7977         GC_TRIGGERS;
7978         MODE_COOPERATIVE;
7979     }
7980     CONTRACTL_END;
7981
7982     LOG((LF_APPDOMAIN | LF_CORDB, LL_INFO10, "AppDomain::Exiting domain [%d] %#08x %ls\n",
7983          GetId().m_dwId, this, GetFriendlyNameForLogging()));
7984
7985     RestrictEnterHolder RestrictEnter(this);
7986
7987     {
7988         SystemDomain::LockHolder lh; // we don't want to close appdomain if other thread can be preparing to unload it
7989         SetStage(STAGE_EXITING);  // Note that we're trying to exit
7990     }
7991
7992     // Raise the event indicating the domain is being unloaded.
7993     if (GetDefaultContext())
7994     {
7995         FastInterlockExchangePointer(&s_pAppDomainToRaiseUnloadEvent, this);
7996
7997         DWORD timeout = GetEEPolicy()->GetTimeout(m_fRudeUnload?OPR_AppDomainRudeUnload : OPR_AppDomainUnload);
7998         //if (timeout == INFINITE)
7999         //{
8000         //    timeout = 20000; // 20 seconds
8001         //}
8002         DWORD timeoutForFinalizer = GetEEPolicy()->GetTimeout(OPR_FinalizerRun);
8003         ULONGLONG curTime = CLRGetTickCount64();
8004         ULONGLONG endTime = 0;
8005         if (timeout != INFINITE)
8006         {
8007             endTime = curTime + timeout;
8008             // We will try to kill AD unload event if it takes too long, and then we move on to the next registered caller.
8009             timeout /= 5;
8010         }
8011
8012         while (s_pAppDomainToRaiseUnloadEvent != NULL)
8013         {
8014             FinalizerThread::FinalizerThreadWait(s_fProcessUnloadDomainEvent?timeout:timeoutForFinalizer);
8015             if (endTime != 0 && s_pAppDomainToRaiseUnloadEvent != NULL)
8016             {
8017                 if (CLRGetTickCount64() >= endTime)
8018                 {
8019                     SString sThreadId;
8020                     sThreadId.Printf(W("%x"), FinalizerThread::GetFinalizerThread()->GetThreadId());
8021                     COMPlusThrow(kCannotUnloadAppDomainException,
8022                                  IDS_EE_ADUNLOAD_CANT_UNWIND_THREAD,
8023                                  sThreadId);
8024                 }
8025             }
8026         }
8027     }
8028
8029     // Tell the tiered compilation manager to stop initiating any new work for background
8030     // jit optimization. Its possible the standard thread unwind mechanisms would pre-emptively
8031     // evacuate the jit threadpool worker threads from the domain on their own, but I see no reason 
8032     // to take the risk of relying on them when we can easily augment with a cooperative 
8033     // shutdown check. This notification only initiates the process of evacuating the threads
8034     // and then the UnwindThreads() call below is where blocking will occur to ensure the threads 
8035     // have exited the domain.
8036     //
8037 #ifdef FEATURE_TIERED_COMPILATION
8038     m_tieredCompilationManager.Shutdown(FALSE);
8039 #endif
8040
8041     //
8042     // Set up blocks so no threads can enter except for the finalizer and the thread
8043     // doing the unload.
8044     //
8045
8046     RestrictThreadEntrance(this);
8047
8048     // Cause existing threads to abort out of this domain.  This should ensure all
8049     // normal threads are outside the domain, and we've already ensured that no new threads
8050     // can enter.
8051
8052     PerAppDomainTPCountList::AppDomainUnloadingHolder tpAdUnloadHolder(GetTPIndex());
8053
8054
8055     if (!NingenEnabled())
8056     {
8057         UnwindThreads();
8058     }
8059     
8060     TESTHOOKCALL(UnwoundThreads(GetId().m_dwId)) ;    
8061     ProcessEventForHost(Event_DomainUnload, (PVOID)(UINT_PTR)GetId().m_dwId);
8062
8063     RestrictEnter.SuppressRelease(); //after this point we don't guarantee appdomain consistency
8064 #ifdef PROFILING_SUPPORTED
8065     // Signal profile if present.
8066     {
8067         BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
8068         GCX_PREEMP();
8069         g_profControlBlock.pProfInterface->AppDomainShutdownStarted((AppDomainID) this);
8070         END_PIN_PROFILER();
8071     }
8072 #endif // PROFILING_SUPPORTED
8073     COUNTER_ONLY(GetPerfCounters().m_Loading.cAppDomains--);
8074     COUNTER_ONLY(GetPerfCounters().m_Loading.cAppDomainsUnloaded++);
8075
8076     LOG((LF_APPDOMAIN | LF_CORDB, LL_INFO10, "AppDomain::Domain [%d] %#08x %ls is exited.\n",
8077          GetId().m_dwId, this, GetFriendlyNameForLogging()));
8078
8079     // Send ETW events for this domain's unload and potentially iterate through this
8080     // domain's modules & assemblies to send events for their unloads as well.  This
8081     // needs to occur before STAGE_FINALIZED (to ensure everything is there), so we do
8082     // this before any finalization occurs at all.
8083     ETW::LoaderLog::DomainUnload(this);
8084
8085     CodeVersionManager::OnAppDomainExit(this);
8086
8087     //
8088     // Spin running finalizers until we flush them all.  We need to make multiple passes
8089     // in case the finalizers create more finalizable objects.  This is important to clear
8090     // the finalizable objects as roots, as well as to actually execute the finalizers. This
8091     // will only finalize instances instances of types that aren't potentially agile becuase we can't
8092     // risk finalizing agile objects. So we will be left with instances of potentially agile types
8093     // in handles or statics.
8094     //
8095     // <TODO>@todo: Need to ensure this will terminate in a reasonable amount of time.  Eventually
8096     // we should probably start passing FALSE for fRunFinalizers. Also I'm not sure we
8097     // guarantee that FinalizerThreadWait will ever terminate in general.</TODO>
8098     //
8099
8100     SetStage(STAGE_FINALIZING);
8101
8102     // Flush finalizers now.
8103     FinalizerThread::UnloadAppDomain(this, fRunFinalizers);
8104     
8105     DWORD timeout = GetEEPolicy()->GetTimeout(m_fRudeUnload?OPR_AppDomainRudeUnload : OPR_AppDomainUnload);
8106     ULONGLONG startTime = CLRGetTickCount64();
8107     ULONGLONG elapsedTime = 0;
8108     DWORD finalizerWait = 0;
8109
8110     while (FinalizerThread::GetUnloadingAppDomain() != NULL)
8111     {
8112
8113         if (timeout != INFINITE)
8114         {
8115             elapsedTime = CLRGetTickCount64() - startTime;
8116         }
8117         if (timeout > elapsedTime)
8118         {
8119             finalizerWait = timeout - static_cast<DWORD>(elapsedTime);
8120         }
8121         FinalizerThread::FinalizerThreadWait(finalizerWait); //will set stage to finalized
8122         if (timeout != INFINITE && FinalizerThread::GetUnloadingAppDomain() != NULL)
8123         {
8124             elapsedTime = CLRGetTickCount64() - startTime;
8125             if (timeout <= elapsedTime)
8126             {
8127                 SetRudeUnload();
8128                 // TODO: Consider escalation from RudeAppDomain
8129                 timeout = INFINITE;
8130             }
8131         }
8132     }
8133
8134     tpAdUnloadHolder.SuppressRelease();
8135     PerAppDomainTPCountList::ResetAppDomainTPCounts(GetTPIndex());
8136
8137     LOG((LF_APPDOMAIN | LF_CORDB, LL_INFO10, "AppDomain::Domain [%d] %#08x %ls is finalized.\n",
8138          GetId().m_dwId, this, GetFriendlyNameForLogging()));
8139
8140
8141     AppDomainRefHolder This(this);
8142     AddRef();           // Hold a reference so CloseDomain won't delete us yet
8143     CloseDomain();      // Remove ourself from the list of app domains
8144
8145     // This needs to be done prior to destroying the handle tables below.
8146     ReleaseDomainBoundInfo();
8147
8148     //
8149     // It should be impossible to run non-mscorlib code in this domain now.
8150     // Cleanup all of our roots except the handles. We do this to allow as many
8151     // finalizers as possible to run correctly. If we delete the handles, they
8152     // can't run.
8153     //
8154     if (!NingenEnabled())
8155     {
8156     }
8157
8158     ClearGCRoots();
8159     ClearGCHandles();
8160
8161     LOG((LF_APPDOMAIN | LF_CORDB, LL_INFO10, "AppDomain::Domain [%d] %#08x %ls is cleared.\n",
8162          GetId().m_dwId, this, GetFriendlyNameForLogging()));
8163
8164     if (fAsyncExit && fRunFinalizers)
8165     {
8166         GCX_PREEMP();
8167         m_AssemblyCache.Clear();
8168         ClearFusionContext();
8169         ReleaseFiles();
8170         if (!NingenEnabled())
8171         {
8172             AddMemoryPressure();
8173         }
8174     }
8175     SystemDomain::System()->AddToDelayedUnloadList(this, fAsyncExit);
8176     SystemDomain::SetUnloadDomainCleared();
8177     if (m_dwId.m_dwId!=0)
8178         SystemDomain::ReleaseAppDomainId(m_dwId);
8179 #ifdef PROFILING_SUPPORTED
8180     // Always signal profile if present, even when failed.
8181     {
8182         BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads());
8183         GCX_PREEMP();
8184         g_profControlBlock.pProfInterface->AppDomainShutdownFinished((AppDomainID) this, S_OK);
8185         END_PIN_PROFILER();
8186     }
8187 #endif // PROFILING_SUPPORTED
8188
8189 }
8190
8191 void AppDomain::Close()
8192 {
8193     CONTRACTL
8194     {
8195         GC_TRIGGERS;
8196         NOTHROW;
8197     }
8198     CONTRACTL_END;
8199
8200     LOG((LF_APPDOMAIN | LF_CORDB, LL_INFO10, "AppDomain::Domain [%d] %#08x %ls is collected.\n",
8201          GetId().m_dwId, this, GetFriendlyNameForLogging()));
8202
8203
8204 #if CHECK_APP_DOMAIN_LEAKS
8205     if (g_pConfig->AppDomainLeaks())
8206         // at this point shouldn't have any non-agile objects in the heap because we finalized all the non-agile ones.
8207         SyncBlockCache::GetSyncBlockCache()->CheckForUnloadedInstances(GetIndex());
8208 #endif // CHECK_APP_DOMAIN_LEAKS
8209     {
8210         GCX_PREEMP();
8211         RemoveMemoryPressure();
8212     }
8213     _ASSERTE(m_cRef>0); //should be alive at this point otherwise iterator can revive us and crash
8214     {
8215         SystemDomain::LockHolder lh;    // Avoid races with AppDomainIterator
8216         SetStage(STAGE_CLOSED);
8217     }
8218
8219     // CONSIDER: move releasing remoting cache from managed code to here.
8220 }
8221
8222
8223 void AppDomain::ResetUnloadRequestThread(ADID Id)
8224 {
8225     CONTRACTL
8226     {
8227         NOTHROW;
8228         MODE_ANY;
8229         PRECONDITION(!IsADUnloadHelperThread());
8230     }
8231     CONTRACTL_END;
8232
8233     GCX_COOP();
8234     AppDomainFromIDHolder ad(Id, TRUE);
8235     if(!ad.IsUnloaded() && ad->m_Stage < STAGE_UNLOAD_REQUESTED)
8236     {
8237         Thread *pThread = ad->GetUnloadRequestThread();
8238         if(pThread==GetThread())
8239         {
8240             ad->m_dwThreadsStillInAppDomain=(ULONG)-1;
8241
8242             if(pThread)
8243             {
8244                 if (pThread->GetUnloadBoundaryFrame() && pThread->IsBeingAbortedForADUnload())
8245                 {
8246                     pThread->UnmarkThreadForAbort(Thread::TAR_ADUnload);
8247                 }
8248                 ad->GetUnloadRequestThread()->ResetUnloadBoundaryFrame();
8249                 pThread->ResetBeginAbortedForADUnload();
8250             }
8251             
8252             ad->SetUnloadRequestThread(NULL);
8253         }
8254     }
8255 }
8256
8257
8258 int g_fADUnloadWorkerOK = -1;
8259
8260 HRESULT AppDomain::UnloadById(ADID dwId, BOOL fSync,BOOL fExceptionsPassThrough)
8261 {
8262     CONTRACTL
8263     {
8264         if(fExceptionsPassThrough) {THROWS;} else {NOTHROW;}
8265         MODE_ANY;
8266         if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_TRIGGERS);}
8267         FORBID_FAULT;
8268     }
8269     CONTRACTL_END;
8270
8271     if (dwId==(ADID)DefaultADID)
8272         return COR_E_CANNOTUNLOADAPPDOMAIN;
8273
8274     Thread *pThread = GetThread();
8275
8276     // Finalizer thread can not wait until AD unload is done,
8277     // because AD unload is going to wait for Finalizer Thread.
8278     if (fSync && pThread == FinalizerThread::GetFinalizerThread() && 
8279         !pThread->HasThreadStateNC(Thread::TSNC_RaiseUnloadEvent))
8280         return COR_E_CANNOTUNLOADAPPDOMAIN;
8281
8282
8283     // AD unload helper thread should have been created.
8284     _ASSERTE (g_fADUnloadWorkerOK == 1);
8285
8286     _ASSERTE (!IsADUnloadHelperThread());
8287
8288     BOOL fIsRaisingUnloadEvent = (pThread != NULL && pThread->HasThreadStateNC(Thread::TSNC_RaiseUnloadEvent));
8289
8290     if (fIsRaisingUnloadEvent)
8291     {
8292         AppDomainFromIDHolder pApp(dwId, TRUE, AppDomainFromIDHolder::SyncType_GC);
8293
8294         if (pApp.IsUnloaded() || ! pApp->CanLoadCode() || pApp->GetId().m_dwId == 0)
8295             return COR_E_APPDOMAINUNLOADED;
8296
8297         pApp->EnableADUnloadWorker();
8298
8299         return S_FALSE;
8300     }
8301
8302
8303     ADUnloadSinkHolder pSink;
8304
8305     {
8306         SystemDomain::LockHolder ulh;
8307
8308         AppDomainFromIDHolder pApp(dwId, TRUE, AppDomainFromIDHolder::SyncType_ADLock);
8309
8310         if (pApp.IsUnloaded() || ! pApp->CanLoadCode() || pApp->GetId().m_dwId == 0)
8311             return COR_E_APPDOMAINUNLOADED;
8312
8313         if (g_fADUnloadWorkerOK != 1)
8314         {
8315             _ASSERTE(FALSE);
8316             return E_UNEXPECTED;
8317         }
8318
8319         if (!fSync)
8320         {
8321             pApp->EnableADUnloadWorker();
8322             return S_OK;
8323         }
8324
8325         pSink = pApp->PrepareForWaitUnloadCompletion();
8326
8327         pApp->EnableADUnloadWorker();
8328
8329         // release the holders - we don't care anymore if the appdomain is gone
8330     }
8331
8332 #ifdef FEATURE_TESTHOOKS        
8333     if (fExceptionsPassThrough)
8334     {
8335         CONTRACT_VIOLATION(FaultViolation);
8336         return UnloadWaitNoCatch(dwId,pSink);
8337     }
8338 #endif            
8339
8340     return UnloadWait(dwId,pSink);
8341 }
8342
8343 HRESULT AppDomain::UnloadWait(ADID Id, ADUnloadSink * pSink)
8344 {
8345     CONTRACTL
8346     {
8347         NOTHROW;
8348         MODE_ANY;
8349         if (GetThread()) {GC_TRIGGERS;} else {DISABLED(GC_TRIGGERS);}
8350     }
8351     CONTRACTL_END;
8352     
8353     HRESULT hr=S_OK;
8354     EX_TRY
8355     {
8356         // IF you ever try to change this to something not using events, please address the fact that
8357         // AppDomain::StopEEAndUnwindThreads relies on that events are used.
8358
8359         pSink->WaitUnloadCompletion();
8360     }
8361     EX_CATCH_HRESULT(hr);
8362
8363     if (SUCCEEDED(hr))
8364         hr=pSink->GetUnloadResult();
8365
8366     if (FAILED(hr))
8367     {
8368         ResetUnloadRequestThread(Id);
8369     }
8370     return hr;
8371 }
8372
8373 #ifdef FEATURE_TESTHOOKS        
8374 HRESULT AppDomain::UnloadWaitNoCatch(ADID Id, ADUnloadSink * pSink)
8375 {
8376     STATIC_CONTRACT_THROWS;
8377     STATIC_CONTRACT_MODE_ANY;    
8378
8379     Holder<ADID, DoNothing<ADID>, AppDomain::ResetUnloadRequestThread> resetUnloadHolder(Id);
8380
8381     // IF you ever try to change this to something not using events, please address the fact that
8382     // AppDomain::StopEEAndUnwindThreads relies on that events are used.
8383     pSink->WaitUnloadCompletion();
8384
8385     HRESULT hr = pSink->GetUnloadResult();
8386
8387     if (SUCCEEDED(hr))
8388         resetUnloadHolder.SuppressRelease();
8389
8390     return hr;
8391 }
8392 #endif
8393
8394 void AppDomain::Unload(BOOL fForceUnload)
8395 {
8396     CONTRACTL
8397     {
8398         THROWS;
8399         MODE_COOPERATIVE;
8400         GC_TRIGGERS;
8401         INJECT_FAULT(COMPlusThrowOM(););
8402     }
8403     CONTRACTL_END;
8404
8405 #ifdef FEATURE_MULTICOREJIT
8406
8407     // Avoid profiling file is partially written in ASP.net scenarios, call it earlier
8408     GetMulticoreJitManager().StopProfile(true);
8409
8410 #endif
8411
8412     Thread *pThread = GetThread();
8413
8414
8415     if (! fForceUnload && !g_pConfig->AppDomainUnload())
8416         return;
8417
8418     EPolicyAction action;
8419     EClrOperation operation;
8420     if (!IsRudeUnload())
8421     {
8422         operation = OPR_AppDomainUnload;
8423     }
8424     else
8425     {
8426         operation = OPR_AppDomainRudeUnload;
8427     }
8428     action = GetEEPolicy()->GetDefaultAction(operation,NULL);
8429     GetEEPolicy()->NotifyHostOnDefaultAction(operation,action);
8430
8431     switch (action)
8432     {
8433     case eUnloadAppDomain:
8434         break;
8435     case eRudeUnloadAppDomain:
8436         SetRudeUnload();
8437         break;
8438     case eExitProcess:
8439     case eFastExitProcess:
8440     case eRudeExitProcess:
8441     case eDisableRuntime:
8442         EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_ADUNLOAD);
8443         _ASSERTE (!"Should not get here");
8444         break;
8445     default:
8446         break;
8447     }
8448
8449 #if (defined(_DEBUG) || defined(BREAK_ON_UNLOAD) || defined(AD_LOG_MEMORY) || defined(AD_SNAPSHOT))
8450     static int unloadCount = 0;
8451 #endif
8452
8453 #ifdef AD_LOG_MEMORY
8454     {
8455         GCX_PREEMP();
8456         static int logMemory = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADLogMemory);
8457         typedef void (__cdecl *LogItFcn) ( int );
8458         static LogItFcn pLogIt = NULL;
8459
8460         if (logMemory && ! pLogIt)
8461         {
8462             HMODULE hMod = CLRLoadLibrary(W("mpdh.dll"));
8463             if (hMod)
8464             {
8465                 pLogIt = (LogItFcn)GetProcAddress(hMod, "logIt");
8466                 if (pLogIt)
8467                 {
8468                     pLogIt(9999);
8469                     pLogIt(9999);
8470                 }
8471             }
8472         }
8473     }
8474 #endif // AD_LOG_MEMORY
8475
8476     if (IsDefaultDomain() && !IsSingleAppDomain())
8477         COMPlusThrow(kCannotUnloadAppDomainException, IDS_EE_ADUNLOAD_DEFAULT);
8478
8479     _ASSERTE(CanUnload());
8480
8481     if (pThread == FinalizerThread::GetFinalizerThread() || GetUnloadRequestThread() == FinalizerThread::GetFinalizerThread())
8482         COMPlusThrow(kCannotUnloadAppDomainException, IDS_EE_ADUNLOAD_IN_FINALIZER);
8483
8484     _ASSERTE(! SystemDomain::AppDomainBeingUnloaded());
8485
8486     // should not be running in this AD because unload spawned thread in default domain
8487     if (!NingenEnabled())
8488     {
8489         _ASSERTE(!pThread->IsRunningIn(this, NULL));
8490     }
8491
8492
8493 #ifdef APPDOMAIN_STATE
8494     _ASSERTE_ALL_BUILDS("clr/src/VM/AppDomain.cpp", pThread->GetDomain()->IsDefaultDomain());
8495 #endif
8496
8497     LOG((LF_APPDOMAIN | LF_CORDB, LL_INFO10, "AppDomain::Unloading domain [%d] %#08x %ls\n", GetId().m_dwId, this, GetFriendlyName()));
8498
8499     STRESS_LOG3 (LF_APPDOMAIN, LL_INFO100, "Unload domain [%d, %d] %p\n", GetId().m_dwId, GetIndex().m_dwIndex, this);
8500
8501     UnloadHolder hold(this);
8502
8503     SystemDomain::System()->SetUnloadRequestingThread(GetUnloadRequestThread());
8504     SystemDomain::System()->SetUnloadingThread(pThread);
8505
8506
8507 #ifdef _DEBUG
8508     static int dumpSB = -1;
8509
8510     if (dumpSB == -1)
8511         dumpSB = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADDumpSB);
8512
8513     if (dumpSB > 1)
8514     {
8515         LogSpewAlways("Starting unload %3.3d\n", unloadCount);
8516         DumpSyncBlockCache();
8517     }
8518 #endif // _DEBUG
8519
8520     BOOL bForceGC=m_bForceGCOnUnload;
8521
8522 #ifdef AD_LOG_MEMORY
8523     if (pLogIt)
8524         bForceGC=TRUE;
8525 #endif // AD_LOG_MEMORY
8526
8527 #ifdef AD_SNAPSHOT
8528     static int takeSnapShot = -1;
8529
8530     if (takeSnapShot == -1)
8531         takeSnapShot = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADTakeSnapShot);
8532
8533     if (takeSnapShot)
8534         bForceGC=TRUE;
8535 #endif // AD_SNAPSHOT
8536
8537 #ifdef _DEBUG
8538     if (dumpSB > 0)
8539         bForceGC=TRUE;
8540 #endif // _DEBUG
8541     static int cfgForceGC = -1;
8542
8543     if (cfgForceGC == -1)
8544         cfgForceGC =!CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_ADULazyMemoryRelease);
8545
8546     bForceGC=bForceGC||cfgForceGC;
8547     AppDomainRefHolder This(this);
8548     AddRef();
8549
8550     // Do the actual unloading
8551     {
8552         // We do not want other threads to abort the current one.
8553         ThreadPreventAsyncHolder preventAsync;
8554         Exit(TRUE, !bForceGC);
8555     }
8556     if(bForceGC)
8557     {
8558         GCHeapUtilities::GetGCHeap()->GarbageCollect();
8559         FinalizerThread::FinalizerThreadWait();
8560         SetStage(STAGE_COLLECTED);
8561         Close(); //NOTHROW!
8562     }
8563
8564 #ifdef AD_LOG_MEMORY
8565     if (pLogIt)
8566     {
8567         GCX_PREEMP();
8568         pLogIt(unloadCount);
8569     }
8570 #endif // AD_LOG_MEMORY
8571
8572 #ifdef AD_SNAPSHOT
8573     if (takeSnapShot)
8574     {
8575         char buffer[1024];
8576         sprintf_s(buffer, _countof(buffer), "vadump -p %d -o > vadump.%d", GetCurrentProcessId(), unloadCount);
8577         system(buffer);
8578         sprintf_s(buffer, _countof(buffer), "umdh -p:%d -d -i:1 -f:umdh.%d", GetCurrentProcessId(), unloadCount);
8579         system(buffer);
8580         int takeDHSnapShot = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADTakeDHSnapShot);
8581         if (takeDHSnapShot)
8582         {
8583             sprintf_s(buffer, _countof(buffer), "dh -p %d -s -g -h -b -f dh.%d", GetCurrentProcessId(), unloadCount);
8584             system(buffer);
8585         }
8586     }
8587 #endif // AD_SNAPSHOT
8588
8589 #ifdef _DEBUG
8590     if (dumpSB > 0)
8591     {
8592         // do extra finalizer wait to remove any leftover sb entries
8593         FinalizerThread::FinalizerThreadWait();
8594         GCHeapUtilities::GetGCHeap()->GarbageCollect();
8595         FinalizerThread::FinalizerThreadWait();
8596         LogSpewAlways("Done unload %3.3d\n", unloadCount);
8597         DumpSyncBlockCache();
8598         ShutdownLogging();
8599         WCHAR buffer[128];
8600         swprintf_s(buffer, NumItems(buffer), W("DumpSB.%d"), unloadCount);
8601         _ASSERTE(WszMoveFileEx(W("COMPLUS.LOG"), buffer, MOVEFILE_REPLACE_EXISTING));
8602         // this will open a new file
8603         InitLogging();
8604     }
8605 #endif // _DEBUG
8606 }
8607
8608 void AppDomain::ExceptionUnwind(Frame *pFrame)
8609 {
8610     CONTRACTL
8611     {
8612         DISABLED(GC_TRIGGERS);  // EEResourceException
8613         DISABLED(THROWS);   // EEResourceException
8614         MODE_ANY;
8615     }
8616     CONTRACTL_END;
8617
8618     LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::ExceptionUnwind for %8.8x\n", pFrame));
8619 #if _DEBUG_ADUNLOAD
8620     printf("%x AppDomain::ExceptionUnwind for %8.8p\n", GetThread()->GetThreadId(), pFrame);
8621 #endif
8622     Thread *pThread = GetThread();
8623     _ASSERTE(pThread);
8624
8625     if (! pThread->ShouldChangeAbortToUnload(pFrame))
8626     {
8627         LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::ExceptionUnwind: not first transition or abort\n"));
8628         return;
8629     }
8630
8631     LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::ExceptionUnwind: changing to unload\n"));
8632
8633     GCX_COOP();
8634     OBJECTREF throwable = NULL;
8635     EEResourceException e(kAppDomainUnloadedException, W("Remoting_AppDomainUnloaded_ThreadUnwound"));
8636     throwable = e.GetThrowable();
8637
8638     // reset the exception to an AppDomainUnloadedException
8639     if (throwable != NULL)
8640     {
8641         GetThread()->SafeSetThrowables(throwable);
8642     }
8643 }
8644
8645 BOOL AppDomain::StopEEAndUnwindThreads(unsigned int retryCount, BOOL *pFMarkUnloadRequestThread)
8646 {
8647     CONTRACTL
8648     {
8649         THROWS;
8650         GC_TRIGGERS;
8651         MODE_ANY;
8652         SO_INTOLERANT;
8653     }
8654     CONTRACTL_END;
8655
8656     Thread *pThread = NULL;
8657     DWORD nThreadsNeedMoreWork=0;
8658     if (retryCount != (unsigned int)-1 && retryCount < g_pConfig->AppDomainUnloadRetryCount())
8659     {
8660         Thread *pCurThread = GetThread();
8661         if (pCurThread->CatchAtSafePoint())
8662             pCurThread->PulseGCMode();
8663
8664         {
8665             // We know which thread is not in the domain now.  We just need to
8666             // work on those threads.  We do not need to suspend the runtime.
8667             ThreadStoreLockHolder tsl;
8668
8669             while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
8670             {
8671                 if (pThread == pCurThread)
8672                 {
8673                     continue;
8674                 }
8675
8676                 if (pThread == FinalizerThread::GetFinalizerThread())
8677                 {
8678                     continue;
8679                 }
8680
8681                 if (pThread->GetUnloadBoundaryFrame() == NULL)
8682                 {
8683                     continue;
8684                 }
8685
8686                 // A thread may have UnloadBoundaryFrame set if
8687                 // 1. Being unloaded by AD unload helper thread
8688                 // 2. Escalation from OOM or SO triggers AD unload
8689                 // Here we only need to work on threads that are in the domain.  If we work on other threads,
8690                 // those threads may be stucked in a finally, and we will not be able to escalate for them,
8691                 // therefore AD unload is blocked.
8692                 if (pThread->IsBeingAbortedForADUnload() ||
8693                     pThread == SystemDomain::System()->GetUnloadRequestingThread())
8694                 {
8695                     nThreadsNeedMoreWork++;
8696                 }
8697
8698                 if (!(IsRudeUnload() ||
8699                       (pThread != SystemDomain::System()->GetUnloadRequestingThread() || OnlyOneThreadLeft())))
8700                 {
8701                     continue;
8702                 }
8703
8704                 if ((pThread == SystemDomain::System()->GetUnloadRequestingThread()) && *pFMarkUnloadRequestThread)
8705                 {
8706                     // Mark thread for abortion only once; later on interrupt only
8707                     *pFMarkUnloadRequestThread = FALSE;
8708                     pThread->SetAbortRequest(m_fRudeUnload? EEPolicy::TA_Rude : EEPolicy::TA_V1Compatible);
8709                 }
8710                 else
8711                 {
8712                     if (pThread->m_State & Thread::TS_Interruptible)
8713                     {
8714                         pThread->UserInterrupt(Thread::TI_Abort);
8715                     }
8716                 }
8717
8718                 if (pThread->PreemptiveGCDisabledOther())
8719                 {
8720         #if defined(FEATURE_HIJACK) && !defined(PLATFORM_UNIX)
8721                     Thread::SuspendThreadResult str = pThread->SuspendThread();
8722                     if (str == Thread::STR_Success)
8723                     {
8724                         if (pThread->PreemptiveGCDisabledOther() &&
8725                             (!pThread->IsAbortInitiated() || pThread->IsRudeAbort()))
8726                         {
8727                             pThread->HandleJITCaseForAbort();
8728                         }
8729                         pThread->ResumeThread();
8730                     }
8731         #endif
8732                 }
8733             }
8734         } // ThreadStoreLockHolder
8735
8736         m_dwThreadsStillInAppDomain=nThreadsNeedMoreWork;
8737         return !nThreadsNeedMoreWork;
8738     }
8739
8740     // For now piggyback on the GC's suspend EE mechanism
8741     ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_APPDOMAIN_SHUTDOWN);
8742 #ifdef _DEBUG
8743     // <TODO>@todo: what to do with any threads that didn't stop?</TODO>
8744     _ASSERTE(ThreadStore::s_pThreadStore->DbgBackgroundThreadCount() > 0);
8745 #endif // _DEBUG
8746
8747     int totalADCount = 0;
8748     int finalizerADCount = 0;
8749     pThread = NULL;
8750
8751     RuntimeExceptionKind reKind = kLastException;
8752     UINT resId = 0;
8753     SmallStackSString ssThreadId;
8754
8755     while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
8756     {
8757         // we already checked that we're not running in the unload domain
8758         if (pThread == GetThread())
8759         {
8760             continue;
8761         }
8762
8763 #ifdef _DEBUG
8764         void PrintStackTraceWithADToLog(Thread *pThread);
8765         if (LoggingOn(LF_APPDOMAIN, LL_INFO100)) {
8766             LOG((LF_APPDOMAIN, LL_INFO100, "\nStackTrace for %x\n", pThread->GetThreadId()));
8767             PrintStackTraceWithADToLog(pThread);
8768         }
8769 #endif // _DEBUG
8770         int count = 0;
8771         Frame *pFrame = pThread->GetFirstTransitionInto(this, &count);
8772         if (! pFrame) {
8773             _ASSERTE(count == 0);
8774             if (pThread->IsBeingAbortedForADUnload())
8775             {
8776                 pThread->ResetBeginAbortedForADUnload();
8777             }
8778             continue;
8779         }
8780
8781         if (pThread != FinalizerThread::GetFinalizerThread())
8782         {
8783             totalADCount += count;
8784             nThreadsNeedMoreWork++;
8785             pThread->SetUnloadBoundaryFrame(pFrame);
8786         }
8787         else
8788         {
8789             finalizerADCount = count;
8790         }
8791
8792         // don't setup the exception info for the unloading thread unless it's the last one in
8793         if (retryCount != ((unsigned int) -1) && retryCount > g_pConfig->AppDomainUnloadRetryCount() && reKind == kLastException &&
8794             (pThread != SystemDomain::System()->GetUnloadRequestingThread() || OnlyOneThreadLeft()))
8795         {
8796 #ifdef AD_BREAK_ON_CANNOT_UNLOAD
8797             static int breakOnCannotUnload = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ADBreakOnCannotUnload);
8798             if (breakOnCannotUnload)
8799                 _ASSERTE(!"Cannot unload AD");
8800 #endif // AD_BREAK_ON_CANNOT_UNLOAD
8801             reKind = kCannotUnloadAppDomainException;
8802             resId = IDS_EE_ADUNLOAD_CANT_UNWIND_THREAD;
8803             ssThreadId.Printf(W("%x"), pThread->GetThreadId());
8804             STRESS_LOG2(LF_APPDOMAIN, LL_INFO10, "AppDomain::UnwindThreads cannot stop thread %x with %d transitions\n", pThread->GetThreadId(), count);
8805             // don't break out of this early or the assert totalADCount == (int)m_dwThreadEnterCount below will fire
8806             // it's better to chew a little extra time here and make sure our counts are consistent
8807         }
8808         // only abort the thread requesting the unload if it's the last one in, that way it will get
8809         // notification that the unload failed for some other thread not being aborted. And don't abort
8810         // the finalizer thread - let it finish it's work as it's allowed to be in there. If it won't finish,
8811         // then we will eventually get a CannotUnloadException on it.
8812
8813         if (pThread != FinalizerThread::GetFinalizerThread() &&
8814             // If the domain is rudely unloaded, we will unwind the requesting thread out
8815             // Rude unload is going to succeed, or escalated to disable runtime or higher.
8816             (IsRudeUnload() ||
8817              (pThread != SystemDomain::System()->GetUnloadRequestingThread() || OnlyOneThreadLeft())
8818             )
8819            )
8820         {
8821
8822             STRESS_LOG2(LF_APPDOMAIN, LL_INFO100, "AppDomain::UnwindThreads stopping %x with %d transitions\n", pThread->GetThreadId(), count);
8823             LOG((LF_APPDOMAIN, LL_INFO100, "AppDomain::UnwindThreads stopping %x with %d transitions\n", pThread->GetThreadId(), count));
8824 #if _DEBUG_ADUNLOAD
8825             printf("AppDomain::UnwindThreads %x stopping %x with first frame %8.8p\n", GetThread()->GetThreadId(), pThread->GetThreadId(), pFrame);
8826 #endif
8827             if (pThread == SystemDomain::System()->GetUnloadRequestingThread())
8828             {
8829                 // Mark thread for abortion only once; later on interrupt only
8830                 *pFMarkUnloadRequestThread = FALSE;
8831             }
8832             pThread->SetAbortRequest(m_fRudeUnload? EEPolicy::TA_Rude : EEPolicy::TA_V1Compatible);
8833         }
8834         TESTHOOKCALL(UnwindingThreads(GetId().m_dwId)) ;
8835     }
8836     _ASSERTE(totalADCount + finalizerADCount == (int)m_dwThreadEnterCount);
8837
8838     //@TODO: This is intended to catch a stress bug. Remove when no longer needed.
8839     if (totalADCount + finalizerADCount != (int)m_dwThreadEnterCount)
8840         FreeBuildDebugBreak();
8841
8842     // if our count did get messed up, set it to whatever count we actually found in the domain to avoid looping
8843     // or other problems related to incorrect count. This is very much a bug if this happens - a thread should always
8844     // exit the domain gracefully.
8845     // m_dwThreadEnterCount = totalADCount;
8846
8847     if (reKind != kLastException)
8848     {
8849         pThread = NULL;
8850         while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
8851         {
8852             if (pThread->IsBeingAbortedForADUnload())
8853             {
8854                 pThread->ResetBeginAbortedForADUnload();
8855             }
8856         }
8857     }
8858
8859     // CommonTripThread will handle the abort for any threads that we've marked
8860     ThreadSuspend::RestartEE(FALSE, TRUE);
8861     if (reKind != kLastException)
8862         COMPlusThrow(reKind, resId, ssThreadId.GetUnicode());
8863
8864     _ASSERTE((totalADCount==0 && nThreadsNeedMoreWork==0) ||(totalADCount!=0 && nThreadsNeedMoreWork!=0));
8865     
8866     m_dwThreadsStillInAppDomain=nThreadsNeedMoreWork;
8867     return (totalADCount == 0);
8868 }
8869
8870 void AppDomain::UnwindThreads()
8871 {
8872     // This function should guarantee appdomain
8873     // consistency even if it fails. Everything that is going
8874     // to make the appdomain impossible to reenter
8875     // should be factored out
8876
8877     // <TODO>@todo: need real synchronization here!!!</TODO>
8878     CONTRACTL
8879     {
8880         MODE_COOPERATIVE;
8881         THROWS;
8882         GC_TRIGGERS;
8883     }
8884     CONTRACTL_END;
8885
8886     int retryCount = -1;
8887     m_dwThreadsStillInAppDomain=(ULONG)-1;
8888     ULONGLONG startTime = CLRGetTickCount64();
8889
8890     if (GetEEPolicy()->GetDefaultAction(OPR_AppDomainUnload, NULL) == eRudeUnloadAppDomain &&
8891         !IsRudeUnload())
8892     {
8893         GetEEPolicy()->NotifyHostOnDefaultAction(OPR_AppDomainUnload, eRudeUnloadAppDomain);
8894         SetRudeUnload();
8895     }
8896
8897     // Force threads to go through slow path during AD unload.
8898     TSSuspendHolder shTrap;
8899
8900     BOOL fCurrentUnloadMode = IsRudeUnload();
8901     BOOL fMarkUnloadRequestThread = TRUE;
8902
8903     // now wait for all the threads running in our AD to get out
8904     do
8905     {
8906         DWORD timeout = GetEEPolicy()->GetTimeout(m_fRudeUnload?OPR_AppDomainRudeUnload : OPR_AppDomainUnload);
8907         EPolicyAction action = GetEEPolicy()->GetActionOnTimeout(m_fRudeUnload?OPR_AppDomainRudeUnload : OPR_AppDomainUnload, NULL);
8908         if (timeout != INFINITE && action > eUnloadAppDomain) {
8909             // Escalation policy specified.
8910             ULONGLONG curTime = CLRGetTickCount64();
8911             ULONGLONG elapseTime = curTime - startTime;
8912             if (elapseTime > timeout)
8913             {
8914                 // Escalate
8915                 switch (action)
8916                 {
8917                 case eRudeUnloadAppDomain:
8918                     GetEEPolicy()->NotifyHostOnTimeout(m_fRudeUnload?OPR_AppDomainRudeUnload : OPR_AppDomainUnload, action);
8919                     SetRudeUnload();
8920                     STRESS_LOG1(LF_APPDOMAIN, LL_INFO100,"Escalating to RADU, adid=%d",GetId().m_dwId);
8921                     break;
8922                 case eExitProcess:
8923                 case eFastExitProcess:
8924                 case eRudeExitProcess:
8925                 case eDisableRuntime:
8926                     GetEEPolicy()->NotifyHostOnTimeout(m_fRudeUnload?OPR_AppDomainRudeUnload : OPR_AppDomainUnload, action);
8927                     EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_TIMEOUT);
8928                     _ASSERTE (!"Should not reach here");
8929                     break;
8930                 default:
8931                     break;
8932                 }
8933             }
8934         }
8935 #ifdef _DEBUG
8936         if (LoggingOn(LF_APPDOMAIN, LL_INFO100))
8937             DumpADThreadTrack();
8938 #endif // _DEBUG
8939         BOOL fNextUnloadMode = IsRudeUnload();
8940         if (fCurrentUnloadMode != fNextUnloadMode)
8941         {
8942             // We have changed from normal unload to rude unload.  We need to mark the thread
8943             // with RudeAbort, but we can only do this safely if the runtime is suspended.
8944             fCurrentUnloadMode = fNextUnloadMode;
8945             retryCount = -1;
8946         }
8947         if (StopEEAndUnwindThreads(retryCount, &fMarkUnloadRequestThread))
8948             break;
8949         if (timeout != INFINITE)
8950         {
8951             // Turn off the timeout used by AD.
8952             retryCount = 1;
8953         }
8954         else
8955         {
8956             // GCStress takes a long time to unwind, due to expensive creation of
8957             // a threadabort exception.
8958             if (!GCStress<cfg_any>::IsEnabled())
8959                 ++retryCount;
8960             LOG((LF_APPDOMAIN, LL_INFO10, "AppDomain::UnwindThreads iteration %d waiting on thread count %d\n", retryCount, m_dwThreadEnterCount));
8961 #if _DEBUG_ADUNLOAD
8962             printf("AppDomain::UnwindThreads iteration %d waiting on thread count %d\n", retryCount, m_dwThreadEnterCount);
8963 #endif
8964         }
8965
8966         if (m_dwThreadEnterCount != 0)
8967         {
8968 #ifdef _DEBUG
8969             GetThread()->UserSleep(20);
8970 #else // !_DEBUG
8971             GetThread()->UserSleep(10);
8972 #endif // !_DEBUG
8973         }
8974     }
8975     while (TRUE) ;
8976 }
8977
8978 void AppDomain::ClearGCHandles()
8979 {
8980     CONTRACTL
8981     {
8982         GC_TRIGGERS;
8983         MODE_COOPERATIVE;
8984         NOTHROW;
8985     }
8986     CONTRACTL_END;
8987
8988     SetStage(STAGE_HANDLETABLE_NOACCESS);
8989
8990     GCHeapUtilities::GetGCHeap()->WaitUntilConcurrentGCComplete();
8991
8992     // Keep async pin handles alive by moving them to default domain
8993     HandleAsyncPinHandles();
8994
8995     // Remove our handle store as a source of GC roots
8996     m_handleStore->Uproot();
8997 }
8998
8999 // When an AD is unloaded, we will release all objects in this AD.
9000 // If a future asynchronous operation, like io completion port function,
9001 // we need to keep the memory space fixed so that the gc heap is not corrupted.
9002 void AppDomain::HandleAsyncPinHandles()
9003 {
9004     CONTRACTL
9005     {
9006         GC_TRIGGERS;
9007         MODE_COOPERATIVE;
9008         NOTHROW;
9009     }
9010     CONTRACTL_END;
9011
9012     IGCHandleStore *pBucket = m_handleStore;
9013
9014     // IO completion port picks IO job using FIFO.  Here is how we know which AsyncPinHandle can be freed.
9015     // 1. We mark all non-pending AsyncPinHandle with READYTOCLEAN.
9016     // 2. We queue a dump Overlapped to the IO completion as a marker.
9017     // 3. When the Overlapped is picked up by completion port, we wait until all previous IO jobs are processed.
9018     // 4. Then we can delete all AsyncPinHandle marked with READYTOCLEAN.
9019     IGCHandleStore *pBucketInDefault = SystemDomain::System()->DefaultDomain()->m_handleStore;
9020
9021     auto clearIfComplete = [](Object* object)
9022     {
9023         LIMITED_METHOD_CONTRACT;
9024
9025         assert(object != nullptr);
9026         if (object->GetGCSafeMethodTable() != g_pOverlappedDataClass)
9027         {
9028             return;
9029         }
9030
9031         OVERLAPPEDDATAREF overlapped = (OVERLAPPEDDATAREF)(ObjectToOBJECTREF((Object*)object));
9032         if (overlapped->HasCompleted())
9033         {
9034             // IO has finished.  We don't need to pin the user buffer any longer.
9035             overlapped->m_userObject = NULL;
9036         }
9037
9038         BashMTForPinnedObject(ObjectToOBJECTREF(object));
9039     };
9040
9041     auto setHandle = [](Object* object, OBJECTHANDLE handle)
9042     {
9043         LIMITED_METHOD_CONTRACT;
9044
9045         assert(object != nullptr);
9046         assert(handle);
9047
9048         if (object->GetGCSafeMethodTable() != g_pOverlappedDataClass)
9049         {
9050             return;
9051         }
9052
9053         OverlappedDataObject* overlapped = (OverlappedDataObject*)object;
9054         overlapped->m_pinSelf = handle;
9055     };
9056
9057     pBucket->RelocateAsyncPinnedHandles(pBucketInDefault, clearIfComplete, setHandle);
9058
9059     OverlappedDataObject::RequestCleanup();
9060 }
9061
9062 void AppDomain::ClearGCRoots()
9063 {
9064     CONTRACTL
9065     {
9066         GC_TRIGGERS;
9067         MODE_COOPERATIVE;
9068         NOTHROW;
9069     }
9070     CONTRACTL_END;
9071
9072     Thread *pThread = NULL;
9073     ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_APPDOMAIN_SHUTDOWN);
9074
9075     // Tell the JIT managers to delete any entries in their structures. All the cooperative mode threads are stopped at
9076     // this point, so only need to synchronize the preemptive mode threads.
9077     ExecutionManager::Unload(GetLoaderAllocator());
9078
9079     while ((pThread = ThreadStore::GetAllThreadList(pThread, 0, 0)) != NULL)
9080     {
9081         // Delete the thread local static store
9082         pThread->DeleteThreadStaticData(this);
9083
9084         // <TODO>@TODO: A pre-allocated AppDomainUnloaded exception might be better.</TODO>
9085         if (m_handleStore->ContainsHandle(pThread->m_LastThrownObjectHandle))
9086         {
9087             // Never delete a handle to a preallocated exception object.
9088             if (!CLRException::IsPreallocatedExceptionHandle(pThread->m_LastThrownObjectHandle))
9089             {
9090                 DestroyHandle(pThread->m_LastThrownObjectHandle);
9091             }
9092
9093             pThread->m_LastThrownObjectHandle = NULL;
9094         }
9095
9096         // Clear out the exceptions objects held by a thread.
9097         pThread->GetExceptionState()->ClearThrowablesForUnload(m_handleStore);
9098     }
9099
9100     //delete them while we still have the runtime suspended
9101     // This must be deleted before the loader heaps are deleted.
9102     if (m_pMarshalingData != NULL)
9103     {
9104         delete m_pMarshalingData;
9105         m_pMarshalingData = NULL;
9106     }
9107
9108     if (m_pLargeHeapHandleTable != NULL)
9109     {
9110         delete m_pLargeHeapHandleTable;
9111         m_pLargeHeapHandleTable = NULL;
9112     }
9113
9114     ThreadSuspend::RestartEE(FALSE, TRUE);
9115 }
9116
9117 #ifdef _DEBUG
9118
9119 void AppDomain::TrackADThreadEnter(Thread *pThread, Frame *pFrame)
9120 {
9121     CONTRACTL
9122     {
9123         NOTHROW;
9124         GC_NOTRIGGER;
9125         // REENTRANT
9126         PRECONDITION(CheckPointer(pThread));
9127         PRECONDITION(pFrame != (Frame*)(size_t) INVALID_POINTER_CD);
9128     }
9129     CONTRACTL_END;
9130
9131     while (FastInterlockCompareExchange((LONG*)&m_TrackSpinLock, 1, 0) != 0)
9132         ;
9133     if (m_pThreadTrackInfoList == NULL)
9134         m_pThreadTrackInfoList = new (nothrow) ThreadTrackInfoList;
9135     // If we don't assert here, we will AV in the for loop below
9136     _ASSERTE(m_pThreadTrackInfoList);
9137
9138     ThreadTrackInfoList *pTrackList= m_pThreadTrackInfoList;
9139
9140     ThreadTrackInfo *pTrack = NULL;
9141     int i;
9142     for (i=0; i < pTrackList->Count(); i++) {
9143         if ((*(pTrackList->Get(i)))->pThread == pThread) {
9144             pTrack = *(pTrackList->Get(i));
9145             break;
9146         }
9147     }
9148     if (! pTrack) {
9149         pTrack = new (nothrow) ThreadTrackInfo;
9150         // If we don't assert here, we will AV in the for loop below.
9151         _ASSERTE(pTrack);
9152         pTrack->pThread = pThread;
9153         ThreadTrackInfo **pSlot = pTrackList->Append();
9154         *pSlot = pTrack;
9155     }
9156
9157     InterlockedIncrement((LONG*)&m_dwThreadEnterCount);
9158     Frame **pSlot;
9159     if (pTrack)
9160     {
9161         pSlot = pTrack->frameStack.Insert(0);
9162         *pSlot = pFrame;
9163     }
9164     int totThreads = 0;
9165     for (i=0; i < pTrackList->Count(); i++)
9166         totThreads += (*(pTrackList->Get(i)))->frameStack.Count();
9167     _ASSERTE(totThreads == (int)m_dwThreadEnterCount);
9168
9169     InterlockedExchange((LONG*)&m_TrackSpinLock, 0);
9170 }
9171
9172
9173 void AppDomain::TrackADThreadExit(Thread *pThread, Frame *pFrame)
9174 {
9175     CONTRACTL
9176     {
9177         if (GetThread()) {MODE_COOPERATIVE;}
9178         NOTHROW;
9179         GC_NOTRIGGER;
9180     }
9181     CONTRACTL_END;
9182
9183     while (FastInterlockCompareExchange((LONG*)&m_TrackSpinLock, 1, 0) != 0)
9184         ;
9185     ThreadTrackInfoList *pTrackList= m_pThreadTrackInfoList;
9186     _ASSERTE(pTrackList);
9187     ThreadTrackInfo *pTrack = NULL;
9188     int i;
9189     for (i=0; i < pTrackList->Count(); i++)
9190     {
9191         if ((*(pTrackList->Get(i)))->pThread == pThread)
9192         {
9193             pTrack = *(pTrackList->Get(i));
9194             break;
9195         }
9196     }
9197     _ASSERTE(pTrack);
9198     _ASSERTE(*(pTrack->frameStack.Get(0)) == pFrame);
9199     pTrack->frameStack.Delete(0);
9200     InterlockedDecrement((LONG*)&m_dwThreadEnterCount);
9201
9202     int totThreads = 0;
9203     for (i=0; i < pTrackList->Count(); i++)
9204         totThreads += (*(pTrackList->Get(i)))->frameStack.Count();
9205     _ASSERTE(totThreads == (int)m_dwThreadEnterCount);
9206
9207     InterlockedExchange((LONG*)&m_TrackSpinLock, 0);
9208 }
9209
9210 void AppDomain::DumpADThreadTrack()
9211 {
9212     CONTRACTL
9213     {
9214         NOTHROW;
9215         GC_NOTRIGGER;
9216         MODE_COOPERATIVE;
9217     }
9218     CONTRACTL_END;
9219
9220     while (FastInterlockCompareExchange((LONG*)&m_TrackSpinLock, 1, 0) != 0)
9221         ;
9222     ThreadTrackInfoList *pTrackList= m_pThreadTrackInfoList;
9223     if (!pTrackList)
9224         goto end;
9225
9226     {
9227         LOG((LF_APPDOMAIN, LL_INFO10000, "\nThread dump of %d threads for [%d] %#08x %S\n",
9228              m_dwThreadEnterCount, GetId().m_dwId, this, GetFriendlyNameForLogging()));
9229         int totThreads = 0;
9230         for (int i=0; i < pTrackList->Count(); i++)
9231         {
9232             ThreadTrackInfo *pTrack = *(pTrackList->Get(i));
9233             if (pTrack->frameStack.Count()==0)
9234                 continue;
9235             LOG((LF_APPDOMAIN, LL_INFO100, "  ADEnterCount for %x is %d\n", pTrack->pThread->GetThreadId(), pTrack->frameStack.Count()));
9236             totThreads += pTrack->frameStack.Count();
9237             for (int j=0; j < pTrack->frameStack.Count(); j++)
9238                 LOG((LF_APPDOMAIN, LL_INFO100, "      frame %8.8x\n", *(pTrack->frameStack.Get(j))));
9239         }
9240         _ASSERTE(totThreads == (int)m_dwThreadEnterCount);
9241     }
9242 end:
9243     InterlockedExchange((LONG*)&m_TrackSpinLock, 0);
9244 }
9245 #endif // _DEBUG
9246
9247
9248 #endif // CROSSGEN_COMPILE
9249
9250 void *SharedDomain::operator new(size_t size, void *pInPlace)
9251 {
9252     LIMITED_METHOD_CONTRACT;
9253     return pInPlace;
9254 }
9255
9256 void SharedDomain::operator delete(void *pMem)
9257 {
9258     LIMITED_METHOD_CONTRACT;
9259     // Do nothing - new() was in-place
9260 }
9261
9262
9263 void SharedDomain::Attach()
9264 {
9265     CONTRACTL
9266     {
9267         THROWS;
9268         GC_TRIGGERS;
9269         MODE_ANY;
9270         INJECT_FAULT(COMPlusThrowOM(););
9271     }
9272     CONTRACTL_END;
9273
9274     // Create the global SharedDomain and initialize it.
9275     m_pSharedDomain = new (&g_pSharedDomainMemory[0]) SharedDomain();
9276     SystemDomain::GetGlobalLoaderAllocator()->m_pDomain = m_pSharedDomain;
9277     // This cannot fail since g_pSharedDomainMemory is a static array.
9278     CONSISTENCY_CHECK(CheckPointer(m_pSharedDomain));
9279
9280     LOG((LF_CLASSLOADER,
9281          LL_INFO10,
9282          "Created shared domain at %p\n",
9283          m_pSharedDomain));
9284
9285     // We need to initialize the memory pools etc. for the system domain.
9286     m_pSharedDomain->Init(); // Setup the memory heaps
9287
9288     // allocate a Virtual Call Stub Manager for the shared domain
9289     m_pSharedDomain->InitVSD();
9290 }
9291
9292 #ifndef CROSSGEN_COMPILE
9293 void SharedDomain::Detach()
9294 {
9295     if (m_pSharedDomain)
9296     {
9297         m_pSharedDomain->Terminate();
9298         delete m_pSharedDomain;
9299         m_pSharedDomain = NULL;
9300     }
9301 }
9302 #endif // CROSSGEN_COMPILE
9303
9304 #endif // !DACCESS_COMPILE
9305
9306 SharedDomain *SharedDomain::GetDomain()
9307 {
9308     LIMITED_METHOD_DAC_CONTRACT;
9309
9310     return m_pSharedDomain;
9311 }
9312
9313 #ifndef DACCESS_COMPILE
9314
9315 #define INITIAL_ASSEMBLY_MAP_SIZE 17
9316 void SharedDomain::Init()
9317 {
9318     CONTRACTL
9319     {
9320         THROWS;
9321         GC_TRIGGERS;
9322         MODE_ANY;
9323         INJECT_FAULT(COMPlusThrowOM(););
9324     }
9325     CONTRACTL_END;
9326
9327     BaseDomain::Init();
9328
9329 #ifdef FEATURE_LOADER_OPTIMIZATION
9330     m_FileCreateLock.Init(CrstSharedAssemblyCreate, CRST_DEFAULT,TRUE);
9331
9332     LockOwner lock = { &m_DomainCrst, IsOwnerOfCrst };
9333     m_assemblyMap.Init(INITIAL_ASSEMBLY_MAP_SIZE, CompareSharedAssembly, TRUE, &lock);
9334 #endif // FEATURE_LOADER_OPTIMIZATION 
9335
9336     ETW::LoaderLog::DomainLoad(this);
9337 }
9338
9339 #ifndef CROSSGEN_COMPILE
9340 void SharedDomain::Terminate()
9341 {
9342     // make sure we delete the StringLiteralMap before unloading
9343     // the asemblies since the string literal map entries can
9344     // point to metadata string literals.
9345     GetLoaderAllocator()->CleanupStringLiteralMap();
9346
9347 #ifdef FEATURE_LOADER_OPTIMIZATION    
9348     PtrHashMap::PtrIterator i = m_assemblyMap.begin();
9349
9350     while (!i.end())
9351     {
9352         Assembly *pAssembly = (Assembly*) i.GetValue();
9353         delete pAssembly;
9354         ++i;
9355     }
9356
9357     ListLockEntry* pElement;
9358     pElement = m_FileCreateLock.Pop(TRUE);
9359     while (pElement)
9360     {
9361 #ifdef STRICT_CLSINITLOCK_ENTRY_LEAK_DETECTION
9362         _ASSERTE (dbg_fDrasticShutdown || g_fInControlC);
9363 #endif
9364         delete(pElement);
9365         pElement = (FileLoadLock*) m_FileCreateLock.Pop(TRUE);
9366     }
9367     m_FileCreateLock.Destroy();
9368 #endif // FEATURE_LOADER_OPTIMIZATION    
9369     BaseDomain::Terminate();
9370 }
9371 #endif // CROSSGEN_COMPILE
9372
9373
9374
9375 #ifdef FEATURE_LOADER_OPTIMIZATION
9376
9377 BOOL SharedDomain::CompareSharedAssembly(UPTR u1, UPTR u2)
9378 {
9379     CONTRACTL
9380     {
9381         THROWS;
9382         GC_TRIGGERS;
9383         MODE_ANY;
9384     }
9385     CONTRACTL_END;
9386
9387     // This is the input to the lookup
9388     SharedAssemblyLocator *pLocator = (SharedAssemblyLocator *) (u1<<1);
9389
9390     // This is the value stored in the table
9391     Assembly *pAssembly = (Assembly *) u2;
9392     if (pLocator->GetType()==SharedAssemblyLocator::DOMAINASSEMBLY)
9393     {
9394         if (!pAssembly->GetManifestFile()->Equals(pLocator->GetDomainAssembly()->GetFile()))
9395             return FALSE;
9396
9397         return pAssembly->CanBeShared(pLocator->GetDomainAssembly());
9398     }
9399     else
9400     if (pLocator->GetType()==SharedAssemblyLocator::PEASSEMBLY)
9401         return pAssembly->GetManifestFile()->Equals(pLocator->GetPEAssembly());
9402     else
9403     if (pLocator->GetType()==SharedAssemblyLocator::PEASSEMBLYEXACT)
9404         return pAssembly->GetManifestFile() == pLocator->GetPEAssembly();
9405      _ASSERTE(!"Unexpected type of assembly locator");
9406     return FALSE;
9407 }
9408
9409 DWORD SharedAssemblyLocator::Hash()
9410 {
9411     CONTRACTL
9412     {
9413         THROWS;
9414         GC_TRIGGERS;
9415         MODE_ANY;
9416         INJECT_FAULT(COMPlusThrowOM(););
9417     }
9418     CONTRACTL_END;
9419     if (m_type==DOMAINASSEMBLY)
9420         return GetDomainAssembly()->HashIdentity();
9421     if (m_type==PEASSEMBLY||m_type==PEASSEMBLYEXACT)
9422         return GetPEAssembly()->HashIdentity();
9423      _ASSERTE(!"Unexpected type of assembly locator");
9424      return 0;
9425 }
9426
9427 Assembly * SharedDomain::FindShareableAssembly(SharedAssemblyLocator * pLocator)
9428 {
9429     CONTRACTL
9430     {
9431         THROWS;
9432         GC_TRIGGERS;
9433         MODE_ANY;
9434         INJECT_FAULT(COMPlusThrowOM(););
9435     }
9436     CONTRACTL_END;
9437
9438     Assembly * match= (Assembly *) m_assemblyMap.LookupValue(pLocator->Hash(), pLocator);
9439     if (match != (Assembly *) INVALIDENTRY)
9440         return match;
9441     else
9442         return NULL;
9443 }
9444
9445 SIZE_T SharedDomain::GetShareableAssemblyCount()
9446 {
9447     LIMITED_METHOD_CONTRACT;
9448
9449     return m_assemblyMap.GetCount();
9450 }
9451
9452 void SharedDomain::AddShareableAssembly(Assembly * pAssembly)
9453 {
9454     CONTRACTL
9455     {
9456         THROWS;
9457         GC_TRIGGERS;
9458         MODE_ANY;
9459         INJECT_FAULT(COMPlusThrowOM(););
9460     }
9461     CONTRACTL_END;
9462
9463     // We have a lock on the file. There should be no races to add the same assembly.
9464
9465     {
9466         LockHolder holder(this);
9467
9468         EX_TRY
9469         {
9470             pAssembly->SetIsTenured();
9471             m_assemblyMap.InsertValue(pAssembly->HashIdentity(), pAssembly);
9472         }
9473         EX_HOOK
9474         {
9475             // There was an error adding the assembly to the assembly hash (probably an OOM),
9476             // so we need to unset the tenured bit so that correct cleanup can happen.
9477             pAssembly->UnsetIsTenured();
9478         }
9479         EX_END_HOOK
9480     }
9481
9482     LOG((LF_CODESHARING,
9483          LL_INFO100,
9484          "Successfully added shareable assembly \"%s\".\n",
9485          pAssembly->GetManifestFile()->GetSimpleName()));
9486 }
9487
9488 #endif // FEATURE_LOADER_OPTIMIZATION
9489 #endif // !DACCESS_COMPILE
9490
9491 DWORD DomainLocalModule::GetClassFlags(MethodTable* pMT, DWORD iClassIndex /*=(DWORD)-1*/)
9492 {
9493     CONTRACTL {
9494         NOTHROW;
9495         GC_NOTRIGGER;
9496         SO_TOLERANT;
9497     } CONTRACTL_END;
9498
9499     {   // SO tolerance exception for debug-only assertion.
9500         CONTRACT_VIOLATION(SOToleranceViolation);
9501         CONSISTENCY_CHECK(GetDomainFile()->GetModule() == pMT->GetModuleForStatics());
9502     }
9503
9504     if (pMT->IsDynamicStatics())
9505     {
9506         _ASSERTE(!pMT->ContainsGenericVariables());
9507         DWORD dynamicClassID = pMT->GetModuleDynamicEntryID();
9508         if(m_aDynamicEntries <= dynamicClassID)
9509             return FALSE;
9510         return (m_pDynamicClassTable[dynamicClassID].m_dwFlags);
9511     }
9512     else
9513     {
9514         if (iClassIndex == (DWORD)-1)
9515             iClassIndex = pMT->GetClassIndex();
9516         return GetPrecomputedStaticsClassData()[iClassIndex];
9517     }
9518 }
9519
9520 #ifndef DACCESS_COMPILE
9521
9522 void DomainLocalModule::SetClassInitialized(MethodTable* pMT)
9523 {
9524     CONTRACTL
9525     {
9526         THROWS;
9527         GC_TRIGGERS;
9528         MODE_ANY;
9529     }
9530     CONTRACTL_END;
9531
9532     BaseDomain::DomainLocalBlockLockHolder lh(GetDomainFile()->GetAppDomain());
9533
9534     _ASSERTE(!IsClassInitialized(pMT));
9535     _ASSERTE(!IsClassInitError(pMT));
9536
9537     SetClassFlags(pMT, ClassInitFlags::INITIALIZED_FLAG);
9538 }
9539
9540 void DomainLocalModule::SetClassInitError(MethodTable* pMT)
9541 {
9542     WRAPPER_NO_CONTRACT;
9543
9544     BaseDomain::DomainLocalBlockLockHolder lh(GetDomainFile()->GetAppDomain());
9545
9546     SetClassFlags(pMT, ClassInitFlags::ERROR_FLAG);
9547 }
9548
9549 void DomainLocalModule::SetClassFlags(MethodTable* pMT, DWORD dwFlags)
9550 {
9551     CONTRACTL {
9552         THROWS;
9553         GC_TRIGGERS;
9554         PRECONDITION(GetDomainFile()->GetModule() == pMT->GetModuleForStatics());
9555         // Assumes BaseDomain::DomainLocalBlockLockHolder is taken
9556         PRECONDITION(GetDomainFile()->GetAppDomain()->OwnDomainLocalBlockLock());
9557     } CONTRACTL_END;
9558
9559     if (pMT->IsDynamicStatics())
9560     {
9561         _ASSERTE(!pMT->ContainsGenericVariables());
9562         DWORD dwID = pMT->GetModuleDynamicEntryID();
9563         EnsureDynamicClassIndex(dwID);
9564         m_pDynamicClassTable[dwID].m_dwFlags |= dwFlags;
9565     }
9566     else
9567     {
9568         GetPrecomputedStaticsClassData()[pMT->GetClassIndex()] |= dwFlags;
9569     }
9570 }
9571
9572 void DomainLocalModule::EnsureDynamicClassIndex(DWORD dwID)
9573 {
9574     CONTRACTL
9575     {
9576         THROWS;
9577         GC_TRIGGERS;
9578         MODE_ANY;
9579         INJECT_FAULT(COMPlusThrowOM(););
9580         // Assumes BaseDomain::DomainLocalBlockLockHolder is taken
9581         PRECONDITION(GetDomainFile()->GetAppDomain()->OwnDomainLocalBlockLock());
9582     }
9583     CONTRACTL_END;
9584
9585     if (dwID < m_aDynamicEntries)
9586     {
9587         _ASSERTE(m_pDynamicClassTable.Load() != NULL);
9588         return;
9589     }
9590
9591     SIZE_T aDynamicEntries = max(16, m_aDynamicEntries.Load());
9592     while (aDynamicEntries <= dwID)
9593     {
9594         aDynamicEntries *= 2;
9595     }
9596
9597     DynamicClassInfo* pNewDynamicClassTable;
9598     pNewDynamicClassTable = (DynamicClassInfo*)
9599         (void*)GetDomainFile()->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(
9600             S_SIZE_T(sizeof(DynamicClassInfo)) * S_SIZE_T(aDynamicEntries));
9601
9602     memcpy(pNewDynamicClassTable, m_pDynamicClassTable, sizeof(DynamicClassInfo) * m_aDynamicEntries);
9603
9604     // Note: Memory allocated on loader heap is zero filled
9605     // memset(pNewDynamicClassTable + m_aDynamicEntries, 0, (aDynamicEntries - m_aDynamicEntries) * sizeof(DynamicClassInfo));
9606
9607     _ASSERTE(m_aDynamicEntries%2 == 0);
9608
9609     // Commit new dynamic table. The lock-free helpers depend on the order.
9610     MemoryBarrier();
9611     m_pDynamicClassTable = pNewDynamicClassTable;
9612     MemoryBarrier();
9613     m_aDynamicEntries = aDynamicEntries;
9614 }
9615
9616 #ifndef CROSSGEN_COMPILE
9617 void    DomainLocalModule::AllocateDynamicClass(MethodTable *pMT)
9618 {
9619     CONTRACTL
9620     {
9621         THROWS;
9622         GC_TRIGGERS;
9623         // Assumes BaseDomain::DomainLocalBlockLockHolder is taken
9624         PRECONDITION(GetDomainFile()->GetAppDomain()->OwnDomainLocalBlockLock());
9625     }
9626     CONTRACTL_END;
9627
9628     _ASSERTE(!pMT->ContainsGenericVariables());
9629     _ASSERTE(!pMT->IsSharedByGenericInstantiations());
9630     _ASSERTE(GetDomainFile()->GetModule() == pMT->GetModuleForStatics());
9631     _ASSERTE(pMT->IsDynamicStatics());
9632
9633     DWORD dynamicEntryIDIndex = pMT->GetModuleDynamicEntryID();
9634
9635     EnsureDynamicClassIndex(dynamicEntryIDIndex);
9636
9637     _ASSERTE(m_aDynamicEntries > dynamicEntryIDIndex);
9638
9639     EEClass *pClass = pMT->GetClass();
9640
9641     DWORD dwStaticBytes = pClass->GetNonGCRegularStaticFieldBytes();
9642     DWORD dwNumHandleStatics = pClass->GetNumHandleRegularStatics();
9643
9644     _ASSERTE(!IsClassAllocated(pMT));
9645     _ASSERTE(!IsClassInitialized(pMT));
9646     _ASSERTE(!IsClassInitError(pMT));
9647
9648     DynamicEntry *pDynamicStatics = m_pDynamicClassTable[dynamicEntryIDIndex].m_pDynamicEntry;
9649
9650     // We need this check because maybe a class had a cctor but no statics
9651     if (dwStaticBytes > 0 || dwNumHandleStatics > 0)
9652     {
9653         if (pDynamicStatics == NULL)
9654         {
9655             LoaderHeap * pLoaderAllocator = GetDomainFile()->GetLoaderAllocator()->GetHighFrequencyHeap();
9656
9657             if (pMT->Collectible())
9658             {
9659                 pDynamicStatics = (DynamicEntry*)(void*)pLoaderAllocator->AllocMem(S_SIZE_T(sizeof(CollectibleDynamicEntry)));
9660             }
9661             else
9662             {
9663                 SIZE_T dynamicEntrySize = DynamicEntry::GetOffsetOfDataBlob() + dwStaticBytes;
9664
9665 #ifdef FEATURE_64BIT_ALIGNMENT
9666                 // Allocate memory with extra alignment only if it is really necessary
9667                 if (dwStaticBytes >= MAX_PRIMITIVE_FIELD_SIZE)
9668                 {
9669                     static_assert_no_msg(sizeof(NormalDynamicEntry) % MAX_PRIMITIVE_FIELD_SIZE == 0);
9670                     pDynamicStatics = (DynamicEntry*)(void*)pLoaderAllocator->AllocAlignedMem(dynamicEntrySize, MAX_PRIMITIVE_FIELD_SIZE);
9671                 }
9672                 else
9673 #endif
9674                     pDynamicStatics = (DynamicEntry*)(void*)pLoaderAllocator->AllocMem(S_SIZE_T(dynamicEntrySize));
9675             }
9676
9677             // Note: Memory allocated on loader heap is zero filled
9678
9679             m_pDynamicClassTable[dynamicEntryIDIndex].m_pDynamicEntry = pDynamicStatics;
9680         }
9681
9682         if (pMT->Collectible() && (dwStaticBytes != 0))
9683         {
9684             GCX_COOP();
9685             OBJECTREF nongcStaticsArray = NULL;
9686             GCPROTECT_BEGIN(nongcStaticsArray);
9687 #ifdef FEATURE_64BIT_ALIGNMENT
9688             // Allocate memory with extra alignment only if it is really necessary
9689             if (dwStaticBytes >= MAX_PRIMITIVE_FIELD_SIZE)
9690                 nongcStaticsArray = AllocatePrimitiveArray(ELEMENT_TYPE_I8, (dwStaticBytes + (sizeof(CLR_I8)-1)) / (sizeof(CLR_I8)));
9691             else
9692 #endif
9693                 nongcStaticsArray = AllocatePrimitiveArray(ELEMENT_TYPE_U1, dwStaticBytes);
9694             ((CollectibleDynamicEntry *)pDynamicStatics)->m_hNonGCStatics = GetDomainFile()->GetModule()->GetLoaderAllocator()->AllocateHandle(nongcStaticsArray);
9695             GCPROTECT_END();
9696         }
9697         if (dwNumHandleStatics > 0)
9698         {
9699             if (!pMT->Collectible())
9700             {
9701                 GetAppDomain()->AllocateStaticFieldObjRefPtrs(dwNumHandleStatics,
9702                                                               &((NormalDynamicEntry *)pDynamicStatics)->m_pGCStatics);
9703             }
9704             else
9705             {
9706                 GCX_COOP();
9707                 OBJECTREF gcStaticsArray = NULL;
9708                 GCPROTECT_BEGIN(gcStaticsArray);
9709                 gcStaticsArray = AllocateObjectArray(dwNumHandleStatics, g_pObjectClass);
9710                 ((CollectibleDynamicEntry *)pDynamicStatics)->m_hGCStatics = GetDomainFile()->GetModule()->GetLoaderAllocator()->AllocateHandle(gcStaticsArray);
9711                 GCPROTECT_END();
9712             }
9713         }
9714     }
9715 }
9716
9717
9718 void DomainLocalModule::PopulateClass(MethodTable *pMT)
9719 {
9720     CONTRACTL
9721     {
9722         THROWS;
9723         GC_TRIGGERS;
9724     }
9725     CONTRACTL_END;
9726
9727     _ASSERTE(!pMT->ContainsGenericVariables());
9728
9729     // <todo> the only work actually done here for non-dynamics is the freezing related work.
9730     // See if we can eliminate this and make this a dynamic-only path </todo>
9731     DWORD iClassIndex = pMT->GetClassIndex();
9732
9733     if (!IsClassAllocated(pMT, iClassIndex))
9734     {
9735         BaseDomain::DomainLocalBlockLockHolder lh(GetDomainFile()->GetAppDomain());
9736
9737         if (!IsClassAllocated(pMT, iClassIndex))
9738         {
9739             // Allocate dynamic space if necessary
9740             if (pMT->IsDynamicStatics())
9741                 AllocateDynamicClass(pMT);
9742
9743             // determine flags to set on the statics block
9744             DWORD dwFlags = ClassInitFlags::ALLOCATECLASS_FLAG;
9745
9746             if (!pMT->HasClassConstructor() && !pMT->HasBoxedRegularStatics())
9747             {
9748                 _ASSERTE(!IsClassInitialized(pMT));
9749                 _ASSERTE(!IsClassInitError(pMT));
9750                 dwFlags |= ClassInitFlags::INITIALIZED_FLAG;
9751             }
9752
9753             if (pMT->Collectible())
9754             {
9755                 dwFlags |= ClassInitFlags::COLLECTIBLE_FLAG;
9756             }
9757
9758             // Set all flags at the same time to avoid races
9759             SetClassFlags(pMT, dwFlags);
9760         }
9761     }
9762
9763     return;
9764 }
9765 #endif // CROSSGEN_COMPILE
9766
9767 void DomainLocalBlock::EnsureModuleIndex(ModuleIndex index)
9768 {
9769     CONTRACTL
9770     {
9771         THROWS;
9772         GC_TRIGGERS;
9773         MODE_ANY;
9774         INJECT_FAULT(COMPlusThrowOM(););
9775         // Assumes BaseDomain::DomainLocalBlockLockHolder is taken
9776         PRECONDITION(m_pDomain->OwnDomainLocalBlockLock());
9777     }
9778     CONTRACTL_END;
9779
9780     if (m_aModuleIndices > index.m_dwIndex)
9781     {
9782         _ASSERTE(m_pModuleSlots != NULL);
9783         return;
9784     }
9785
9786     SIZE_T aModuleIndices = max(16, m_aModuleIndices);
9787     while (aModuleIndices <= index.m_dwIndex)
9788     {
9789         aModuleIndices *= 2;
9790     }
9791
9792     PTR_DomainLocalModule* pNewModuleSlots = (PTR_DomainLocalModule*) (void*)m_pDomain->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(PTR_DomainLocalModule)) * S_SIZE_T(aModuleIndices));
9793
9794     memcpy(pNewModuleSlots, m_pModuleSlots, sizeof(SIZE_T)*m_aModuleIndices);
9795
9796     // Note: Memory allocated on loader heap is zero filled
9797     // memset(pNewModuleSlots + m_aModuleIndices, 0 , (aModuleIndices - m_aModuleIndices)*sizeof(PTR_DomainLocalModule) );
9798
9799     // Commit new table. The lock-free helpers depend on the order.
9800     MemoryBarrier();
9801     m_pModuleSlots = pNewModuleSlots;
9802     MemoryBarrier();
9803     m_aModuleIndices = aModuleIndices;
9804
9805 }
9806
9807 void DomainLocalBlock::SetModuleSlot(ModuleIndex index, PTR_DomainLocalModule pLocalModule)
9808 {
9809     // Need to synchronize with table growth in this domain
9810     BaseDomain::DomainLocalBlockLockHolder lh(m_pDomain);
9811
9812     EnsureModuleIndex(index);
9813
9814     _ASSERTE(index.m_dwIndex < m_aModuleIndices);
9815
9816     // We would like this assert here, unfortunately, loading a module in this appdomain can fail
9817     // after here  and we will keep the module around and reuse the slot when we retry (if
9818     // the failure happened due to a transient error, such as OOM). In that case the slot wont
9819     // be null.
9820     //_ASSERTE(m_pModuleSlots[index.m_dwIndex] == 0);
9821
9822     m_pModuleSlots[index.m_dwIndex] = pLocalModule;
9823 }
9824
9825 #ifndef CROSSGEN_COMPILE
9826
9827 DomainAssembly* AppDomain::RaiseTypeResolveEventThrowing(DomainAssembly* pAssembly, LPCSTR szName, ASSEMBLYREF *pResultingAssemblyRef)
9828 {
9829     CONTRACTL
9830     {
9831         MODE_ANY;
9832         GC_TRIGGERS;
9833         THROWS;
9834         INJECT_FAULT(COMPlusThrowOM(););
9835     }
9836     CONTRACTL_END;
9837
9838     OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
9839
9840
9841     DomainAssembly* pResolvedAssembly = NULL;
9842     _ASSERTE(strcmp(szName, g_AppDomainClassName));
9843
9844     GCX_COOP();
9845
9846     struct _gc {
9847         OBJECTREF AppDomainRef;
9848         OBJECTREF AssemblyRef;
9849         STRINGREF str;
9850     } gc;
9851     ZeroMemory(&gc, sizeof(gc));
9852
9853     GCPROTECT_BEGIN(gc);
9854     if ((gc.AppDomainRef = GetRawExposedObject()) != NULL)
9855     {
9856         if (pAssembly != NULL)
9857             gc.AssemblyRef = pAssembly->GetExposedAssemblyObject();
9858
9859         MethodDescCallSite onTypeResolve(METHOD__APP_DOMAIN__ON_TYPE_RESOLVE, &gc.AppDomainRef);
9860
9861         gc.str = StringObject::NewString(szName);
9862         ARG_SLOT args[3] =
9863         {
9864             ObjToArgSlot(gc.AppDomainRef),
9865             ObjToArgSlot(gc.AssemblyRef),
9866             ObjToArgSlot(gc.str)
9867         };
9868         ASSEMBLYREF ResultingAssemblyRef = (ASSEMBLYREF) onTypeResolve.Call_RetOBJECTREF(args);
9869
9870         if (ResultingAssemblyRef != NULL)
9871         {
9872             pResolvedAssembly = ResultingAssemblyRef->GetDomainAssembly();
9873
9874             if (pResultingAssemblyRef)
9875                 *pResultingAssemblyRef = ResultingAssemblyRef;
9876             else
9877             {
9878                 if (pResolvedAssembly->IsCollectible())
9879                 {
9880                     COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleBoundNonCollectible"));
9881                 }
9882             }
9883         }
9884     }
9885     GCPROTECT_END();
9886
9887     return pResolvedAssembly;
9888 }
9889
9890
9891 Assembly* AppDomain::RaiseResourceResolveEvent(DomainAssembly* pAssembly, LPCSTR szName)
9892 {
9893     CONTRACT(Assembly*)
9894     {
9895         THROWS;
9896         GC_TRIGGERS;
9897         MODE_ANY;
9898         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
9899         INJECT_FAULT(COMPlusThrowOM(););
9900     }
9901     CONTRACT_END;
9902
9903     Assembly* pResolvedAssembly = NULL;
9904
9905     GCX_COOP();
9906
9907     struct _gc {
9908         OBJECTREF AppDomainRef;
9909         OBJECTREF AssemblyRef;
9910         STRINGREF str;
9911     } gc;
9912     ZeroMemory(&gc, sizeof(gc));
9913
9914     GCPROTECT_BEGIN(gc);
9915     if ((gc.AppDomainRef = GetRawExposedObject()) != NULL)
9916     {
9917         if (pAssembly != NULL)
9918             gc.AssemblyRef=pAssembly->GetExposedAssemblyObject();
9919
9920         MethodDescCallSite onResourceResolve(METHOD__APP_DOMAIN__ON_RESOURCE_RESOLVE, &gc.AppDomainRef);
9921         gc.str = StringObject::NewString(szName);
9922         ARG_SLOT args[3] =
9923         {
9924             ObjToArgSlot(gc.AppDomainRef),
9925             ObjToArgSlot(gc.AssemblyRef),
9926             ObjToArgSlot(gc.str)
9927         };
9928         ASSEMBLYREF ResultingAssemblyRef = (ASSEMBLYREF) onResourceResolve.Call_RetOBJECTREF(args);
9929         if (ResultingAssemblyRef != NULL)
9930         {
9931             pResolvedAssembly = ResultingAssemblyRef->GetAssembly();
9932             if (pResolvedAssembly->IsCollectible())
9933             {
9934                 COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleAssemblyResolve"));
9935             }
9936         }
9937     }
9938     GCPROTECT_END();
9939
9940     RETURN pResolvedAssembly;
9941 }
9942
9943
9944 Assembly * 
9945 AppDomain::RaiseAssemblyResolveEvent(
9946     AssemblySpec * pSpec, 
9947     BOOL           fIntrospection, 
9948     BOOL           fPreBind)
9949 {
9950     CONTRACT(Assembly*)
9951     {
9952         THROWS;
9953         GC_TRIGGERS;
9954         MODE_ANY;
9955         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
9956         INJECT_FAULT(COMPlusThrowOM(););
9957     }
9958     CONTRACT_END;
9959
9960     BinderMethodID methodId;
9961     StackSString ssName;
9962     pSpec->GetFileOrDisplayName(0, ssName);
9963     
9964     if (!fPreBind) 
9965     {
9966         methodId = METHOD__APP_DOMAIN__ON_ASSEMBLY_RESOLVE;  // post-bind execution event (the classic V1.0 event)
9967     }
9968     else
9969     {
9970         RETURN NULL;
9971     }
9972         
9973
9974     // Elevate threads allowed loading level.  This allows the host to load an assembly even in a restricted
9975     // condition.  Note, however, that this exposes us to possible recursion failures, if the host tries to
9976     // load the assemblies currently being loaded.  (Such cases would then throw an exception.)
9977
9978     OVERRIDE_LOAD_LEVEL_LIMIT(FILE_ACTIVE);
9979     OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
9980
9981     GCX_COOP();
9982
9983     Assembly* pAssembly = NULL;
9984
9985     struct _gc {
9986         OBJECTREF AppDomainRef;
9987         OBJECTREF AssemblyRef;
9988         STRINGREF str;
9989     } gc;
9990     ZeroMemory(&gc, sizeof(gc));
9991
9992     GCPROTECT_BEGIN(gc);
9993     if ((gc.AppDomainRef = GetRawExposedObject()) != NULL)
9994     {
9995         if (pSpec->GetParentAssembly() != NULL)
9996         {
9997             {
9998                 gc.AssemblyRef=pSpec->GetParentAssembly()->GetExposedAssemblyObject();
9999             }
10000         }
10001         MethodDescCallSite onAssemblyResolve(methodId, &gc.AppDomainRef);
10002
10003         gc.str = StringObject::NewString(ssName);
10004         ARG_SLOT args[3] = {
10005             ObjToArgSlot(gc.AppDomainRef),
10006             ObjToArgSlot(gc.AssemblyRef),
10007             ObjToArgSlot(gc.str)
10008         };
10009             
10010         ASSEMBLYREF ResultingAssemblyRef = (ASSEMBLYREF) onAssemblyResolve.Call_RetOBJECTREF(args);
10011             
10012         if (ResultingAssemblyRef != NULL)
10013         {
10014             pAssembly = ResultingAssemblyRef->GetAssembly();
10015             if (pAssembly->IsCollectible())
10016             {
10017                 COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleAssemblyResolve"));
10018             }
10019         }
10020     }
10021     GCPROTECT_END();
10022
10023     if (pAssembly != NULL)
10024     {
10025         if  ((!(pAssembly->IsIntrospectionOnly())) != (!fIntrospection))
10026         {
10027             // Cannot return an introspection assembly from an execution callback or vice-versa
10028             COMPlusThrow(kFileLoadException, pAssembly->IsIntrospectionOnly() ? IDS_CLASSLOAD_ASSEMBLY_RESOLVE_RETURNED_INTROSPECTION : IDS_CLASSLOAD_ASSEMBLY_RESOLVE_RETURNED_EXECUTION);
10029         }
10030
10031         // Check that the public key token matches the one specified in the spec
10032         // MatchPublicKeys throws as appropriate
10033         pSpec->MatchPublicKeys(pAssembly);
10034     }
10035
10036     RETURN pAssembly;
10037 } // AppDomain::RaiseAssemblyResolveEvent
10038
10039
10040 //---------------------------------------------------------------------------------------
10041 //
10042 // Determine the type of AppDomainManager to use for the default AppDomain
10043 //
10044 // Notes:
10045 //   v2.0 of the CLR used environment variables APPDOMAIN_MANAGER_ASM and APPDOMAIN_MANAGER_TYPE to set the
10046 //   domain manager. For compatibility these are still supported, along with appDomainManagerAsm and
10047 //   appDomainManagerType config file switches. If the config switches are supplied, the entry point must be
10048 //   fully trusted.  
10049 //
10050
10051 void AppDomain::InitializeDefaultDomainManager()
10052 {
10053     CONTRACTL
10054     {
10055         MODE_COOPERATIVE;
10056         GC_TRIGGERS;
10057         THROWS;
10058         INJECT_FAULT(COMPlusThrowOM(););
10059         PRECONDITION(GetId().m_dwId == DefaultADID);
10060     }
10061     CONTRACTL_END;
10062
10063     OBJECTREF orThis = GetExposedObject();
10064     GCPROTECT_BEGIN(orThis);
10065
10066     MethodDescCallSite initCompatFlags(METHOD__APP_DOMAIN__INITIALIZE_COMPATIBILITY_FLAGS);
10067     ARG_SLOT args[] =
10068     {
10069         ObjToArgSlot(orThis)
10070     };
10071
10072     initCompatFlags.Call(args);
10073
10074     GCPROTECT_END();
10075 }
10076
10077 CLREvent * AppDomain::g_pUnloadStartEvent;
10078
10079 void AppDomain::CreateADUnloadWorker()
10080 {
10081     STANDARD_VM_CONTRACT;
10082
10083     // Do not create adUnload thread if there is only default domain
10084     if(IsSingleAppDomain())
10085         return;
10086
10087 Retry:
10088     BOOL fCreator = FALSE;
10089     if (FastInterlockCompareExchange((LONG *)&g_fADUnloadWorkerOK,-2,-1)==-1)  //we're first
10090     {
10091 #ifdef _TARGET_X86_  // use the smallest possible stack on X86 
10092         DWORD stackSize = 128 * 1024;
10093 #else
10094         DWORD stackSize = 512 * 1024; // leave X64 unchanged since we have plenty of VM
10095 #endif
10096         Thread *pThread = SetupUnstartedThread();
10097         if (pThread->CreateNewThread(stackSize, ADUnloadThreadStart, pThread))
10098         {
10099             fCreator = TRUE;
10100             DWORD dwRet;
10101             dwRet = pThread->StartThread();
10102
10103             // When running under a user mode native debugger there is a race
10104             // between the moment we've created the thread (in CreateNewThread) and 
10105             // the moment we resume it (in StartThread); the debugger may receive 
10106             // the "ct" (create thread) notification, and it will attempt to 
10107             // suspend/resume all threads in the process.  Now imagine the debugger
10108             // resumes this thread first, and only later does it try to resume the
10109             // newly created thread (the ADU worker thread).  In these conditions our
10110             // call to ResumeThread may come before the debugger's call to ResumeThread
10111             // actually causing dwRet to equal 2.
10112             // We cannot use IsDebuggerPresent() in the condition below because the 
10113             // debugger may have been detached between the time it got the notification
10114             // and the moment we execute the test below.
10115             _ASSERTE(dwRet == 1 || dwRet == 2);
10116         }
10117         else
10118         {
10119             pThread->DecExternalCount(FALSE);
10120             FastInterlockExchange((LONG *)&g_fADUnloadWorkerOK, -1);
10121             ThrowOutOfMemory();
10122         }
10123     }
10124
10125     YIELD_WHILE (g_fADUnloadWorkerOK == -2);
10126
10127     if (g_fADUnloadWorkerOK == -1) {
10128         if (fCreator)
10129         {
10130             ThrowOutOfMemory();
10131         }
10132         else
10133         {
10134             goto Retry;
10135         }
10136     }
10137 }
10138
10139 /*static*/ void AppDomain::ADUnloadWorkerHelper(AppDomain *pDomain)
10140 {
10141     STATIC_CONTRACT_NOTHROW;
10142     STATIC_CONTRACT_GC_TRIGGERS;
10143     STATIC_CONTRACT_MODE_COOPERATIVE;
10144     ADUnloadSink* pADUnloadSink=pDomain->GetADUnloadSinkForUnload();
10145     HRESULT hr=S_OK;
10146
10147     EX_TRY
10148     {
10149         pDomain->Unload(FALSE);
10150     }
10151     EX_CATCH_HRESULT(hr);
10152
10153     if(pADUnloadSink)
10154     {
10155         SystemDomain::LockHolder lh;
10156         pADUnloadSink->ReportUnloadResult(hr,NULL);
10157         pADUnloadSink->Release();
10158     }
10159 }
10160
10161 void AppDomain::DoADUnloadWork()
10162 {
10163     CONTRACTL
10164     {
10165         THROWS;
10166         GC_TRIGGERS;
10167         MODE_COOPERATIVE;
10168         INJECT_FAULT(COMPlusThrowOM(););
10169     }
10170     CONTRACTL_END;
10171
10172     DWORD i = 1;
10173     while (TRUE) {
10174
10175         AppDomain *pDomainToUnload = NULL;
10176
10177         {
10178             // Take the lock so that no domain can be added or removed from the system domain
10179             SystemDomain::LockHolder lh;
10180
10181             DWORD numDomain = SystemDomain::GetCurrentAppDomainMaxIndex();
10182             for (; i <= numDomain; i ++) {
10183                 AppDomain * pDomain = SystemDomain::TestGetAppDomainAtIndex(ADIndex(i));
10184                 //
10185                 // @todo: We used to also select a domain if pDomain->IsUnload() returned true. But that causes
10186                 // problems when we've failed to completely unload the AD in the past. If we've reached the CLEARED
10187                 // stage, for instance, then there will be no default context and AppDomain::Exit() will simply crash.
10188                 //
10189                 if (pDomain && pDomain->IsUnloadRequested())
10190                 {
10191                     pDomainToUnload = pDomain;
10192                     i ++;
10193                     break;
10194                 }
10195             }
10196         }
10197
10198         if (!pDomainToUnload) {
10199             break;
10200         }
10201
10202         // We are the only thread that can unload domains so no one else can delete the appdomain
10203         ADUnloadWorkerHelper(pDomainToUnload);            
10204     }
10205 }
10206
10207 static void DoADUnloadWorkHelper()
10208 {
10209     STATIC_CONTRACT_NOTHROW;
10210     STATIC_CONTRACT_GC_TRIGGERS;
10211     STATIC_CONTRACT_MODE_COOPERATIVE;
10212
10213     EX_TRY {
10214         AppDomain::DoADUnloadWork();
10215     }
10216     EX_CATCH
10217     {
10218     }
10219     EX_END_CATCH(SwallowAllExceptions);
10220 }
10221
10222 ULONGLONG g_ObjFinalizeStartTime = 0;
10223 Volatile<BOOL> g_FinalizerIsRunning = FALSE;
10224 Volatile<ULONG> g_FinalizerLoopCount = 0;
10225
10226 ULONGLONG GetObjFinalizeStartTime()
10227 {
10228     LIMITED_METHOD_CONTRACT;
10229     return g_ObjFinalizeStartTime;
10230 }
10231
10232 void FinalizerThreadAbortOnTimeout()
10233 {
10234     STATIC_CONTRACT_NOTHROW;
10235     STATIC_CONTRACT_MODE_COOPERATIVE;
10236     STATIC_CONTRACT_GC_TRIGGERS;
10237
10238     {
10239         // If finalizer thread is blocked because scheduler is running another task,
10240         // or it is waiting for another thread, we first see if we get finalizer thread
10241         // running again.
10242         Thread::ThreadAbortWatchDog();
10243     }
10244
10245     EX_TRY
10246     {
10247         Thread *pFinalizerThread = FinalizerThread::GetFinalizerThread();
10248         EPolicyAction action = GetEEPolicy()->GetActionOnTimeout(OPR_FinalizerRun, pFinalizerThread);
10249         switch (action)
10250         {
10251         case eAbortThread:
10252             GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action);
10253             pFinalizerThread->UserAbort(Thread::TAR_Thread,
10254                                         EEPolicy::TA_Safe,
10255                                         INFINITE,
10256                                         Thread::UAC_FinalizerTimeout);
10257             break;
10258         case eRudeAbortThread:
10259             GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action);
10260             pFinalizerThread->UserAbort(Thread::TAR_Thread,
10261                                         EEPolicy::TA_Rude,
10262                                         INFINITE,
10263                                         Thread::UAC_FinalizerTimeout);
10264             break;
10265         case eUnloadAppDomain:
10266             {
10267                 AppDomain *pDomain = pFinalizerThread->GetDomain();
10268                 pFinalizerThread->UserAbort(Thread::TAR_Thread,
10269                                             EEPolicy::TA_Safe,
10270                                             INFINITE,
10271                                             Thread::UAC_FinalizerTimeout);
10272                 if (!pDomain->IsDefaultDomain())
10273                 {
10274                     GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action);
10275                     pDomain->EnableADUnloadWorker(EEPolicy::ADU_Safe);
10276                 }
10277             }
10278             break;
10279         case eRudeUnloadAppDomain:
10280             {
10281                 AppDomain *pDomain = pFinalizerThread->GetDomain();
10282                 pFinalizerThread->UserAbort(Thread::TAR_Thread,
10283                                             EEPolicy::TA_Rude,
10284                                             INFINITE,
10285                                             Thread::UAC_FinalizerTimeout);
10286                 if (!pDomain->IsDefaultDomain())
10287                 {
10288                     GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action);
10289                     pDomain->EnableADUnloadWorker(EEPolicy::ADU_Rude);
10290                 }
10291             }
10292             break;
10293         case eExitProcess:
10294         case eFastExitProcess:
10295         case eRudeExitProcess:
10296         case eDisableRuntime:
10297             GetEEPolicy()->NotifyHostOnTimeout(OPR_FinalizerRun, action);
10298             EEPolicy::HandleExitProcessFromEscalation(action, HOST_E_EXITPROCESS_TIMEOUT);
10299             _ASSERTE (!"Should not get here");
10300             break;
10301         default:
10302             break;
10303         }
10304     }
10305     EX_CATCH
10306     {
10307     }
10308     EX_END_CATCH(SwallowAllExceptions);
10309 }
10310
10311 enum WorkType
10312 {
10313     WT_UnloadDomain = 0x1,
10314     WT_ThreadAbort = 0x2,
10315     WT_FinalizerThread = 0x4,
10316     WT_ClearCollectedDomains=0x8
10317 };
10318
10319 static Volatile<DWORD> s_WorkType = 0;
10320
10321
10322 DWORD WINAPI AppDomain::ADUnloadThreadStart(void *args)
10323 {
10324     CONTRACTL
10325     {
10326         NOTHROW;
10327         DISABLED(GC_TRIGGERS);
10328
10329         // This function will always be at the very bottom of the stack. The only
10330         // user code it calls is the AppDomainUnload notifications which we will
10331         // not be hardenning for Whidbey.
10332         //
10333         ENTRY_POINT;
10334     }
10335     CONTRACTL_END;
10336
10337     BEGIN_ENTRYPOINT_NOTHROW;
10338
10339     ClrFlsSetThreadType (ThreadType_ADUnloadHelper);
10340
10341     Thread *pThread = (Thread*)args;
10342     bool fOK = (pThread->HasStarted() != 0);
10343
10344     {
10345         GCX_MAYBE_PREEMP(fOK);
10346
10347         _ASSERTE (g_fADUnloadWorkerOK == -2);
10348
10349         FastInterlockExchange((LONG *)&g_fADUnloadWorkerOK,fOK?1:-1);
10350
10351         if (!fOK)
10352         {
10353             DestroyThread(pThread);
10354             goto Exit;
10355         }
10356
10357         pThread->SetBackground(TRUE);
10358
10359         pThread->SetThreadStateNC(Thread::TSNC_ADUnloadHelper);
10360
10361         while (TRUE) {
10362             DWORD TAtimeout = INFINITE;
10363             ULONGLONG endTime = Thread::GetNextSelfAbortEndTime();
10364             ULONGLONG curTime = CLRGetTickCount64();
10365             if (endTime <= curTime) {
10366                 TAtimeout = 5;
10367             }
10368             else
10369             {
10370                 ULONGLONG diff = endTime - curTime;
10371                 if (diff < MAXULONG)
10372                 {
10373                     TAtimeout = (DWORD)diff;
10374                 }
10375             }
10376             ULONGLONG finalizeStartTime = GetObjFinalizeStartTime();
10377             DWORD finalizeTimeout = INFINITE;
10378             DWORD finalizeTimeoutSetting = GetEEPolicy()->GetTimeout(OPR_FinalizerRun);
10379             if (finalizeTimeoutSetting != INFINITE && g_FinalizerIsRunning)
10380             {
10381                 if (finalizeStartTime == 0)
10382                 {
10383                     finalizeTimeout = finalizeTimeoutSetting;
10384                 }
10385                 else
10386                 {
10387                     endTime = finalizeStartTime + finalizeTimeoutSetting;
10388                     if (endTime <= curTime) {
10389                         finalizeTimeout = 0;
10390                     }
10391                     else
10392                     {
10393                         ULONGLONG diff = endTime - curTime;
10394                         if (diff < MAXULONG)
10395                         {
10396                             finalizeTimeout = (DWORD)diff;
10397                         }
10398                     }
10399                 }
10400             }
10401
10402             if (AppDomain::HasWorkForFinalizerThread())
10403             {
10404                 if (finalizeTimeout > finalizeTimeoutSetting)
10405                 {
10406                     finalizeTimeout = finalizeTimeoutSetting;
10407                 }
10408             }
10409
10410             DWORD timeout = INFINITE;
10411             if (finalizeTimeout <= TAtimeout)
10412             {
10413                 timeout = finalizeTimeout;
10414             }
10415             else
10416             {
10417                 timeout = TAtimeout;
10418             }
10419
10420             if (timeout != 0)
10421             {
10422                 LOG((LF_APPDOMAIN, LL_INFO10, "Waiting to start unload\n"));
10423                 g_pUnloadStartEvent->Wait(timeout,FALSE);
10424             }
10425
10426             if (finalizeTimeout != INFINITE || (s_WorkType & WT_FinalizerThread) != 0)
10427             {
10428                 STRESS_LOG0(LF_ALWAYS, LL_ALWAYS, "ADUnloadThreadStart work for Finalizer thread\n");
10429                 FastInterlockAnd(&s_WorkType, ~WT_FinalizerThread);
10430                 // only watch finalizer thread is finalizer method or unloadevent is being processed
10431                 if (GetObjFinalizeStartTime() == finalizeStartTime && finalizeStartTime != 0 && g_FinalizerIsRunning)
10432                 {
10433                     if (CLRGetTickCount64() >= finalizeStartTime+finalizeTimeoutSetting)
10434                     {
10435                         GCX_COOP();
10436                         FinalizerThreadAbortOnTimeout();
10437                     }
10438                 }
10439                 if (s_fProcessUnloadDomainEvent && g_FinalizerIsRunning)
10440                 {
10441                     GCX_COOP();
10442                     FinalizerThreadAbortOnTimeout();
10443                 }
10444             }
10445
10446             if (TAtimeout != INFINITE || (s_WorkType & WT_ThreadAbort) != 0)
10447             {
10448                 STRESS_LOG0(LF_ALWAYS, LL_ALWAYS, "ADUnloadThreadStart work for thread abort\n");
10449                 FastInterlockAnd(&s_WorkType, ~WT_ThreadAbort);
10450                 GCX_COOP();
10451                 Thread::ThreadAbortWatchDog();
10452             }
10453
10454             if ((s_WorkType & WT_UnloadDomain) != 0 && !AppDomain::HasWorkForFinalizerThread())
10455             {
10456                 STRESS_LOG0(LF_ALWAYS, LL_ALWAYS, "ADUnloadThreadStart work for AD unload\n");
10457                 FastInterlockAnd(&s_WorkType, ~WT_UnloadDomain);
10458                 GCX_COOP();
10459                 DoADUnloadWorkHelper();
10460             }
10461
10462             if ((s_WorkType & WT_ClearCollectedDomains) != 0)
10463             {
10464                 STRESS_LOG0(LF_ALWAYS, LL_ALWAYS, "ADUnloadThreadStart work for AD cleanup\n");
10465                 FastInterlockAnd(&s_WorkType, ~WT_ClearCollectedDomains);
10466                 GCX_COOP();
10467                 SystemDomain::System()->ClearCollectedDomains();
10468             }
10469
10470         }
10471 Exit:;
10472     }
10473
10474     END_ENTRYPOINT_NOTHROW;
10475
10476     return 0;
10477 }
10478
10479 void AppDomain::EnableADUnloadWorker()
10480 {
10481     CONTRACTL
10482     {
10483         NOTHROW;
10484         GC_NOTRIGGER;
10485         SO_TOLERANT; // Called during a SO
10486     }
10487     CONTRACTL_END;
10488
10489     EEPolicy::AppDomainUnloadTypes type = EEPolicy::ADU_Safe;
10490
10491 #ifdef _DEBUG
10492     DWORD hostTestADUnload = g_pConfig->GetHostTestADUnload();
10493     if (hostTestADUnload == 2) {
10494         type = EEPolicy::ADU_Rude;
10495     }
10496 #endif // _DEBUG
10497
10498     EnableADUnloadWorker(type);
10499 }
10500
10501 void AppDomain::EnableADUnloadWorker(EEPolicy::AppDomainUnloadTypes type, BOOL fHasStack)
10502 {
10503     CONTRACTL
10504     {
10505         NOTHROW;
10506         GC_NOTRIGGER;
10507         SO_TOLERANT; // Called during a SO
10508     }
10509     CONTRACTL_END;
10510
10511     FastInterlockOr (&s_WorkType, WT_UnloadDomain);
10512
10513     LONG stage = m_Stage;
10514     static_assert_no_msg(sizeof(m_Stage) == sizeof(int));
10515
10516     _ASSERTE(!IsDefaultDomain());
10517
10518     // Mark unload requested.
10519     if (type == EEPolicy::ADU_Rude) {
10520         SetRudeUnload();
10521     }
10522     while (stage < STAGE_UNLOAD_REQUESTED) {
10523         stage = FastInterlockCompareExchange((LONG*)&m_Stage,STAGE_UNLOAD_REQUESTED,stage);
10524     }
10525
10526     if (!fHasStack)
10527     {
10528         // Can not call Set due to limited stack.
10529         return;
10530     }
10531     LOG((LF_APPDOMAIN, LL_INFO10, "Enabling unload worker\n"));
10532     g_pUnloadStartEvent->Set();
10533 }
10534
10535 void AppDomain::EnableADUnloadWorkerForThreadAbort()
10536 {
10537     LIMITED_METHOD_CONTRACT;
10538     STRESS_LOG0(LF_ALWAYS, LL_ALWAYS, "Enabling unload worker for thread abort\n");
10539     LOG((LF_APPDOMAIN, LL_INFO10, "Enabling unload worker for thread abort\n"));
10540     FastInterlockOr (&s_WorkType, WT_ThreadAbort);
10541     g_pUnloadStartEvent->Set();
10542 }
10543
10544
10545 void AppDomain::EnableADUnloadWorkerForFinalizer()
10546 {
10547     LIMITED_METHOD_CONTRACT;
10548     if (GetEEPolicy()->GetTimeout(OPR_FinalizerRun) != INFINITE)
10549     {
10550         LOG((LF_APPDOMAIN, LL_INFO10, "Enabling unload worker for Finalizer Thread\n"));
10551         FastInterlockOr (&s_WorkType, WT_FinalizerThread);
10552         g_pUnloadStartEvent->Set();
10553     }
10554 }
10555
10556 void AppDomain::EnableADUnloadWorkerForCollectedADCleanup()
10557 {
10558     LIMITED_METHOD_CONTRACT;
10559     LOG((LF_APPDOMAIN, LL_INFO10, "Enabling unload worker for collected domains\n"));
10560     FastInterlockOr (&s_WorkType, WT_ClearCollectedDomains);
10561     g_pUnloadStartEvent->Set();
10562 }
10563
10564
10565 void SystemDomain::ClearCollectedDomains()
10566 {
10567     CONTRACTL
10568     {
10569         GC_TRIGGERS;
10570         NOTHROW;
10571         MODE_COOPERATIVE;
10572     }
10573     CONTRACTL_END;
10574         
10575     AppDomain* pDomainsToClear=NULL;
10576     {
10577         CrstHolder lh(&m_DelayedUnloadCrst); 
10578         for (AppDomain** ppDomain=&m_pDelayedUnloadList;(*ppDomain)!=NULL; )
10579         {
10580             if ((*ppDomain)->m_Stage==AppDomain::STAGE_COLLECTED)
10581             {
10582                 AppDomain* pAppDomain=*ppDomain;
10583                 *ppDomain=(*ppDomain)->m_pNextInDelayedUnloadList;
10584                 pAppDomain->m_pNextInDelayedUnloadList=pDomainsToClear;
10585                 pDomainsToClear=pAppDomain;
10586             }
10587             else
10588                 ppDomain=&((*ppDomain)->m_pNextInDelayedUnloadList);
10589         }
10590     }
10591         
10592     for (AppDomain* pDomain=pDomainsToClear;pDomain!=NULL;)
10593     {
10594         AppDomain* pNext=pDomain->m_pNextInDelayedUnloadList;
10595         pDomain->Close(); //NOTHROW!
10596         pDomain->Release();
10597         pDomain=pNext;
10598     }
10599 }
10600  
10601 void SystemDomain::ProcessClearingDomains()
10602 {
10603     CONTRACTL
10604     {
10605         NOTHROW;
10606         GC_NOTRIGGER;
10607         MODE_ANY;           
10608     }
10609     CONTRACTL_END;
10610     CrstHolder lh(&m_DelayedUnloadCrst); 
10611
10612     for (AppDomain** ppDomain=&m_pDelayedUnloadList;(*ppDomain)!=NULL; )
10613     {
10614         if ((*ppDomain)->m_Stage==AppDomain::STAGE_HANDLETABLE_NOACCESS)
10615         {
10616             AppDomain* pAppDomain=*ppDomain;
10617             pAppDomain->SetStage(AppDomain::STAGE_CLEARED);
10618         }
10619         ppDomain=&((*ppDomain)->m_pNextInDelayedUnloadList);
10620     }
10621         
10622     if (!m_UnloadIsAsync)
10623     {
10624         // For synchronous mode, we are now done with the list.
10625         m_pDelayedUnloadList = NULL;    
10626     }
10627 }
10628
10629 void SystemDomain::ProcessDelayedUnloadDomains()
10630 {
10631     CONTRACTL
10632     {
10633         NOTHROW;
10634         GC_TRIGGERS;
10635         MODE_COOPERATIVE;
10636     }
10637     CONTRACTL_END;    
10638
10639     int iGCRefPoint=GCHeapUtilities::GetGCHeap()->CollectionCount(GCHeapUtilities::GetGCHeap()->GetMaxGeneration());
10640     if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCInProgress())
10641         iGCRefPoint--;
10642
10643     BOOL bAppDomainToCleanup = FALSE;
10644     LoaderAllocator * pAllocatorsToDelete = NULL;
10645
10646     {
10647         CrstHolder lh(&m_DelayedUnloadCrst); 
10648
10649         for (AppDomain* pDomain=m_pDelayedUnloadList; pDomain!=NULL; pDomain=pDomain->m_pNextInDelayedUnloadList)
10650         {
10651             if (pDomain->m_Stage==AppDomain::STAGE_CLEARED)
10652             {
10653                 // Compare with 0 to handle overflows gracefully
10654                 if (0 < iGCRefPoint - pDomain->GetGCRefPoint())
10655                 {
10656                     bAppDomainToCleanup=TRUE;
10657                     pDomain->SetStage(AppDomain::STAGE_COLLECTED);
10658                 }
10659             }
10660         }
10661
10662         LoaderAllocator ** ppAllocator=&m_pDelayedUnloadListOfLoaderAllocators;
10663         while (*ppAllocator!= NULL)
10664         {
10665             LoaderAllocator * pAllocator = *ppAllocator;
10666             if (0 < iGCRefPoint - pAllocator->GetGCRefPoint())
10667             {
10668                 *ppAllocator = pAllocator->m_pLoaderAllocatorDestroyNext;
10669
10670                 pAllocator->m_pLoaderAllocatorDestroyNext = pAllocatorsToDelete;
10671                 pAllocatorsToDelete = pAllocator;
10672             }
10673             else
10674             {
10675                 ppAllocator = &pAllocator->m_pLoaderAllocatorDestroyNext;
10676             }
10677         }
10678     }
10679
10680     if (bAppDomainToCleanup)
10681         AppDomain::EnableADUnloadWorkerForCollectedADCleanup();
10682
10683     // Delete collected loader allocators on the finalizer thread. We cannot offload it to appdomain unload thread because of 
10684     // there is not guaranteed to be one, and it is not that expensive operation anyway.
10685     while (pAllocatorsToDelete != NULL)
10686     {
10687         LoaderAllocator * pAllocator = pAllocatorsToDelete;
10688         pAllocatorsToDelete = pAllocator->m_pLoaderAllocatorDestroyNext;
10689         delete pAllocator;
10690     }
10691 }
10692
10693 #endif // CROSSGEN_COMPILE
10694
10695 AppDomainFromIDHolder::AppDomainFromIDHolder(ADID adId, BOOL bUnsafePoint, SyncType synctype)
10696 {
10697     WRAPPER_NO_CONTRACT;
10698     ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
10699 #ifdef _DEBUG
10700     m_bAcquired=false;   
10701     m_bChecked=false;
10702     m_type=synctype;
10703     
10704 #endif
10705     Assign(adId, bUnsafePoint);
10706 }
10707
10708 AppDomainFromIDHolder::AppDomainFromIDHolder(SyncType synctype)
10709 {
10710     LIMITED_METHOD_CONTRACT;
10711     ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT;
10712     m_pDomain=NULL;
10713 #ifdef _DEBUG
10714     m_bAcquired=false;
10715     m_bChecked=false;
10716     m_type=synctype;
10717 #endif
10718 }
10719
10720 #ifndef CROSSGEN_COMPILE
10721 void ADUnloadSink::ReportUnloadResult (HRESULT hr, OBJECTREF* pException)
10722 {
10723     CONTRACTL
10724     {
10725         NOTHROW;
10726         GC_NOTRIGGER;
10727         PRECONDITION(CheckPointer(this));
10728         PRECONDITION(m_UnloadCompleteEvent.IsValid());
10729     }
10730     CONTRACTL_END;
10731
10732     //pException is unused;
10733     m_UnloadResult=hr;
10734     m_UnloadCompleteEvent.Set();
10735 };
10736
10737 void ADUnloadSink::WaitUnloadCompletion()
10738 {
10739     CONTRACTL
10740     {
10741         THROWS;
10742         GC_TRIGGERS;
10743         PRECONDITION(CheckPointer(this));
10744         PRECONDITION(m_UnloadCompleteEvent.IsValid());
10745     }
10746     CONTRACTL_END;
10747
10748     CONTRACT_VIOLATION(FaultViolation);
10749     m_UnloadCompleteEvent.WaitEx(INFINITE, (WaitMode)(WaitMode_Alertable | WaitMode_ADUnload));
10750 };
10751
10752 ADUnloadSink* AppDomain::PrepareForWaitUnloadCompletion()
10753 {
10754     CONTRACTL
10755     {
10756         NOTHROW;
10757         GC_NOTRIGGER;
10758         PRECONDITION(SystemDomain::IsUnderDomainLock());
10759         FORBID_FAULT;
10760     }
10761     CONTRACTL_END;
10762
10763     ADUnloadSink* pADSink=GetADUnloadSink();
10764     PREFIX_ASSUME(pADSink!=NULL);
10765     if (m_Stage < AppDomain::STAGE_UNLOAD_REQUESTED) //we're first
10766     {
10767         pADSink->Reset();
10768         SetUnloadRequestThread(GetThread());
10769     }
10770     return pADSink;
10771 };
10772
10773 ADUnloadSink::ADUnloadSink()
10774 {
10775     CONTRACTL
10776     {
10777         CONSTRUCTOR_CHECK;
10778         THROWS;
10779         GC_NOTRIGGER;
10780         MODE_ANY;
10781         INJECT_FAULT(COMPlusThrowOM(););
10782     }
10783     CONTRACTL_END;
10784
10785     m_cRef=1;
10786     m_UnloadCompleteEvent.CreateManualEvent(FALSE);
10787     m_UnloadResult=S_OK;
10788 };
10789
10790 ADUnloadSink::~ADUnloadSink()
10791 {
10792     CONTRACTL
10793     {
10794         DESTRUCTOR_CHECK;
10795         NOTHROW;
10796         GC_NOTRIGGER;
10797         MODE_ANY;
10798     }
10799     CONTRACTL_END;
10800     m_UnloadCompleteEvent.CloseEvent();
10801
10802 };
10803
10804
10805 ULONG ADUnloadSink::AddRef()
10806 {
10807     LIMITED_METHOD_CONTRACT;
10808     return InterlockedIncrement(&m_cRef);
10809 };
10810
10811 ULONG ADUnloadSink::Release()
10812 {
10813     LIMITED_METHOD_CONTRACT;
10814     ULONG ulRef = InterlockedDecrement(&m_cRef);
10815     if (ulRef == 0)
10816     {
10817         delete this;
10818     }
10819     return ulRef;
10820 };
10821
10822 void ADUnloadSink::Reset()
10823 {
10824     LIMITED_METHOD_CONTRACT;
10825     m_UnloadResult=S_OK;
10826     m_UnloadCompleteEvent.Reset();
10827 }
10828
10829 ADUnloadSink* AppDomain::GetADUnloadSink()
10830 {
10831     LIMITED_METHOD_CONTRACT;
10832     _ASSERTE(SystemDomain::IsUnderDomainLock());
10833     if(m_ADUnloadSink)
10834         m_ADUnloadSink->AddRef();
10835     return m_ADUnloadSink;
10836 };
10837
10838 ADUnloadSink* AppDomain::GetADUnloadSinkForUnload()
10839 {
10840     // unload thread only. Doesn't need to have AD lock
10841     LIMITED_METHOD_CONTRACT;
10842     if(m_ADUnloadSink)
10843         m_ADUnloadSink->AddRef();
10844     return m_ADUnloadSink;
10845 }
10846 #endif // CROSSGEN_COMPILE
10847
10848 void AppDomain::EnumStaticGCRefs(promote_func* fn, ScanContext* sc)
10849 {
10850     CONTRACT_VOID
10851     {
10852         NOTHROW;
10853         GC_NOTRIGGER;
10854     }
10855     CONTRACT_END;
10856
10857     _ASSERTE(GCHeapUtilities::IsGCInProgress() &&
10858              GCHeapUtilities::IsServerHeap()   &&
10859              IsGCSpecialThread());
10860
10861     AppDomain::AssemblyIterator asmIterator = IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution));
10862     CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
10863     while (asmIterator.Next(pDomainAssembly.This()))
10864     {
10865         // @TODO: Review when DomainAssemblies get added.
10866         _ASSERTE(pDomainAssembly != NULL);
10867         pDomainAssembly->EnumStaticGCRefs(fn, sc);
10868     }
10869
10870     RETURN;
10871 }
10872
10873 #endif // !DACCESS_COMPILE
10874
10875 //------------------------------------------------------------------------
10876 UINT32 BaseDomain::GetTypeID(PTR_MethodTable pMT) {
10877     CONTRACTL {
10878         THROWS;
10879         GC_TRIGGERS;
10880         PRECONDITION(pMT->GetDomain() == this);
10881     } CONTRACTL_END;
10882
10883     return m_typeIDMap.GetTypeID(pMT);
10884 }
10885
10886 //------------------------------------------------------------------------
10887 // Returns the ID of the type if found. If not found, returns INVALID_TYPE_ID
10888 UINT32 BaseDomain::LookupTypeID(PTR_MethodTable pMT)
10889 {
10890     CONTRACTL {
10891         NOTHROW;
10892         SO_TOLERANT;
10893         WRAPPER(GC_TRIGGERS);
10894         PRECONDITION(pMT->GetDomain() == this);
10895     } CONTRACTL_END;
10896
10897     return m_typeIDMap.LookupTypeID(pMT);
10898 }
10899
10900 //------------------------------------------------------------------------
10901 PTR_MethodTable BaseDomain::LookupType(UINT32 id) {
10902     CONTRACTL {
10903         NOTHROW;
10904         SO_TOLERANT;
10905         WRAPPER(GC_TRIGGERS);
10906         CONSISTENCY_CHECK(id != TYPE_ID_THIS_CLASS);
10907     } CONTRACTL_END;
10908
10909     PTR_MethodTable pMT = m_typeIDMap.LookupType(id);
10910     if (pMT == NULL && !IsSharedDomain()) {
10911         pMT = SharedDomain::GetDomain()->LookupType(id);
10912     }
10913
10914     CONSISTENCY_CHECK(CheckPointer(pMT));
10915     CONSISTENCY_CHECK(pMT->IsInterface());
10916     return pMT;
10917 }
10918
10919 //---------------------------------------------------------------------------------------
10920 // 
10921 BOOL 
10922 AppDomain::AssemblyIterator::Next(
10923     CollectibleAssemblyHolder<DomainAssembly *> * pDomainAssemblyHolder)
10924 {
10925     CONTRACTL {
10926         NOTHROW;
10927         WRAPPER(GC_TRIGGERS); // Triggers only in MODE_COOPERATIVE (by taking the lock)
10928         MODE_ANY;
10929     } CONTRACTL_END;
10930     
10931     CrstHolder ch(m_pAppDomain->GetAssemblyListLock());
10932     return Next_Unlocked(pDomainAssemblyHolder);
10933 }
10934
10935 //---------------------------------------------------------------------------------------
10936 // 
10937 // Note: Does not lock the assembly list, but locks collectible assemblies for adding references.
10938 // 
10939 BOOL 
10940 AppDomain::AssemblyIterator::Next_Unlocked(
10941     CollectibleAssemblyHolder<DomainAssembly *> * pDomainAssemblyHolder)
10942 {
10943     CONTRACTL {
10944         NOTHROW;
10945         GC_NOTRIGGER;
10946         MODE_ANY;
10947     } CONTRACTL_END;
10948     
10949 #ifndef DACCESS_COMPILE
10950     _ASSERTE(m_pAppDomain->GetAssemblyListLock()->OwnedByCurrentThread());
10951 #endif
10952     
10953     while (m_Iterator.Next())
10954     {
10955         // Get element from the list/iterator (without adding reference to the assembly)
10956         DomainAssembly * pDomainAssembly = dac_cast<PTR_DomainAssembly>(m_Iterator.GetElement());
10957         if (pDomainAssembly == NULL)
10958         {
10959             continue;
10960         }
10961
10962         if (pDomainAssembly->IsError())
10963         {
10964             if (m_assemblyIterationFlags & kIncludeFailedToLoad)
10965             {
10966                 *pDomainAssemblyHolder = pDomainAssembly;
10967                 return TRUE;
10968             }
10969             continue; // reject
10970         }
10971
10972         // First, reject DomainAssemblies whose load status is not to be included in
10973         // the enumeration
10974         
10975         if (pDomainAssembly->IsAvailableToProfilers() && 
10976             (m_assemblyIterationFlags & kIncludeAvailableToProfilers))
10977         {
10978             // The assembly has reached the state at which we would notify profilers,
10979             // and we're supposed to include such assemblies in the enumeration. So
10980             // don't reject it (i.e., noop here, and don't bother with the rest of
10981             // the load status checks). Check for this first, since
10982             // kIncludeAvailableToProfilers contains some loaded AND loading
10983             // assemblies.
10984         }
10985         else if (pDomainAssembly->IsLoaded())
10986         {
10987             // A loaded assembly
10988             if (!(m_assemblyIterationFlags & kIncludeLoaded))
10989             {
10990                 continue; // reject
10991             }
10992         }
10993         else
10994         {
10995             // A loading assembly
10996             if (!(m_assemblyIterationFlags & kIncludeLoading))
10997             {
10998                 continue; // reject
10999             }
11000         }
11001
11002         // Next, reject DomainAssemblies whose execution / introspection status is
11003         // not to be included in the enumeration
11004         
11005         if (pDomainAssembly->IsIntrospectionOnly())
11006         {
11007             // introspection assembly
11008             if (!(m_assemblyIterationFlags & kIncludeIntrospection))
11009             {
11010                 continue; // reject
11011             }
11012         }
11013         else
11014         {
11015             // execution assembly
11016             if (!(m_assemblyIterationFlags & kIncludeExecution))
11017             {
11018                 continue; // reject
11019             }
11020         }
11021
11022         // Next, reject collectible assemblies
11023         if (pDomainAssembly->IsCollectible())
11024         {
11025             if (m_assemblyIterationFlags & kExcludeCollectible)
11026             {
11027                 _ASSERTE(!(m_assemblyIterationFlags & kIncludeCollected));
11028                 continue; // reject
11029             }
11030             
11031             // Un-tenured collectible assemblies should not be returned. (This can only happen in a brief
11032             // window during collectible assembly creation. No thread should need to have a pointer
11033             // to the just allocated DomainAssembly at this stage.)
11034             if (!pDomainAssembly->GetAssembly()->GetManifestModule()->IsTenured())
11035             {
11036                 continue; // reject
11037             }
11038
11039             if (pDomainAssembly->GetLoaderAllocator()->AddReferenceIfAlive())
11040             {   // The assembly is alive
11041                 
11042                 // Set the holder value (incl. increasing ref-count)
11043                 *pDomainAssemblyHolder = pDomainAssembly;
11044                 
11045                 // Now release the reference we took in the if-condition
11046                 pDomainAssembly->GetLoaderAllocator()->Release();
11047                 return TRUE;
11048             }
11049             // The assembly is not alive anymore (and we didn't increase its ref-count in the 
11050             // if-condition)
11051             
11052             if (!(m_assemblyIterationFlags & kIncludeCollected))
11053             {
11054                 continue; // reject
11055             }
11056             // Set the holder value to assembly with 0 ref-count without increasing the ref-count (won't 
11057             // call Release either)
11058             pDomainAssemblyHolder->Assign(pDomainAssembly, FALSE);
11059             return TRUE;
11060         }
11061
11062         *pDomainAssemblyHolder = pDomainAssembly;
11063         return TRUE;
11064     }
11065
11066     *pDomainAssemblyHolder = NULL;
11067     return FALSE;
11068 } // AppDomain::AssemblyIterator::Next_Unlocked
11069
11070 #ifndef DACCESS_COMPILE
11071
11072 //---------------------------------------------------------------------------------------
11073 // 
11074 // Can be called only from AppDomain shutdown code:AppDomain::ShutdownAssemblies.
11075 // Does not add-ref collectible assemblies (as the LoaderAllocator might not be reachable from the 
11076 // DomainAssembly anymore).
11077 // 
11078 BOOL 
11079 AppDomain::AssemblyIterator::Next_UnsafeNoAddRef(
11080     DomainAssembly ** ppDomainAssembly)
11081 {
11082     CONTRACTL {
11083         NOTHROW;
11084         GC_TRIGGERS;
11085         MODE_ANY;
11086     } CONTRACTL_END;
11087     
11088     // Make sure we are iterating all assemblies (see the only caller code:AppDomain::ShutdownAssemblies)
11089     _ASSERTE(m_assemblyIterationFlags == 
11090         (kIncludeLoaded | kIncludeLoading | kIncludeExecution | kIncludeIntrospection | kIncludeFailedToLoad | kIncludeCollected));
11091     // It also means that we do not exclude anything
11092     _ASSERTE((m_assemblyIterationFlags & kExcludeCollectible) == 0);
11093     
11094     // We are on shutdown path, so lock shouldn't be neccessary, but all _Unlocked methods on AssemblyList 
11095     // have asserts that the lock is held, so why not to take it ...
11096     CrstHolder ch(m_pAppDomain->GetAssemblyListLock());
11097     
11098     while (m_Iterator.Next())
11099     {
11100         // Get element from the list/iterator (without adding reference to the assembly)
11101         *ppDomainAssembly = dac_cast<PTR_DomainAssembly>(m_Iterator.GetElement());
11102         if (*ppDomainAssembly == NULL)
11103         {
11104             continue;
11105         }
11106         
11107         return TRUE;
11108     }
11109     
11110     *ppDomainAssembly = NULL;
11111     return FALSE;
11112 } // AppDomain::AssemblyIterator::Next_UnsafeNoAddRef
11113
11114
11115 //---------------------------------------------------------------------------------------
11116 // 
11117 BOOL AppDomain::IsImageFromTrustedPath(PEImage* pPEImage)
11118 {
11119     CONTRACTL
11120     {
11121         MODE_ANY;
11122         GC_TRIGGERS;
11123         THROWS;
11124         PRECONDITION(CheckPointer(pPEImage));
11125     }
11126     CONTRACTL_END;
11127
11128     const SString &sImagePath = pPEImage->GetPath();
11129
11130     return !sImagePath.IsEmpty();
11131 }
11132
11133 #endif //!DACCESS_COMPILE
11134
11135 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
11136
11137 // Returns a BOOL indicating if the binding model has been locked for the AppDomain
11138 BOOL AppDomain::IsBindingModelLocked()
11139 {
11140     CONTRACTL
11141     {
11142         NOTHROW;
11143         GC_NOTRIGGER;
11144         MODE_ANY;
11145     }
11146     CONTRACTL_END;
11147     
11148     return m_fIsBindingModelLocked.Load();
11149 }
11150
11151 // Marks the binding model locked for AppDomain
11152 BOOL AppDomain::LockBindingModel()
11153 {
11154     LIMITED_METHOD_CONTRACT;
11155     
11156     BOOL fDidWeLockBindingModel = FALSE;
11157     
11158     if (InterlockedCompareExchangeT<BOOL>(&m_fIsBindingModelLocked, TRUE, FALSE) == FALSE)
11159     {
11160         fDidWeLockBindingModel = TRUE;
11161     }
11162     
11163     return fDidWeLockBindingModel;
11164 }
11165
11166 BOOL AppDomain::IsHostAssemblyResolverInUse()
11167 {
11168     LIMITED_METHOD_CONTRACT;
11169     
11170     return (GetFusionContext() != GetTPABinderContext());
11171 }
11172
11173 // Helper used by the assembly binder to check if the specified AppDomain can use apppath assembly resolver
11174 BOOL RuntimeCanUseAppPathAssemblyResolver(DWORD adid)
11175 {
11176     CONTRACTL
11177     {
11178         NOTHROW; // Cannot throw since it is invoked by the Binder that expects to get a hresult
11179         GC_TRIGGERS;
11180         MODE_ANY;
11181     }
11182     CONTRACTL_END;
11183
11184     ADID id(adid);
11185
11186     // We need to be in COOP mode to get the AppDomain*
11187     GCX_COOP();
11188         
11189     AppDomain *pTargetDomain = SystemDomain::GetAppDomainFromId(id, ADV_CURRENTAD);
11190     _ASSERTE(pTargetDomain != NULL);
11191
11192     pTargetDomain->LockBindingModel();
11193         
11194     return !pTargetDomain->IsHostAssemblyResolverInUse();
11195 }
11196
11197 // Returns S_OK if the assembly was successfully loaded
11198 HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToBindWithin, IAssemblyName *pIAssemblyName, CLRPrivBinderCoreCLR *pTPABinder, BINDER_SPACE::AssemblyName *pAssemblyName, ICLRPrivAssembly **ppLoadedAssembly)
11199 {
11200     CONTRACTL
11201     {
11202         THROWS;
11203         GC_TRIGGERS;
11204         MODE_ANY;
11205         PRECONDITION(ppLoadedAssembly != NULL);
11206     }
11207     CONTRACTL_END;
11208     
11209     HRESULT hr = E_FAIL;
11210
11211     // DevDiv #933506: Exceptions thrown during AssemblyLoadContext.Load should propagate
11212     // EX_TRY
11213     {
11214         // Switch to COOP mode since we are going to work with managed references
11215         GCX_COOP();
11216         
11217         struct 
11218         {
11219             ASSEMBLYNAMEREF oRefAssemblyName;
11220             ASSEMBLYREF oRefLoadedAssembly;
11221         } _gcRefs;
11222         
11223         ZeroMemory(&_gcRefs, sizeof(_gcRefs));
11224         
11225         GCPROTECT_BEGIN(_gcRefs);
11226         
11227         ICLRPrivAssembly *pAssemblyBindingContext = NULL;
11228
11229         bool fInvokedForTPABinder = (pTPABinder == NULL)?true:false;
11230         
11231         // Prepare to invoke System.Runtime.Loader.AssemblyLoadContext.Resolve method.
11232         //
11233         // First, initialize an assembly spec for the requested assembly
11234         //
11235         AssemblySpec spec;
11236         hr = spec.Init(pIAssemblyName);
11237         if (SUCCEEDED(hr))
11238         {
11239             bool fResolvedAssembly = false;
11240             bool fResolvedAssemblyViaTPALoadContext = false;
11241
11242             // Allocate an AssemblyName managed object
11243             _gcRefs.oRefAssemblyName = (ASSEMBLYNAMEREF) AllocateObject(MscorlibBinder::GetClass(CLASS__ASSEMBLY_NAME));
11244             
11245             // Initialize the AssemblyName object from the AssemblySpec
11246             spec.AssemblyNameInit(&_gcRefs.oRefAssemblyName, NULL);
11247                 
11248             if (!fInvokedForTPABinder)
11249             {
11250                 // Step 2 (of CLRPrivBinderAssemblyLoadContext::BindUsingAssemblyName) - Invoke Load method
11251                 // This is not invoked for TPA Binder since it always returns NULL.
11252
11253                 // Finally, setup arguments for invocation
11254                 BinderMethodID idHAR_Resolve = METHOD__ASSEMBLYLOADCONTEXT__RESOLVE;
11255                 MethodDescCallSite methLoadAssembly(idHAR_Resolve);
11256                 
11257                 // Setup the arguments for the call
11258                 ARG_SLOT args[2] =
11259                 {
11260                     PtrToArgSlot(pManagedAssemblyLoadContextToBindWithin), // IntPtr for managed assembly load context instance
11261                     ObjToArgSlot(_gcRefs.oRefAssemblyName), // AssemblyName instance
11262                 };
11263
11264                 // Make the call
11265                 _gcRefs.oRefLoadedAssembly = (ASSEMBLYREF) methLoadAssembly.Call_RetOBJECTREF(args);
11266                 if (_gcRefs.oRefLoadedAssembly != NULL)
11267                 {
11268                     fResolvedAssembly = true;
11269                 }
11270             
11271                 // Step 3 (of CLRPrivBinderAssemblyLoadContext::BindUsingAssemblyName)
11272                 if (!fResolvedAssembly)
11273                 {
11274                     // If we could not resolve the assembly using Load method, then attempt fallback with TPA Binder.
11275                     // Since TPA binder cannot fallback to itself, this fallback does not happen for binds within TPA binder.
11276                     //
11277                     // Switch to pre-emp mode before calling into the binder
11278                     GCX_PREEMP();
11279                     ICLRPrivAssembly *pCoreCLRFoundAssembly = NULL;
11280                     hr = pTPABinder->BindAssemblyByName(pIAssemblyName, &pCoreCLRFoundAssembly);
11281                     if (SUCCEEDED(hr))
11282                     {
11283                         pAssemblyBindingContext = pCoreCLRFoundAssembly;
11284                         fResolvedAssembly = true;
11285                         fResolvedAssemblyViaTPALoadContext = true;
11286                     }
11287                 }
11288             }
11289             
11290             if (!fResolvedAssembly)
11291             {
11292                 // Step 4 (of CLRPrivBinderAssemblyLoadContext::BindUsingAssemblyName)
11293                 //
11294                 // If we couldnt resolve the assembly using TPA LoadContext as well, then
11295                 // attempt to resolve it using the Resolving event.
11296                 // Finally, setup arguments for invocation
11297                 BinderMethodID idHAR_ResolveUsingEvent = METHOD__ASSEMBLYLOADCONTEXT__RESOLVEUSINGEVENT;
11298                 MethodDescCallSite methLoadAssembly(idHAR_ResolveUsingEvent);
11299                 
11300                 // Setup the arguments for the call
11301                 ARG_SLOT args[2] =
11302                 {
11303                     PtrToArgSlot(pManagedAssemblyLoadContextToBindWithin), // IntPtr for managed assembly load context instance
11304                     ObjToArgSlot(_gcRefs.oRefAssemblyName), // AssemblyName instance
11305                 };
11306
11307                 // Make the call
11308                 _gcRefs.oRefLoadedAssembly = (ASSEMBLYREF) methLoadAssembly.Call_RetOBJECTREF(args);
11309                 if (_gcRefs.oRefLoadedAssembly != NULL)
11310                 {
11311                     // Set the flag indicating we found the assembly
11312                     fResolvedAssembly = true;
11313                 }
11314             }
11315             
11316             if (fResolvedAssembly && !fResolvedAssemblyViaTPALoadContext)
11317             {
11318                 // If we are here, assembly was successfully resolved via Load or Resolving events.
11319                 _ASSERTE(_gcRefs.oRefLoadedAssembly != NULL);
11320                     
11321                 // We were able to get the assembly loaded. Now, get its name since the host could have
11322                 // performed the resolution using an assembly with different name.
11323                 DomainAssembly *pDomainAssembly = _gcRefs.oRefLoadedAssembly->GetDomainAssembly();
11324                 PEAssembly *pLoadedPEAssembly = NULL;
11325                 bool fFailLoad = false;
11326                 if (!pDomainAssembly)
11327                 {
11328                     // Reflection emitted assemblies will not have a domain assembly.
11329                     fFailLoad = true;
11330                 }
11331                 else
11332                 {
11333                     pLoadedPEAssembly = pDomainAssembly->GetFile();
11334                     if (pLoadedPEAssembly->HasHostAssembly() != true)
11335                     {
11336                         // Reflection emitted assemblies will not have a domain assembly.
11337                         fFailLoad = true;
11338                     }
11339                 }
11340                 
11341                 // The loaded assembly's ICLRPrivAssembly* is saved as HostAssembly in PEAssembly
11342                 if (fFailLoad)
11343                 {
11344                     SString name;
11345                     spec.GetFileOrDisplayName(0, name);
11346                     COMPlusThrowHR(COR_E_INVALIDOPERATION, IDS_HOST_ASSEMBLY_RESOLVER_DYNAMICALLY_EMITTED_ASSEMBLIES_UNSUPPORTED, name);
11347                 }
11348                 
11349                 // Is the assembly already bound using a binding context that will be incompatible?
11350                 // An example is attempting to consume an assembly bound to WinRT binder.
11351                 pAssemblyBindingContext = pLoadedPEAssembly->GetHostAssembly();
11352             }
11353             
11354 #ifdef FEATURE_COMINTEROP
11355             if (AreSameBinderInstance(pAssemblyBindingContext, GetAppDomain()->GetWinRtBinder()))
11356             {
11357                 // It is invalid to return an assembly bound to an incompatible binder
11358                 *ppLoadedAssembly = NULL;
11359                 SString name;
11360                 spec.GetFileOrDisplayName(0, name);
11361                 COMPlusThrowHR(COR_E_INVALIDOPERATION, IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_BINDING_CONTEXT, name);
11362             }
11363 #endif // FEATURE_COMINTEROP
11364
11365             // Get the ICLRPrivAssembly reference to return back to.
11366             *ppLoadedAssembly = clr::SafeAddRef(pAssemblyBindingContext);
11367             hr = S_OK;
11368         }
11369         
11370         GCPROTECT_END();
11371     }
11372     // EX_CATCH_HRESULT(hr);
11373     
11374     return hr;
11375     
11376 }
11377 #endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
11378
11379 //approximate size of loader data
11380 //maintained for each assembly
11381 #define APPROX_LOADER_DATA_PER_ASSEMBLY 8196
11382
11383 size_t AppDomain::EstimateSize()
11384 {
11385     CONTRACTL
11386     {
11387         NOTHROW;
11388         GC_TRIGGERS;
11389         MODE_ANY;
11390     }
11391     CONTRACTL_END;
11392     
11393     size_t retval = sizeof(AppDomain);
11394     retval += GetLoaderAllocator()->EstimateSize();
11395     //very rough estimate
11396     retval += GetAssemblyCount() * APPROX_LOADER_DATA_PER_ASSEMBLY;
11397     return retval;
11398 }
11399
11400 #ifdef DACCESS_COMPILE
11401
11402 void
11403 DomainLocalModule::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
11404 {
11405     SUPPORTS_DAC;
11406
11407     // Enumerate the DomainLocalModule itself. DLMs are allocated to be larger than
11408     // sizeof(DomainLocalModule) to make room for ClassInit flags and non-GC statics.
11409     // "DAC_ENUM_DTHIS()" probably does not account for this, so we might not enumerate
11410     // all of the ClassInit flags and non-GC statics.
11411     // sizeof(DomainLocalModule) == 0x28
11412     DAC_ENUM_DTHIS();
11413
11414     if (m_pDomainFile.IsValid())
11415     {
11416         m_pDomainFile->EnumMemoryRegions(flags);
11417     }
11418
11419     if (m_pDynamicClassTable.Load().IsValid())
11420     {
11421         DacEnumMemoryRegion(dac_cast<TADDR>(m_pDynamicClassTable.Load()),
11422                             m_aDynamicEntries * sizeof(DynamicClassInfo));
11423
11424         for (SIZE_T i = 0; i < m_aDynamicEntries; i++)
11425         {
11426             PTR_DynamicEntry entry = dac_cast<PTR_DynamicEntry>(m_pDynamicClassTable[i].m_pDynamicEntry.Load());
11427             if (entry.IsValid())
11428             {
11429                 // sizeof(DomainLocalModule::DynamicEntry) == 8
11430                 entry.EnumMem();
11431             }
11432         }
11433     }
11434 }
11435
11436 void
11437 DomainLocalBlock::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
11438 {
11439     SUPPORTS_DAC;
11440     // Block is contained in AppDomain, don't enum this.
11441
11442     if (m_pModuleSlots.IsValid())
11443     {
11444         DacEnumMemoryRegion(dac_cast<TADDR>(m_pModuleSlots),
11445                             m_aModuleIndices * sizeof(TADDR));
11446
11447         for (SIZE_T i = 0; i < m_aModuleIndices; i++)
11448         {
11449             PTR_DomainLocalModule domMod = m_pModuleSlots[i];
11450             if (domMod.IsValid())
11451             {
11452                 domMod->EnumMemoryRegions(flags);
11453             }
11454         }
11455     }
11456 }
11457
11458 void
11459 BaseDomain::EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
11460                               bool enumThis)
11461 {
11462     SUPPORTS_DAC;
11463     if (enumThis)
11464     {
11465         // This is wrong.  Don't do it.
11466         // BaseDomain cannot be instantiated.
11467         // The only thing this code can hope to accomplish is to potentially break
11468         // memory enumeration walking through the derived class if we
11469         // explicitly call the base class enum first.
11470 //        DAC_ENUM_VTHIS();
11471     }
11472
11473     EMEM_OUT(("MEM: %p BaseDomain\n", dac_cast<TADDR>(this)));
11474 }
11475
11476 void
11477 AppDomain::EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
11478                              bool enumThis)
11479 {
11480     SUPPORTS_DAC;
11481
11482     if (enumThis)
11483     {
11484         //sizeof(AppDomain) == 0xeb0
11485         DAC_ENUM_VTHIS();
11486     }
11487     BaseDomain::EnumMemoryRegions(flags, false);
11488
11489     // We don't need AppDomain name in triage dumps.
11490     if (flags != CLRDATA_ENUM_MEM_TRIAGE)
11491     {
11492         m_friendlyName.EnumMemoryRegions(flags);
11493     }
11494
11495     m_Assemblies.EnumMemoryRegions(flags);
11496     AssemblyIterator assem = IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution | kIncludeIntrospection));
11497     CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
11498     
11499     while (assem.Next(pDomainAssembly.This()))
11500     {
11501         pDomainAssembly->EnumMemoryRegions(flags);
11502     }
11503
11504     m_sDomainLocalBlock.EnumMemoryRegions(flags);
11505
11506     m_LoaderAllocator.EnumMemoryRegions(flags);
11507 }
11508
11509 void
11510 SystemDomain::EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
11511                                 bool enumThis)
11512 {
11513     SUPPORTS_DAC;
11514     if (enumThis)
11515     {
11516         DAC_ENUM_VTHIS();
11517     }
11518     BaseDomain::EnumMemoryRegions(flags, false);
11519
11520     if (m_pSystemFile.IsValid())
11521     {
11522         m_pSystemFile->EnumMemoryRegions(flags);
11523     }
11524     if (m_pSystemAssembly.IsValid())
11525     {
11526         m_pSystemAssembly->EnumMemoryRegions(flags);
11527     }
11528     if (m_pDefaultDomain.IsValid())
11529     {
11530         m_pDefaultDomain->EnumMemoryRegions(flags, true);
11531     }
11532
11533     m_appDomainIndexList.EnumMem();
11534     (&m_appDomainIndexList)->EnumMemoryRegions(flags);
11535 }
11536
11537 void
11538 SharedDomain::EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
11539                                 bool enumThis)
11540 {
11541     SUPPORTS_DAC;
11542     if (enumThis)
11543     {
11544         DAC_ENUM_VTHIS();
11545     }
11546     BaseDomain::EnumMemoryRegions(flags, false);
11547 #ifdef FEATURE_LOADER_OPTIMIZATION
11548     m_assemblyMap.EnumMemoryRegions(flags);
11549     SharedAssemblyIterator assem;
11550     while (assem.Next())
11551     {
11552         assem.GetAssembly()->EnumMemoryRegions(flags);
11553     }
11554 #endif    
11555 }
11556
11557 #endif //DACCESS_COMPILE
11558
11559
11560 PTR_LoaderAllocator SystemDomain::GetGlobalLoaderAllocator()
11561 {
11562     return PTR_LoaderAllocator(PTR_HOST_MEMBER_TADDR(SystemDomain,System(),m_GlobalAllocator));
11563 }
11564
11565 #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
11566
11567 #ifndef CROSSGEN_COMPILE
11568 // Return the total processor time (user and kernel) used by threads executing in this AppDomain so far. The
11569 // result is in 100ns units.
11570 ULONGLONG AppDomain::QueryProcessorUsage()
11571 {
11572     CONTRACTL
11573     {
11574         NOTHROW;
11575         GC_TRIGGERS;
11576         MODE_ANY;
11577     }
11578     CONTRACTL_END;
11579
11580 #ifndef DACCESS_COMPILE
11581     Thread *pThread = NULL;
11582
11583     // Need to update our accumulated processor time count with current values from each thread that is
11584     // currently executing in this domain.
11585
11586     // Take the thread store lock while we enumerate threads.
11587     ThreadStoreLockHolder tsl;
11588     while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
11589     {
11590         // Skip unstarted and dead threads and those that are currently executing in a different AppDomain.
11591         if (pThread->IsUnstarted() || pThread->IsDead() || pThread->GetDomain(INDEBUG(TRUE)) != this)
11592             continue;
11593
11594         // Add the amount of time spent by the thread in the AppDomain since the last time we asked (calling
11595         // Thread::QueryThreadProcessorUsage() will reset the thread's counter).
11596         UpdateProcessorUsage(pThread->QueryThreadProcessorUsage());
11597     }
11598 #endif // !DACCESS_COMPILE
11599
11600     // Return the updated total.
11601     return m_ullTotalProcessorUsage;
11602 }
11603
11604 // Add to the current count of processor time used by threads within this AppDomain. This API is called by
11605 // threads transitioning between AppDomains.
11606 void AppDomain::UpdateProcessorUsage(ULONGLONG ullAdditionalUsage)
11607 {
11608     LIMITED_METHOD_CONTRACT;
11609
11610     // Need to be careful to synchronize here, multiple threads could be racing to update this count.
11611     ULONGLONG ullOldValue;
11612     ULONGLONG ullNewValue;
11613     do
11614     {
11615         ullOldValue = m_ullTotalProcessorUsage;
11616         ullNewValue = ullOldValue + ullAdditionalUsage;
11617     } while (InterlockedCompareExchange64((LONGLONG*)&m_ullTotalProcessorUsage,
11618                                           (LONGLONG)ullNewValue,
11619                                           (LONGLONG)ullOldValue) != (LONGLONG)ullOldValue);
11620 }
11621 #endif // CROSSGEN_COMPILE
11622
11623 #endif // FEATURE_APPDOMAIN_RESOURCE_MONITORING
11624
11625 #if defined(FEATURE_TYPEEQUIVALENCE)
11626
11627 #ifndef DACCESS_COMPILE
11628 TypeEquivalenceHashTable * AppDomain::GetTypeEquivalenceCache()
11629 {
11630     CONTRACTL
11631     {
11632         THROWS;
11633         GC_TRIGGERS;
11634         INJECT_FAULT(COMPlusThrowOM());
11635         MODE_ANY;
11636     }
11637     CONTRACTL_END;
11638
11639     // Take the critical section all of the time in debug builds to ensure that it is safe to take
11640     // the critical section in the unusual times when it may actually be needed in retail builds
11641 #ifdef _DEBUG
11642     CrstHolder ch(&m_TypeEquivalenceCrst);
11643 #endif
11644
11645     if (m_pTypeEquivalenceTable.Load() == NULL)
11646     {
11647 #ifndef _DEBUG
11648         CrstHolder ch(&m_TypeEquivalenceCrst);
11649 #endif
11650         if (m_pTypeEquivalenceTable.Load() == NULL)
11651         {
11652             m_pTypeEquivalenceTable = TypeEquivalenceHashTable::Create(this, 12, &m_TypeEquivalenceCrst);
11653         }
11654     }
11655     return m_pTypeEquivalenceTable;
11656 }
11657 #endif //!DACCESS_COMPILE
11658
11659 #endif //FEATURE_TYPEEQUIVALENCE
11660
11661 #if !defined(DACCESS_COMPILE)
11662
11663 //---------------------------------------------------------------------------------------------------------------------
11664 void AppDomain::PublishHostedAssembly(
11665     DomainAssembly * pDomainAssembly)
11666 {
11667     CONTRACTL
11668     {
11669         THROWS;
11670         GC_NOTRIGGER;
11671         MODE_ANY;
11672     }
11673     CONTRACTL_END
11674
11675     if (pDomainAssembly->GetFile()->HasHostAssembly())
11676     {
11677         // We have to serialize all Add operations
11678         CrstHolder lockAdd(&m_crstHostAssemblyMapAdd);
11679         _ASSERTE(m_hostAssemblyMap.Lookup(pDomainAssembly->GetFile()->GetHostAssembly()) == nullptr);
11680         
11681         // Wrapper for m_hostAssemblyMap.Add that avoids call out into host
11682         HostAssemblyMap::AddPhases addCall;
11683         
11684         // 1. Preallocate one element
11685         addCall.PreallocateForAdd(&m_hostAssemblyMap);
11686         {
11687             // 2. Take the reader lock which can be taken during stack walking
11688             // We cannot call out into host from ForbidSuspend region (i.e. no allocations/deallocations)
11689             ForbidSuspendThreadHolder suspend;
11690             {
11691                 CrstHolder lock(&m_crstHostAssemblyMap);
11692                 // 3. Add the element to the hash table (no call out into host)
11693                 addCall.Add(pDomainAssembly);
11694             }
11695         }
11696         // 4. Cleanup the old memory (if any)
11697         addCall.DeleteOldTable();
11698     }
11699     else
11700     {
11701     }
11702 }
11703
11704 //---------------------------------------------------------------------------------------------------------------------
11705 void AppDomain::UpdatePublishHostedAssembly(
11706     DomainAssembly * pAssembly, 
11707     PTR_PEFile       pFile)
11708 {
11709     CONTRACTL
11710     {
11711         THROWS;
11712         GC_NOTRIGGER;
11713         MODE_ANY;
11714         CAN_TAKE_LOCK;
11715     }
11716     CONTRACTL_END
11717
11718     if (pAssembly->GetFile()->HasHostAssembly())
11719     {
11720         // We have to serialize all Add operations
11721         CrstHolder lockAdd(&m_crstHostAssemblyMapAdd);
11722         {
11723             // Wrapper for m_hostAssemblyMap.Add that avoids call out into host
11724             OriginalFileHostAssemblyMap::AddPhases addCall;
11725             bool fAddOrigFile = false;
11726         
11727             // For cases where the pefile is being updated 
11728             // 1. Preallocate one element
11729             if (pFile != pAssembly->GetFile())
11730             {
11731                 addCall.PreallocateForAdd(&m_hostAssemblyMapForOrigFile);
11732                 fAddOrigFile = true;
11733             }
11734
11735             {
11736                 // We cannot call out into host from ForbidSuspend region (i.e. no allocations/deallocations)
11737                 ForbidSuspendThreadHolder suspend;
11738                 {
11739                     CrstHolder lock(&m_crstHostAssemblyMap);
11740                 
11741                     // Remove from hash table.
11742                     _ASSERTE(m_hostAssemblyMap.Lookup(pAssembly->GetFile()->GetHostAssembly()) != nullptr);
11743                     m_hostAssemblyMap.Remove(pAssembly->GetFile()->GetHostAssembly());
11744                 
11745                     // Update PEFile on DomainAssembly. (This may cause the key for the hash to change, which is why we need this function)
11746                     pAssembly->UpdatePEFileWorker(pFile);
11747                 
11748                     _ASSERTE(fAddOrigFile == (pAssembly->GetOriginalFile() != pAssembly->GetFile()));
11749                     if (fAddOrigFile)
11750                     {
11751                         // Add to the orig file hash table if we might be in a case where we've cached the original pefile and not the final pe file (for use during GetAssemblyIfLoaded)
11752                         addCall.Add(pAssembly);
11753                     }
11754
11755                     // Add back to the hashtable (the call to Remove above guarantees that we will not call into host for table reallocation)
11756                     _ASSERTE(m_hostAssemblyMap.Lookup(pAssembly->GetFile()->GetHostAssembly()) == nullptr);
11757                     m_hostAssemblyMap.Add(pAssembly);
11758                 }
11759             }
11760
11761             // 4. Cleanup the old memory (if any)
11762             if (fAddOrigFile)
11763                 addCall.DeleteOldTable();
11764         }
11765     }
11766     else
11767     {
11768
11769         pAssembly->UpdatePEFileWorker(pFile);
11770     }
11771 }
11772
11773 //---------------------------------------------------------------------------------------------------------------------
11774 void AppDomain::UnPublishHostedAssembly(
11775     DomainAssembly * pAssembly)
11776 {
11777     CONTRACTL
11778     {
11779         NOTHROW;
11780         GC_NOTRIGGER;
11781         MODE_ANY;
11782         CAN_TAKE_LOCK;
11783     }
11784     CONTRACTL_END
11785
11786     if (pAssembly->GetFile()->HasHostAssembly())
11787     {
11788         ForbidSuspendThreadHolder suspend;
11789         {
11790             CrstHolder lock(&m_crstHostAssemblyMap);
11791             _ASSERTE(m_hostAssemblyMap.Lookup(pAssembly->GetFile()->GetHostAssembly()) != nullptr);
11792             m_hostAssemblyMap.Remove(pAssembly->GetFile()->GetHostAssembly());
11793
11794             // We also have an entry in m_hostAssemblyMapForOrigFile. Handle that case.
11795             if (pAssembly->GetOriginalFile() != pAssembly->GetFile())
11796             {
11797                 m_hostAssemblyMapForOrigFile.Remove(pAssembly->GetOriginalFile()->GetHostAssembly());
11798             }
11799         }
11800     }
11801     else
11802     {
11803         // In AppX processes, all PEAssemblies that are reach this stage should have host binders.
11804         _ASSERTE(!AppX::IsAppXProcess());
11805     }
11806 }
11807
11808 #if defined(FEATURE_COMINTEROP)
11809 HRESULT AppDomain::SetWinrtApplicationContext(SString &appLocalWinMD)
11810 {
11811     STANDARD_VM_CONTRACT;
11812     
11813     _ASSERTE(WinRTSupported());
11814     _ASSERTE(m_pWinRtBinder != nullptr);
11815
11816     _ASSERTE(GetTPABinderContext() != NULL);
11817     BINDER_SPACE::ApplicationContext *pApplicationContext = GetTPABinderContext()->GetAppContext();
11818     _ASSERTE(pApplicationContext != NULL);
11819     
11820     return m_pWinRtBinder->SetApplicationContext(pApplicationContext, appLocalWinMD);
11821 }
11822
11823 #endif // FEATURE_COMINTEROP
11824
11825 #endif //!DACCESS_COMPILE
11826
11827 //---------------------------------------------------------------------------------------------------------------------
11828 PTR_DomainAssembly AppDomain::FindAssembly(PTR_ICLRPrivAssembly pHostAssembly)
11829 {
11830     CONTRACTL
11831     {
11832         NOTHROW;
11833         GC_NOTRIGGER;
11834         MODE_ANY;
11835         SUPPORTS_DAC;
11836     }
11837     CONTRACTL_END
11838     
11839     if (pHostAssembly == nullptr)
11840         return NULL;
11841     
11842     {
11843         ForbidSuspendThreadHolder suspend;
11844         {
11845             CrstHolder lock(&m_crstHostAssemblyMap);
11846             PTR_DomainAssembly returnValue = m_hostAssemblyMap.Lookup(pHostAssembly);
11847             if (returnValue == NULL)
11848             {
11849                 // If not found in the m_hostAssemblyMap, look in the m_hostAssemblyMapForOrigFile
11850                 // This is necessary as it may happen during in a second AppDomain that the PEFile 
11851                 // first discovered in the AppDomain may not be used by the DomainFile, but the CLRPrivBinderFusion
11852                 // will in some cases find the pHostAssembly associated with this no longer used PEFile
11853                 // instead of the PEFile that was finally decided upon.
11854                 returnValue = m_hostAssemblyMapForOrigFile.Lookup(pHostAssembly);
11855             }
11856
11857             return returnValue;
11858         }
11859     }
11860 }
11861
11862 #if !defined(DACCESS_COMPILE) && defined(FEATURE_NATIVE_IMAGE_GENERATION)
11863
11864 void ZapperSetBindingPaths(ICorCompilationDomain *pDomain, SString &trustedPlatformAssemblies, SString &platformResourceRoots, SString &appPaths, SString &appNiPaths)
11865 {
11866     CLRPrivBinderCoreCLR *pBinder = static_cast<CLRPrivBinderCoreCLR*>(((CompilationDomain *)pDomain)->GetFusionContext());
11867     _ASSERTE(pBinder != NULL);
11868     pBinder->SetupBindingPaths(trustedPlatformAssemblies, platformResourceRoots, appPaths, appNiPaths);
11869 #ifdef FEATURE_COMINTEROP
11870     SString emptString;
11871     ((CompilationDomain*)pDomain)->SetWinrtApplicationContext(emptString);
11872 #endif
11873 }
11874
11875 #endif