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