summaryrefslogtreecommitdiff
path: root/src/vm/codeversion.h
diff options
context:
space:
mode:
authornoahfalk <noahfalk@microsoft.com>2017-07-24 17:38:30 -0700
committernoahfalk <noahfalk@microsoft.com>2017-07-24 17:38:30 -0700
commitfd1998903d5eef356f27c54e5a9d490711cbc9e7 (patch)
treeb1d3d7ff1978483060a0f7c879b22006edd417b4 /src/vm/codeversion.h
parent39cd3cfcb078154f9b595ae476f2c5fb7b445e18 (diff)
downloadcoreclr-fd1998903d5eef356f27c54e5a9d490711cbc9e7.tar.gz
coreclr-fd1998903d5eef356f27c54e5a9d490711cbc9e7.tar.bz2
coreclr-fd1998903d5eef356f27c54e5a9d490711cbc9e7.zip
Add the runtime code versioning feature
This makes tiered compilation work properly with profiler ReJIT, and positions the runtime to integrate other versioning related features together in the future. See the newly added code-versioning design-doc in this commit for more information. Breaking changes for profilers: See code-versioning-profiler-breaking-changes.md for more details.
Diffstat (limited to 'src/vm/codeversion.h')
-rw-r--r--src/vm/codeversion.h689
1 files changed, 689 insertions, 0 deletions
diff --git a/src/vm/codeversion.h b/src/vm/codeversion.h
new file mode 100644
index 0000000000..7bb2a24294
--- /dev/null
+++ b/src/vm/codeversion.h
@@ -0,0 +1,689 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// ===========================================================================
+// File: CodeVersion.h
+//
+// ===========================================================================
+
+
+#ifndef CODE_VERSION_H
+#define CODE_VERSION_H
+
+class NativeCodeVersion;
+class ILCodeVersion;
+typedef DWORD NativeCodeVersionId;
+
+#ifdef FEATURE_CODE_VERSIONING
+class NativeCodeVersionNode;
+typedef DPTR(class NativeCodeVersionNode) PTR_NativeCodeVersionNode;
+class NativeCodeVersionCollection;
+class NativeCodeVersionIterator;
+class ILCodeVersionNode;
+typedef DPTR(class ILCodeVersionNode) PTR_ILCodeVersionNode;
+class ILCodeVersionCollection;
+class ILCodeVersionIterator;
+class MethodDescVersioningState;
+typedef DPTR(class MethodDescVersioningState) PTR_MethodDescVersioningState;
+
+class ILCodeVersioningState;
+typedef DPTR(class ILCodeVersioningState) PTR_ILCodeVersioningState;
+class CodeVersionManager;
+typedef DPTR(class CodeVersionManager) PTR_CodeVersionManager;
+
+// This HRESULT is only used as a private implementation detail. Corerror.xml has a comment in it
+// reserving this value for our use but it doesn't appear in the public headers.
+#define CORPROF_E_RUNTIME_SUSPEND_REQUIRED 0x80131381
+
+#endif
+
+
+
+
+class NativeCodeVersion
+{
+#ifdef FEATURE_CODE_VERSIONING
+ friend class MethodDescVersioningState;
+ friend class ILCodeVersion;
+#endif
+
+public:
+ NativeCodeVersion();
+ NativeCodeVersion(const NativeCodeVersion & rhs);
+#ifdef FEATURE_CODE_VERSIONING
+ NativeCodeVersion(PTR_NativeCodeVersionNode pVersionNode);
+#endif
+ NativeCodeVersion(PTR_MethodDesc pMethod);
+ BOOL IsNull() const;
+ PTR_MethodDesc GetMethodDesc() const;
+ NativeCodeVersionId GetVersionId() const;
+ BOOL IsDefaultVersion() const;
+ PCODE GetNativeCode() const;
+ ILCodeVersion GetILCodeVersion() const;
+ ReJITID GetILCodeVersionId() const;
+#ifndef DACCESS_COMPILE
+ BOOL SetNativeCodeInterlocked(PCODE pCode, PCODE pExpected = NULL);
+#endif
+#ifdef FEATURE_TIERED_COMPILATION
+ enum OptimizationTier
+ {
+ OptimizationTier0,
+ OptimizationTier1
+ };
+ OptimizationTier GetOptimizationTier() const;
+#ifndef DACCESS_COMPILE
+ void SetOptimizationTier(OptimizationTier tier);
+#endif
+#endif // FEATURE_TIERED_COMPILATION
+ bool operator==(const NativeCodeVersion & rhs) const;
+ bool operator!=(const NativeCodeVersion & rhs) const;
+#if defined(DACCESS_COMPILE) && defined(FEATURE_CODE_VERSIONING)
+ // The DAC is privy to the backing node abstraction
+ PTR_NativeCodeVersionNode AsNode() const;
+#endif
+
+private:
+
+#ifndef FEATURE_CODE_VERSIONING
+ MethodDesc* m_pMethodDesc;
+#else // FEATURE_CODE_VERSIONING
+
+#ifndef DACCESS_COMPILE
+ NativeCodeVersionNode* AsNode() const;
+ NativeCodeVersionNode* AsNode();
+ void SetActiveChildFlag(BOOL isActive);
+ MethodDescVersioningState* GetMethodDescVersioningState();
+#endif
+
+ BOOL IsActiveChildVersion() const;
+ PTR_MethodDescVersioningState GetMethodDescVersioningState() const;
+
+ enum StorageKind
+ {
+ Unknown,
+ Explicit,
+ Synthetic
+ };
+
+ StorageKind m_storageKind;
+ union
+ {
+ PTR_NativeCodeVersionNode m_pVersionNode;
+ struct SyntheticStorage
+ {
+ PTR_MethodDesc m_pMethodDesc;
+ } m_synthetic;
+ };
+#endif // FEATURE_CODE_VERSIONING
+};
+
+
+
+#ifdef FEATURE_CODE_VERSIONING
+
+
+
+class ILCodeVersion
+{
+ friend class NativeCodeVersionIterator;
+
+public:
+ ILCodeVersion();
+ ILCodeVersion(const ILCodeVersion & ilCodeVersion);
+ ILCodeVersion(PTR_ILCodeVersionNode pILCodeVersionNode);
+ ILCodeVersion(PTR_Module pModule, mdMethodDef methodDef);
+
+ bool operator==(const ILCodeVersion & rhs) const;
+ bool operator!=(const ILCodeVersion & rhs) const;
+ BOOL IsNull() const;
+ BOOL IsDefaultVersion() const;
+ PTR_Module GetModule() const;
+ mdMethodDef GetMethodDef() const;
+ ReJITID GetVersionId() const;
+ NativeCodeVersionCollection GetNativeCodeVersions(PTR_MethodDesc pClosedMethodDesc) const;
+ NativeCodeVersion GetActiveNativeCodeVersion(PTR_MethodDesc pClosedMethodDesc) const;
+ PTR_COR_ILMETHOD GetIL() const;
+ PTR_COR_ILMETHOD GetILNoThrow() const;
+ DWORD GetJitFlags() const;
+ const InstrumentedILOffsetMapping* GetInstrumentedILMap() const;
+
+#ifndef DACCESS_COMPILE
+ void SetIL(COR_ILMETHOD* pIL);
+ void SetJitFlags(DWORD flags);
+ void SetInstrumentedILMap(SIZE_T cMap, COR_IL_MAP * rgMap);
+ HRESULT AddNativeCodeVersion(MethodDesc* pClosedMethodDesc, NativeCodeVersion* pNativeCodeVersion);
+ HRESULT GetOrCreateActiveNativeCodeVersion(MethodDesc* pClosedMethodDesc, NativeCodeVersion* pNativeCodeVersion);
+ HRESULT SetActiveNativeCodeVersion(NativeCodeVersion activeNativeCodeVersion, BOOL fEESuspended);
+#endif //DACCESS_COMPILE
+
+ enum RejitFlags
+ {
+ // The profiler has requested a ReJit, so we've allocated stuff, but we haven't
+ // called back to the profiler to get any info or indicate that the ReJit has
+ // started. (This Info can be 'reused' for a new ReJit if the
+ // profiler calls RequestRejit again before we transition to the next state.)
+ kStateRequested = 0x00000000,
+
+ // The CLR has initiated the call to the profiler's GetReJITParameters() callback
+ // but it hasn't completed yet. At this point we have to assume the profiler has
+ // commited to a specific IL body, even if the CLR doesn't know what it is yet.
+ // If the profiler calls RequestRejit we need to allocate a new ILCodeVersion
+ // and call GetReJITParameters() again.
+ kStateGettingReJITParameters = 0x00000001,
+
+ // We have asked the profiler about this method via ICorProfilerFunctionControl,
+ // and have thus stored the IL and codegen flags the profiler specified.
+ kStateActive = 0x00000002,
+
+ kStateMask = 0x0000000F,
+ };
+
+ RejitFlags GetRejitState() const;
+#ifndef DACCESS_COMPILE
+ void SetRejitState(RejitFlags newState);
+#endif
+
+#ifdef DACCESS_COMPILE
+ // The DAC is privy to the backing node abstraction
+ PTR_ILCodeVersionNode AsNode() const;
+#endif
+
+private:
+
+#ifndef DACCESS_COMPILE
+ PTR_ILCodeVersionNode AsNode();
+ PTR_ILCodeVersionNode AsNode() const;
+#endif
+
+ enum StorageKind
+ {
+ Unknown,
+ Explicit,
+ Synthetic
+ };
+
+ StorageKind m_storageKind;
+ union
+ {
+ PTR_ILCodeVersionNode m_pVersionNode;
+ struct SyntheticStorage
+ {
+ PTR_Module m_pModule;
+ mdMethodDef m_methodDef;
+ } m_synthetic;
+ };
+};
+
+
+class NativeCodeVersionNode
+{
+ friend NativeCodeVersionIterator;
+ friend MethodDescVersioningState;
+ friend ILCodeVersionNode;
+public:
+#ifndef DACCESS_COMPILE
+ NativeCodeVersionNode(NativeCodeVersionId id, MethodDesc* pMethod, ReJITID parentId);
+#endif
+#ifdef DEBUG
+ BOOL LockOwnedByCurrentThread() const;
+#endif
+ PTR_MethodDesc GetMethodDesc() const;
+ NativeCodeVersionId GetVersionId() const;
+ PCODE GetNativeCode() const;
+ ReJITID GetILVersionId() const;
+ ILCodeVersion GetILCodeVersion() const;
+ BOOL IsActiveChildVersion() const;
+#ifndef DACCESS_COMPILE
+ BOOL SetNativeCodeInterlocked(PCODE pCode, PCODE pExpected);
+ void SetActiveChildFlag(BOOL isActive);
+#endif
+#ifdef FEATURE_TIERED_COMPILATION
+ NativeCodeVersion::OptimizationTier GetOptimizationTier() const;
+#ifndef DACCESS_COMPILE
+ void SetOptimizationTier(NativeCodeVersion::OptimizationTier tier);
+#endif
+#endif
+
+private:
+ //union - could save a little memory?
+ //{
+ PCODE m_pNativeCode;
+ PTR_MethodDesc m_pMethodDesc;
+ //};
+
+ ReJITID m_parentId;
+ PTR_NativeCodeVersionNode m_pNextMethodDescSibling;
+ NativeCodeVersionId m_id;
+#ifdef FEATURE_TIERED_COMPILATION
+ Volatile<NativeCodeVersion::OptimizationTier> m_optTier;
+#endif
+
+ enum NativeCodeVersionNodeFlags
+ {
+ IsActiveChildFlag = 1
+ };
+ DWORD m_flags;
+};
+
+class NativeCodeVersionCollection
+{
+ friend class NativeCodeVersionIterator;
+public:
+ NativeCodeVersionCollection(PTR_MethodDesc pMethodDescFilter, ILCodeVersion ilCodeFilter);
+ NativeCodeVersionIterator Begin();
+ NativeCodeVersionIterator End();
+
+private:
+ PTR_MethodDesc m_pMethodDescFilter;
+ ILCodeVersion m_ilCodeFilter;
+};
+
+class NativeCodeVersionIterator : public Enumerator<const NativeCodeVersion, NativeCodeVersionIterator>
+{
+ friend class Enumerator<const NativeCodeVersion, NativeCodeVersionIterator>;
+
+public:
+ NativeCodeVersionIterator(NativeCodeVersionCollection* pCollection);
+ CHECK Check() const { CHECK_OK; }
+
+protected:
+ const NativeCodeVersion & Get() const;
+ void First();
+ void Next();
+ bool Equal(const NativeCodeVersionIterator &i) const;
+
+ CHECK DoCheck() const { CHECK_OK; }
+
+private:
+ enum IterationStage
+ {
+ Initial,
+ ImplicitCodeVersion,
+ LinkedList,
+ End
+ };
+ IterationStage m_stage;
+ NativeCodeVersionCollection* m_pCollection;
+ PTR_NativeCodeVersionNode m_pLinkedListCur;
+ NativeCodeVersion m_cur;
+};
+
+class ILCodeVersionNode
+{
+public:
+ ILCodeVersionNode();
+#ifndef DACCESS_COMPILE
+ ILCodeVersionNode(Module* pModule, mdMethodDef methodDef, ReJITID id);
+#endif
+#ifdef DEBUG
+ BOOL LockOwnedByCurrentThread() const;
+#endif //DEBUG
+ PTR_Module GetModule() const;
+ mdMethodDef GetMethodDef() const;
+ ReJITID GetVersionId() const;
+ PTR_COR_ILMETHOD GetIL() const;
+ DWORD GetJitFlags() const;
+ const InstrumentedILOffsetMapping* GetInstrumentedILMap() const;
+ ILCodeVersion::RejitFlags GetRejitState() const;
+ PTR_ILCodeVersionNode GetNextILVersionNode() const;
+#ifndef DACCESS_COMPILE
+ void SetIL(COR_ILMETHOD* pIL);
+ void SetJitFlags(DWORD flags);
+ void SetInstrumentedILMap(SIZE_T cMap, COR_IL_MAP * rgMap);
+ void SetRejitState(ILCodeVersion::RejitFlags newState);
+ void SetNextILVersionNode(ILCodeVersionNode* pNextVersionNode);
+#endif
+
+private:
+ PTR_Module m_pModule;
+ mdMethodDef m_methodDef;
+ ReJITID m_rejitId;
+ PTR_ILCodeVersionNode m_pNextILVersionNode;
+ Volatile<ILCodeVersion::RejitFlags> m_rejitState;
+ VolatilePtr<COR_ILMETHOD> m_pIL;
+ Volatile<DWORD> m_jitFlags;
+ InstrumentedILOffsetMapping m_instrumentedILMap;
+};
+
+class ILCodeVersionCollection
+{
+ friend class ILCodeVersionIterator;
+
+public:
+ ILCodeVersionCollection(PTR_Module pModule, mdMethodDef methodDef);
+ ILCodeVersionIterator Begin();
+ ILCodeVersionIterator End();
+
+private:
+ PTR_Module m_pModule;
+ mdMethodDef m_methodDef;
+};
+
+class ILCodeVersionIterator : public Enumerator<const ILCodeVersion, ILCodeVersionIterator>
+{
+ friend class Enumerator<const ILCodeVersion, ILCodeVersionIterator>;
+
+public:
+ ILCodeVersionIterator();
+ ILCodeVersionIterator(const ILCodeVersionIterator & iter);
+ ILCodeVersionIterator(ILCodeVersionCollection* pCollection);
+ CHECK Check() const { CHECK_OK; }
+
+protected:
+ const ILCodeVersion & Get() const;
+ void First();
+ void Next();
+ bool Equal(const ILCodeVersionIterator &i) const;
+
+ CHECK DoCheck() const { CHECK_OK; }
+
+private:
+ enum IterationStage
+ {
+ Initial,
+ ImplicitCodeVersion,
+ LinkedList,
+ End
+ };
+ IterationStage m_stage;
+ ILCodeVersion m_cur;
+ PTR_ILCodeVersionNode m_pLinkedListCur;
+ ILCodeVersionCollection* m_pCollection;
+};
+
+class MethodDescVersioningState
+{
+public:
+ // The size of the code used to jump stamp the prolog
+#ifdef FEATURE_JUMPSTAMP
+ static const size_t JumpStubSize =
+#if defined(_X86_) || defined(_AMD64_)
+ 5;
+#else
+#error "Need to define size of jump-stamp for this platform"
+#endif
+#endif // FEATURE_JUMPSTAMP
+
+ MethodDescVersioningState(PTR_MethodDesc pMethodDesc);
+ PTR_MethodDesc GetMethodDesc() const;
+ NativeCodeVersionId AllocateVersionId();
+ PTR_NativeCodeVersionNode GetFirstVersionNode() const;
+
+#ifndef DACCESS_COMPILE
+#ifdef FEATURE_JUMPSTAMP
+ HRESULT SyncJumpStamp(NativeCodeVersion nativeCodeVersion, BOOL fEESuspended);
+ HRESULT UpdateJumpTarget(BOOL fEESuspended, PCODE pRejittedCode);
+ HRESULT UndoJumpStampNativeCode(BOOL fEESuspended);
+ HRESULT JumpStampNativeCode(PCODE pCode = NULL);
+#endif // FEATURE_JUMPSTAMP
+ void LinkNativeCodeVersionNode(NativeCodeVersionNode* pNativeCodeVersionNode);
+#endif // DACCESS_COMPILE
+
+#ifdef FEATURE_JUMPSTAMP
+ enum JumpStampFlags
+ {
+ // There is no jump stamp in place on this method (Either because
+ // there is no code at all, or there is code that hasn't been
+ // overwritten with a jump)
+ JumpStampNone = 0x0,
+
+ // The method code has the jump stamp written in, and it points to the Prestub
+ JumpStampToPrestub = 0x1,
+
+ // The method code has the jump stamp written in, and it points to the currently
+ // active code version
+ JumpStampToActiveVersion = 0x2,
+ };
+
+ JumpStampFlags GetJumpStampState();
+ void SetJumpStampState(JumpStampFlags newState);
+#endif // FEATURE_JUMPSTAMP
+
+ //read-write data for the default native code version
+ BOOL IsDefaultVersionActiveChild() const;
+#ifndef DACCESS_COMPILE
+ void SetDefaultVersionActiveChildFlag(BOOL isActive);
+#endif
+
+private:
+#if !defined(DACCESS_COMPILE) && defined(FEATURE_JUMPSTAMP)
+ INDEBUG(BOOL CodeIsSaved();)
+ HRESULT UpdateJumpStampHelper(BYTE* pbCode, INT64 i64OldValue, INT64 i64NewValue, BOOL fContentionPossible);
+#endif
+ PTR_MethodDesc m_pMethodDesc;
+
+ enum MethodDescVersioningStateFlags
+ {
+ JumpStampMask = 0x3,
+ IsDefaultVersionActiveChildFlag = 0x4
+ };
+ BYTE m_flags;
+ NativeCodeVersionId m_nextId;
+ PTR_NativeCodeVersionNode m_pFirstVersionNode;
+
+
+ // The originally JITted code that was overwritten with the jmp stamp.
+#ifdef FEATURE_JUMPSTAMP
+ BYTE m_rgSavedCode[JumpStubSize];
+#endif
+};
+
+class MethodDescVersioningStateHashTraits : public NoRemoveSHashTraits<DefaultSHashTraits<PTR_MethodDescVersioningState>>
+{
+public:
+ typedef typename DefaultSHashTraits<PTR_MethodDescVersioningState>::element_t element_t;
+ typedef typename DefaultSHashTraits<PTR_MethodDescVersioningState>::count_t count_t;
+
+ typedef const PTR_MethodDesc key_t;
+
+ static key_t GetKey(element_t e)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return e->GetMethodDesc();
+ }
+ static BOOL Equals(key_t k1, key_t k2)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return k1 == k2;
+ }
+ static count_t Hash(key_t k)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return (count_t)(size_t)dac_cast<TADDR>(k);
+ }
+
+ static const element_t Null() { LIMITED_METHOD_CONTRACT; return element_t(); }
+ static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; }
+};
+
+typedef SHash<MethodDescVersioningStateHashTraits> MethodDescVersioningStateHash;
+
+class ILCodeVersioningState
+{
+public:
+ ILCodeVersioningState(PTR_Module pModule, mdMethodDef methodDef);
+ ILCodeVersion GetActiveVersion() const;
+ PTR_ILCodeVersionNode GetFirstVersionNode() const;
+#ifndef DACCESS_COMPILE
+ void SetActiveVersion(ILCodeVersion ilActiveCodeVersion);
+ void LinkILCodeVersionNode(ILCodeVersionNode* pILCodeVersionNode);
+#endif
+
+ struct Key
+ {
+ public:
+ Key();
+ Key(PTR_Module pModule, mdMethodDef methodDef);
+ size_t Hash() const;
+ bool operator==(const Key & rhs) const;
+ private:
+ PTR_Module m_pModule;
+ mdMethodDef m_methodDef;
+ };
+
+ Key GetKey() const;
+
+private:
+ ILCodeVersion m_activeVersion;
+ PTR_ILCodeVersionNode m_pFirstVersionNode;
+ PTR_Module m_pModule;
+ mdMethodDef m_methodDef;
+};
+
+class ILCodeVersioningStateHashTraits : public NoRemoveSHashTraits<DefaultSHashTraits<PTR_ILCodeVersioningState>>
+{
+public:
+ typedef typename DefaultSHashTraits<PTR_ILCodeVersioningState>::element_t element_t;
+ typedef typename DefaultSHashTraits<PTR_ILCodeVersioningState>::count_t count_t;
+
+ typedef const ILCodeVersioningState::Key key_t;
+
+ static key_t GetKey(element_t e)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return e->GetKey();
+ }
+ static BOOL Equals(key_t k1, key_t k2)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return k1 == k2;
+ }
+ static count_t Hash(key_t k)
+ {
+ LIMITED_METHOD_CONTRACT;
+ return (count_t)k.Hash();
+ }
+
+ static const element_t Null() { LIMITED_METHOD_CONTRACT; return element_t(); }
+ static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; }
+};
+
+typedef SHash<ILCodeVersioningStateHashTraits> ILCodeVersioningStateHash;
+
+
+class CodeVersionManager
+{
+ friend class ILCodeVersion;
+ friend class PublishMethodHolder;
+ friend class PublishMethodTableHolder;
+
+public:
+ CodeVersionManager();
+
+ void PreInit(BOOL fSharedDomain);
+
+ class TableLockHolder : public CrstHolder
+ {
+ public:
+ TableLockHolder(CodeVersionManager * pCodeVersionManager);
+ };
+ //Using the holder is preferable, but in some cases the holder can't be used
+#ifndef DACCESS_COMPILE
+ void EnterLock();
+ void LeaveLock();
+#endif
+
+#ifdef DEBUG
+ BOOL LockOwnedByCurrentThread() const;
+#endif
+
+ DWORD GetNonDefaultILVersionCount();
+ ILCodeVersionCollection GetILCodeVersions(PTR_MethodDesc pMethod);
+ ILCodeVersionCollection GetILCodeVersions(PTR_Module pModule, mdMethodDef methodDef);
+ ILCodeVersion GetActiveILCodeVersion(PTR_MethodDesc pMethod);
+ ILCodeVersion GetActiveILCodeVersion(PTR_Module pModule, mdMethodDef methodDef);
+ ILCodeVersion GetILCodeVersion(PTR_MethodDesc pMethod, ReJITID rejitId);
+ NativeCodeVersionCollection GetNativeCodeVersions(PTR_MethodDesc pMethod) const;
+ NativeCodeVersion GetNativeCodeVersion(PTR_MethodDesc pMethod, PCODE codeStartAddress) const;
+ PTR_ILCodeVersioningState GetILCodeVersioningState(PTR_Module pModule, mdMethodDef methodDef) const;
+ PTR_MethodDescVersioningState GetMethodDescVersioningState(PTR_MethodDesc pMethod) const;
+
+#ifndef DACCESS_COMPILE
+ struct CodePublishError
+ {
+ Module* pModule;
+ mdMethodDef methodDef;
+ MethodDesc* pMethodDesc;
+ HRESULT hrStatus;
+ };
+
+ HRESULT AddILCodeVersion(Module* pModule, mdMethodDef methodDef, ReJITID rejitId, ILCodeVersion* pILCodeVersion);
+ HRESULT AddNativeCodeVersion(ILCodeVersion ilCodeVersion, MethodDesc* pClosedMethodDesc, NativeCodeVersion* pNativeCodeVersion);
+ HRESULT DoJumpStampIfNecessary(MethodDesc* pMD, PCODE pCode);
+ PCODE PublishVersionableCodeIfNecessary(MethodDesc* pMethodDesc, BOOL fCanBackpatchPrestub);
+ HRESULT PublishNativeCodeVersion(MethodDesc* pMethodDesc, NativeCodeVersion nativeCodeVersion, BOOL fEESuspended);
+ HRESULT GetOrCreateMethodDescVersioningState(MethodDesc* pMethod, MethodDescVersioningState** ppMethodDescVersioningState);
+ HRESULT GetOrCreateILCodeVersioningState(Module* pModule, mdMethodDef methodDef, ILCodeVersioningState** ppILCodeVersioningState);
+ HRESULT SetActiveILCodeVersions(ILCodeVersion* pActiveVersions, DWORD cActiveVersions, BOOL fEESuspended, CDynArray<CodePublishError> * pPublishErrors);
+ static HRESULT AddCodePublishError(Module* pModule, mdMethodDef methodDef, MethodDesc* pMD, HRESULT hrStatus, CDynArray<CodePublishError> * pErrors);
+ static HRESULT AddCodePublishError(NativeCodeVersion nativeCodeVersion, HRESULT hrStatus, CDynArray<CodePublishError> * pErrors);
+ static void OnAppDomainExit(AppDomain* pAppDomain);
+#endif
+
+private:
+
+#ifndef DACCESS_COMPILE
+ static HRESULT EnumerateClosedMethodDescs(MethodDesc* pMD, CDynArray<MethodDesc*> * pClosedMethodDescs, CDynArray<CodePublishError> * pUnsupportedMethodErrors);
+ static HRESULT EnumerateDomainClosedMethodDescs(
+ AppDomain * pAppDomainToSearch,
+ Module* pModuleContainingMethodDef,
+ mdMethodDef methodDef,
+ CDynArray<MethodDesc*> * pClosedMethodDescs,
+ CDynArray<CodePublishError> * pUnsupportedMethodErrors);
+ static HRESULT GetNonVersionableError(MethodDesc* pMD);
+ void ReportCodePublishError(CodePublishError* pErrorRecord);
+ void ReportCodePublishError(Module* pModule, mdMethodDef methodDef, MethodDesc* pMD, HRESULT hrStatus);
+#endif
+
+ //Module,MethodDef -> ILCodeVersioningState
+ ILCodeVersioningStateHash m_ilCodeVersioningStateMap;
+
+ //closed MethodDesc -> MethodDescVersioningState
+ MethodDescVersioningStateHash m_methodDescVersioningStateMap;
+
+ CrstExplicitInit m_crstTable;
+};
+
+#endif // FEATURE_CODE_VERSIONING
+
+//
+// These holders are used by runtime code that is making new code
+// available for execution, either by publishing jitted code
+// or restoring NGEN code. It ensures the publishing is synchronized
+// with rejit requests
+//
+class PublishMethodHolder
+{
+public:
+#if !defined(FEATURE_CODE_VERSIONING) || defined(DACCESS_COMPILE) || defined(CROSSGEN_COMPILE)
+ PublishMethodHolder(MethodDesc* pMethod, PCODE pCode) { }
+#else
+ PublishMethodHolder(MethodDesc* pMethod, PCODE pCode);
+ ~PublishMethodHolder();
+#endif
+
+private:
+#if defined(FEATURE_CODE_VERSIONING)
+ MethodDesc * m_pMD;
+ HRESULT m_hr;
+#endif
+};
+
+class PublishMethodTableHolder
+{
+public:
+#if !defined(FEATURE_CODE_VERSIONING) || defined(DACCESS_COMPILE) || defined(CROSSGEN_COMPILE)
+ PublishMethodTableHolder(MethodTable* pMethodTable) { }
+#else
+ PublishMethodTableHolder(MethodTable* pMethodTable);
+ ~PublishMethodTableHolder();
+#endif
+
+private:
+#if defined(FEATURE_CODE_VERSIONING) && !defined(DACCESS_COMPILE)
+ MethodTable* m_pMethodTable;
+ CDynArray<CodeVersionManager::CodePublishError> m_errors;
+#endif
+};
+
+#endif // CODE_VERSION_H