docs/design/datacontracts/ReJIT.md
This contract encapsulates support for ReJIT in the runtime.
public enum RejitState
{
Requested,
Active
}
bool IsEnabled();
RejitState GetRejitState(ILCodeVersionHandle codeVersionHandle);
TargetNUInt GetRejitId(ILCodeVersionHandle codeVersionHandle);
IEnumerable<TargetNUInt> GetRejitIds(TargetPointer methodDesc)
Data descriptors used:
| Data Descriptor Name | Field | Meaning |
|---|---|---|
| ProfControlBlock | GlobalEventMask | an ICorProfiler COR_PRF_MONITOR value |
| ProfControlBlock | RejitOnAttachEnabled | cached value of the ProfAPI_RejitOnAttach configuration knob |
| ILCodeVersionNode | VersionId | ILCodeVersion ReJIT ID |
| ILCodeVersionNode | RejitState | a RejitFlags value |
Global variables used:
| Global Name | Type | Purpose |
|---|---|---|
| ProfilerControlBlock | TargetPointer | pointer to the ProfControlBlock |
Contracts used:
| Contract Name |
|---|
| CodeVersions |
// see src/coreclr/inc/corprof.idl
[Flags]
private enum COR_PRF_MONITOR
{
COR_PRF_ENABLE_REJIT = 0x00040000,
}
// see src/coreclr/vm/codeversion.h
[Flags]
public enum RejitFlags : uint
{
kStateRequested = 0x00000000,
kStateActive = 0x00000002,
kStateMask = 0x0000000F
}
bool IsEnabled()
{
TargetPointer address = target.ReadGlobalPointer("ProfilerControlBlock");
ulong globalEventMask = target.Read<ulong>(address + /* ProfControlBlock::GlobalEventMask offset*/);
bool profEnabledReJIT = (globalEventMask & (ulong)COR_PRF_MONITOR.COR_PRF_ENABLE_REJIT) != 0;
bool rejitOnAttachEnabled = target.Read<uint>(address + /* ProfControlBlock::RejitOnAttachEnabled offset*/) != 0;
return profEnabledReJIT || rejitOnAttachEnabled;
}
RejitState GetRejitState(ILCodeVersionHandle codeVersion)
{
// ILCodeVersion::GetRejitState
if (codeVersion is not explicit)
{
// for non explicit ILCodeVersions, ReJITState is always kStateActive
return RejitState.Active;
}
else
{
// ILCodeVersionNode::GetRejitState
ILCodeVersionNode codeVersionNode = AsNode(codeVersion);
return ((RejitFlags)ilCodeVersionNode.RejitState & RejitFlags.kStateMask) switch
{
RejitFlags.kStateRequested => RejitState.Requested,
RejitFlags.kStateActive => RejitState.Active,
_ => throw new NotImplementedException($"Unknown ReJIT state: {ilCodeVersionNode.RejitState}"),
};
}
}
TargetNUInt GetRejitId(ILCodeVersionHandle codeVersion)
{
// ILCodeVersion::GetVersionId
if (codeVersion is not explicit)
{
// for non explicit ILCodeVersions, ReJITId is always 0
return new TargetNUInt(0);
}
else
{
// ILCodeVersionNode::GetVersionId
ILCodeVersionNode codeVersionNode = AsNode(codeVersion);
return codeVersionNode.VersionId;
}
}
IEnumerable<TargetNUInt> GetRejitIds(TargetPointer methodDesc)
{
// ReJitManager::GetReJITIDs
ICodeVersions cv = _target.Contracts.CodeVersions;
IEnumerable<ILCodeVersionHandle> ilCodeVersions = cv.GetILCodeVersions(methodDesc);
foreach (ILCodeVersionHandle ilCodeVersionHandle in ilCodeVersions)
{
if (GetRejitState(ilCodeVersionHandle) == RejitState.Active)
{
yield return GetRejitId(ilCodeVersionHandle);
}
}
}