2726a162961fae0b0e5d15b10e76abce2bdc5a4f
[platform/upstream/coreclr.git] / src / vm / codeversion.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 // File: CodeVersion.cpp
6 //
7 // ===========================================================================
8
9 #include "common.h"
10 #include "codeversion.h"
11
12 #ifdef FEATURE_CODE_VERSIONING
13 #include "threadsuspend.h"
14 #include "methoditer.h"
15 #include "../debug/ee/debugger.h"
16 #include "../debug/ee/walker.h"
17 #include "../debug/ee/controller.h"
18 #endif // FEATURE_CODE_VERSIONING
19
20 #ifndef FEATURE_CODE_VERSIONING
21
22 //
23 // When not using code versioning we've got a minimal implementation of 
24 // NativeCodeVersion that simply wraps a MethodDesc* with no additional
25 // versioning information
26 //
27
28 NativeCodeVersion::NativeCodeVersion(const NativeCodeVersion & rhs) : m_pMethod(rhs.m_pMethod) {}
29 NativeCodeVersion::NativeCodeVersion(PTR_MethodDesc pMethod) : m_pMethod(pMethod) {}
30 BOOL NativeCodeVersion::IsNull() const { return m_pMethod == NULL; }
31 PTR_MethodDesc NativeCodeVersion::GetMethodDesc() const { return m_pMethod; }
32 PCODE NativeCodeVersion::GetNativeCode() const { return m_pMethod->GetNativeCode(); }
33 NativeCodeVersionId NativeCodeVersion::GetVersionId() const { return 0; }
34 ReJITID NativeCodeVersion::GetILCodeVersionId() const; { return 0; }
35 ILCodeVersion NativeCodeVersion::GetILCodeVersion() const { return ILCodeVersion(m_pMethod); }
36 #ifndef DACCESS_COMPILE
37 BOOL NativeCodeVersion::SetNativeCodeInterlocked(PCODE pCode, PCODE pExpected) { return m_pMethod->SetNativeCodeInterlocked(pCode, pExpected); }
38 #endif
39 bool NativeCodeVersion::operator==(const NativeCodeVersion & rhs) const { return m_pMethod == rhs.m_pMethod; }
40 bool NativeCodeVersion::operator!=(const NativeCodeVersion & rhs) const { return !operator==(rhs); }
41
42
43 #else // FEATURE_CODE_VERSIONING
44
45
46 // This HRESULT is only used as a private implementation detail. If it escapes through public APIS
47 // it is a bug. Corerror.xml has a comment in it reserving this value for our use but it doesn't
48 // appear in the public headers.
49
50 #define CORPROF_E_RUNTIME_SUSPEND_REQUIRED 0x80131381
51
52 #ifndef DACCESS_COMPILE
53 NativeCodeVersionNode::NativeCodeVersionNode(NativeCodeVersionId id, MethodDesc* pMethodDesc, ReJITID parentId) :
54     m_pNativeCode(NULL),
55     m_pMethodDesc(pMethodDesc),
56     m_parentId(parentId),
57     m_pNextMethodDescSibling(NULL),
58     m_id(id),
59     m_optTier(NativeCodeVersion::OptimizationTier0),
60     m_flags(0)
61 {}
62 #endif
63
64 #ifdef DEBUG
65 BOOL NativeCodeVersionNode::LockOwnedByCurrentThread() const
66 {
67     LIMITED_METHOD_DAC_CONTRACT;
68     return GetMethodDesc()->GetCodeVersionManager()->LockOwnedByCurrentThread();
69 }
70 #endif //DEBUG
71
72 PTR_MethodDesc NativeCodeVersionNode::GetMethodDesc() const
73 {
74     LIMITED_METHOD_DAC_CONTRACT;
75     return m_pMethodDesc;
76 }
77
78 PCODE NativeCodeVersionNode::GetNativeCode() const
79 {
80     LIMITED_METHOD_DAC_CONTRACT;
81     return m_pNativeCode;
82 }
83
84 ReJITID NativeCodeVersionNode::GetILVersionId() const
85 {
86     LIMITED_METHOD_DAC_CONTRACT;
87     return m_parentId;
88 }
89
90 ILCodeVersion NativeCodeVersionNode::GetILCodeVersion() const
91 {
92     LIMITED_METHOD_DAC_CONTRACT;
93 #ifdef DEBUG
94     if (GetILVersionId() != 0)
95     {
96         _ASSERTE(LockOwnedByCurrentThread());
97     }
98 #endif
99     PTR_MethodDesc pMD = GetMethodDesc();
100     return pMD->GetCodeVersionManager()->GetILCodeVersion(pMD, GetILVersionId());
101 }
102
103 NativeCodeVersionId NativeCodeVersionNode::GetVersionId() const
104 {
105     LIMITED_METHOD_DAC_CONTRACT;
106     return m_id;
107 }
108
109 #ifndef DACCESS_COMPILE
110 BOOL NativeCodeVersionNode::SetNativeCodeInterlocked(PCODE pCode, PCODE pExpected)
111 {
112     LIMITED_METHOD_CONTRACT;
113     return FastInterlockCompareExchangePointer(&m_pNativeCode,
114         (TADDR&)pCode, (TADDR&)pExpected) == (TADDR&)pExpected;
115 }
116 #endif
117
118 BOOL NativeCodeVersionNode::IsActiveChildVersion() const
119 {
120     LIMITED_METHOD_DAC_CONTRACT;
121     _ASSERTE(LockOwnedByCurrentThread());
122     return (m_flags & IsActiveChildFlag) != 0;
123 }
124
125 #ifndef DACCESS_COMPILE
126 void NativeCodeVersionNode::SetActiveChildFlag(BOOL isActive)
127 {
128     LIMITED_METHOD_CONTRACT;
129     _ASSERTE(LockOwnedByCurrentThread());
130     if (isActive)
131     {
132         m_flags |= IsActiveChildFlag;
133     }
134     else
135     {
136         m_flags &= ~IsActiveChildFlag;
137     }
138 }
139 #endif
140
141
142 #ifdef FEATURE_TIERED_COMPILATION
143 NativeCodeVersion::OptimizationTier NativeCodeVersionNode::GetOptimizationTier() const
144 {
145     LIMITED_METHOD_DAC_CONTRACT;
146     return m_optTier.Load();
147 }
148 #ifndef DACCESS_COMPILE
149 void NativeCodeVersionNode::SetOptimizationTier(NativeCodeVersion::OptimizationTier tier)
150 {
151     LIMITED_METHOD_DAC_CONTRACT;
152     m_optTier.Store(tier);
153 }
154 #endif
155 #endif // FEATURE_TIERED_COMPILATION
156
157 NativeCodeVersion::NativeCodeVersion() :
158     m_storageKind(StorageKind::Unknown)
159 {}
160
161 NativeCodeVersion::NativeCodeVersion(const NativeCodeVersion & rhs) :
162     m_storageKind(rhs.m_storageKind)
163 {
164     if(m_storageKind == StorageKind::Explicit)
165     {
166         m_pVersionNode = rhs.m_pVersionNode; 
167     }
168     else if(m_storageKind == StorageKind::Synthetic)
169     {
170         m_synthetic = rhs.m_synthetic;
171     }
172 }
173
174 NativeCodeVersion::NativeCodeVersion(PTR_NativeCodeVersionNode pVersionNode) :
175     m_storageKind(pVersionNode != NULL ? StorageKind::Explicit : StorageKind::Unknown),
176     m_pVersionNode(pVersionNode)
177 {}
178
179 NativeCodeVersion::NativeCodeVersion(PTR_MethodDesc pMethod) :
180     m_storageKind(pMethod != NULL ? StorageKind::Synthetic : StorageKind::Unknown)
181 {
182     LIMITED_METHOD_DAC_CONTRACT;
183     m_synthetic.m_pMethodDesc = pMethod;
184 }
185
186 BOOL NativeCodeVersion::IsNull() const
187 {
188     LIMITED_METHOD_DAC_CONTRACT;
189     return m_storageKind == StorageKind::Unknown;
190 }
191
192 BOOL NativeCodeVersion::IsDefaultVersion() const
193 {
194     LIMITED_METHOD_DAC_CONTRACT;
195     return m_storageKind == StorageKind::Synthetic;
196 }
197
198 PTR_MethodDesc NativeCodeVersion::GetMethodDesc() const
199 {
200     LIMITED_METHOD_DAC_CONTRACT;
201     if (m_storageKind == StorageKind::Explicit)
202     {
203         return AsNode()->GetMethodDesc();
204     }
205     else
206     {
207         return m_synthetic.m_pMethodDesc;
208     }
209 }
210
211 PCODE NativeCodeVersion::GetNativeCode() const
212 {
213     LIMITED_METHOD_DAC_CONTRACT;
214     if (m_storageKind == StorageKind::Explicit)
215     {
216         return AsNode()->GetNativeCode();
217     }
218     else
219     {
220         return GetMethodDesc()->GetNativeCode();
221     }
222 }
223
224 ReJITID NativeCodeVersion::GetILCodeVersionId() const
225 {
226     LIMITED_METHOD_DAC_CONTRACT;
227     if (m_storageKind == StorageKind::Explicit)
228     {
229         return AsNode()->GetILVersionId();
230     }
231     else
232     {
233         return 0;
234     }
235 }
236
237 ILCodeVersion NativeCodeVersion::GetILCodeVersion() const
238 {
239     LIMITED_METHOD_DAC_CONTRACT;
240     if (m_storageKind == StorageKind::Explicit)
241     {
242         return AsNode()->GetILCodeVersion();
243     }
244     else
245     {
246         PTR_MethodDesc pMethod = GetMethodDesc();
247         return ILCodeVersion(dac_cast<PTR_Module>(pMethod->GetModule()), pMethod->GetMemberDef());
248     }
249 }
250
251 NativeCodeVersionId NativeCodeVersion::GetVersionId() const 
252 {
253     LIMITED_METHOD_DAC_CONTRACT;
254     if (m_storageKind == StorageKind::Explicit)
255     {
256         return AsNode()->GetVersionId();
257     }
258     else
259     {
260         return 0;
261     }
262 }
263
264 #ifndef DACCESS_COMPILE
265 BOOL NativeCodeVersion::SetNativeCodeInterlocked(PCODE pCode, PCODE pExpected)
266 {
267     LIMITED_METHOD_CONTRACT;
268     if (m_storageKind == StorageKind::Explicit)
269     {
270         return AsNode()->SetNativeCodeInterlocked(pCode, pExpected);
271     }
272     else
273     {
274         return GetMethodDesc()->SetNativeCodeInterlocked(pCode, pExpected);
275     }
276 }
277 #endif
278
279 BOOL NativeCodeVersion::IsActiveChildVersion() const
280 {
281     LIMITED_METHOD_DAC_CONTRACT;
282     if (m_storageKind == StorageKind::Explicit)
283     {
284         return AsNode()->IsActiveChildVersion();
285     }
286     else
287     {
288         MethodDescVersioningState* pMethodVersioningState = GetMethodDescVersioningState();
289         if (pMethodVersioningState == NULL)
290         {
291             return TRUE;
292         }
293         return pMethodVersioningState->IsDefaultVersionActiveChild();
294     }
295 }
296
297 PTR_MethodDescVersioningState NativeCodeVersion::GetMethodDescVersioningState() const
298 {
299     LIMITED_METHOD_DAC_CONTRACT;
300     PTR_MethodDesc pMethodDesc = GetMethodDesc();
301     CodeVersionManager* pCodeVersionManager = pMethodDesc->GetCodeVersionManager();
302     return pCodeVersionManager->GetMethodDescVersioningState(pMethodDesc);
303 }
304
305 #ifndef DACCESS_COMPILE
306 void NativeCodeVersion::SetActiveChildFlag(BOOL isActive)
307 {
308     LIMITED_METHOD_DAC_CONTRACT;
309     if (m_storageKind == StorageKind::Explicit)
310     {
311         AsNode()->SetActiveChildFlag(isActive);
312     }
313     else
314     {
315         MethodDescVersioningState* pMethodVersioningState = GetMethodDescVersioningState();
316         pMethodVersioningState->SetDefaultVersionActiveChildFlag(isActive);
317     }
318 }
319
320 MethodDescVersioningState* NativeCodeVersion::GetMethodDescVersioningState()
321 {
322     LIMITED_METHOD_DAC_CONTRACT;
323     MethodDesc* pMethodDesc = GetMethodDesc();
324     CodeVersionManager* pCodeVersionManager = pMethodDesc->GetCodeVersionManager();
325     return pCodeVersionManager->GetMethodDescVersioningState(pMethodDesc);
326 }
327 #endif
328
329 #ifdef FEATURE_TIERED_COMPILATION
330 NativeCodeVersion::OptimizationTier NativeCodeVersion::GetOptimizationTier() const
331 {
332     LIMITED_METHOD_DAC_CONTRACT;
333     if (m_storageKind == StorageKind::Explicit)
334     {
335         return AsNode()->GetOptimizationTier();
336     }
337     else
338     {
339         return NativeCodeVersion::OptimizationTier0;
340     }
341 }
342
343 #ifndef DACCESS_COMPILE
344 void NativeCodeVersion::SetOptimizationTier(NativeCodeVersion::OptimizationTier tier)
345 {
346     LIMITED_METHOD_CONTRACT;
347     if (m_storageKind == StorageKind::Explicit)
348     {
349         AsNode()->SetOptimizationTier(tier);
350     }
351     else
352     {
353         _ASSERTE(!"Do not call SetOptimizationTier on default code versions - these versions are immutable");
354     }
355 }
356 #endif
357 #endif
358
359 PTR_NativeCodeVersionNode NativeCodeVersion::AsNode() const
360 {
361     LIMITED_METHOD_DAC_CONTRACT;
362     if (m_storageKind == StorageKind::Explicit)
363     {
364         return m_pVersionNode;
365     }
366     else
367     {
368         return NULL;
369     }
370 }
371
372 #ifndef DACCESS_COMPILE
373 PTR_NativeCodeVersionNode NativeCodeVersion::AsNode()
374 {
375     LIMITED_METHOD_CONTRACT;
376     if (m_storageKind == StorageKind::Explicit)
377     {
378         return m_pVersionNode;
379     }
380     else
381     {
382         return NULL;
383     }
384 }
385 #endif
386
387 bool NativeCodeVersion::operator==(const NativeCodeVersion & rhs) const
388 {
389     LIMITED_METHOD_DAC_CONTRACT;
390     if (m_storageKind == StorageKind::Explicit)
391     {
392         return (rhs.m_storageKind == StorageKind::Explicit) &&
393             (rhs.AsNode() == AsNode());
394     }
395     else if (m_storageKind == StorageKind::Synthetic)
396     {
397         return (rhs.m_storageKind == StorageKind::Synthetic) &&
398             (m_synthetic.m_pMethodDesc == rhs.m_synthetic.m_pMethodDesc);
399     }
400     else
401     {
402         return rhs.m_storageKind == StorageKind::Unknown;
403     }
404 }
405 bool NativeCodeVersion::operator!=(const NativeCodeVersion & rhs) const
406 {
407     LIMITED_METHOD_DAC_CONTRACT;
408     return !operator==(rhs);
409 }
410
411 NativeCodeVersionCollection::NativeCodeVersionCollection(PTR_MethodDesc pMethodDescFilter, ILCodeVersion ilCodeFilter) :
412     m_pMethodDescFilter(pMethodDescFilter),
413     m_ilCodeFilter(ilCodeFilter)
414 {
415 }
416
417 NativeCodeVersionIterator NativeCodeVersionCollection::Begin()
418 {
419     LIMITED_METHOD_DAC_CONTRACT;
420     return NativeCodeVersionIterator(this);
421 }
422 NativeCodeVersionIterator NativeCodeVersionCollection::End()
423 {
424     LIMITED_METHOD_DAC_CONTRACT;
425     return NativeCodeVersionIterator(NULL);
426 }
427
428 NativeCodeVersionIterator::NativeCodeVersionIterator(NativeCodeVersionCollection* pNativeCodeVersionCollection) :
429     m_stage(IterationStage::Initial),
430     m_pCollection(pNativeCodeVersionCollection),
431     m_pLinkedListCur(dac_cast<PTR_NativeCodeVersionNode>(nullptr))
432 {
433     LIMITED_METHOD_DAC_CONTRACT;
434     First();
435 }
436 void NativeCodeVersionIterator::First()
437 {
438     LIMITED_METHOD_DAC_CONTRACT;
439     if (m_pCollection == NULL)
440     {
441         m_stage = IterationStage::End;
442     }
443     Next();
444 }
445 void NativeCodeVersionIterator::Next()
446 {
447     LIMITED_METHOD_DAC_CONTRACT;
448     if (m_stage == IterationStage::Initial)
449     {
450         ILCodeVersion ilCodeFilter = m_pCollection->m_ilCodeFilter;
451         m_stage = IterationStage::ImplicitCodeVersion;
452         if (ilCodeFilter.IsNull() || ilCodeFilter.IsDefaultVersion())
453         {
454             m_cur = NativeCodeVersion(m_pCollection->m_pMethodDescFilter);
455             return;
456         }
457     }
458     if (m_stage == IterationStage::ImplicitCodeVersion)
459     {
460         m_stage = IterationStage::LinkedList;
461         CodeVersionManager* pCodeVersionManager = m_pCollection->m_pMethodDescFilter->GetCodeVersionManager();
462         MethodDescVersioningState* pMethodDescVersioningState = pCodeVersionManager->GetMethodDescVersioningState(m_pCollection->m_pMethodDescFilter);
463         if (pMethodDescVersioningState == NULL)
464         {
465             m_pLinkedListCur = NULL;
466         }
467         else
468         {
469             ILCodeVersion ilCodeFilter = m_pCollection->m_ilCodeFilter;
470             m_pLinkedListCur = pMethodDescVersioningState->GetFirstVersionNode();
471             while (m_pLinkedListCur != NULL && !ilCodeFilter.IsNull() && ilCodeFilter.GetVersionId() != m_pLinkedListCur->GetILVersionId())
472             {
473                 m_pLinkedListCur = m_pLinkedListCur->m_pNextMethodDescSibling;
474             }
475         }
476         if (m_pLinkedListCur != NULL)
477         {
478             m_cur = NativeCodeVersion(m_pLinkedListCur);
479             return;
480         }
481     }
482     if (m_stage == IterationStage::LinkedList)
483     {
484         if (m_pLinkedListCur != NULL)
485         {
486             ILCodeVersion ilCodeFilter = m_pCollection->m_ilCodeFilter;
487             do
488             {
489                 m_pLinkedListCur = m_pLinkedListCur->m_pNextMethodDescSibling;
490             } while (m_pLinkedListCur != NULL && !ilCodeFilter.IsNull() && ilCodeFilter.GetVersionId() != m_pLinkedListCur->GetILVersionId());
491         }
492         if (m_pLinkedListCur != NULL)
493         {
494             m_cur = NativeCodeVersion(m_pLinkedListCur);
495             return;
496         }
497         else
498         {
499             m_stage = IterationStage::End;
500             m_cur = NativeCodeVersion();
501         }
502     }
503 }
504 const NativeCodeVersion & NativeCodeVersionIterator::Get() const
505 {
506     LIMITED_METHOD_DAC_CONTRACT;
507     return m_cur;
508 }
509 bool NativeCodeVersionIterator::Equal(const NativeCodeVersionIterator &i) const
510 {
511     LIMITED_METHOD_DAC_CONTRACT;
512     return m_cur == i.m_cur;
513 }
514
515 ILCodeVersionNode::ILCodeVersionNode() :
516     m_pModule(dac_cast<PTR_Module>(nullptr)),
517     m_methodDef(0),
518     m_rejitId(0),
519     m_pNextILVersionNode(dac_cast<PTR_ILCodeVersionNode>(nullptr)),
520     m_rejitState(ILCodeVersion::kStateRequested),
521     m_pIL(),
522     m_jitFlags(0)
523 {
524     m_pIL.Store(dac_cast<PTR_COR_ILMETHOD>(nullptr));
525 }
526
527 #ifndef DACCESS_COMPILE
528 ILCodeVersionNode::ILCodeVersionNode(Module* pModule, mdMethodDef methodDef, ReJITID id) :
529     m_pModule(pModule),
530     m_methodDef(methodDef),
531     m_rejitId(id),
532     m_pNextILVersionNode(dac_cast<PTR_ILCodeVersionNode>(nullptr)),
533     m_rejitState(ILCodeVersion::kStateRequested),
534     m_pIL(nullptr),
535     m_jitFlags(0)
536 {}
537 #endif
538
539 #ifdef DEBUG
540 BOOL ILCodeVersionNode::LockOwnedByCurrentThread() const
541 {
542     LIMITED_METHOD_DAC_CONTRACT;
543     return GetModule()->GetCodeVersionManager()->LockOwnedByCurrentThread();
544 }
545 #endif //DEBUG
546
547 PTR_Module ILCodeVersionNode::GetModule() const
548 {
549     LIMITED_METHOD_DAC_CONTRACT;
550     return m_pModule;
551 }
552
553 mdMethodDef ILCodeVersionNode::GetMethodDef() const
554 {
555     LIMITED_METHOD_DAC_CONTRACT;
556     return m_methodDef;
557 }
558
559 ReJITID ILCodeVersionNode::GetVersionId() const
560 {
561     LIMITED_METHOD_DAC_CONTRACT;
562     return m_rejitId;
563 }
564
565 ILCodeVersion::RejitFlags ILCodeVersionNode::GetRejitState() const
566 {
567     LIMITED_METHOD_DAC_CONTRACT;
568     return m_rejitState.Load();
569 }
570
571 PTR_COR_ILMETHOD ILCodeVersionNode::GetIL() const
572 {
573     LIMITED_METHOD_DAC_CONTRACT;
574     return dac_cast<PTR_COR_ILMETHOD>(m_pIL.Load());
575 }
576
577 DWORD ILCodeVersionNode::GetJitFlags() const
578 {
579     LIMITED_METHOD_DAC_CONTRACT;
580     return m_jitFlags.Load();
581 }
582
583 const InstrumentedILOffsetMapping* ILCodeVersionNode::GetInstrumentedILMap() const
584 {
585     LIMITED_METHOD_DAC_CONTRACT;
586     _ASSERTE(LockOwnedByCurrentThread());
587     return &m_instrumentedILMap;
588 }
589
590 PTR_ILCodeVersionNode ILCodeVersionNode::GetNextILVersionNode() const
591 {
592     LIMITED_METHOD_DAC_CONTRACT;
593     _ASSERTE(LockOwnedByCurrentThread());
594     return m_pNextILVersionNode;
595 }
596
597 #ifndef DACCESS_COMPILE
598 void ILCodeVersionNode::SetRejitState(ILCodeVersion::RejitFlags newState)
599 {
600     LIMITED_METHOD_CONTRACT;
601     m_rejitState.Store(newState);
602 }
603
604 void ILCodeVersionNode::SetIL(COR_ILMETHOD* pIL)
605 {
606     LIMITED_METHOD_CONTRACT;
607     m_pIL.Store(pIL);
608 }
609
610 void ILCodeVersionNode::SetJitFlags(DWORD flags)
611 {
612     LIMITED_METHOD_CONTRACT;
613     m_jitFlags.Store(flags);
614 }
615
616 void ILCodeVersionNode::SetInstrumentedILMap(SIZE_T cMap, COR_IL_MAP * rgMap)
617 {
618     LIMITED_METHOD_CONTRACT;
619     _ASSERTE(LockOwnedByCurrentThread());
620     m_instrumentedILMap.SetMappingInfo(cMap, rgMap);
621 }
622
623 void ILCodeVersionNode::SetNextILVersionNode(ILCodeVersionNode* pNextILVersionNode)
624 {
625     LIMITED_METHOD_CONTRACT;
626     _ASSERTE(LockOwnedByCurrentThread());
627     m_pNextILVersionNode = pNextILVersionNode;
628 }
629 #endif
630
631 ILCodeVersion::ILCodeVersion() :
632     m_storageKind(StorageKind::Unknown)
633 {}
634
635 ILCodeVersion::ILCodeVersion(const ILCodeVersion & ilCodeVersion) :
636     m_storageKind(ilCodeVersion.m_storageKind)
637 {
638     if(m_storageKind == StorageKind::Explicit)
639     {
640         m_pVersionNode = ilCodeVersion.m_pVersionNode;
641     }
642     else if(m_storageKind == StorageKind::Synthetic)
643     {
644         m_synthetic = ilCodeVersion.m_synthetic;
645     }
646 }
647
648 ILCodeVersion::ILCodeVersion(PTR_ILCodeVersionNode pILCodeVersionNode) :
649     m_storageKind(pILCodeVersionNode != NULL ? StorageKind::Explicit : StorageKind::Unknown),
650     m_pVersionNode(pILCodeVersionNode)
651 {}
652
653 ILCodeVersion::ILCodeVersion(PTR_Module pModule, mdMethodDef methodDef) :
654     m_storageKind(pModule != NULL ? StorageKind::Synthetic : StorageKind::Unknown)
655 {
656     LIMITED_METHOD_DAC_CONTRACT;
657     m_synthetic.m_pModule = pModule;
658     m_synthetic.m_methodDef = methodDef;
659 }
660
661 bool ILCodeVersion::operator==(const ILCodeVersion & rhs) const
662 {
663     LIMITED_METHOD_DAC_CONTRACT;
664     if (m_storageKind == StorageKind::Explicit)
665     {
666         return (rhs.m_storageKind == StorageKind::Explicit) &&
667             (AsNode() == rhs.AsNode());
668     }
669     else if (m_storageKind == StorageKind::Synthetic)
670     {
671         return (rhs.m_storageKind == StorageKind::Synthetic) &&
672             (m_synthetic.m_pModule == rhs.m_synthetic.m_pModule) &&
673             (m_synthetic.m_methodDef == rhs.m_synthetic.m_methodDef);
674     }
675     else
676     {
677         return rhs.m_storageKind == StorageKind::Unknown;
678     }
679 }
680
681 BOOL ILCodeVersion::IsNull() const
682 {
683     LIMITED_METHOD_DAC_CONTRACT;
684     return m_storageKind == StorageKind::Unknown;
685 }
686
687 BOOL ILCodeVersion::IsDefaultVersion() const
688 {
689     LIMITED_METHOD_DAC_CONTRACT;
690     return m_storageKind == StorageKind::Synthetic;
691 }
692
693 PTR_Module ILCodeVersion::GetModule() const
694 {
695     LIMITED_METHOD_DAC_CONTRACT;
696     if (m_storageKind == StorageKind::Explicit)
697     {
698         return AsNode()->GetModule();
699     }
700     else
701     {
702         return m_synthetic.m_pModule;
703     }
704 }
705
706 mdMethodDef ILCodeVersion::GetMethodDef() const
707 {
708     LIMITED_METHOD_DAC_CONTRACT;
709     if (m_storageKind == StorageKind::Explicit)
710     {
711         return AsNode()->GetMethodDef();
712     }
713     else
714     {
715         return m_synthetic.m_methodDef;
716     }
717 }
718
719 ReJITID ILCodeVersion::GetVersionId() const
720 {
721     LIMITED_METHOD_DAC_CONTRACT;
722     if (m_storageKind == StorageKind::Explicit)
723     {
724         return AsNode()->GetVersionId();
725     }
726     else
727     {
728         return 0;
729     }
730 }
731
732 NativeCodeVersionCollection ILCodeVersion::GetNativeCodeVersions(PTR_MethodDesc pClosedMethodDesc) const
733 {
734     LIMITED_METHOD_DAC_CONTRACT;
735     return NativeCodeVersionCollection(pClosedMethodDesc, *this);
736 }
737
738 NativeCodeVersion ILCodeVersion::GetActiveNativeCodeVersion(PTR_MethodDesc pClosedMethodDesc) const
739 {
740     LIMITED_METHOD_DAC_CONTRACT;
741     NativeCodeVersionCollection versions = GetNativeCodeVersions(pClosedMethodDesc);
742     for (NativeCodeVersionIterator cur = versions.Begin(), end = versions.End(); cur != end; cur++)
743     {
744         if (cur->IsActiveChildVersion())
745         {
746             return *cur;
747         }
748     }
749     return NativeCodeVersion();
750 }
751
752 ILCodeVersion::RejitFlags ILCodeVersion::GetRejitState() const
753 {
754     LIMITED_METHOD_DAC_CONTRACT;
755     if (m_storageKind == StorageKind::Explicit)
756     {
757         return AsNode()->GetRejitState();
758     }
759     else
760     {
761         return ILCodeVersion::kStateActive;
762     }
763 }
764
765 PTR_COR_ILMETHOD ILCodeVersion::GetIL() const
766 {
767     CONTRACTL
768     {
769         THROWS; //GetILHeader throws
770         GC_NOTRIGGER;
771         FORBID_FAULT;
772         MODE_ANY;
773     }
774     CONTRACTL_END
775
776     PTR_COR_ILMETHOD pIL = NULL;
777     if (m_storageKind == StorageKind::Explicit)
778     {
779         pIL = AsNode()->GetIL();
780     }
781     
782     // For the default code version we always fetch the globally stored default IL for a method
783     //
784     // In the non-default code version we assume NULL is the equivalent of explicitly requesting to
785     // re-use the default IL. Ideally there would be no reason to create a new version that re-uses
786     // the default IL (just use the default code version for that) but we do it here for compat. We've 
787     // got some profilers that use ReJIT to create a new code version and then instead of calling
788     // ICorProfilerFunctionControl::SetILFunctionBody they call ICorProfilerInfo::SetILFunctionBody. 
789     // This mutates the default IL so that it is now correct for their new code version. Of course this
790     // also overwrote the previous default IL so now the default code version GetIL() is out of sync
791     // with the jitted code. In the majority of cases we never re-read the IL after the initial
792     // jitting so this issue goes unnoticed.
793     //
794     // If changing the default IL after it is in use becomes more problematic in the future we would
795     // need to add enforcement that prevents profilers from using ICorProfilerInfo::SetILFunctionBody
796     // that way + coordinate with them because it is a breaking change for any profiler currently doing it.
797     if(pIL == NULL)
798     {
799         PTR_Module pModule = GetModule();
800         PTR_MethodDesc pMethodDesc = dac_cast<PTR_MethodDesc>(pModule->LookupMethodDef(GetMethodDef()));
801         if (pMethodDesc != NULL)
802         {
803             pIL = dac_cast<PTR_COR_ILMETHOD>(pMethodDesc->GetILHeader(TRUE));
804         }
805     }
806
807     return pIL;
808 }
809
810 PTR_COR_ILMETHOD ILCodeVersion::GetILNoThrow() const
811 {
812     LIMITED_METHOD_DAC_CONTRACT;
813     PTR_COR_ILMETHOD ret;
814     EX_TRY
815     {
816         ret = GetIL();
817     }
818     EX_CATCH
819     {
820         ret = NULL;
821     }
822     EX_END_CATCH(RethrowTerminalExceptions);
823     return ret;
824 }
825
826 DWORD ILCodeVersion::GetJitFlags() const
827 {
828     LIMITED_METHOD_DAC_CONTRACT;
829     if (m_storageKind == StorageKind::Explicit)
830     {
831         return AsNode()->GetJitFlags();
832     }
833     else
834     {
835         return 0;
836     }
837 }
838
839 const InstrumentedILOffsetMapping* ILCodeVersion::GetInstrumentedILMap() const
840 {
841     LIMITED_METHOD_DAC_CONTRACT;
842     if (m_storageKind == StorageKind::Explicit)
843     {
844         return AsNode()->GetInstrumentedILMap();
845     }
846     else
847     {
848         return NULL;
849     }
850 }
851
852 #ifndef DACCESS_COMPILE
853 void ILCodeVersion::SetRejitState(RejitFlags newState)
854 {
855     LIMITED_METHOD_CONTRACT;
856     AsNode()->SetRejitState(newState);
857 }
858
859 void ILCodeVersion::SetIL(COR_ILMETHOD* pIL)
860 {
861     LIMITED_METHOD_CONTRACT;
862     AsNode()->SetIL(pIL);
863 }
864
865 void ILCodeVersion::SetJitFlags(DWORD flags)
866 {
867     LIMITED_METHOD_CONTRACT;
868     AsNode()->SetJitFlags(flags);
869 }
870
871 void ILCodeVersion::SetInstrumentedILMap(SIZE_T cMap, COR_IL_MAP * rgMap)
872 {
873     LIMITED_METHOD_CONTRACT;
874     AsNode()->SetInstrumentedILMap(cMap, rgMap);
875 }
876
877 HRESULT ILCodeVersion::AddNativeCodeVersion(MethodDesc* pClosedMethodDesc, NativeCodeVersion* pNativeCodeVersion)
878 {
879     LIMITED_METHOD_CONTRACT;
880     CodeVersionManager* pManager = GetModule()->GetCodeVersionManager();
881     HRESULT hr = pManager->AddNativeCodeVersion(*this, pClosedMethodDesc, pNativeCodeVersion);
882     if (FAILED(hr))
883     {
884         _ASSERTE(hr == E_OUTOFMEMORY);
885         return hr;
886     }
887     return S_OK;
888 }
889
890 HRESULT ILCodeVersion::GetOrCreateActiveNativeCodeVersion(MethodDesc* pClosedMethodDesc, NativeCodeVersion* pActiveNativeCodeVersion)
891 {
892     LIMITED_METHOD_CONTRACT;
893     HRESULT hr = S_OK;
894     NativeCodeVersion activeNativeChild = GetActiveNativeCodeVersion(pClosedMethodDesc);
895     if (activeNativeChild.IsNull())
896     {
897         if (FAILED(hr = AddNativeCodeVersion(pClosedMethodDesc, &activeNativeChild)))
898         {
899             _ASSERTE(hr == E_OUTOFMEMORY);
900             return hr;
901         }
902     }
903     // The first added child should automatically become active
904     _ASSERTE(GetActiveNativeCodeVersion(pClosedMethodDesc) == activeNativeChild);
905     *pActiveNativeCodeVersion = activeNativeChild;
906     return S_OK;
907 }
908
909 HRESULT ILCodeVersion::SetActiveNativeCodeVersion(NativeCodeVersion activeNativeCodeVersion, BOOL fEESuspended)
910 {
911     LIMITED_METHOD_CONTRACT;
912     HRESULT hr = S_OK;
913     MethodDesc* pMethodDesc = activeNativeCodeVersion.GetMethodDesc();
914     NativeCodeVersion prevActiveVersion = GetActiveNativeCodeVersion(pMethodDesc);
915     if (prevActiveVersion == activeNativeCodeVersion)
916     {
917         //nothing to do, this version is already active
918         return S_OK;
919     }
920
921     if (!prevActiveVersion.IsNull())
922     {
923         prevActiveVersion.SetActiveChildFlag(FALSE);
924     }
925     activeNativeCodeVersion.SetActiveChildFlag(TRUE);
926
927     // If needed update the published code body for this method
928     CodeVersionManager* pCodeVersionManager = GetModule()->GetCodeVersionManager();
929     if (pCodeVersionManager->GetActiveILCodeVersion(GetModule(), GetMethodDef()) == *this)
930     {
931         if (FAILED(hr = pCodeVersionManager->PublishNativeCodeVersion(pMethodDesc, activeNativeCodeVersion, fEESuspended)))
932         {
933             return hr;
934         }
935     }
936
937     return S_OK;
938 }
939
940 ILCodeVersionNode* ILCodeVersion::AsNode()
941 {
942     LIMITED_METHOD_CONTRACT;
943     //This is dangerous - NativeCodeVersion coerces non-explicit versions to NULL but ILCodeVersion assumes the caller
944     //will never invoke AsNode() on a non-explicit node. Asserting for now as a minimal fix, but we should revisit this.
945     _ASSERTE(m_storageKind == StorageKind::Explicit);
946     return m_pVersionNode;
947 }
948 #endif //DACCESS_COMPILE
949
950 PTR_ILCodeVersionNode ILCodeVersion::AsNode() const
951 {
952     LIMITED_METHOD_DAC_CONTRACT;
953     //This is dangerous - NativeCodeVersion coerces non-explicit versions to NULL but ILCodeVersion assumes the caller
954     //will never invoke AsNode() on a non-explicit node. Asserting for now as a minimal fix, but we should revisit this.
955     _ASSERTE(m_storageKind == StorageKind::Explicit);
956     return m_pVersionNode;
957 }
958
959 ILCodeVersionCollection::ILCodeVersionCollection(PTR_Module pModule, mdMethodDef methodDef) :
960     m_pModule(pModule),
961     m_methodDef(methodDef)
962 {}
963
964 ILCodeVersionIterator ILCodeVersionCollection::Begin()
965 {
966     LIMITED_METHOD_DAC_CONTRACT;
967     return ILCodeVersionIterator(this);
968 }
969
970 ILCodeVersionIterator ILCodeVersionCollection::End()
971 {
972     LIMITED_METHOD_DAC_CONTRACT;
973     return ILCodeVersionIterator(NULL);
974 }
975
976 ILCodeVersionIterator::ILCodeVersionIterator(const ILCodeVersionIterator & iter) :
977     m_stage(iter.m_stage),
978     m_cur(iter.m_cur),
979     m_pLinkedListCur(iter.m_pLinkedListCur),
980     m_pCollection(iter.m_pCollection)
981 {}
982
983 ILCodeVersionIterator::ILCodeVersionIterator(ILCodeVersionCollection* pCollection) :
984     m_stage(pCollection != NULL ? IterationStage::Initial : IterationStage::End),
985     m_pLinkedListCur(dac_cast<PTR_ILCodeVersionNode>(nullptr)),
986     m_pCollection(pCollection)
987 {
988     LIMITED_METHOD_DAC_CONTRACT;
989     First();
990 }
991
992 const ILCodeVersion & ILCodeVersionIterator::Get() const
993 {
994     LIMITED_METHOD_DAC_CONTRACT;
995     return m_cur;
996 }
997
998 void ILCodeVersionIterator::First()
999 {
1000     LIMITED_METHOD_DAC_CONTRACT;
1001     Next();
1002 }
1003
1004 void ILCodeVersionIterator::Next()
1005 {
1006     LIMITED_METHOD_DAC_CONTRACT;
1007     if (m_stage == IterationStage::Initial)
1008     {
1009         m_stage = IterationStage::ImplicitCodeVersion;
1010         m_cur = ILCodeVersion(m_pCollection->m_pModule, m_pCollection->m_methodDef);
1011         return;
1012     }
1013     if (m_stage == IterationStage::ImplicitCodeVersion)
1014     {
1015         CodeVersionManager* pCodeVersionManager = m_pCollection->m_pModule->GetCodeVersionManager();
1016         _ASSERTE(pCodeVersionManager->LockOwnedByCurrentThread());
1017         PTR_ILCodeVersioningState pILCodeVersioningState = pCodeVersionManager->GetILCodeVersioningState(m_pCollection->m_pModule, m_pCollection->m_methodDef);
1018         if (pILCodeVersioningState != NULL)
1019         {
1020             m_pLinkedListCur = pILCodeVersioningState->GetFirstVersionNode();
1021         }
1022         m_stage = IterationStage::LinkedList;
1023         if (m_pLinkedListCur != NULL)
1024         {
1025             m_cur = ILCodeVersion(m_pLinkedListCur);
1026             return;
1027         }
1028     }
1029     if (m_stage == IterationStage::LinkedList)
1030     {
1031         if (m_pLinkedListCur != NULL)
1032         {
1033             m_pLinkedListCur = m_pLinkedListCur->GetNextILVersionNode();
1034         }
1035         if (m_pLinkedListCur != NULL)
1036         {
1037             m_cur = ILCodeVersion(m_pLinkedListCur);
1038             return;
1039         }
1040         else
1041         {
1042             m_stage = IterationStage::End;
1043             m_cur = ILCodeVersion();
1044             return;
1045         }
1046     }
1047 }
1048
1049 bool ILCodeVersionIterator::Equal(const ILCodeVersionIterator &i) const
1050 {
1051     LIMITED_METHOD_DAC_CONTRACT;
1052     return m_cur == i.m_cur;
1053 }
1054
1055 MethodDescVersioningState::MethodDescVersioningState(PTR_MethodDesc pMethodDesc) :
1056     m_pMethodDesc(pMethodDesc),
1057     m_flags(IsDefaultVersionActiveChildFlag),
1058     m_nextId(1),
1059     m_pFirstVersionNode(dac_cast<PTR_NativeCodeVersionNode>(nullptr))
1060 {
1061     LIMITED_METHOD_DAC_CONTRACT;
1062 #ifdef FEATURE_JUMPSTAMP
1063     ZeroMemory(m_rgSavedCode, JumpStubSize);
1064 #endif
1065 }
1066
1067 PTR_MethodDesc MethodDescVersioningState::GetMethodDesc() const
1068 {
1069     LIMITED_METHOD_DAC_CONTRACT;
1070     return m_pMethodDesc;
1071 }
1072
1073 #ifndef DACCESS_COMPILE
1074 NativeCodeVersionId MethodDescVersioningState::AllocateVersionId()
1075 {
1076     LIMITED_METHOD_CONTRACT;
1077     return m_nextId++;
1078 }
1079 #endif
1080
1081 PTR_NativeCodeVersionNode MethodDescVersioningState::GetFirstVersionNode() const
1082 {
1083     LIMITED_METHOD_DAC_CONTRACT;
1084     return m_pFirstVersionNode;
1085 }
1086
1087 #ifdef FEATURE_JUMPSTAMP
1088 MethodDescVersioningState::JumpStampFlags MethodDescVersioningState::GetJumpStampState()
1089 {
1090     LIMITED_METHOD_DAC_CONTRACT;
1091     return (JumpStampFlags)(m_flags & JumpStampMask);
1092 }
1093
1094 #ifndef DACCESS_COMPILE
1095 void MethodDescVersioningState::SetJumpStampState(JumpStampFlags newState)
1096 {
1097     LIMITED_METHOD_CONTRACT;
1098     m_flags = (m_flags & ~JumpStampMask) | (BYTE)newState;
1099 }
1100 #endif // DACCESS_COMPILE
1101
1102 #ifndef DACCESS_COMPILE
1103 HRESULT MethodDescVersioningState::SyncJumpStamp(NativeCodeVersion nativeCodeVersion, BOOL fEESuspended)
1104  {
1105     LIMITED_METHOD_CONTRACT;
1106     HRESULT hr = S_OK;
1107     PCODE pCode = nativeCodeVersion.IsNull() ? NULL : nativeCodeVersion.GetNativeCode();
1108     MethodDesc* pMethod = GetMethodDesc();
1109     _ASSERTE(pMethod->IsVersionable() && pMethod->IsVersionableWithJumpStamp());
1110
1111     if (!pMethod->HasNativeCode())
1112     {
1113         //we'll set up the jump-stamp when the default native code is created
1114         return S_OK;
1115     }
1116
1117     if (!nativeCodeVersion.IsNull() && nativeCodeVersion.IsDefaultVersion())
1118     {
1119         return UndoJumpStampNativeCode(fEESuspended);
1120     }
1121     else
1122     {
1123         // We don't have new code ready yet, jumpstamp back to the prestub to let us generate it the next time
1124         // the method is called
1125         if (pCode == NULL)
1126         {
1127             if (!fEESuspended)
1128             {
1129                 return CORPROF_E_RUNTIME_SUSPEND_REQUIRED;
1130             }
1131             return JumpStampNativeCode();
1132         }
1133         // We do know the new code body, install the jump stamp now
1134         else
1135         {
1136             return UpdateJumpTarget(fEESuspended, pCode);
1137         }
1138     }
1139 }
1140 #endif // DACCESS_COMPILE
1141
1142 //---------------------------------------------------------------------------------------
1143 //
1144 // Simple, thin abstraction of debugger breakpoint patching. Given an address and a
1145 // previously procured DebuggerControllerPatch governing the code address, this decides
1146 // whether the code address is patched. If so, it returns a pointer to the debugger's
1147 // buffer (of what's "underneath" the int 3 patch); otherwise, it returns the code
1148 // address itself.
1149 //
1150 // Arguments:
1151 //      * pbCode - Code address to return if unpatched
1152 //      * dbgpatch - DebuggerControllerPatch to test
1153 //
1154 // Return Value:
1155 //      Either pbCode or the debugger's patch buffer, as per description above.
1156 //
1157 // Assumptions:
1158 //      Caller must manually grab (and hold) the ControllerLockHolder and get the
1159 //      DebuggerControllerPatch before calling this helper.
1160 //      
1161 // Notes:
1162 //     pbCode need not equal the code address governed by dbgpatch, but is always
1163 //     "related" (and sometimes really is equal). For example, this helper may be used
1164 //     when writing a code byte to an internal rejit buffer (e.g., in preparation for an
1165 //     eventual 64-bit interlocked write into the code stream), and thus pbCode would
1166 //     point into the internal rejit buffer whereas dbgpatch governs the corresponding
1167 //     code byte in the live code stream. This function would then be used to determine
1168 //     whether a byte should be written into the internal rejit buffer OR into the
1169 //     debugger controller's breakpoint buffer.
1170 //
1171
1172 LPBYTE FirstCodeByteAddr(LPBYTE pbCode, DebuggerControllerPatch * dbgpatch)
1173 {
1174     LIMITED_METHOD_CONTRACT;
1175
1176     if (dbgpatch != NULL && dbgpatch->IsActivated())
1177     {
1178         // Debugger has patched the code, so return the address of the buffer
1179         return LPBYTE(&(dbgpatch->opcode));
1180     }
1181
1182     // no active patch, just return the direct code address
1183     return pbCode;
1184 }
1185
1186
1187 #ifdef _DEBUG
1188 #ifndef DACCESS_COMPILE
1189 BOOL MethodDescVersioningState::CodeIsSaved()
1190 {
1191     LIMITED_METHOD_CONTRACT;
1192
1193     for (size_t i = 0; i < sizeof(m_rgSavedCode); i++)
1194     {
1195         if (m_rgSavedCode[i] != 0)
1196             return TRUE;
1197     }
1198     return FALSE;
1199 }
1200 #endif //DACCESS_COMPILE
1201 #endif //_DEBUG
1202
1203 //---------------------------------------------------------------------------------------
1204 //
1205 // Do the actual work of stamping the top of originally-jitted-code with a jmp that goes
1206 // to the prestub. This can be called in one of three ways:
1207 //     * Case 1: By RequestReJIT against an already-jitted function, in which case the
1208 //         PCODE may be inferred by the MethodDesc, and our caller will have suspended
1209 //         the EE for us, OR
1210 //     * Case 2: By the prestub worker after jitting the original code of a function
1211 //         (i.e., the "pre-rejit" scenario). In this case, the EE is not suspended. But
1212 //         that's ok, because the PCODE has not yet been published to the MethodDesc, and
1213 //         no thread can be executing inside the originally JITted function yet.
1214 //     * Case 3: At type/method restore time for an NGEN'ed assembly. This is also the pre-rejit
1215 //         scenario because we are guaranteed to do this before the code in the module
1216 //         is executable. EE suspend is not required.
1217 //
1218 // Arguments:
1219 //    * pCode - Case 1 (above): will be NULL, and we can infer the PCODE from the
1220 //        MethodDesc; Case 2+3 (above, pre-rejit): will be non-NULL, and we'll need to use
1221 //        this to find the code to stamp on top of.
1222 //
1223 // Return Value:
1224 //    * S_OK: Either we successfully did the jmp-stamp, or a racing thread took care of
1225 //        it for us.
1226 //    * Else, HRESULT indicating failure.
1227 //
1228 // Assumptions:
1229 //     The caller will have suspended the EE if necessary (case 1), before this is
1230 //     called.
1231 //
1232 #ifndef DACCESS_COMPILE
1233 HRESULT MethodDescVersioningState::JumpStampNativeCode(PCODE pCode /* = NULL */)
1234 {
1235     CONTRACTL
1236     {
1237         NOTHROW;
1238         GC_NOTRIGGER;
1239         // It may seem dangerous to be stamping jumps over code while a GC is going on,
1240         // but we're actually safe. As we assert below, either we're holding the thread
1241         // store lock (and thus preventing a GC) OR we're stamping code that has not yet
1242         // been published (and will thus not be executed by managed therads or examined
1243         // by the GC).
1244         MODE_ANY;
1245     }
1246     CONTRACTL_END;
1247
1248     PCODE pCodePublished = GetMethodDesc()->GetNativeCode();
1249
1250     _ASSERTE((pCode != NULL) || (pCodePublished != NULL));
1251     _ASSERTE(GetMethodDesc()->GetCodeVersionManager()->LockOwnedByCurrentThread());
1252
1253     HRESULT hr = S_OK;
1254
1255     // We'll jump-stamp over pCode, or if pCode is NULL, jump-stamp over the published
1256     // code for this's MethodDesc.
1257     LPBYTE pbCode = (LPBYTE)pCode;
1258     if (pbCode == NULL)
1259     {
1260         // If caller didn't specify a pCode, just use the one that was published after
1261         // the original JIT.  (A specific pCode would be passed in the pre-rejit case,
1262         // to jump-stamp the original code BEFORE the PCODE gets published.)
1263         pbCode = (LPBYTE)pCodePublished;
1264     }
1265     _ASSERTE(pbCode != NULL);
1266
1267     // The debugging API may also try to write to the very top of this function (though
1268     // with an int 3 for breakpoint purposes). Coordinate with the debugger so we know
1269     // whether we can safely patch the actual code, or instead write to the debugger's
1270     // buffer.
1271     DebuggerController::ControllerLockHolder lockController;
1272
1273     if (GetJumpStampState() == JumpStampToPrestub)
1274     {
1275         // The method has already been jump stamped so nothing left to do
1276         _ASSERTE(CodeIsSaved());
1277         return S_OK;
1278     }
1279
1280     // Remember what we're stamping our jump on top of, so we can replace it during a
1281     // revert.
1282     if (GetJumpStampState() == JumpStampNone)
1283     {
1284         for (int i = 0; i < sizeof(m_rgSavedCode); i++)
1285         {
1286             m_rgSavedCode[i] = *FirstCodeByteAddr(pbCode + i, DebuggerController::GetPatchTable()->GetPatch((CORDB_ADDRESS_TYPE *)(pbCode + i)));
1287         }
1288     }
1289
1290     EX_TRY
1291     {
1292         AllocMemTracker amt;
1293
1294         // This guy might throw on out-of-memory, so rely on the tracker to clean-up
1295         Precode * pPrecode = Precode::Allocate(PRECODE_STUB, GetMethodDesc(), GetMethodDesc()->GetLoaderAllocator(), &amt);
1296         PCODE target = pPrecode->GetEntryPoint();
1297
1298 #if defined(_X86_) || defined(_AMD64_)
1299
1300         // Normal unpatched code never starts with a jump
1301         _ASSERTE(GetJumpStampState() == JumpStampToActiveVersion ||
1302             *FirstCodeByteAddr(pbCode, DebuggerController::GetPatchTable()->GetPatch((CORDB_ADDRESS_TYPE *)pbCode)) != X86_INSTR_JMP_REL32);
1303
1304         INT64 i64OldCode = *(INT64*)pbCode;
1305         INT64 i64NewCode = i64OldCode;
1306         LPBYTE pbNewValue = (LPBYTE)&i64NewCode;
1307         *pbNewValue = X86_INSTR_JMP_REL32;
1308         INT32 UNALIGNED * pOffset = reinterpret_cast<INT32 UNALIGNED *>(&pbNewValue[1]);
1309         // This will throw for out-of-memory, so don't write anything until
1310         // after he succeeds
1311         // This guy will leak/cache/reuse the jumpstub
1312         *pOffset = rel32UsingJumpStub(reinterpret_cast<INT32 UNALIGNED *>(pbCode + 1), target, GetMethodDesc(), GetMethodDesc()->GetLoaderAllocator());
1313
1314         // If we have the EE suspended or the code is unpublished there won't be contention on this code
1315         hr = UpdateJumpStampHelper(pbCode, i64OldCode, i64NewCode, FALSE);
1316         if (FAILED(hr))
1317         {
1318             ThrowHR(hr);
1319         }
1320
1321         //
1322         // No failure point after this!
1323         //
1324         amt.SuppressRelease();
1325
1326 #else // _X86_ || _AMD64_
1327 #error "Need to define a way to jump-stamp the prolog in a safe way for this platform"
1328 #endif // _X86_ || _AMD64_
1329
1330         SetJumpStampState(JumpStampToPrestub);
1331     }
1332     EX_CATCH_HRESULT(hr);
1333     _ASSERT(hr == S_OK || hr == E_OUTOFMEMORY);
1334
1335     if (SUCCEEDED(hr))
1336     {
1337         _ASSERTE(GetJumpStampState() == JumpStampToPrestub);
1338         _ASSERTE(m_rgSavedCode[0] != 0); // saved code should not start with 0
1339     }
1340
1341     return hr;
1342 }
1343
1344
1345 //---------------------------------------------------------------------------------------
1346 //
1347 // After code has been rejitted, this is called to update the jump-stamp to go from
1348 // pointing to the prestub, to pointing to the newly rejitted code.
1349 //
1350 // Arguments:
1351 //     fEESuspended - TRUE if the caller keeps the EE suspended during this call
1352 //     pRejittedCode - jitted code for the updated IL this method should execute
1353 //
1354 // Assumptions:
1355 //      This rejit manager's table crst should be held by the caller
1356 //
1357 // Returns - S_OK if the jump target is updated
1358 //           CORPROF_E_RUNTIME_SUSPEND_REQUIRED if the ee isn't suspended and it
1359 //             will need to be in order to do the update safely
1360 HRESULT MethodDescVersioningState::UpdateJumpTarget(BOOL fEESuspended, PCODE pRejittedCode)
1361 {
1362     CONTRACTL
1363     {
1364         NOTHROW;
1365         GC_NOTRIGGER;
1366         MODE_PREEMPTIVE;
1367     }
1368     CONTRACTL_END;
1369
1370     MethodDesc * pMD = GetMethodDesc();
1371     _ASSERTE(pMD->GetCodeVersionManager()->LockOwnedByCurrentThread());
1372
1373     // It isn't safe to overwrite the original method prolog with a jmp because threads might
1374     // be at an IP in the middle of the jump stamp already. However converting between different
1375     // jump stamps is OK (when done atomically) because this only changes the jmp target, not
1376     // instruction boundaries.
1377     if (GetJumpStampState() == JumpStampNone && !fEESuspended)
1378     {
1379         return CORPROF_E_RUNTIME_SUSPEND_REQUIRED;
1380     }
1381
1382     // Beginning of originally JITted code containing the jmp that we will redirect.
1383     BYTE * pbCode = (BYTE*)pMD->GetNativeCode();
1384
1385     // Remember what we're stamping our jump on top of, so we can replace it during a
1386     // revert.
1387     if (GetJumpStampState() == JumpStampNone)
1388     {
1389         for (int i = 0; i < sizeof(m_rgSavedCode); i++)
1390         {
1391             m_rgSavedCode[i] = *FirstCodeByteAddr(pbCode + i, DebuggerController::GetPatchTable()->GetPatch((CORDB_ADDRESS_TYPE *)(pbCode + i)));
1392         }
1393     }
1394
1395 #if defined(_X86_) || defined(_AMD64_)
1396
1397     HRESULT hr = S_OK;
1398     {
1399         DebuggerController::ControllerLockHolder lockController;
1400
1401         // This will throw for out-of-memory, so don't write anything until
1402         // after he succeeds
1403         // This guy will leak/cache/reuse the jumpstub
1404         INT32 offset = 0;
1405         EX_TRY
1406         {
1407             offset = rel32UsingJumpStub(
1408             reinterpret_cast<INT32 UNALIGNED *>(&pbCode[1]),    // base of offset
1409             pRejittedCode,                                      // target of jump
1410             pMD,
1411             pMD->GetLoaderAllocator());
1412         }
1413         EX_CATCH_HRESULT(hr);
1414         _ASSERT(hr == S_OK || hr == E_OUTOFMEMORY);
1415         if (FAILED(hr))
1416         {
1417             return hr;
1418         }
1419         // For validation later, remember what pbCode is right now
1420         INT64 i64OldValue = *(INT64 *)pbCode;
1421
1422         // Assemble the INT64 of the new code bytes to write.  Start with what's there now
1423         INT64 i64NewValue = i64OldValue;
1424         LPBYTE pbNewValue = (LPBYTE)&i64NewValue;
1425
1426         // First byte becomes a rel32 jmp instruction (if it wasn't already)
1427         *pbNewValue = X86_INSTR_JMP_REL32;
1428         // Next 4 bytes are the jmp target (offset to jmp stub)
1429         INT32 UNALIGNED * pnOffset = reinterpret_cast<INT32 UNALIGNED *>(&pbNewValue[1]);
1430         *pnOffset = offset;
1431
1432         hr = UpdateJumpStampHelper(pbCode, i64OldValue, i64NewValue, !fEESuspended);
1433         _ASSERTE(hr == S_OK || (hr == CORPROF_E_RUNTIME_SUSPEND_REQUIRED && !fEESuspended));
1434     }
1435     if (FAILED(hr))
1436     {
1437         return hr;
1438     }
1439
1440 #else // _X86_ || _AMD64_
1441 #error "Need to define a way to jump-stamp the prolog in a safe way for this platform"
1442 #endif // _X86_ || _AMD64_
1443
1444     // State transition
1445     SetJumpStampState(JumpStampToActiveVersion);
1446     return S_OK;
1447 }
1448
1449
1450 //---------------------------------------------------------------------------------------
1451 //
1452 // Poke the JITted code to satsify a revert request (or to perform an implicit revert as
1453 // part of a second, third, etc. rejit request). Reinstates the originally JITted code
1454 // that had been jump-stamped over to perform a prior rejit.
1455 //
1456 // Arguments
1457 //     fEESuspended - TRUE if the caller keeps the EE suspended during this call
1458 //
1459 //
1460 // Return Value:
1461 //     S_OK to indicate the revert succeeded,
1462 //     CORPROF_E_RUNTIME_SUSPEND_REQUIRED to indicate the jumpstamp hasn't been reverted
1463 //       and EE suspension will be needed for success
1464 //     other failure HRESULT indicating what went wrong.
1465 //
1466 // Assumptions:
1467 //     Caller must be holding the owning ReJitManager's table crst.
1468 //
1469 HRESULT MethodDescVersioningState::UndoJumpStampNativeCode(BOOL fEESuspended)
1470 {
1471     CONTRACTL
1472     {
1473         NOTHROW;
1474         GC_NOTRIGGER;
1475         MODE_ANY;
1476     }
1477     CONTRACTL_END;
1478
1479     _ASSERTE(GetMethodDesc()->GetCodeVersionManager()->LockOwnedByCurrentThread());
1480     if (GetJumpStampState() == JumpStampNone)
1481     {
1482         return S_OK;
1483     }
1484
1485     _ASSERTE(m_rgSavedCode[0] != 0); // saved code should not start with 0
1486
1487     BYTE * pbCode = (BYTE*)GetMethodDesc()->GetNativeCode();
1488     DebuggerController::ControllerLockHolder lockController;
1489
1490 #if defined(_X86_) || defined(_AMD64_)
1491     _ASSERTE(m_rgSavedCode[0] != X86_INSTR_JMP_REL32);
1492     _ASSERTE(*FirstCodeByteAddr(pbCode, DebuggerController::GetPatchTable()->GetPatch((CORDB_ADDRESS_TYPE *)pbCode)) == X86_INSTR_JMP_REL32);
1493 #else
1494 #error "Need to define a way to jump-stamp the prolog in a safe way for this platform"
1495 #endif // _X86_ || _AMD64_
1496
1497     // For the interlocked compare, remember what pbCode is right now
1498     INT64 i64OldValue = *(INT64 *)pbCode;
1499     // Assemble the INT64 of the new code bytes to write.  Start with what's there now
1500     INT64 i64NewValue = i64OldValue;
1501     memcpy(LPBYTE(&i64NewValue), m_rgSavedCode, sizeof(m_rgSavedCode));
1502     HRESULT hr = UpdateJumpStampHelper(pbCode, i64OldValue, i64NewValue, !fEESuspended);
1503     _ASSERTE(hr == S_OK || (hr == CORPROF_E_RUNTIME_SUSPEND_REQUIRED && !fEESuspended));
1504     if (hr != S_OK)
1505         return hr;
1506
1507     // Transition state of this ReJitInfo to indicate the MD no longer has any jump stamp
1508     SetJumpStampState(JumpStampNone);
1509     return S_OK;
1510 }
1511 #endif
1512
1513 //---------------------------------------------------------------------------------------
1514 //
1515 // This is called to modify the jump-stamp area, the first ReJitInfo::JumpStubSize bytes
1516 // in the method's code. 
1517 //
1518 // Notes:
1519 //      Callers use this method in a variety of circumstances:
1520 //      a) when the code is unpublished (fContentionPossible == FALSE)
1521 //      b) when the caller has taken the ThreadStoreLock and suspended the EE 
1522 //         (fContentionPossible == FALSE)
1523 //      c) when the code is published, the EE isn't suspended, and the jumpstamp
1524 //         area consists of a single 5 byte long jump instruction
1525 //         (fContentionPossible == TRUE)
1526 //      This method will attempt to alter the jump-stamp even if the caller has not prevented
1527 //      contention, but there is no guarantee it will be succesful. When the caller has prevented
1528 //      contention, then success is assured. Callers may oportunistically try without
1529 //      EE suspension, and then upgrade to EE suspension if the first attempt fails. 
1530 //
1531 // Assumptions:
1532 //      This rejit manager's table crst should be held by the caller or fContentionPossible==FALSE
1533 //      The debugger patch table lock should be held by the caller
1534 //
1535 // Arguments:
1536 //      pbCode - pointer to the code where the jump stamp is placed
1537 //      i64OldValue - the bytes which should currently be at the start of the method code
1538 //      i64NewValue - the new bytes which should be written at the start of the method code
1539 //      fContentionPossible - See the Notes section above.
1540 //
1541 // Returns:
1542 //      S_OK => the jumpstamp has been succesfully updated.
1543 //      CORPROF_E_RUNTIME_SUSPEND_REQUIRED => the jumpstamp remains unchanged (preventing contention will be necessary)
1544 //      other failing HR => VirtualProtect failed, the jumpstamp remains unchanged
1545 //
1546 #ifndef DACCESS_COMPILE
1547 HRESULT MethodDescVersioningState::UpdateJumpStampHelper(BYTE* pbCode, INT64 i64OldValue, INT64 i64NewValue, BOOL fContentionPossible)
1548 {
1549     CONTRACTL
1550     {
1551         NOTHROW;
1552         GC_NOTRIGGER;
1553         MODE_ANY;
1554     }
1555     CONTRACTL_END;
1556
1557     MethodDesc * pMD = GetMethodDesc();
1558     _ASSERTE(pMD->GetCodeVersionManager()->LockOwnedByCurrentThread() || !fContentionPossible);
1559
1560     // When ReJIT is enabled, method entrypoints are always at least 8-byte aligned (see
1561     // code:EEJitManager::allocCode), so we can do a single 64-bit interlocked operation
1562     // to update the jump target.  However, some code may have gotten compiled before
1563     // the profiler had a chance to enable ReJIT (e.g., NGENd code, or code JITted
1564     // before a profiler attaches).  In such cases, we cannot rely on a simple
1565     // interlocked operation, and instead must suspend the runtime to ensure we can
1566     // safely update the jmp instruction.
1567     //
1568     // This method doesn't verify that the method is actually safe to rejit, we expect
1569     // callers to do that. At the moment NGEN'ed code is safe to rejit even if
1570     // it is unaligned, but code generated before the profiler attaches is not.
1571     if (fContentionPossible && !(IS_ALIGNED(pbCode, sizeof(INT64))))
1572     {
1573         return CORPROF_E_RUNTIME_SUSPEND_REQUIRED;
1574     }
1575
1576     // The debugging API may also try to write to this function (though
1577     // with an int 3 for breakpoint purposes). Coordinate with the debugger so we know
1578     // whether we can safely patch the actual code, or instead write to the debugger's
1579     // buffer.
1580     if (fContentionPossible)
1581     {
1582         for (CORDB_ADDRESS_TYPE* pbProbeAddr = pbCode; pbProbeAddr < pbCode + MethodDescVersioningState::JumpStubSize; pbProbeAddr++)
1583         {
1584             if (NULL != DebuggerController::GetPatchTable()->GetPatch(pbProbeAddr))
1585             {
1586                 return CORPROF_E_RUNTIME_SUSPEND_REQUIRED;
1587             }
1588         }
1589     }
1590
1591 #if defined(_X86_) || defined(_AMD64_)
1592
1593     DWORD oldProt;
1594     if (!ClrVirtualProtect((LPVOID)pbCode, 8, PAGE_EXECUTE_READWRITE, &oldProt))
1595     {
1596         return HRESULT_FROM_WIN32(GetLastError());
1597     }
1598
1599     if (fContentionPossible)
1600     {
1601         INT64 i64InterlockReportedOldValue = FastInterlockCompareExchangeLong((INT64 *)pbCode, i64NewValue, i64OldValue);
1602         // Since changes to these bytes are protected by this rejitmgr's m_crstTable, we
1603         // shouldn't have two writers conflicting.
1604         _ASSERTE(i64InterlockReportedOldValue == i64OldValue);
1605     }
1606     else
1607     {
1608         // In this path the caller ensures:
1609         //   a) no thread will execute through the prologue area we are modifying
1610         //   b) no thread is stopped in a prologue such that it resumes in the middle of code we are modifying
1611         //   c) no thread is doing a debugger patch skip operation in which an unmodified copy of the method's 
1612         //      code could be executed from a patch skip buffer.
1613
1614         // PERF: we might still want a faster path through here if we aren't debugging that doesn't do
1615         // all the patch checks
1616         for (int i = 0; i < MethodDescVersioningState::JumpStubSize; i++)
1617         {
1618             *FirstCodeByteAddr(pbCode + i, DebuggerController::GetPatchTable()->GetPatch(pbCode + i)) = ((BYTE*)&i64NewValue)[i];
1619         }
1620     }
1621
1622     if (oldProt != PAGE_EXECUTE_READWRITE)
1623     {
1624         // The CLR codebase in many locations simply ignores failures to restore the page protections
1625         // Its true that it isn't a problem functionally, but it seems a bit sketchy?
1626         // I am following the convention for now.
1627         ClrVirtualProtect((LPVOID)pbCode, 8, oldProt, &oldProt);
1628     }
1629
1630     FlushInstructionCache(GetCurrentProcess(), pbCode, MethodDescVersioningState::JumpStubSize);
1631     return S_OK;
1632
1633 #else // _X86_ || _AMD64_
1634 #error "Need to define a way to jump-stamp the prolog in a safe way for this platform"
1635 #endif // _X86_ || _AMD64_
1636 }
1637 #endif
1638 #endif // FEATURE_JUMPSTAMP
1639
1640 BOOL MethodDescVersioningState::IsDefaultVersionActiveChild() const
1641 {
1642     LIMITED_METHOD_DAC_CONTRACT;
1643     return (m_flags & IsDefaultVersionActiveChildFlag) != 0;
1644 }
1645 #ifndef DACCESS_COMPILE
1646 void MethodDescVersioningState::SetDefaultVersionActiveChildFlag(BOOL isActive)
1647 {
1648     LIMITED_METHOD_CONTRACT;
1649     if (isActive)
1650     {
1651         m_flags |= IsDefaultVersionActiveChildFlag;
1652     }
1653     else
1654     {
1655         m_flags &= ~IsDefaultVersionActiveChildFlag;
1656     }
1657 }
1658
1659 void MethodDescVersioningState::LinkNativeCodeVersionNode(NativeCodeVersionNode* pNativeCodeVersionNode)
1660 {
1661     LIMITED_METHOD_CONTRACT;
1662     pNativeCodeVersionNode->m_pNextMethodDescSibling = m_pFirstVersionNode;
1663     m_pFirstVersionNode = pNativeCodeVersionNode;
1664 }
1665 #endif
1666
1667 ILCodeVersioningState::ILCodeVersioningState(PTR_Module pModule, mdMethodDef methodDef) :
1668     m_activeVersion(ILCodeVersion(pModule,methodDef)),
1669     m_pFirstVersionNode(dac_cast<PTR_ILCodeVersionNode>(nullptr)),
1670     m_pModule(pModule),
1671     m_methodDef(methodDef)
1672 {}
1673
1674
1675 ILCodeVersioningState::Key::Key() :
1676     m_pModule(dac_cast<PTR_Module>(nullptr)),
1677     m_methodDef(0)
1678 {}
1679
1680 ILCodeVersioningState::Key::Key(PTR_Module pModule, mdMethodDef methodDef) :
1681     m_pModule(pModule),
1682     m_methodDef(methodDef)
1683 {}
1684
1685 size_t ILCodeVersioningState::Key::Hash() const
1686 {
1687     LIMITED_METHOD_DAC_CONTRACT;
1688     return (size_t)(dac_cast<TADDR>(m_pModule) ^ m_methodDef);
1689 }
1690
1691 bool ILCodeVersioningState::Key::operator==(const Key & rhs) const
1692 {
1693     LIMITED_METHOD_DAC_CONTRACT;
1694     return (m_pModule == rhs.m_pModule) && (m_methodDef == rhs.m_methodDef);
1695 }
1696
1697 ILCodeVersioningState::Key ILCodeVersioningState::GetKey() const
1698 {
1699     LIMITED_METHOD_DAC_CONTRACT;
1700     return Key(m_pModule, m_methodDef);
1701 }
1702
1703 ILCodeVersion ILCodeVersioningState::GetActiveVersion() const
1704 {
1705     LIMITED_METHOD_DAC_CONTRACT;
1706     return m_activeVersion;
1707 }
1708
1709 PTR_ILCodeVersionNode ILCodeVersioningState::GetFirstVersionNode() const
1710 {
1711     LIMITED_METHOD_DAC_CONTRACT;
1712     return m_pFirstVersionNode;
1713 }
1714
1715 #ifndef DACCESS_COMPILE
1716 void ILCodeVersioningState::SetActiveVersion(ILCodeVersion ilActiveCodeVersion)
1717 {
1718     LIMITED_METHOD_CONTRACT;
1719     m_activeVersion = ilActiveCodeVersion;
1720 }
1721
1722 void ILCodeVersioningState::LinkILCodeVersionNode(ILCodeVersionNode* pILCodeVersionNode)
1723 {
1724     LIMITED_METHOD_CONTRACT;
1725     pILCodeVersionNode->SetNextILVersionNode(m_pFirstVersionNode);
1726     m_pFirstVersionNode = pILCodeVersionNode;
1727 }
1728 #endif
1729
1730 CodeVersionManager::CodeVersionManager()
1731 {}
1732
1733 //---------------------------------------------------------------------------------------
1734 //
1735 // Called from BaseDomain::BaseDomain to do any constructor-time initialization.
1736 // Presently, this takes care of initializing the Crst, choosing the type based on
1737 // whether this ReJitManager belongs to the SharedDomain.
1738 //
1739 // Arguments:
1740 //    * fSharedDomain - nonzero iff this ReJitManager belongs to the SharedDomain.
1741 //    
1742
1743 void CodeVersionManager::PreInit(BOOL fSharedDomain)
1744 {
1745     CONTRACTL
1746     {
1747         THROWS;
1748         GC_TRIGGERS;
1749         CAN_TAKE_LOCK;
1750         MODE_ANY;
1751     }
1752     CONTRACTL_END;
1753
1754 #ifndef DACCESS_COMPILE
1755     m_crstTable.Init(
1756         fSharedDomain ? CrstReJITSharedDomainTable : CrstReJITDomainTable,
1757         CrstFlags(CRST_UNSAFE_ANYMODE | CRST_DEBUGGER_THREAD | CRST_REENTRANCY | CRST_TAKEN_DURING_SHUTDOWN));
1758 #endif // DACCESS_COMPILE
1759 }
1760
1761 CodeVersionManager::TableLockHolder::TableLockHolder(CodeVersionManager* pCodeVersionManager) :
1762     CrstHolder(&pCodeVersionManager->m_crstTable)
1763 {
1764 }
1765 #ifndef DACCESS_COMPILE
1766 void CodeVersionManager::EnterLock()
1767 {
1768     m_crstTable.Enter();
1769 }
1770 void CodeVersionManager::LeaveLock()
1771 {
1772     m_crstTable.Leave();
1773 }
1774 #endif
1775
1776 #ifdef DEBUG
1777 BOOL CodeVersionManager::LockOwnedByCurrentThread() const
1778 {
1779     LIMITED_METHOD_DAC_CONTRACT;
1780 #ifdef DACCESS_COMPILE
1781     return TRUE;
1782 #else
1783     return const_cast<CrstExplicitInit &>(m_crstTable).OwnedByCurrentThread();
1784 #endif
1785 }
1786 #endif
1787
1788 PTR_ILCodeVersioningState CodeVersionManager::GetILCodeVersioningState(PTR_Module pModule, mdMethodDef methodDef) const
1789 {
1790     LIMITED_METHOD_DAC_CONTRACT;
1791     ILCodeVersioningState::Key key = ILCodeVersioningState::Key(pModule, methodDef);
1792     return m_ilCodeVersioningStateMap.Lookup(key);
1793 }
1794
1795 PTR_MethodDescVersioningState CodeVersionManager::GetMethodDescVersioningState(PTR_MethodDesc pClosedMethodDesc) const
1796 {
1797     LIMITED_METHOD_DAC_CONTRACT;
1798     return m_methodDescVersioningStateMap.Lookup(pClosedMethodDesc);
1799 }
1800
1801 #ifndef DACCESS_COMPILE
1802 HRESULT CodeVersionManager::GetOrCreateILCodeVersioningState(Module* pModule, mdMethodDef methodDef, ILCodeVersioningState** ppILCodeVersioningState)
1803 {
1804     LIMITED_METHOD_CONTRACT;
1805     HRESULT hr = S_OK;
1806     ILCodeVersioningState* pILCodeVersioningState = GetILCodeVersioningState(pModule, methodDef);
1807     if (pILCodeVersioningState == NULL)
1808     {
1809         pILCodeVersioningState = new (nothrow) ILCodeVersioningState(pModule, methodDef);
1810         if (pILCodeVersioningState == NULL)
1811         {
1812             return E_OUTOFMEMORY;
1813         }
1814         EX_TRY
1815         {
1816             // This throws when out of memory, but remains internally
1817             // consistent (without adding the new element)
1818             m_ilCodeVersioningStateMap.Add(pILCodeVersioningState);
1819         }
1820         EX_CATCH_HRESULT(hr);
1821         if (FAILED(hr))
1822         {
1823             delete pILCodeVersioningState;
1824             return hr;
1825         }
1826     }
1827     *ppILCodeVersioningState = pILCodeVersioningState;
1828     return S_OK;
1829 }
1830
1831 HRESULT CodeVersionManager::GetOrCreateMethodDescVersioningState(MethodDesc* pMethod, MethodDescVersioningState** ppMethodVersioningState)
1832 {
1833     LIMITED_METHOD_CONTRACT;
1834     HRESULT hr = S_OK;
1835     MethodDescVersioningState* pMethodVersioningState = m_methodDescVersioningStateMap.Lookup(pMethod);
1836     if (pMethodVersioningState == NULL)
1837     {
1838         pMethodVersioningState = new (nothrow) MethodDescVersioningState(pMethod);
1839         if (pMethodVersioningState == NULL)
1840         {
1841             return E_OUTOFMEMORY;
1842         }
1843         EX_TRY
1844         {
1845             // This throws when out of memory, but remains internally
1846             // consistent (without adding the new element)
1847             m_methodDescVersioningStateMap.Add(pMethodVersioningState);
1848         }
1849         EX_CATCH_HRESULT(hr);
1850         if (FAILED(hr))
1851         {
1852             delete pMethodVersioningState;
1853             return hr;
1854         }
1855     }
1856     *ppMethodVersioningState = pMethodVersioningState;
1857     return S_OK;
1858 }
1859 #endif // DACCESS_COMPILE
1860
1861 DWORD CodeVersionManager::GetNonDefaultILVersionCount()
1862 {
1863     LIMITED_METHOD_DAC_CONTRACT;
1864
1865     //This function is legal to call WITHOUT taking the lock
1866     //It is used to do a quick check if work might be needed without paying the overhead
1867     //of acquiring the lock and doing dictionary lookups
1868     return m_ilCodeVersioningStateMap.GetCount();
1869 }
1870
1871 ILCodeVersionCollection CodeVersionManager::GetILCodeVersions(PTR_MethodDesc pMethod)
1872 {
1873     LIMITED_METHOD_DAC_CONTRACT;
1874     _ASSERTE(LockOwnedByCurrentThread());
1875     return GetILCodeVersions(dac_cast<PTR_Module>(pMethod->GetModule()), pMethod->GetMemberDef());
1876 }
1877
1878 ILCodeVersionCollection CodeVersionManager::GetILCodeVersions(PTR_Module pModule, mdMethodDef methodDef)
1879 {
1880     LIMITED_METHOD_DAC_CONTRACT;
1881     _ASSERTE(LockOwnedByCurrentThread());
1882     return ILCodeVersionCollection(pModule, methodDef);
1883 }
1884
1885 ILCodeVersion CodeVersionManager::GetActiveILCodeVersion(PTR_MethodDesc pMethod)
1886 {
1887     LIMITED_METHOD_DAC_CONTRACT;
1888     _ASSERTE(LockOwnedByCurrentThread());
1889     return GetActiveILCodeVersion(dac_cast<PTR_Module>(pMethod->GetModule()), pMethod->GetMemberDef());
1890 }
1891
1892 ILCodeVersion CodeVersionManager::GetActiveILCodeVersion(PTR_Module pModule, mdMethodDef methodDef)
1893 {
1894     LIMITED_METHOD_DAC_CONTRACT;
1895     _ASSERTE(LockOwnedByCurrentThread());
1896     ILCodeVersioningState* pILCodeVersioningState = GetILCodeVersioningState(pModule, methodDef);
1897     if (pILCodeVersioningState == NULL)
1898     {
1899         return ILCodeVersion(pModule, methodDef);
1900     }
1901     else
1902     {
1903         return pILCodeVersioningState->GetActiveVersion();
1904     }
1905 }
1906
1907 ILCodeVersion CodeVersionManager::GetILCodeVersion(PTR_MethodDesc pMethod, ReJITID rejitId)
1908 {
1909     LIMITED_METHOD_DAC_CONTRACT;
1910     _ASSERTE(LockOwnedByCurrentThread());
1911
1912 #ifdef FEATURE_REJIT
1913     ILCodeVersionCollection collection = GetILCodeVersions(pMethod);
1914     for (ILCodeVersionIterator cur = collection.Begin(), end = collection.End(); cur != end; cur++)
1915     {
1916         if (cur->GetVersionId() == rejitId)
1917         {
1918             return *cur;
1919         }
1920     }
1921     return ILCodeVersion();
1922 #else // FEATURE_REJIT
1923     _ASSERTE(rejitId == 0);
1924     return ILCodeVersion(dac_cast<PTR_Module>(pMethod->GetModule()), pMethod->GetMemberDef());
1925 #endif // FEATURE_REJIT
1926 }
1927
1928 NativeCodeVersionCollection CodeVersionManager::GetNativeCodeVersions(PTR_MethodDesc pMethod) const
1929 {
1930     LIMITED_METHOD_DAC_CONTRACT;
1931     _ASSERTE(LockOwnedByCurrentThread());
1932     return NativeCodeVersionCollection(pMethod, ILCodeVersion());
1933 }
1934
1935 NativeCodeVersion CodeVersionManager::GetNativeCodeVersion(PTR_MethodDesc pMethod, PCODE codeStartAddress) const
1936 {
1937     LIMITED_METHOD_DAC_CONTRACT;
1938     _ASSERTE(LockOwnedByCurrentThread());
1939
1940     NativeCodeVersionCollection nativeCodeVersions = GetNativeCodeVersions(pMethod);
1941     for (NativeCodeVersionIterator cur = nativeCodeVersions.Begin(), end = nativeCodeVersions.End(); cur != end; cur++)
1942     {
1943         if (cur->GetNativeCode() == codeStartAddress)
1944         {
1945             return *cur;
1946         }
1947     }
1948     return NativeCodeVersion();
1949 }
1950
1951 #ifndef DACCESS_COMPILE
1952 HRESULT CodeVersionManager::AddILCodeVersion(Module* pModule, mdMethodDef methodDef, ReJITID rejitId, ILCodeVersion* pILCodeVersion)
1953 {
1954     LIMITED_METHOD_CONTRACT;
1955     _ASSERTE(LockOwnedByCurrentThread());
1956
1957     ILCodeVersioningState* pILCodeVersioningState;
1958     HRESULT hr = GetOrCreateILCodeVersioningState(pModule, methodDef, &pILCodeVersioningState);
1959     if (FAILED(hr))
1960     {
1961         _ASSERTE(hr == E_OUTOFMEMORY);
1962         return hr;
1963     }
1964
1965     ILCodeVersionNode* pILCodeVersionNode = new (nothrow) ILCodeVersionNode(pModule, methodDef, rejitId);
1966     if (pILCodeVersionNode == NULL)
1967     {
1968         return E_OUTOFMEMORY;
1969     }
1970     pILCodeVersioningState->LinkILCodeVersionNode(pILCodeVersionNode);
1971     *pILCodeVersion = ILCodeVersion(pILCodeVersionNode);
1972     return S_OK;
1973 }
1974
1975 HRESULT CodeVersionManager::SetActiveILCodeVersions(ILCodeVersion* pActiveVersions, DWORD cActiveVersions, BOOL fEESuspended, CDynArray<CodePublishError> * pErrors)
1976 {
1977     // If the IL version is in the shared domain we need to iterate all domains
1978     // looking for instantiations. The domain iterator lock is bigger than
1979     // the code version manager lock so we can't do this atomically. In one atomic
1980     // update the bookkeeping for IL versioning will happen and then in a second
1981     // update the active native code versions will change/code jumpstamps+precodes
1982     // will update.
1983     //
1984     // Note: For all domains other than the shared AppDomain we could do this
1985     // atomically, but for now we use the lowest common denominator for all
1986     // domains.
1987     CONTRACTL
1988     {
1989         NOTHROW;
1990         GC_NOTRIGGER;
1991         MODE_PREEMPTIVE;
1992         CAN_TAKE_LOCK;
1993         PRECONDITION(CheckPointer(pActiveVersions));
1994         PRECONDITION(CheckPointer(pErrors, NULL_OK));
1995     }
1996     CONTRACTL_END;
1997     _ASSERTE(!LockOwnedByCurrentThread());
1998     HRESULT hr = S_OK;
1999
2000 #if DEBUG
2001     for (DWORD i = 0; i < cActiveVersions; i++)
2002     {
2003         ILCodeVersion activeVersion = pActiveVersions[i];
2004         if (activeVersion.IsNull())
2005         {
2006             _ASSERTE(!"The active IL version can't be NULL");
2007         }
2008     }
2009 #endif
2010
2011     // step 1 - mark the IL versions as being active, this ensures that
2012     // any new method instantiations added after this point will bind to
2013     // the correct version
2014     {
2015         TableLockHolder(this);
2016         for (DWORD i = 0; i < cActiveVersions; i++)
2017         {
2018             ILCodeVersion activeVersion = pActiveVersions[i];
2019             ILCodeVersioningState* pILCodeVersioningState = NULL;
2020             if (FAILED(hr = GetOrCreateILCodeVersioningState(activeVersion.GetModule(), activeVersion.GetMethodDef(), &pILCodeVersioningState)))
2021             {
2022                 _ASSERTE(hr == E_OUTOFMEMORY);
2023                 return hr;
2024             }
2025             pILCodeVersioningState->SetActiveVersion(activeVersion);
2026         }
2027     }
2028
2029     // step 2 - determine the set of pre-existing method instantiations
2030
2031     // a parallel array to activeVersions
2032     // for each ILCodeVersion in activeVersions, this lists the set
2033     // MethodDescs that will need to be updated
2034     CDynArray<CDynArray<MethodDesc*>> methodDescsToUpdate;
2035     CDynArray<CodePublishError> errorRecords;
2036     for (DWORD i = 0; i < cActiveVersions; i++)
2037     {
2038         CDynArray<MethodDesc*>* pMethodDescs = methodDescsToUpdate.Append();
2039         if (pMethodDescs == NULL)
2040         {
2041             return E_OUTOFMEMORY;
2042         }
2043         *pMethodDescs = CDynArray<MethodDesc*>();
2044
2045         MethodDesc* pLoadedMethodDesc = pActiveVersions[i].GetModule()->LookupMethodDef(pActiveVersions[i].GetMethodDef());
2046         if (FAILED(hr = CodeVersionManager::EnumerateClosedMethodDescs(pLoadedMethodDesc, pMethodDescs, &errorRecords)))
2047         {
2048             _ASSERTE(hr == E_OUTOFMEMORY);
2049             return hr;
2050         }
2051     }
2052
2053     // step 3 - update each pre-existing method instantiation
2054     {
2055         TableLockHolder lock(this);
2056         for (DWORD i = 0; i < cActiveVersions; i++)
2057         {
2058             // Its possible the active IL version has changed if
2059             // another caller made an update while this method wasn't
2060             // holding the lock. We will ensure that we synchronize
2061             // publishing to whatever version is currently active, even
2062             // if that isn't the IL version we set above.
2063             //
2064             // Note: Although we attempt to handle this case gracefully
2065             // it isn't recommended for callers to do this. Racing two calls
2066             // that set the IL version to different results means it will be
2067             // completely arbitrary which version wins.
2068             ILCodeVersion requestedActiveILVersion = pActiveVersions[i];
2069             ILCodeVersion activeILVersion = GetActiveILCodeVersion(requestedActiveILVersion.GetModule(), requestedActiveILVersion.GetMethodDef());
2070
2071             CDynArray<MethodDesc*> methodDescs = methodDescsToUpdate[i];
2072             for (int j = 0; j < methodDescs.Count(); j++)
2073             {
2074                 // Get an the active child code version for this method instantiation (it might be NULL, that is OK)
2075                 NativeCodeVersion activeNativeChild = activeILVersion.GetActiveNativeCodeVersion(methodDescs[j]);
2076
2077                 // Publish that child version, because it is the active native child of the active IL version
2078                 // Failing to publish is non-fatal, but we do record it so the caller is aware
2079                 if (FAILED(hr = PublishNativeCodeVersion(methodDescs[j], activeNativeChild, fEESuspended)))
2080                 {
2081                     if (FAILED(hr = AddCodePublishError(activeILVersion.GetModule(), activeILVersion.GetMethodDef(), methodDescs[j], hr, &errorRecords)))
2082                     {
2083                         _ASSERTE(hr == E_OUTOFMEMORY);
2084                         return hr;
2085                     }
2086                 }
2087             }
2088         }
2089     }
2090
2091     return S_OK;
2092 }
2093
2094 HRESULT CodeVersionManager::AddNativeCodeVersion(ILCodeVersion ilCodeVersion, MethodDesc* pClosedMethodDesc, NativeCodeVersion* pNativeCodeVersion)
2095 {
2096     LIMITED_METHOD_CONTRACT;
2097     _ASSERTE(LockOwnedByCurrentThread());
2098
2099     MethodDescVersioningState* pMethodVersioningState;
2100     HRESULT hr = GetOrCreateMethodDescVersioningState(pClosedMethodDesc, &pMethodVersioningState);
2101     if (FAILED(hr))
2102     {
2103         _ASSERTE(hr == E_OUTOFMEMORY);
2104         return hr;
2105     }
2106
2107     NativeCodeVersionId newId = pMethodVersioningState->AllocateVersionId();
2108     NativeCodeVersionNode* pNativeCodeVersionNode = new (nothrow) NativeCodeVersionNode(newId, pClosedMethodDesc, ilCodeVersion.GetVersionId());
2109     if (pNativeCodeVersionNode == NULL)
2110     {
2111         return E_OUTOFMEMORY;
2112     }
2113
2114     pMethodVersioningState->LinkNativeCodeVersionNode(pNativeCodeVersionNode);
2115
2116     // the first child added is automatically considered the active one.
2117     if (ilCodeVersion.GetActiveNativeCodeVersion(pClosedMethodDesc).IsNull())
2118     {
2119         pNativeCodeVersionNode->SetActiveChildFlag(TRUE);
2120         _ASSERTE(!ilCodeVersion.GetActiveNativeCodeVersion(pClosedMethodDesc).IsNull());
2121
2122         // the new child shouldn't have any native code. If it did we might need to
2123         // publish that code as part of adding the node which would require callers
2124         // to pay attention to GC suspension and we'd need to report publishing errors
2125         // back to them.
2126         _ASSERTE(pNativeCodeVersionNode->GetNativeCode() == NULL);
2127     }
2128     *pNativeCodeVersion = NativeCodeVersion(pNativeCodeVersionNode);
2129     return S_OK;
2130 }
2131
2132 PCODE CodeVersionManager::PublishVersionableCodeIfNecessary(MethodDesc* pMethodDesc, BOOL fCanBackpatchPrestub)
2133 {
2134     STANDARD_VM_CONTRACT;
2135     _ASSERTE(!LockOwnedByCurrentThread());
2136     _ASSERTE(pMethodDesc->IsVersionable());
2137     _ASSERTE(!pMethodDesc->IsPointingToPrestub() || !pMethodDesc->IsVersionableWithJumpStamp());
2138
2139     HRESULT hr = S_OK;
2140     PCODE pCode = NULL;
2141     BOOL fIsJumpStampMethod = pMethodDesc->IsVersionableWithJumpStamp();
2142
2143     NativeCodeVersion activeVersion;
2144     {
2145         TableLockHolder lock(this);
2146         if (FAILED(hr = GetActiveILCodeVersion(pMethodDesc).GetOrCreateActiveNativeCodeVersion(pMethodDesc, &activeVersion)))
2147         {
2148             _ASSERTE(hr == E_OUTOFMEMORY);
2149             ReportCodePublishError(pMethodDesc->GetModule(), pMethodDesc->GetMemberDef(), pMethodDesc, hr);
2150             return NULL;
2151         }
2152     }
2153
2154     BOOL fEESuspend = FALSE;
2155     while (true)
2156     {
2157         // compile the code if needed
2158         pCode = activeVersion.GetNativeCode();
2159         if (pCode == NULL)
2160         {
2161             pCode = pMethodDesc->PrepareCode(activeVersion);
2162         }
2163
2164         // suspend in preparation for publishing if needed
2165         if (fEESuspend)
2166         {
2167             ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_FOR_REJIT);
2168         }
2169
2170         {
2171             TableLockHolder lock(this);
2172             // The common case is that newActiveCode == activeCode, however we did leave the lock so there is
2173             // possibility that the active version has changed. If it has we need to restart the compilation
2174             // and publishing process with the new active version instead.
2175             //
2176             // In theory it should be legitimate to break out of this loop and run the less recent active version,
2177             // because ultimately this is a race between one thread that is updating the version and another thread
2178             // trying to run the current version. However for back-compat with ReJIT we need to guarantee that
2179             // a versioning update at least as late as the profiler JitCompilationFinished callback wins the race.
2180             NativeCodeVersion newActiveVersion;
2181             if (FAILED(hr = GetActiveILCodeVersion(pMethodDesc).GetOrCreateActiveNativeCodeVersion(pMethodDesc, &newActiveVersion)))
2182             {
2183                 _ASSERTE(hr == E_OUTOFMEMORY);
2184                 ReportCodePublishError(pMethodDesc->GetModule(), pMethodDesc->GetMemberDef(), pMethodDesc, hr);
2185                 pCode = NULL;
2186                 break;
2187             }
2188             if (newActiveVersion != activeVersion)
2189             {
2190                 activeVersion = newActiveVersion;
2191             }
2192             else
2193             {
2194                 // if we aren't allowed to backpatch we are done
2195                 if (!fCanBackpatchPrestub)
2196                 {
2197                     break;
2198                 }
2199
2200                 // attempt to publish the active version still under the lock
2201                 if (FAILED(hr = PublishNativeCodeVersion(pMethodDesc, activeVersion, fEESuspend)))
2202                 {
2203                     // If we need an EESuspend to publish then start over. We have to leave the lock in order to suspend,
2204                     // and when we leave the lock the active version might change again. However now we know that suspend is
2205                     // necessary.
2206                     if (hr == CORPROF_E_RUNTIME_SUSPEND_REQUIRED)
2207                     {
2208                         _ASSERTE(!fEESuspend);
2209                         fEESuspend = true;
2210                         continue; // skip RestartEE() below since SuspendEE() has not been called yet
2211                     }
2212                     else
2213                     {
2214                         ReportCodePublishError(pMethodDesc->GetModule(), pMethodDesc->GetMemberDef(), pMethodDesc, hr);
2215                         pCode = NULL;
2216                         break;
2217                     }
2218                 }
2219                 else
2220                 {
2221                     //success
2222                     break;
2223                 }
2224             }
2225         } // exit lock
2226
2227         if (fEESuspend)
2228         {
2229             ThreadSuspend::RestartEE(FALSE, TRUE);
2230         }
2231     }
2232     
2233     // if the EE is still suspended from breaking in the middle of the loop, resume it
2234     if (fEESuspend)
2235     {
2236         ThreadSuspend::RestartEE(FALSE, TRUE);
2237     }
2238     return pCode;
2239 }
2240
2241 HRESULT CodeVersionManager::PublishNativeCodeVersion(MethodDesc* pMethod, NativeCodeVersion nativeCodeVersion, BOOL fEESuspended)
2242 {
2243     // TODO: This function needs to make sure it does not change the precode's target if call counting is in progress. Track
2244     // whether call counting is currently being done for the method, and use a lock to ensure the expected precode target.
2245     LIMITED_METHOD_CONTRACT;
2246     _ASSERTE(LockOwnedByCurrentThread());
2247     _ASSERTE(pMethod->IsVersionable());
2248     HRESULT hr = S_OK;
2249     PCODE pCode = nativeCodeVersion.IsNull() ? NULL : nativeCodeVersion.GetNativeCode();
2250     if (pMethod->IsVersionableWithPrecode())
2251     {
2252         Precode* pPrecode = pMethod->GetOrCreatePrecode();
2253         if (pCode == NULL)
2254         {
2255             EX_TRY
2256             {
2257                 pPrecode->Reset();
2258             }
2259             EX_CATCH_HRESULT(hr);
2260             return hr;
2261         }
2262         else
2263         {
2264             EX_TRY
2265             {
2266                 pPrecode->SetTargetInterlocked(pCode, FALSE);
2267
2268                 // SetTargetInterlocked() would return false if it lost the race with another thread. That is fine, this thread
2269                 // can continue assuming it was successful, similarly to it successfully updating the target and another thread
2270                 // updating the target again shortly afterwards.
2271                 hr = S_OK;
2272             }
2273             EX_CATCH_HRESULT(hr);
2274             return hr;
2275         }
2276     }
2277     else
2278     {
2279 #ifndef FEATURE_JUMPSTAMP
2280         _ASSERTE(!"This platform doesn't support JumpStamp but this method doesn't version with Precode,"
2281             " this method can't be updated");
2282         return E_FAIL;
2283 #else
2284         MethodDescVersioningState* pVersioningState;
2285         if (FAILED(hr = GetOrCreateMethodDescVersioningState(pMethod, &pVersioningState)))
2286         {
2287             _ASSERTE(hr == E_OUTOFMEMORY);
2288             return hr;
2289         }
2290         return pVersioningState->SyncJumpStamp(nativeCodeVersion, fEESuspended);
2291 #endif
2292     }
2293 }
2294
2295 // static
2296 HRESULT CodeVersionManager::EnumerateClosedMethodDescs(
2297     MethodDesc* pMD,
2298     CDynArray<MethodDesc*> * pClosedMethodDescs,
2299     CDynArray<CodePublishError> * pUnsupportedMethodErrors)
2300 {
2301     CONTRACTL
2302     {
2303         NOTHROW;
2304         GC_NOTRIGGER;
2305         MODE_PREEMPTIVE;
2306         CAN_TAKE_LOCK;
2307         PRECONDITION(CheckPointer(pMD, NULL_OK));
2308         PRECONDITION(CheckPointer(pClosedMethodDescs));
2309         PRECONDITION(CheckPointer(pUnsupportedMethodErrors));
2310     }
2311     CONTRACTL_END;
2312     HRESULT hr = S_OK;
2313     if (pMD == NULL)
2314     {
2315         // nothing is loaded yet so we're done for this method.
2316         return S_OK;
2317     }
2318
2319     if (!pMD->HasClassOrMethodInstantiation())
2320     {
2321         // We have a JITted non-generic.
2322         MethodDesc ** ppMD = pClosedMethodDescs->Append();
2323         if (ppMD == NULL)
2324         {
2325             return E_OUTOFMEMORY;
2326         }
2327         *ppMD = pMD;
2328     }
2329
2330     if (!pMD->HasClassOrMethodInstantiation())
2331     {
2332         // not generic, we're done for this method
2333         return S_OK;
2334     }
2335
2336     // Ok, now the case of a generic function (or function on generic class), which
2337     // is loaded, and may thus have compiled instantiations.
2338     // It's impossible to get to any other kind of domain from the profiling API
2339     Module* pModule = pMD->GetModule();
2340     mdMethodDef methodDef = pMD->GetMemberDef();
2341     BaseDomain * pBaseDomainFromModule = pModule->GetDomain();
2342     _ASSERTE(pBaseDomainFromModule->IsAppDomain() ||
2343         pBaseDomainFromModule->IsSharedDomain());
2344
2345     if (pBaseDomainFromModule->IsSharedDomain())
2346     {
2347         // Iterate through all modules loaded into the shared domain, to
2348         // find all instantiations living in the shared domain. This will
2349         // include orphaned code (i.e., shared code used by ADs that have
2350         // all unloaded), which is good, because orphaned code could get
2351         // re-adopted if a new AD is created that can use that shared code
2352         hr = EnumerateDomainClosedMethodDescs(
2353             NULL,  // NULL means to search SharedDomain instead of an AD
2354             pModule,
2355             methodDef,
2356             pClosedMethodDescs,
2357             pUnsupportedMethodErrors);
2358     }
2359     else
2360     {
2361         // Module is unshared, so just use the module's domain to find instantiations.
2362         hr = EnumerateDomainClosedMethodDescs(
2363             pBaseDomainFromModule->AsAppDomain(),
2364             pModule,
2365             methodDef,
2366             pClosedMethodDescs,
2367             pUnsupportedMethodErrors);
2368     }
2369     if (FAILED(hr))
2370     {
2371         _ASSERTE(hr == E_OUTOFMEMORY);
2372         return hr;
2373     }
2374
2375     // We want to iterate through all compilations of existing instantiations to
2376     // ensure they get marked for rejit.  Note: There may be zero instantiations,
2377     // but we won't know until we try.
2378     if (pBaseDomainFromModule->IsSharedDomain())
2379     {
2380         // Iterate through all real domains, to find shared instantiations.
2381         AppDomainIterator appDomainIterator(TRUE);
2382         while (appDomainIterator.Next())
2383         {
2384             AppDomain * pAppDomain = appDomainIterator.GetDomain();
2385             if (pAppDomain->IsUnloading())
2386             {
2387                 continue;
2388             }
2389             hr = EnumerateDomainClosedMethodDescs(
2390                 pAppDomain,
2391                 pModule,
2392                 methodDef,
2393                 pClosedMethodDescs,
2394                 pUnsupportedMethodErrors);
2395             if (FAILED(hr))
2396             {
2397                 _ASSERTE(hr == E_OUTOFMEMORY);
2398                 return hr;
2399             }
2400         }
2401     }
2402     return S_OK;
2403 }
2404
2405 // static
2406 HRESULT CodeVersionManager::EnumerateDomainClosedMethodDescs(
2407     AppDomain * pAppDomainToSearch,
2408     Module* pModuleContainingMethodDef,
2409     mdMethodDef methodDef,
2410     CDynArray<MethodDesc*> * pClosedMethodDescs,
2411     CDynArray<CodePublishError> * pUnsupportedMethodErrors)
2412 {
2413     CONTRACTL
2414     {
2415         NOTHROW;
2416         GC_NOTRIGGER;
2417         MODE_PREEMPTIVE;
2418         CAN_TAKE_LOCK;
2419         PRECONDITION(CheckPointer(pAppDomainToSearch, NULL_OK));
2420         PRECONDITION(CheckPointer(pModuleContainingMethodDef));
2421         PRECONDITION(CheckPointer(pClosedMethodDescs));
2422         PRECONDITION(CheckPointer(pUnsupportedMethodErrors));
2423     }
2424     CONTRACTL_END;
2425
2426     _ASSERTE(methodDef != mdTokenNil);
2427
2428     HRESULT hr;
2429
2430     BaseDomain * pDomainContainingGenericDefinition = pModuleContainingMethodDef->GetDomain();
2431
2432 #ifdef _DEBUG
2433     // If the generic definition is not loaded domain-neutral, then all its
2434     // instantiations will also be non-domain-neutral and loaded into the same
2435     // domain as the generic definition.  So the caller may only pass the
2436     // domain containing the generic definition as pAppDomainToSearch
2437     if (!pDomainContainingGenericDefinition->IsSharedDomain())
2438     {
2439         _ASSERTE(pDomainContainingGenericDefinition == pAppDomainToSearch);
2440     }
2441 #endif //_DEBUG
2442
2443     // If pAppDomainToSearch is NULL, iterate through all existing 
2444     // instantiations loaded into the SharedDomain. If pAppDomainToSearch is non-NULL, 
2445     // iterate through all existing instantiations in pAppDomainToSearch, and only consider
2446     // instantiations in non-domain-neutral assemblies (as we already covered domain 
2447     // neutral assemblies when we searched the SharedDomain).
2448     LoadedMethodDescIterator::AssemblyIterationMode mode = LoadedMethodDescIterator::kModeSharedDomainAssemblies;
2449     // these are the default flags which won't actually be used in shared mode other than
2450     // asserting they were specified with their default values
2451     AssemblyIterationFlags assemFlags = (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution);
2452     ModuleIterationOption moduleFlags = (ModuleIterationOption)kModIterIncludeLoaded;
2453     if (pAppDomainToSearch != NULL)
2454     {
2455         mode = LoadedMethodDescIterator::kModeUnsharedADAssemblies;
2456         assemFlags = (AssemblyIterationFlags)(kIncludeAvailableToProfilers | kIncludeExecution);
2457         moduleFlags = (ModuleIterationOption)kModIterIncludeAvailableToProfilers;
2458     }
2459     LoadedMethodDescIterator it(
2460         pAppDomainToSearch,
2461         pModuleContainingMethodDef,
2462         methodDef,
2463         mode,
2464         assemFlags,
2465         moduleFlags);
2466     CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
2467     while (it.Next(pDomainAssembly.This()))
2468     {
2469         MethodDesc * pLoadedMD = it.Current();
2470
2471         if (!pLoadedMD->IsVersionable())
2472         {
2473             // For compatibility with the rejit APIs we ensure certain errors are detected and reported using their
2474             // original HRESULTS
2475             HRESULT errorHR = GetNonVersionableError(pLoadedMD);
2476             if (FAILED(errorHR))
2477             {
2478                 if (FAILED(hr = CodeVersionManager::AddCodePublishError(pModuleContainingMethodDef, methodDef, pLoadedMD, CORPROF_E_FUNCTION_IS_COLLECTIBLE, pUnsupportedMethodErrors)))
2479                 {
2480                     _ASSERTE(hr == E_OUTOFMEMORY);
2481                     return hr;
2482                 }
2483             }
2484             continue;
2485         }
2486         
2487 #ifdef _DEBUG
2488         if (!pDomainContainingGenericDefinition->IsSharedDomain())
2489         {
2490             // Method is defined outside of the shared domain, so its instantiation must
2491             // be defined in the AD we're iterating over (pAppDomainToSearch, which, as
2492             // asserted above, must be the same domain as the generic's definition)
2493             _ASSERTE(pLoadedMD->GetDomain() == pAppDomainToSearch);
2494         }
2495 #endif // _DEBUG
2496
2497         MethodDesc ** ppMD = pClosedMethodDescs->Append();
2498         if (ppMD == NULL)
2499         {
2500             return E_OUTOFMEMORY;
2501         }
2502         *ppMD = pLoadedMD;
2503     }
2504     return S_OK;
2505 }
2506 #endif // DACCESS_COMPILE
2507
2508
2509 //---------------------------------------------------------------------------------------
2510 //
2511 // Given the default version code for a MethodDesc that is about to published, add 
2512 // a jumpstamp pointing back to the prestub if the currently active version isn't
2513 // the default one. This called from the PublishMethodHolder.
2514 //
2515 // Arguments:
2516 //    * pMD - MethodDesc to jmp-stamp
2517 //    * pCode - Top of the code that was just jitted (using original IL).
2518 //
2519 //
2520 // Return value:
2521 //    * S_OK: Either we successfully did the jmp-stamp, or we didn't have to
2522 //    * Else, HRESULT indicating failure.
2523
2524 // Assumptions:
2525 //     The caller has not yet published pCode to the MethodDesc, so no threads can be
2526 //     executing inside pMD's code yet. Thus, we don't need to suspend the runtime while
2527 //     applying the jump-stamp like we usually do for rejit requests that are made after
2528 //     a function has been JITted.
2529 //
2530 #ifndef DACCESS_COMPILE
2531 HRESULT CodeVersionManager::DoJumpStampIfNecessary(MethodDesc* pMD, PCODE pCode)
2532 {
2533     CONTRACTL
2534     {
2535         NOTHROW;
2536         GC_NOTRIGGER;
2537         MODE_ANY;
2538         CAN_TAKE_LOCK;
2539         PRECONDITION(CheckPointer(pMD));
2540         PRECONDITION(pCode != NULL);
2541     }
2542     CONTRACTL_END;
2543
2544     _ASSERTE(LockOwnedByCurrentThread());
2545
2546     NativeCodeVersion activeCodeVersion = GetActiveILCodeVersion(pMD).GetActiveNativeCodeVersion(pMD);
2547     if (activeCodeVersion.IsDefaultVersion())
2548     {
2549         //Method not requested to be rejitted, nothing to do
2550         return S_OK;
2551     }
2552
2553     if (!(pMD->IsVersionable() && pMD->IsVersionableWithJumpStamp()))
2554     {
2555         return GetNonVersionableError(pMD);
2556     }
2557
2558 #ifndef FEATURE_JUMPSTAMP
2559     _ASSERTE(!"How did we get here? IsVersionableWithJumpStamp() should have been FALSE above");
2560     return S_OK;
2561 #else
2562     HRESULT hr;
2563     MethodDescVersioningState* pVersioningState;
2564     if (FAILED(hr = GetOrCreateMethodDescVersioningState(pMD, &pVersioningState)))
2565     {
2566         _ASSERTE(hr == E_OUTOFMEMORY);
2567         return hr;
2568     }
2569     if (pVersioningState->GetJumpStampState() != MethodDescVersioningState::JumpStampNone)
2570     {
2571         //JumpStamp already in place
2572         return S_OK;
2573     }
2574     return pVersioningState->JumpStampNativeCode(pCode);
2575 #endif // FEATURE_JUMPSTAMP
2576
2577 }
2578 #endif // DACCESS_COMPILE
2579
2580 #ifndef DACCESS_COMPILE
2581 //static
2582 void CodeVersionManager::OnAppDomainExit(AppDomain * pAppDomain)
2583 {
2584     LIMITED_METHOD_CONTRACT;
2585     // This would clean up all the allocations we have done and synchronize with any threads that might
2586     // still be using the data
2587     _ASSERTE(!".Net Core shouldn't be doing app domain shutdown - if we start doing so this needs to be implemented");
2588 }
2589 #endif
2590
2591 //---------------------------------------------------------------------------------------
2592 //
2593 // Small helper to determine whether a given (possibly instantiated generic) MethodDesc
2594 // is safe to rejit.
2595 //
2596 // Arguments:
2597 //      pMD - MethodDesc to test
2598 // Return Value:
2599 //      S_OK iff pMD is safe to rejit
2600 //      CORPROF_E_FUNCTION_IS_COLLECTIBLE - function can't be rejitted because it is collectible
2601 //      
2602
2603 // static
2604 #ifndef DACCESS_COMPILE
2605 HRESULT CodeVersionManager::GetNonVersionableError(MethodDesc* pMD)
2606 {
2607     CONTRACTL
2608     {
2609         NOTHROW;
2610         GC_NOTRIGGER;
2611         CAN_TAKE_LOCK;
2612         MODE_ANY;
2613     }
2614     CONTRACTL_END;
2615
2616     _ASSERTE(pMD != NULL);
2617
2618     // Weird, non-user functions were already weeded out in RequestReJIT(), and will
2619     // also never be passed to us by the prestub worker (for the pre-rejit case).
2620     _ASSERTE(pMD->IsIL());
2621
2622     // Any MethodDescs that could be collected are not currently supported.  Although we
2623     // rule out all Ref.Emit modules in RequestReJIT(), there can still exist types defined
2624     // in a non-reflection module and instantiated into a collectible assembly
2625     // (e.g., List<MyCollectibleStruct>).  In the future we may lift this
2626     // restriction by updating the ReJitManager when the collectible assemblies
2627     // owning the instantiations get collected.
2628     if (pMD->GetLoaderAllocator()->IsCollectible())
2629     {
2630         return CORPROF_E_FUNCTION_IS_COLLECTIBLE;
2631     }
2632
2633     return S_OK;
2634 }
2635 #endif
2636
2637 //---------------------------------------------------------------------------------------
2638 //
2639 // Helper that inits a new CodePublishError and adds it to the pErrors array
2640 //
2641 // Arguments:
2642 //      * pModule - The module in the module/MethodDef identifier pair for the method which
2643 //                  had an error during rejit
2644 //      * methodDef - The MethodDef in the module/MethodDef identifier pair for the method which
2645 //                  had an error during rejit
2646 //      * pMD - If available, the specific method instance which had an error during rejit
2647 //      * hrStatus - HRESULT for the rejit error that occurred
2648 //      * pErrors - the list of error records that this method will append to
2649 //
2650 // Return Value:
2651 //      * S_OK: error was appended
2652 //      * E_OUTOFMEMORY: Not enough memory to create the new error item. The array is unchanged.
2653 //
2654
2655 //static
2656 #ifndef DACCESS_COMPILE
2657 HRESULT CodeVersionManager::AddCodePublishError(Module* pModule, mdMethodDef methodDef, MethodDesc* pMD, HRESULT hrStatus, CDynArray<CodePublishError> * pErrors)
2658 {
2659     CONTRACTL
2660     {
2661         NOTHROW;
2662         GC_NOTRIGGER;
2663         MODE_ANY;
2664     }
2665     CONTRACTL_END;
2666
2667     if (pErrors == NULL)
2668     {
2669         return S_OK;
2670     }
2671
2672     CodePublishError* pError = pErrors->Append();
2673     if (pError == NULL)
2674     {
2675         return E_OUTOFMEMORY;
2676     }
2677     pError->pModule = pModule;
2678     pError->methodDef = methodDef;
2679     pError->pMethodDesc = pMD;
2680     pError->hrStatus = hrStatus;
2681     return S_OK;
2682 }
2683 #endif
2684
2685 #ifndef DACCESS_COMPILE
2686 void CodeVersionManager::ReportCodePublishError(CodePublishError* pErrorRecord)
2687 {
2688     CONTRACTL
2689     {
2690         NOTHROW;
2691         GC_TRIGGERS;
2692         CAN_TAKE_LOCK;
2693         MODE_ANY;
2694     }
2695     CONTRACTL_END;
2696
2697     ReportCodePublishError(pErrorRecord->pModule, pErrorRecord->methodDef, pErrorRecord->pMethodDesc, pErrorRecord->hrStatus);
2698 }
2699
2700 void CodeVersionManager::ReportCodePublishError(Module* pModule, mdMethodDef methodDef, MethodDesc* pMD, HRESULT hrStatus)
2701 {
2702     CONTRACTL
2703     {
2704         NOTHROW;
2705         GC_TRIGGERS;
2706         CAN_TAKE_LOCK;
2707         MODE_ANY;
2708     }
2709     CONTRACTL_END;
2710
2711 #ifdef FEATURE_REJIT
2712     BOOL isRejitted = FALSE;
2713     {
2714         TableLockHolder(this);
2715         isRejitted = !GetActiveILCodeVersion(pModule, methodDef).IsDefaultVersion();
2716     }
2717
2718     // this isn't perfect, we might be activating a tiered jitting variation of a rejitted
2719     // method for example. If it proves to be an issue we can revisit.
2720     if (isRejitted)
2721     {
2722         ReJitManager::ReportReJITError(pModule, methodDef, pMD, hrStatus);
2723     }
2724 #endif
2725 }
2726 #endif // DACCESS_COMPILE
2727
2728 //---------------------------------------------------------------------------------------
2729 //
2730 // PrepareCodeConfig::SetNativeCode() calls this to determine if there's a non-default code
2731 // version requested for a MethodDesc that has just been jitted for the first time.
2732 // This is also called when methods are being restored in NGEN images. The sequence looks like:
2733 // *Enter holder
2734 //   Enter code version manager lock
2735 //   DoJumpStampIfNecessary
2736 // *Runtime code publishes/restores method
2737 // *Exit holder
2738 //   Leave code version manager lock
2739 //   Send rejit error callbacks if needed
2740 // 
2741 //
2742 // #PublishCode:
2743 // Note that the runtime needs to publish/restore the PCODE while this holder is
2744 // on the stack, so it can happen under the code version manager's lock.
2745 // This prevents a race with a profiler that calls
2746 // RequestReJIT just as the method finishes compiling. In particular, the locking ensures
2747 // atomicity between this set of steps (performed in DoJumpStampIfNecessary):
2748 //     * (1) Checking whether there is a non-default version for this MD
2749 //     * (2) If not, skip doing the jmp-stamp
2750 //     * (3) Publishing the PCODE
2751 //     
2752 // with respect to these steps performed in RequestReJIT:
2753 //     * (a) Is PCODE published yet?
2754 //     * (b) Create non-default ILCodeVersion which the prestub will
2755 //         consult when it JITs the original IL
2756 //         
2757 // Without this atomicity, we could get the ordering (1), (2), (a), (b), (3), resulting
2758 // in the rejit request getting completely ignored (i.e., we file away the new ILCodeVersion
2759 // AFTER the prestub checks for it).
2760 //
2761 // A similar race is possible for code being restored. In that case the restoring thread
2762 // does:
2763 //      * (1) Check if there is a non-default ILCodeVersion for this MD
2764 //      * (2) If not, no need to jmp-stamp
2765 //      * (3) Restore the MD
2766
2767 // And RequestRejit does:
2768 //      * (a) [In LoadedMethodDescIterator] Is a potential MD restored yet?
2769 //      * (b) [In EnumerateDomainClosedMethodDescs] If not, don't queue it for jump-stamping
2770 //
2771 // Same ordering (1), (2), (a), (b), (3) results in missing both opportunities to jump
2772 // stamp.
2773
2774 #if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
2775 PublishMethodHolder::PublishMethodHolder(MethodDesc* pMethodDesc, PCODE pCode) :
2776     m_pMD(NULL), m_hr(S_OK)
2777 {
2778     // This method can't have a contract because entering the table lock
2779     // below increments GCNoTrigger count. Contracts always revert these changes
2780     // at the end of the method but we need the incremented count to flow out of the
2781     // method. The balancing decrement occurs in the destructor.
2782     STATIC_CONTRACT_NOTHROW;
2783     STATIC_CONTRACT_GC_NOTRIGGER;
2784     STATIC_CONTRACT_CAN_TAKE_LOCK;
2785     STATIC_CONTRACT_MODE_ANY;
2786
2787     // We come here from the PreStub and from MethodDesc::CheckRestore
2788     // The method should be effectively restored, but we haven't yet
2789     // cleared the unrestored bit so we can't assert pMethodDesc->IsRestored()
2790     // We can assert:
2791     _ASSERTE(pMethodDesc->GetMethodTable()->IsRestored());
2792
2793     if (pCode != NULL)
2794     {
2795         m_pMD = pMethodDesc;
2796         CodeVersionManager* pCodeVersionManager = pMethodDesc->GetCodeVersionManager();
2797         pCodeVersionManager->EnterLock();
2798         m_hr = pCodeVersionManager->DoJumpStampIfNecessary(pMethodDesc, pCode);
2799     }
2800 }
2801
2802
2803 PublishMethodHolder::~PublishMethodHolder()
2804 {
2805     // This method can't have a contract because leaving the table lock
2806     // below decrements GCNoTrigger count. Contracts always revert these changes
2807     // at the end of the method but we need the decremented count to flow out of the
2808     // method. The balancing increment occurred in the constructor.
2809     STATIC_CONTRACT_NOTHROW;
2810     STATIC_CONTRACT_GC_TRIGGERS; // NOTRIGGER until we leave the lock
2811     STATIC_CONTRACT_CAN_TAKE_LOCK;
2812     STATIC_CONTRACT_MODE_ANY;
2813
2814     if (m_pMD)
2815     {
2816         CodeVersionManager* pCodeVersionManager = m_pMD->GetCodeVersionManager();
2817         pCodeVersionManager->LeaveLock();
2818         if (FAILED(m_hr))
2819         {
2820             pCodeVersionManager->ReportCodePublishError(m_pMD->GetModule(), m_pMD->GetMemberDef(), m_pMD, m_hr);
2821         }
2822     }
2823 }
2824
2825 PublishMethodTableHolder::PublishMethodTableHolder(MethodTable* pMethodTable) :
2826     m_pMethodTable(NULL)
2827 {
2828     // This method can't have a contract because entering the table lock
2829     // below increments GCNoTrigger count. Contracts always revert these changes
2830     // at the end of the method but we need the incremented count to flow out of the
2831     // method. The balancing decrement occurs in the destructor.
2832     STATIC_CONTRACT_NOTHROW;
2833     STATIC_CONTRACT_GC_NOTRIGGER;
2834     STATIC_CONTRACT_CAN_TAKE_LOCK;
2835     STATIC_CONTRACT_MODE_ANY;
2836
2837     // We come here from MethodTable::SetIsRestored
2838     // The method table should be effectively restored, but we haven't yet
2839     // cleared the unrestored bit so we can't assert pMethodTable->IsRestored()
2840
2841     m_pMethodTable = pMethodTable;
2842     CodeVersionManager* pCodeVersionManager = pMethodTable->GetModule()->GetCodeVersionManager();
2843     pCodeVersionManager->EnterLock();
2844     MethodTable::IntroducedMethodIterator itMethods(pMethodTable, FALSE);
2845     for (; itMethods.IsValid(); itMethods.Next())
2846     {
2847         // Although the MethodTable is restored, the methods might not be.
2848         // We need to be careful to only query portions of the MethodDesc
2849         // that work in a partially restored state. The only methods that need
2850         // further restoration are IL stubs (which aren't rejittable) and
2851         // generic methods. The only generic methods directly accesible from
2852         // the MethodTable are definitions. GetNativeCode() on generic defs
2853         // will run succesfully and return NULL which short circuits the
2854         // rest of the logic.
2855         MethodDesc * pMD = itMethods.GetMethodDesc();
2856         PCODE pCode = pMD->GetNativeCode();
2857         if (pCode != NULL)
2858         {
2859             HRESULT hr = pCodeVersionManager->DoJumpStampIfNecessary(pMD, pCode);
2860             if (FAILED(hr))
2861             {
2862                 CodeVersionManager::AddCodePublishError(pMD->GetModule(), pMD->GetMemberDef(), pMD, hr, &m_errors);
2863             }
2864         }
2865     }
2866 }
2867
2868
2869 PublishMethodTableHolder::~PublishMethodTableHolder()
2870 {
2871     // This method can't have a contract because leaving the table lock
2872     // below decrements GCNoTrigger count. Contracts always revert these changes
2873     // at the end of the method but we need the decremented count to flow out of the
2874     // method. The balancing increment occurred in the constructor.
2875     STATIC_CONTRACT_NOTHROW;
2876     STATIC_CONTRACT_GC_TRIGGERS; // NOTRIGGER until we leave the lock
2877     STATIC_CONTRACT_CAN_TAKE_LOCK;
2878     STATIC_CONTRACT_MODE_ANY;
2879
2880     if (m_pMethodTable)
2881     {
2882         CodeVersionManager* pCodeVersionManager = m_pMethodTable->GetModule()->GetCodeVersionManager();
2883         pCodeVersionManager->LeaveLock();
2884         for (int i = 0; i < m_errors.Count(); i++)
2885         {
2886             pCodeVersionManager->ReportCodePublishError(&(m_errors[i]));
2887         }
2888     }
2889 }
2890 #endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
2891
2892 #endif // FEATURE_CODE_VERSIONING
2893