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