summaryrefslogtreecommitdiff
path: root/src/vm/rejit.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/rejit.h')
-rw-r--r--src/vm/rejit.h482
1 files changed, 41 insertions, 441 deletions
diff --git a/src/vm/rejit.h b/src/vm/rejit.h
index 3c8bfd66b2..8401ecb960 100644
--- a/src/vm/rejit.h
+++ b/src/vm/rejit.h
@@ -19,9 +19,8 @@
#include "contractimpl.h"
#include "shash.h"
#include "corprof.h"
+#include "codeversion.h"
-struct ReJitInfo;
-struct SharedReJitInfo;
class ReJitManager;
class MethodDesc;
class ClrDataAccess;
@@ -68,347 +67,9 @@ protected:
COR_IL_MAP * m_rgInstrumentedMapEntries;
};
-//---------------------------------------------------------------------------------------
-// Helper base class used by the structures below to enforce that their
-// pieces get allocated on the appropriate loader heaps
-//
-struct LoaderHeapAllocatedRejitStructure
-{
-public:
- void * operator new (size_t size, LoaderHeap * pHeap, const NoThrow&);
- void * operator new (size_t size, LoaderHeap * pHeap);
-};
-
-//---------------------------------------------------------------------------------------
-// One instance of this per rejit request for each mdMethodDef. Contains IL and
-// compilation flags. This is used primarily as a structure, so most of its
-// members are left public.
-//
-struct SharedReJitInfo : public LoaderHeapAllocatedRejitStructure
-{
-private:
- // This determines what to use next as the value of the profiling API's ReJITID.
- static ReJITID s_GlobalReJitId;
-
-public:
- // These represent the various states a SharedReJitInfo can be in.
- enum InternalFlags
- {
- // 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 SharedReJitInfo
- // 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. Can only
- // transition to kStateReverted from this state.
- kStateActive = 0x00000002,
-
- // The methoddef has been reverted, but not freed yet. It (or its instantiations
- // for generics) *MAY* still be active on the stack someplace or have outstanding
- // memory references.
- kStateReverted = 0x00000003,
-
-
- kStateMask = 0x0000000F,
- };
-
- DWORD m_dwInternalFlags;
-
- // Data
- LPBYTE m_pbIL;
- DWORD m_dwCodegenFlags;
- InstrumentedILOffsetMapping m_instrumentedILMap;
-
-private:
- // This is the value of the profiling API's ReJITID for this particular
- // rejit request.
- const ReJITID m_reJitId;
-
- // Children
- ReJitInfo * m_pInfoList;
-
-public:
- // Constructor
- SharedReJitInfo();
-
- // Intentionally no destructor. SharedReJitInfo and its contents are
- // allocated on a loader heap, so SharedReJitInfo and its contents will be
- // freed when the AD is unloaded.
-
- // Read-Only Identifcation
- ReJITID GetId() { return m_reJitId; }
-
- void AddMethod(ReJitInfo * pInfo);
-
- void RemoveMethod(ReJitInfo * pInfo);
-
- ReJitInfo * GetMethods() { return m_pInfoList; }
-
- InternalFlags GetState();
-};
-
-//---------------------------------------------------------------------------------------
-// One instance of this per rejit request for each MethodDesc*. One SharedReJitInfo
-// corresponds to many ReJitInfos, as the SharedReJitInfo tracks the rejit request for
-// the methodDef token whereas the ReJitInfo tracks the rejit request for each correspond
-// MethodDesc* (instantiation). Points to actual generated code.
-//
-// In the case of "pre-rejit" (see comment at top of rejit.cpp), a special "placeholder"
-// instance of ReJitInfo is used to "remember" to jmp-stamp a not-yet-jitted-method once
-// it finally gets jitted the first time.
-//
-// Each ReJitManager contains a hash table of ReJitInfo instances, keyed by
-// ReJitManager::m_key.
-//
-// This is used primarily as a structure, so most of its members are left public.
-//
-struct ReJitInfo : public LoaderHeapAllocatedRejitStructure
-{
-public:
- // The size of the code used to jump stamp the prolog
- static const size_t JumpStubSize =
-#if defined(_X86_) || defined(_AMD64_)
- 5;
-#else
-#error "Need to define size of rejit jump-stamp for this platform"
- 1;
-#endif
-
- // Used by PtrSHash template as the key for this ReJitInfo. For regular
- // ReJitInfos, the key is the MethodDesc*. For placeholder ReJitInfos
- // (to facilitate pre-rejit), the key is (Module*, mdMethodDef).
- struct Key
- {
- public:
- enum
- {
- // The key has not yet had its values initialized
- kUninitialized = 0x0,
-
- // The key represents a loaded MethodDesc, and is identified by the m_pMD
- // field
- kMethodDesc = 0x1,
-
- // The key represents a "placeholder" ReJitInfo identified not by loaded
- // MethodDesc, but by the module and metadata token (m_pModule,
- // m_methodDef).
- kMetadataToken = 0x2,
- };
-
- // Storage consists of a discriminated union between MethodDesc* or
- // (Module*, mdMethodDef), with the key type as the discriminator.
- union
- {
- TADDR m_pMD;
- TADDR m_pModule;
- };
- ULONG32 m_methodDef : 28;
- ULONG32 m_keyType : 2;
-
- Key();
- Key(PTR_MethodDesc pMD);
- Key(PTR_Module pModule, mdMethodDef methodDef);
- };
-
- static COUNT_T Hash(Key key);
-
- enum InternalFlags
- {
- // This ReJitInfo is either a placeholder (identified by module and
- // metadata token, rather than loaded MethodDesc) OR this ReJitInfo is
- // identified by a loaded MethodDesc that has been reverted OR not yet
- // been jump-stamped. In the last case, the time window where this
- // ReJitInfo would stay in kJumpNone is rather small, as
- // RequestReJIT() will immediately cause the originally JITted code to
- // be jump-stamped.
- kJumpNone = 0x00000000,
-
- // This ReJitInfo is identified by a loaded MethodDesc that has been compiled and
- // jump-stamped, with the target being the prestub. The MethodDesc has not yet
- // been rejitted
- kJumpToPrestub = 0x00000001,
-
- // This ReJitInfo is identified by a loaded MethodDesc that has been compiled AND
- // rejitted. The top of the originally JITted code has been jump-stamped, with
- // the target being the latest version of the rejitted code.
- kJumpToRejittedCode = 0x00000002,
-
- kStateMask = 0x0000000F,
- };
-
- Key m_key;
- DWORD m_dwInternalFlags;
-
- // The beginning of the rejitted code
- PCODE m_pCode;
-
- // The parent SharedReJitInfo, which manages the rejit request for all
- // instantiations.
- PTR_SharedReJitInfo const m_pShared;
-
- // My next sibling ReJitInfo for this rejit request (e.g., another
- // generic instantiation of the same method)
- PTR_ReJitInfo m_pNext;
-
- // The originally JITted code that was overwritten with the jmp stamp.
- BYTE m_rgSavedCode[JumpStubSize];
-
-
- ReJitInfo(PTR_MethodDesc pMD, SharedReJitInfo * pShared);
- ReJitInfo(PTR_Module pModule, mdMethodDef methodDef, SharedReJitInfo * pShared);
-
- // Intentionally no destructor. ReJitInfo is allocated on a loader heap,
- // and will be freed (along with its associated SharedReJitInfo) when the
- // AD is unloaded.
-
- Key GetKey();
- PTR_MethodDesc GetMethodDesc();
- void GetModuleAndToken(Module ** ppModule, mdMethodDef * pMethodDef);
- void GetModuleAndTokenRegardlessOfKeyType(Module ** ppModule, mdMethodDef * pMethodDef);
- InternalFlags GetState();
-
- COR_ILMETHOD * GetIL();
-
- HRESULT JumpStampNativeCode(PCODE pCode = NULL);
- HRESULT UndoJumpStampNativeCode(BOOL fEESuspended);
- HRESULT UpdateJumpTarget(BOOL fEESuspended, PCODE pRejittedCode);
- HRESULT UpdateJumpStampHelper(BYTE* pbCode, INT64 i64OldValue, INT64 i64newValue, BOOL fContentionPossible);
-
-
-protected:
- void CommonInit();
- INDEBUG(BOOL CodeIsSaved();)
-};
-
-//---------------------------------------------------------------------------------------
-// Used by the SHash inside ReJitManager which maintains the set of ReJitInfo instances.
-//
-class ReJitInfoTraits : public DefaultSHashTraits<PTR_ReJitInfo>
-{
-public:
-
- // explicitly declare local typedefs for these traits types, otherwise
- // the compiler may get confused
- typedef DefaultSHashTraits<PTR_ReJitInfo> PARENT;
- typedef PARENT::element_t element_t;
- typedef PARENT::count_t count_t;
-
- typedef ReJitInfo::Key key_t;
-
- static key_t GetKey(const element_t &e);
- static BOOL Equals(key_t k1, key_t k2);
- static count_t Hash(key_t k);
- static bool IsNull(const element_t &e);
-};
-
-// RequestRejit and RequestRevert use these batches to accumulate ReJitInfos that need their
-// jump stamps updated
-class ReJitManager;
-struct ReJitManagerJumpStampBatch
-{
- ReJitManagerJumpStampBatch(ReJitManager * pReJitManager) : undoMethods(), preStubMethods()
- {
- LIMITED_METHOD_CONTRACT;
- this->pReJitManager = pReJitManager;
- }
-
- ReJitManager* pReJitManager;
- CDynArray<ReJitInfo *> undoMethods;
- CDynArray<ReJitInfo *> preStubMethods;
-};
-
-class ReJitManagerJumpStampBatchTraits : public DefaultSHashTraits<ReJitManagerJumpStampBatch *>
-{
-public:
-
- // explicitly declare local typedefs for these traits types, otherwise
- // the compiler may get confused
- typedef DefaultSHashTraits<ReJitManagerJumpStampBatch *> PARENT;
- typedef PARENT::element_t element_t;
- typedef PARENT::count_t count_t;
-
- typedef ReJitManager * key_t;
-
- static key_t GetKey(const element_t &e)
- {
- return e->pReJitManager;
- }
-
- static BOOL Equals(key_t k1, key_t k2)
- {
- return (k1 == k2);
- }
-
- static count_t Hash(key_t k)
- {
- return (count_t)k;
- }
-
- static bool IsNull(const element_t &e)
- {
- return (e == NULL);
- }
-};
-
-struct ReJitReportErrorWorkItem
-{
- Module* pModule;
- mdMethodDef methodDef;
- MethodDesc* pMethodDesc;
- HRESULT hrStatus;
-};
-
-
#endif // FEATURE_REJIT
-//
-// 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 ReJitPublishMethodHolder
-{
-public:
-#if !defined(FEATURE_REJIT) || defined(DACCESS_COMPILE) || defined(CROSSGEN_COMPILE)
- ReJitPublishMethodHolder(MethodDesc* pMethod, PCODE pCode) { }
-#else
- ReJitPublishMethodHolder(MethodDesc* pMethod, PCODE pCode);
- ~ReJitPublishMethodHolder();
-#endif
-
-private:
-#if defined(FEATURE_REJIT)
- MethodDesc * m_pMD;
- HRESULT m_hr;
-#endif
-};
-class ReJitPublishMethodTableHolder
-{
-public:
-#if !defined(FEATURE_REJIT) || defined(DACCESS_COMPILE) || defined(CROSSGEN_COMPILE)
- ReJitPublishMethodTableHolder(MethodTable* pMethodTable) { }
-#else
- ReJitPublishMethodTableHolder(MethodTable* pMethodTable);
- ~ReJitPublishMethodTableHolder();
-#endif
-
-private:
-#if defined(FEATURE_REJIT)
- MethodTable* m_pMethodTable;
- CDynArray<ReJitReportErrorWorkItem> m_errors;
-#endif
-};
//---------------------------------------------------------------------------------------
// The big honcho. One of these per AppDomain, plus one for the
@@ -420,55 +81,23 @@ class ReJitManager
friend class ClrDataAccess;
friend class DacDbiInterfaceImpl;
- //I would have prefered to make these inner classes, but
- //then I can't friend them from crst easily.
- friend class ReJitPublishMethodHolder;
- friend class ReJitPublishMethodTableHolder;
-
private:
#ifdef FEATURE_REJIT
- // Hash table mapping MethodDesc* (or (ModuleID, mdMethodDef)) to its
- // ReJitInfos. One key may map to multiple ReJitInfos if there have been
- // multiple rejit requests made for the same MD. See
- // code:ReJitManager::ReJitManager#Invariants for more information.
- typedef SHash<ReJitInfoTraits> ReJitInfoHash;
-
// One global crst (for the entire CLR instance) to synchronize
// cross-ReJitManager operations, such as batch calls to RequestRejit and
// RequestRevert (which modify multiple ReJitManager instances).
static CrstStatic s_csGlobalRequest;
- // All The ReJitInfos (and their linked SharedReJitInfos) for this domain.
- ReJitInfoHash m_table;
-
- // The crst that synchronizes the data in m_table, including
- // adding/removing to m_table, as well as state changes made to
- // individual ReJitInfos & SharedReJitInfos in m_table.
- CrstExplicitInit m_crstTable;
-
#endif //FEATURE_REJIT
public:
- // The ReJITManager takes care of grabbing its m_crstTable when necessary. However,
- // for clients who need to do this explicitly (like ETW rundown), this holder may be
- // used.
- class TableLockHolder
-#ifdef FEATURE_REJIT
- : public CrstHolder
-#endif
- {
- public:
- TableLockHolder(ReJitManager * pReJitManager);
- };
static void InitStatic();
static BOOL IsReJITEnabled();
- static void OnAppDomainExit(AppDomain * pAppDomain);
-
static HRESULT RequestReJIT(
ULONG cFunctions,
ModuleID rgModuleIDs[],
@@ -480,85 +109,56 @@ public:
mdMethodDef rgMethodDefs[],
HRESULT rgHrStatuses[]);
- static PCODE DoReJitIfNecessary(PTR_MethodDesc pMD); // Invokes the jit, or returns previously rejitted code
-
- static void DoJumpStampForAssemblyIfNecessary(Assembly* pAssemblyToSearch);
-
- static DWORD GetCurrentReJitFlags(PTR_MethodDesc pMD);
-
- ReJitManager();
-
- void PreInit(BOOL fSharedDomain);
-
- ReJITID GetReJitId(PTR_MethodDesc pMD, PCODE pCodeStart);
-
- ReJITID GetReJitIdNoLock(PTR_MethodDesc pMD, PCODE pCodeStart);
+ static HRESULT ConfigureILCodeVersion(ILCodeVersion ilCodeVersion);
+ static CORJIT_FLAGS JitFlagsFromProfCodegenFlags(DWORD dwCodegenFlags);
- PCODE GetCodeStart(PTR_MethodDesc pMD, ReJITID reJitId);
-
- HRESULT GetReJITIDs(PTR_MethodDesc pMD, ULONG cReJitIds, ULONG * pcReJitIds, ReJITID reJitIds[]);
+ static ReJITID GetReJitId(PTR_MethodDesc pMD, PCODE pCodeStart);
+ static ReJITID GetReJitIdNoLock(PTR_MethodDesc pMD, PCODE pCodeStart);
+ static HRESULT GetReJITIDs(PTR_MethodDesc pMD, ULONG cReJitIds, ULONG * pcReJitIds, ReJITID reJitIds[]);
#ifdef FEATURE_REJIT
-
- INDEBUG(BOOL IsTableCrstOwnedByCurrentThread());
+#ifndef DACCESS_COMPILE
+ static void ReportReJITError(CodeVersionManager::CodePublishError* pErrorRecord);
+ static void ReportReJITError(Module* pModule, mdMethodDef methodDef, MethodDesc* pMD, HRESULT hrStatus);
+#endif
private:
- static HRESULT IsMethodSafeForReJit(PTR_MethodDesc pMD);
- static void ReportReJITError(ReJitReportErrorWorkItem* pErrorRecord);
- static void ReportReJITError(Module* pModule, mdMethodDef methodDef, MethodDesc* pMD, HRESULT hrStatus);
- static HRESULT AddReJITError(ReJitInfo* pReJitInfo, HRESULT hrStatus, CDynArray<ReJitReportErrorWorkItem> * pErrors);
- static HRESULT AddReJITError(Module* pModule, mdMethodDef methodDef, MethodDesc* pMD, HRESULT hrStatus, CDynArray<ReJitReportErrorWorkItem> * pErrors);
- HRESULT BatchUpdateJumpStamps(CDynArray<ReJitInfo *> * pUndoMethods, CDynArray<ReJitInfo *> * pPreStubMethods, CDynArray<ReJitReportErrorWorkItem> * pErrors);
- PCODE DoReJitIfNecessaryWorker(PTR_MethodDesc pMD); // Invokes the jit, or returns previously rejitted code
- DWORD GetCurrentReJitFlagsWorker(PTR_MethodDesc pMD);
+ static HRESULT UpdateActiveILVersions(
+ ULONG cFunctions,
+ ModuleID rgModuleIDs[],
+ mdMethodDef rgMethodDefs[],
+ HRESULT rgHrStatuses[],
+ BOOL fIsRevert);
- HRESULT MarkAllInstantiationsForReJit(
- SharedReJitInfo * pSharedForAllGenericInstantiations,
- AppDomain * pAppDomainToSearch,
- PTR_Module pModuleContainingGenericDefinition,
- mdMethodDef methodDef,
- ReJitManagerJumpStampBatch* pJumpStampBatch,
- CDynArray<ReJitReportErrorWorkItem> * pRejitErrors);
-
- INDEBUG(BaseDomain * m_pDomain;)
- INDEBUG(void Dump(LPCSTR szIntroText);)
- INDEBUG(void AssertRestOfEntriesAreReverted(
- ReJitInfoHash::KeyIterator iter,
- ReJitInfoHash::KeyIterator end);)
-
-
- HRESULT DoJumpStampIfNecessary(MethodDesc* pMD, PCODE pCode);
- HRESULT MarkForReJit(PTR_MethodDesc pMD, SharedReJitInfo * pSharedToReuse, ReJitManagerJumpStampBatch* pJumpStampBatch, CDynArray<ReJitReportErrorWorkItem> * pRejitErrors, SharedReJitInfo ** ppSharedUsed);
- HRESULT MarkForReJit(PTR_Module pModule, mdMethodDef methodDef, ReJitManagerJumpStampBatch* pJumpStampBatch, CDynArray<ReJitReportErrorWorkItem> * pRejitErrors, SharedReJitInfo ** ppSharedUsed);
- HRESULT MarkForReJitHelper(
- PTR_MethodDesc pMD,
- PTR_Module pModule,
- mdMethodDef methodDef,
- SharedReJitInfo * pSharedToReuse,
- ReJitManagerJumpStampBatch* pJumpStampBatch,
- CDynArray<ReJitReportErrorWorkItem> * pRejitErrors,
- /* out */ SharedReJitInfo ** ppSharedUsed);
- HRESULT AddNewReJitInfo(
- PTR_MethodDesc pMD,
+ struct CodeActivationBatch
+ {
+ CodeActivationBatch(CodeVersionManager * pCodeVersionManager) :
+ m_pCodeVersionManager(pCodeVersionManager)
+ {}
+ CodeVersionManager* m_pCodeVersionManager;
+ CDynArray<ILCodeVersion> m_methodsToActivate;
+ };
+
+ class CodeActivationBatchTraits : public DefaultSHashTraits<CodeActivationBatch *>
+ {
+ public:
+ typedef DefaultSHashTraits<CodeActivationBatch *> PARENT;
+ typedef PARENT::element_t element_t;
+ typedef PARENT::count_t count_t;
+ typedef CodeVersionManager * key_t;
+ static key_t GetKey(const element_t &e) { return e->m_pCodeVersionManager; }
+ static BOOL Equals(key_t k1, key_t k2) { return (k1 == k2); }
+ static count_t Hash(key_t k) { return (count_t)k; }
+ static bool IsNull(const element_t &e) { return (e == NULL); }
+ };
+
+ static HRESULT BindILVersion(
+ CodeVersionManager* pCodeVersionManager,
PTR_Module pModule,
mdMethodDef methodDef,
- SharedReJitInfo * pShared,
- ReJitInfo ** ppInfo);
- HRESULT RequestRevertByToken(PTR_Module pModule, mdMethodDef methodDef);
- PTR_ReJitInfo FindReJitInfo(PTR_MethodDesc pMD, PCODE pCodeStart, ReJITID reJitId);
- PTR_ReJitInfo FindNonRevertedReJitInfo(PTR_Module pModule, mdMethodDef methodDef);
- PTR_ReJitInfo FindNonRevertedReJitInfo(PTR_MethodDesc pMD);
- PTR_ReJitInfo FindNonRevertedReJitInfoHelper(PTR_MethodDesc pMD, PTR_Module pModule, mdMethodDef methodDef);
- ReJitInfo* FindPreReJittedReJitInfo(ReJitInfoHash::KeyIterator beginIter, ReJitInfoHash::KeyIterator endIter);
- HRESULT Revert(SharedReJitInfo * pShared, ReJitManagerJumpStampBatch* pJumpStampBatch);
- PCODE DoReJit(ReJitInfo * pInfo);
- ReJitInfoHash::KeyIterator GetBeginIterator(PTR_MethodDesc pMD);
- ReJitInfoHash::KeyIterator GetEndIterator(PTR_MethodDesc pMD);
- ReJitInfoHash::KeyIterator GetBeginIterator(PTR_Module pModule, mdMethodDef methodDef);
- ReJitInfoHash::KeyIterator GetEndIterator(PTR_Module pModule, mdMethodDef methodDef);
- void RemoveReJitInfosFromDomain(AppDomain * pAppDomain);
+ ILCodeVersion *pILCodeVersion);
#endif // FEATURE_REJIT