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