Make dumpmd work with tiered jitting. Now displays previous code addresses (#13805)
[platform/upstream/coreclr.git] / src / vm / codeversion.h
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.h
6 //
7 // ===========================================================================
8
9
10 #ifndef CODE_VERSION_H
11 #define CODE_VERSION_H
12
13 class NativeCodeVersion;
14 class ILCodeVersion;
15 typedef DWORD NativeCodeVersionId;
16
17 #ifdef FEATURE_CODE_VERSIONING
18 class NativeCodeVersionNode;
19 typedef DPTR(class NativeCodeVersionNode) PTR_NativeCodeVersionNode;
20 class NativeCodeVersionCollection;
21 class NativeCodeVersionIterator;
22 class ILCodeVersionNode;
23 typedef DPTR(class ILCodeVersionNode) PTR_ILCodeVersionNode;
24 class ILCodeVersionCollection;
25 class ILCodeVersionIterator;
26 class MethodDescVersioningState;
27 typedef DPTR(class MethodDescVersioningState) PTR_MethodDescVersioningState;
28
29 class ILCodeVersioningState;
30 typedef DPTR(class ILCodeVersioningState) PTR_ILCodeVersioningState;
31 class CodeVersionManager;
32 typedef DPTR(class CodeVersionManager) PTR_CodeVersionManager;
33
34 // This HRESULT is only used as a private implementation detail. Corerror.xml has a comment in it
35 //  reserving this value for our use but it doesn't appear in the public headers.
36 #define CORPROF_E_RUNTIME_SUSPEND_REQUIRED 0x80131381
37
38 #endif
39
40
41
42
43 class NativeCodeVersion
44 {
45 #ifdef FEATURE_CODE_VERSIONING
46     friend class MethodDescVersioningState;
47     friend class ILCodeVersion;
48 #endif
49
50 public:
51     NativeCodeVersion();
52     NativeCodeVersion(const NativeCodeVersion & rhs);
53 #ifdef FEATURE_CODE_VERSIONING
54     NativeCodeVersion(PTR_NativeCodeVersionNode pVersionNode);
55 #endif
56     NativeCodeVersion(PTR_MethodDesc pMethod);
57     BOOL IsNull() const;
58     PTR_MethodDesc GetMethodDesc() const;
59     NativeCodeVersionId GetVersionId() const;
60     BOOL IsDefaultVersion() const;
61     PCODE GetNativeCode() const;
62     ILCodeVersion GetILCodeVersion() const;
63     ReJITID GetILCodeVersionId() const;
64 #ifndef DACCESS_COMPILE
65     BOOL SetNativeCodeInterlocked(PCODE pCode, PCODE pExpected = NULL);
66 #endif
67 #ifdef FEATURE_TIERED_COMPILATION
68     enum OptimizationTier
69     {
70         OptimizationTier0,
71         OptimizationTier1
72     };
73     OptimizationTier GetOptimizationTier() const;
74 #ifndef DACCESS_COMPILE
75     void SetOptimizationTier(OptimizationTier tier);
76 #endif
77 #endif // FEATURE_TIERED_COMPILATION
78     bool operator==(const NativeCodeVersion & rhs) const;
79     bool operator!=(const NativeCodeVersion & rhs) const;
80 #if defined(DACCESS_COMPILE) && defined(FEATURE_CODE_VERSIONING)
81     // The DAC is privy to the backing node abstraction
82     PTR_NativeCodeVersionNode AsNode() const;
83 #endif
84
85 private:
86
87 #ifndef FEATURE_CODE_VERSIONING
88     MethodDesc* m_pMethodDesc;
89 #else // FEATURE_CODE_VERSIONING
90
91 #ifndef DACCESS_COMPILE
92     NativeCodeVersionNode* AsNode() const;
93     NativeCodeVersionNode* AsNode();
94     void SetActiveChildFlag(BOOL isActive);
95     MethodDescVersioningState* GetMethodDescVersioningState();
96 #endif
97
98     BOOL IsActiveChildVersion() const;
99     PTR_MethodDescVersioningState GetMethodDescVersioningState() const;
100
101     enum StorageKind
102     {
103         Unknown,
104         Explicit,
105         Synthetic
106     };
107
108     StorageKind m_storageKind;
109     union
110     {
111         PTR_NativeCodeVersionNode m_pVersionNode;
112         struct SyntheticStorage
113         {
114             PTR_MethodDesc m_pMethodDesc;
115         } m_synthetic;
116     };
117 #endif // FEATURE_CODE_VERSIONING
118 };
119
120
121
122 #ifdef FEATURE_CODE_VERSIONING
123
124
125
126 class ILCodeVersion
127 {
128     friend class NativeCodeVersionIterator;
129
130 public:
131     ILCodeVersion();
132     ILCodeVersion(const ILCodeVersion & ilCodeVersion);
133     ILCodeVersion(PTR_ILCodeVersionNode pILCodeVersionNode);
134     ILCodeVersion(PTR_Module pModule, mdMethodDef methodDef);
135
136     bool operator==(const ILCodeVersion & rhs) const;
137     bool operator!=(const ILCodeVersion & rhs) const;
138     BOOL IsNull() const;
139     BOOL IsDefaultVersion() const;
140     PTR_Module GetModule() const;
141     mdMethodDef GetMethodDef() const;
142     ReJITID GetVersionId() const;
143     NativeCodeVersionCollection GetNativeCodeVersions(PTR_MethodDesc pClosedMethodDesc) const;
144     NativeCodeVersion GetActiveNativeCodeVersion(PTR_MethodDesc pClosedMethodDesc) const;
145     PTR_COR_ILMETHOD GetIL() const;
146     PTR_COR_ILMETHOD GetILNoThrow() const;
147     DWORD GetJitFlags() const;
148     const InstrumentedILOffsetMapping* GetInstrumentedILMap() const;
149
150 #ifndef DACCESS_COMPILE
151     void SetIL(COR_ILMETHOD* pIL);
152     void SetJitFlags(DWORD flags);
153     void SetInstrumentedILMap(SIZE_T cMap, COR_IL_MAP * rgMap);
154     HRESULT AddNativeCodeVersion(MethodDesc* pClosedMethodDesc, NativeCodeVersion* pNativeCodeVersion);
155     HRESULT GetOrCreateActiveNativeCodeVersion(MethodDesc* pClosedMethodDesc, NativeCodeVersion* pNativeCodeVersion);
156     HRESULT SetActiveNativeCodeVersion(NativeCodeVersion activeNativeCodeVersion, BOOL fEESuspended);
157 #endif //DACCESS_COMPILE
158
159     enum RejitFlags
160     {
161         // The profiler has requested a ReJit, so we've allocated stuff, but we haven't
162         // called back to the profiler to get any info or indicate that the ReJit has
163         // started. (This Info can be 'reused' for a new ReJit if the
164         // profiler calls RequestRejit again before we transition to the next state.)
165         kStateRequested = 0x00000000,
166
167         // The CLR has initiated the call to the profiler's GetReJITParameters() callback
168         // but it hasn't completed yet. At this point we have to assume the profiler has
169         // commited to a specific IL body, even if the CLR doesn't know what it is yet.
170         // If the profiler calls RequestRejit we need to allocate a new ILCodeVersion
171         // and call GetReJITParameters() again.
172         kStateGettingReJITParameters = 0x00000001,
173
174         // We have asked the profiler about this method via ICorProfilerFunctionControl,
175         // and have thus stored the IL and codegen flags the profiler specified.
176         kStateActive = 0x00000002,
177
178         kStateMask = 0x0000000F,
179     };
180
181     RejitFlags GetRejitState() const;
182 #ifndef DACCESS_COMPILE
183     void SetRejitState(RejitFlags newState);
184 #endif
185
186 #ifdef DACCESS_COMPILE
187     // The DAC is privy to the backing node abstraction
188     PTR_ILCodeVersionNode AsNode() const;
189 #endif
190
191 private:
192
193 #ifndef DACCESS_COMPILE
194     PTR_ILCodeVersionNode AsNode();
195     PTR_ILCodeVersionNode AsNode() const;
196 #endif
197
198     enum StorageKind
199     {
200         Unknown,
201         Explicit,
202         Synthetic
203     };
204
205     StorageKind m_storageKind;
206     union
207     {
208         PTR_ILCodeVersionNode m_pVersionNode;
209         struct SyntheticStorage
210         {
211             PTR_Module m_pModule;
212             mdMethodDef m_methodDef;
213         } m_synthetic;
214     };
215 };
216
217
218 class NativeCodeVersionNode
219 {
220     friend NativeCodeVersionIterator;
221     friend MethodDescVersioningState;
222     friend ILCodeVersionNode;
223 public:
224 #ifndef DACCESS_COMPILE
225     NativeCodeVersionNode(NativeCodeVersionId id, MethodDesc* pMethod, ReJITID parentId);
226 #endif
227 #ifdef DEBUG
228     BOOL LockOwnedByCurrentThread() const;
229 #endif
230     PTR_MethodDesc GetMethodDesc() const;
231     NativeCodeVersionId GetVersionId() const;
232     PCODE GetNativeCode() const;
233     ReJITID GetILVersionId() const;
234     ILCodeVersion GetILCodeVersion() const;
235     BOOL IsActiveChildVersion() const;
236 #ifndef DACCESS_COMPILE
237     BOOL SetNativeCodeInterlocked(PCODE pCode, PCODE pExpected);
238     void SetActiveChildFlag(BOOL isActive);
239 #endif
240 #ifdef FEATURE_TIERED_COMPILATION
241     NativeCodeVersion::OptimizationTier GetOptimizationTier() const;
242 #ifndef DACCESS_COMPILE
243     void SetOptimizationTier(NativeCodeVersion::OptimizationTier tier);
244 #endif
245 #endif
246
247 private:
248     //union - could save a little memory?
249     //{
250     PCODE m_pNativeCode;
251     PTR_MethodDesc m_pMethodDesc;
252     //};
253
254     ReJITID m_parentId;
255     PTR_NativeCodeVersionNode m_pNextMethodDescSibling;
256     NativeCodeVersionId m_id;
257 #ifdef FEATURE_TIERED_COMPILATION
258     Volatile<NativeCodeVersion::OptimizationTier> m_optTier;
259 #endif
260
261     enum NativeCodeVersionNodeFlags
262     {
263         IsActiveChildFlag = 1
264     };
265     DWORD m_flags;
266 };
267
268 class NativeCodeVersionCollection
269 {
270     friend class NativeCodeVersionIterator;
271 public:
272     NativeCodeVersionCollection(PTR_MethodDesc pMethodDescFilter, ILCodeVersion ilCodeFilter);
273     NativeCodeVersionIterator Begin();
274     NativeCodeVersionIterator End();
275
276 private:
277     PTR_MethodDesc m_pMethodDescFilter;
278     ILCodeVersion m_ilCodeFilter;
279 };
280
281 class NativeCodeVersionIterator : public Enumerator<const NativeCodeVersion, NativeCodeVersionIterator>
282 {
283     friend class Enumerator<const NativeCodeVersion, NativeCodeVersionIterator>;
284
285 public:
286     NativeCodeVersionIterator(NativeCodeVersionCollection* pCollection);
287     CHECK Check() const { CHECK_OK; }
288
289 protected:
290     const NativeCodeVersion & Get() const;
291     void First();
292     void Next();
293     bool Equal(const NativeCodeVersionIterator &i) const;
294
295     CHECK DoCheck() const { CHECK_OK; }
296
297 private:
298     enum IterationStage
299     {
300         Initial,
301         ImplicitCodeVersion,
302         LinkedList,
303         End
304     };
305     IterationStage m_stage;
306     NativeCodeVersionCollection* m_pCollection;
307     PTR_NativeCodeVersionNode m_pLinkedListCur;
308     NativeCodeVersion m_cur;
309 };
310
311 class ILCodeVersionNode
312 {
313 public:
314     ILCodeVersionNode();
315 #ifndef DACCESS_COMPILE
316     ILCodeVersionNode(Module* pModule, mdMethodDef methodDef, ReJITID id);
317 #endif
318 #ifdef DEBUG
319     BOOL LockOwnedByCurrentThread() const;
320 #endif //DEBUG
321     PTR_Module GetModule() const;
322     mdMethodDef GetMethodDef() const;
323     ReJITID GetVersionId() const;
324     PTR_COR_ILMETHOD GetIL() const;
325     DWORD GetJitFlags() const;
326     const InstrumentedILOffsetMapping* GetInstrumentedILMap() const;
327     ILCodeVersion::RejitFlags GetRejitState() const;
328     PTR_ILCodeVersionNode GetNextILVersionNode() const;
329 #ifndef DACCESS_COMPILE
330     void SetIL(COR_ILMETHOD* pIL);
331     void SetJitFlags(DWORD flags);
332     void SetInstrumentedILMap(SIZE_T cMap, COR_IL_MAP * rgMap);
333     void SetRejitState(ILCodeVersion::RejitFlags newState);
334     void SetNextILVersionNode(ILCodeVersionNode* pNextVersionNode);
335 #endif
336
337 private:
338     PTR_Module m_pModule;
339     mdMethodDef m_methodDef;
340     ReJITID m_rejitId;
341     PTR_ILCodeVersionNode m_pNextILVersionNode;
342     Volatile<ILCodeVersion::RejitFlags> m_rejitState;
343     VolatilePtr<COR_ILMETHOD> m_pIL;
344     Volatile<DWORD> m_jitFlags;
345     InstrumentedILOffsetMapping m_instrumentedILMap;
346 };
347
348 class ILCodeVersionCollection
349 {
350     friend class ILCodeVersionIterator;
351
352 public:
353     ILCodeVersionCollection(PTR_Module pModule, mdMethodDef methodDef);
354     ILCodeVersionIterator Begin();
355     ILCodeVersionIterator End();
356
357 private:
358     PTR_Module m_pModule;
359     mdMethodDef m_methodDef;
360 };
361
362 class ILCodeVersionIterator : public Enumerator<const ILCodeVersion, ILCodeVersionIterator>
363 {
364     friend class Enumerator<const ILCodeVersion, ILCodeVersionIterator>;
365
366 public:
367     ILCodeVersionIterator();
368     ILCodeVersionIterator(const ILCodeVersionIterator & iter);
369     ILCodeVersionIterator(ILCodeVersionCollection* pCollection);
370     CHECK Check() const { CHECK_OK; }
371
372 protected:
373     const ILCodeVersion & Get() const;
374     void First();
375     void Next();
376     bool Equal(const ILCodeVersionIterator &i) const;
377
378     CHECK DoCheck() const { CHECK_OK; }
379
380 private:
381     enum IterationStage
382     {
383         Initial,
384         ImplicitCodeVersion,
385         LinkedList,
386         End
387     };
388     IterationStage m_stage;
389     ILCodeVersion m_cur;
390     PTR_ILCodeVersionNode m_pLinkedListCur;
391     ILCodeVersionCollection* m_pCollection;
392 };
393
394 class MethodDescVersioningState
395 {
396 public:
397     // The size of the code used to jump stamp the prolog
398 #ifdef FEATURE_JUMPSTAMP
399     static const size_t JumpStubSize =
400 #if defined(_X86_) || defined(_AMD64_)
401         5;
402 #else
403 #error "Need to define size of jump-stamp for this platform"
404 #endif
405 #endif // FEATURE_JUMPSTAMP
406
407     MethodDescVersioningState(PTR_MethodDesc pMethodDesc);
408     PTR_MethodDesc GetMethodDesc() const;
409     NativeCodeVersionId AllocateVersionId();
410     PTR_NativeCodeVersionNode GetFirstVersionNode() const;
411
412 #ifndef DACCESS_COMPILE
413 #ifdef FEATURE_JUMPSTAMP
414     HRESULT SyncJumpStamp(NativeCodeVersion nativeCodeVersion, BOOL fEESuspended);
415     HRESULT UpdateJumpTarget(BOOL fEESuspended, PCODE pRejittedCode);
416     HRESULT UndoJumpStampNativeCode(BOOL fEESuspended);
417     HRESULT JumpStampNativeCode(PCODE pCode = NULL);
418 #endif // FEATURE_JUMPSTAMP
419     void LinkNativeCodeVersionNode(NativeCodeVersionNode* pNativeCodeVersionNode);
420 #endif // DACCESS_COMPILE
421
422 #ifdef FEATURE_JUMPSTAMP
423     enum JumpStampFlags
424     {
425         // There is no jump stamp in place on this method (Either because
426         // there is no code at all, or there is code that hasn't been
427         // overwritten with a jump)
428         JumpStampNone = 0x0,
429
430         // The method code has the jump stamp written in, and it points to the Prestub
431         JumpStampToPrestub = 0x1,
432
433         // The method code has the jump stamp written in, and it points to the currently
434         // active code version
435         JumpStampToActiveVersion = 0x2,
436     };
437
438     JumpStampFlags GetJumpStampState();
439     void SetJumpStampState(JumpStampFlags newState);
440 #endif // FEATURE_JUMPSTAMP
441
442     //read-write data for the default native code version
443     BOOL IsDefaultVersionActiveChild() const;
444 #ifndef DACCESS_COMPILE
445     void SetDefaultVersionActiveChildFlag(BOOL isActive);
446 #endif
447
448 private:
449 #if !defined(DACCESS_COMPILE) && defined(FEATURE_JUMPSTAMP)
450     INDEBUG(BOOL CodeIsSaved();)
451     HRESULT UpdateJumpStampHelper(BYTE* pbCode, INT64 i64OldValue, INT64 i64NewValue, BOOL fContentionPossible);
452 #endif
453     PTR_MethodDesc m_pMethodDesc;
454     
455     enum MethodDescVersioningStateFlags
456     {
457         JumpStampMask = 0x3,
458         IsDefaultVersionActiveChildFlag = 0x4
459     };
460     BYTE m_flags;
461     NativeCodeVersionId m_nextId;
462     PTR_NativeCodeVersionNode m_pFirstVersionNode;
463
464
465     // The originally JITted code that was overwritten with the jmp stamp.
466 #ifdef FEATURE_JUMPSTAMP
467     BYTE m_rgSavedCode[JumpStubSize];
468 #endif
469 };
470
471 class MethodDescVersioningStateHashTraits : public NoRemoveSHashTraits<DefaultSHashTraits<PTR_MethodDescVersioningState>>
472 {
473 public:
474     typedef typename DefaultSHashTraits<PTR_MethodDescVersioningState>::element_t element_t;
475     typedef typename DefaultSHashTraits<PTR_MethodDescVersioningState>::count_t count_t;
476
477     typedef const PTR_MethodDesc key_t;
478
479     static key_t GetKey(element_t e)
480     {
481         LIMITED_METHOD_CONTRACT;
482         return e->GetMethodDesc();
483     }
484     static BOOL Equals(key_t k1, key_t k2)
485     {
486         LIMITED_METHOD_CONTRACT;
487         return k1 == k2;
488     }
489     static count_t Hash(key_t k)
490     {
491         LIMITED_METHOD_CONTRACT;
492         return (count_t)(size_t)dac_cast<TADDR>(k);
493     }
494
495     static const element_t Null() { LIMITED_METHOD_CONTRACT; return dac_cast<PTR_MethodDescVersioningState>(nullptr); }
496     static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; }
497 };
498
499 typedef SHash<MethodDescVersioningStateHashTraits> MethodDescVersioningStateHash;
500
501 class ILCodeVersioningState
502 {
503 public:
504     ILCodeVersioningState(PTR_Module pModule, mdMethodDef methodDef);
505     ILCodeVersion GetActiveVersion() const;
506     PTR_ILCodeVersionNode GetFirstVersionNode() const;
507 #ifndef DACCESS_COMPILE
508     void SetActiveVersion(ILCodeVersion ilActiveCodeVersion);
509     void LinkILCodeVersionNode(ILCodeVersionNode* pILCodeVersionNode);
510 #endif
511
512     struct Key
513     {
514     public:
515         Key();
516         Key(PTR_Module pModule, mdMethodDef methodDef);
517         size_t Hash() const;
518         bool operator==(const Key & rhs) const;
519     private:
520         PTR_Module m_pModule;
521         mdMethodDef m_methodDef;
522     };
523
524     Key GetKey() const;
525
526 private:
527     ILCodeVersion m_activeVersion;
528     PTR_ILCodeVersionNode m_pFirstVersionNode;
529     PTR_Module m_pModule;
530     mdMethodDef m_methodDef;
531 };
532
533 class ILCodeVersioningStateHashTraits : public NoRemoveSHashTraits<DefaultSHashTraits<PTR_ILCodeVersioningState>>
534 {
535 public:
536     typedef typename DefaultSHashTraits<PTR_ILCodeVersioningState>::element_t element_t;
537     typedef typename DefaultSHashTraits<PTR_ILCodeVersioningState>::count_t count_t;
538
539     typedef const ILCodeVersioningState::Key key_t;
540
541     static key_t GetKey(element_t e)
542     {
543         LIMITED_METHOD_CONTRACT;
544         return e->GetKey();
545     }
546     static BOOL Equals(key_t k1, key_t k2)
547     {
548         LIMITED_METHOD_CONTRACT;
549         return k1 == k2;
550     }
551     static count_t Hash(key_t k)
552     {
553         LIMITED_METHOD_CONTRACT;
554         return (count_t)k.Hash();
555     }
556
557     static const element_t Null() { LIMITED_METHOD_CONTRACT; return dac_cast<PTR_ILCodeVersioningState>(nullptr); }
558     static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; }
559 };
560
561 typedef SHash<ILCodeVersioningStateHashTraits> ILCodeVersioningStateHash;
562
563
564 class CodeVersionManager
565 {
566     friend class ILCodeVersion;
567     friend class PublishMethodHolder;
568     friend class PublishMethodTableHolder;
569
570 public:
571     CodeVersionManager();
572
573     void PreInit(BOOL fSharedDomain);
574
575     class TableLockHolder : public CrstHolder
576     {
577     public:
578         TableLockHolder(CodeVersionManager * pCodeVersionManager);
579     };
580     //Using the holder is preferable, but in some cases the holder can't be used
581 #ifndef DACCESS_COMPILE
582     void EnterLock();
583     void LeaveLock();
584 #endif
585     
586 #ifdef DEBUG
587     BOOL LockOwnedByCurrentThread() const;
588 #endif
589
590     DWORD GetNonDefaultILVersionCount();
591     ILCodeVersionCollection GetILCodeVersions(PTR_MethodDesc pMethod);
592     ILCodeVersionCollection GetILCodeVersions(PTR_Module pModule, mdMethodDef methodDef);
593     ILCodeVersion GetActiveILCodeVersion(PTR_MethodDesc pMethod);
594     ILCodeVersion GetActiveILCodeVersion(PTR_Module pModule, mdMethodDef methodDef);
595     ILCodeVersion GetILCodeVersion(PTR_MethodDesc pMethod, ReJITID rejitId);
596     NativeCodeVersionCollection GetNativeCodeVersions(PTR_MethodDesc pMethod) const;
597     NativeCodeVersion GetNativeCodeVersion(PTR_MethodDesc pMethod, PCODE codeStartAddress) const;
598     PTR_ILCodeVersioningState GetILCodeVersioningState(PTR_Module pModule, mdMethodDef methodDef) const;
599     PTR_MethodDescVersioningState GetMethodDescVersioningState(PTR_MethodDesc pMethod) const;
600
601 #ifndef DACCESS_COMPILE
602     struct CodePublishError
603     {
604         Module* pModule;
605         mdMethodDef methodDef;
606         MethodDesc* pMethodDesc;
607         HRESULT hrStatus;
608     };
609
610     HRESULT AddILCodeVersion(Module* pModule, mdMethodDef methodDef, ReJITID rejitId, ILCodeVersion* pILCodeVersion);
611     HRESULT AddNativeCodeVersion(ILCodeVersion ilCodeVersion, MethodDesc* pClosedMethodDesc, NativeCodeVersion* pNativeCodeVersion);
612     HRESULT DoJumpStampIfNecessary(MethodDesc* pMD, PCODE pCode);
613     PCODE PublishVersionableCodeIfNecessary(MethodDesc* pMethodDesc, BOOL fCanBackpatchPrestub);
614     HRESULT PublishNativeCodeVersion(MethodDesc* pMethodDesc, NativeCodeVersion nativeCodeVersion, BOOL fEESuspended);
615     HRESULT GetOrCreateMethodDescVersioningState(MethodDesc* pMethod, MethodDescVersioningState** ppMethodDescVersioningState);
616     HRESULT GetOrCreateILCodeVersioningState(Module* pModule, mdMethodDef methodDef, ILCodeVersioningState** ppILCodeVersioningState);
617     HRESULT SetActiveILCodeVersions(ILCodeVersion* pActiveVersions, DWORD cActiveVersions, BOOL fEESuspended, CDynArray<CodePublishError> * pPublishErrors);
618     static HRESULT AddCodePublishError(Module* pModule, mdMethodDef methodDef, MethodDesc* pMD, HRESULT hrStatus, CDynArray<CodePublishError> * pErrors);
619     static HRESULT AddCodePublishError(NativeCodeVersion nativeCodeVersion, HRESULT hrStatus, CDynArray<CodePublishError> * pErrors);
620     static void OnAppDomainExit(AppDomain* pAppDomain);
621 #endif
622
623 private:
624
625 #ifndef DACCESS_COMPILE
626     static HRESULT EnumerateClosedMethodDescs(MethodDesc* pMD, CDynArray<MethodDesc*> * pClosedMethodDescs, CDynArray<CodePublishError> * pUnsupportedMethodErrors);
627     static HRESULT EnumerateDomainClosedMethodDescs(
628         AppDomain * pAppDomainToSearch,
629         Module* pModuleContainingMethodDef,
630         mdMethodDef methodDef,
631         CDynArray<MethodDesc*> * pClosedMethodDescs,
632         CDynArray<CodePublishError> * pUnsupportedMethodErrors);
633     static HRESULT GetNonVersionableError(MethodDesc* pMD);
634     void ReportCodePublishError(CodePublishError* pErrorRecord);
635     void ReportCodePublishError(Module* pModule, mdMethodDef methodDef, MethodDesc* pMD, HRESULT hrStatus);
636 #endif
637
638     //Module,MethodDef -> ILCodeVersioningState
639     ILCodeVersioningStateHash m_ilCodeVersioningStateMap;
640
641     //closed MethodDesc -> MethodDescVersioningState
642     MethodDescVersioningStateHash m_methodDescVersioningStateMap;
643     
644     CrstExplicitInit m_crstTable;
645 };
646
647 #endif // FEATURE_CODE_VERSIONING
648
649 //
650 // These holders are used by runtime code that is making new code
651 // available for execution, either by publishing jitted code
652 // or restoring NGEN code. It ensures the publishing is synchronized
653 // with rejit requests
654 //
655 class PublishMethodHolder
656 {
657 public:
658 #if !defined(FEATURE_CODE_VERSIONING) || defined(DACCESS_COMPILE) || defined(CROSSGEN_COMPILE)
659     PublishMethodHolder(MethodDesc* pMethod, PCODE pCode) { }
660 #else
661     PublishMethodHolder(MethodDesc* pMethod, PCODE pCode);
662     ~PublishMethodHolder();
663 #endif
664
665 private:
666 #if defined(FEATURE_CODE_VERSIONING)
667     MethodDesc * m_pMD;
668     HRESULT m_hr;
669 #endif
670 };
671
672 class PublishMethodTableHolder
673 {
674 public:
675 #if !defined(FEATURE_CODE_VERSIONING) || defined(DACCESS_COMPILE) || defined(CROSSGEN_COMPILE)
676     PublishMethodTableHolder(MethodTable* pMethodTable) { }
677 #else
678     PublishMethodTableHolder(MethodTable* pMethodTable);
679     ~PublishMethodTableHolder();
680 #endif
681
682 private:
683 #if defined(FEATURE_CODE_VERSIONING) && !defined(DACCESS_COMPILE)
684     MethodTable* m_pMethodTable;
685     CDynArray<CodeVersionManager::CodePublishError> m_errors;
686 #endif
687 };
688
689 #endif // CODE_VERSION_H