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