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 | 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 | |
82 | private: |
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 | |
123 | class ILCodeVersion |
124 | { |
125 | friend class NativeCodeVersionIterator; |
126 | |
127 | public: |
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 | |
189 | private: |
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 | |
216 | class NativeCodeVersionNode |
217 | { |
218 | friend NativeCodeVersionIterator; |
219 | friend MethodDescVersioningState; |
220 | friend ILCodeVersionNode; |
221 | public: |
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 | |
242 | private: |
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 | |
263 | class NativeCodeVersionCollection |
264 | { |
265 | friend class NativeCodeVersionIterator; |
266 | public: |
267 | NativeCodeVersionCollection(PTR_MethodDesc pMethodDescFilter, ILCodeVersion ilCodeFilter); |
268 | NativeCodeVersionIterator Begin(); |
269 | NativeCodeVersionIterator End(); |
270 | |
271 | private: |
272 | PTR_MethodDesc m_pMethodDescFilter; |
273 | ILCodeVersion m_ilCodeFilter; |
274 | }; |
275 | |
276 | class NativeCodeVersionIterator : public Enumerator<const NativeCodeVersion, NativeCodeVersionIterator> |
277 | { |
278 | friend class Enumerator<const NativeCodeVersion, NativeCodeVersionIterator>; |
279 | |
280 | public: |
281 | NativeCodeVersionIterator(NativeCodeVersionCollection* pCollection); |
282 | CHECK Check() const { CHECK_OK; } |
283 | |
284 | protected: |
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 | |
292 | private: |
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 | |
306 | class ILCodeVersionNode |
307 | { |
308 | public: |
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 | |
332 | private: |
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 | |
343 | class ILCodeVersionCollection |
344 | { |
345 | friend class ILCodeVersionIterator; |
346 | |
347 | public: |
348 | ILCodeVersionCollection(PTR_Module pModule, mdMethodDef methodDef); |
349 | ILCodeVersionIterator Begin(); |
350 | ILCodeVersionIterator End(); |
351 | |
352 | private: |
353 | PTR_Module m_pModule; |
354 | mdMethodDef m_methodDef; |
355 | }; |
356 | |
357 | class ILCodeVersionIterator : public Enumerator<const ILCodeVersion, ILCodeVersionIterator> |
358 | { |
359 | friend class Enumerator<const ILCodeVersion, ILCodeVersionIterator>; |
360 | |
361 | public: |
362 | ILCodeVersionIterator(); |
363 | ILCodeVersionIterator(const ILCodeVersionIterator & iter); |
364 | ILCodeVersionIterator(ILCodeVersionCollection* pCollection); |
365 | CHECK Check() const { CHECK_OK; } |
366 | |
367 | protected: |
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 | |
375 | private: |
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 | |
389 | class MethodDescVersioningState |
390 | { |
391 | public: |
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 | |
443 | private: |
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 | |
466 | class MethodDescVersioningStateHashTraits : public NoRemoveSHashTraits<DefaultSHashTraits<PTR_MethodDescVersioningState>> |
467 | { |
468 | public: |
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 | |
494 | typedef SHash<MethodDescVersioningStateHashTraits> MethodDescVersioningStateHash; |
495 | |
496 | class ILCodeVersioningState |
497 | { |
498 | public: |
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 | |
521 | private: |
522 | ILCodeVersion m_activeVersion; |
523 | PTR_ILCodeVersionNode m_pFirstVersionNode; |
524 | PTR_Module m_pModule; |
525 | mdMethodDef m_methodDef; |
526 | }; |
527 | |
528 | class ILCodeVersioningStateHashTraits : public NoRemoveSHashTraits<DefaultSHashTraits<PTR_ILCodeVersioningState>> |
529 | { |
530 | public: |
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 | |
556 | typedef SHash<ILCodeVersioningStateHashTraits> ILCodeVersioningStateHash; |
557 | |
558 | |
559 | class CodeVersionManager |
560 | { |
561 | friend class ILCodeVersion; |
562 | friend class PublishMethodHolder; |
563 | friend class PublishMethodTableHolder; |
564 | |
565 | public: |
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 | |
618 | private: |
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 | // |
650 | class PublishMethodHolder |
651 | { |
652 | public: |
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 | |
660 | private: |
661 | #if defined(FEATURE_CODE_VERSIONING) |
662 | MethodDesc * m_pMD; |
663 | HRESULT m_hr; |
664 | #endif |
665 | }; |
666 | |
667 | class PublishMethodTableHolder |
668 | { |
669 | public: |
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 | |
677 | private: |
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 | |