diff options
Diffstat (limited to 'src/vm/codeversion.h')
-rw-r--r-- | src/vm/codeversion.h | 689 |
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..768c9cdb55 --- /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 dac_cast<PTR_MethodDescVersioningState>(nullptr); } + 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 dac_cast<PTR_ILCodeVersioningState>(nullptr); } + 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 |