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