File: Contracts\ReJIT_1.cs
Web Access
Project: src\src\runtime\src\native\managed\cdac\Microsoft.Diagnostics.DataContractReader.Contracts\Microsoft.Diagnostics.DataContractReader.Contracts.csproj (Microsoft.Diagnostics.DataContractReader.Contracts)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using Microsoft.Diagnostics.DataContractReader.Data;

namespace Microsoft.Diagnostics.DataContractReader.Contracts;

internal readonly partial struct ReJIT_1 : IReJIT
{
    internal readonly Target _target;
    private readonly Data.ProfControlBlock _profControlBlock;

    // 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
    }

    public ReJIT_1(Target target)
    {
        _target = target;
        TargetPointer profControlBlockAddress = target.ReadGlobalPointer(Constants.Globals.ProfilerControlBlock);
        _profControlBlock = target.ProcessedData.GetOrAdd<Data.ProfControlBlock>(profControlBlockAddress);
    }

    bool IReJIT.IsEnabled()
    {
        bool profEnabledReJIT = (_profControlBlock.GlobalEventMask & (ulong)COR_PRF_MONITOR.COR_PRF_ENABLE_REJIT) != 0;
        return profEnabledReJIT || _profControlBlock.RejitOnAttachEnabled;
    }

    RejitState IReJIT.GetRejitState(ILCodeVersionHandle ilCodeVersionHandle)
    {
        if (!ilCodeVersionHandle.IsExplicit)
        {
            // for non explicit ILCodeVersions, ReJITState is always kStateActive
            return RejitState.Active;
        }
        ILCodeVersionNode ilCodeVersionNode = AsNode(ilCodeVersionHandle);
        return ((RejitFlags)ilCodeVersionNode.RejitState & RejitFlags.kStateMask) switch
        {
            RejitFlags.kStateRequested => RejitState.Requested,
            RejitFlags.kStateActive => RejitState.Active,
            _ => throw new InvalidOperationException($"Unknown ReJIT state: {ilCodeVersionNode.RejitState}"),
        };
    }

    TargetNUInt IReJIT.GetRejitId(ILCodeVersionHandle ilCodeVersionHandle)
    {
        if (ilCodeVersionHandle.ILCodeVersionNode == TargetPointer.Null)
        {
            // for non explicit ILCodeVersions, ReJITId is always 0
            return new TargetNUInt(0);
        }
        ILCodeVersionNode ilCodeVersionNode = AsNode(ilCodeVersionHandle);
        return ilCodeVersionNode.VersionId;
    }

    private ILCodeVersionNode AsNode(ILCodeVersionHandle ilCodeVersionHandle)
    {
        if (ilCodeVersionHandle.ILCodeVersionNode == TargetPointer.Null)
        {
            throw new InvalidOperationException("Synthetic ILCodeVersion does not have a backing node.");
        }

        return _target.ProcessedData.GetOrAdd<ILCodeVersionNode>(ilCodeVersionHandle.ILCodeVersionNode);
    }
}