File: Contracts\Notifications_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.Diagnostics.CodeAnalysis;

namespace Microsoft.Diagnostics.DataContractReader.Contracts;

internal readonly struct Notifications_1 : INotifications
{
    private enum NotificationType_1 : uint
    {
        ModuleLoad = 1,
        ModuleUnload = 2,
        Exception = 5,
        Gc = 6,
        ExceptionCatcherEnter = 7,
        Jit2 = 8,
    }

    private readonly Target _target;

    internal Notifications_1(Target target)
    {
        _target = target;
    }

    void INotifications.SetGcNotification(int condemnedGeneration)
    {
        TargetPointer pGcNotificationFlags = _target.ReadGlobalPointer(Constants.Globals.GcNotificationFlags);
        uint currentFlags = _target.Read<uint>(pGcNotificationFlags);
        if (condemnedGeneration == 0)
            _target.Write<uint>(pGcNotificationFlags, 0);
        else
        {
            _target.Write<uint>(pGcNotificationFlags, currentFlags | (uint)condemnedGeneration);
        }
    }

    bool INotifications.TryParseNotification(ReadOnlySpan<TargetPointer> exceptionInformation, [NotNullWhen(true)] out NotificationData? notification)
    {
        notification = null;

        if (exceptionInformation.IsEmpty)
            return false;

        notification = (NotificationType_1)(uint)exceptionInformation[0].Value switch
        {
            NotificationType_1.ModuleLoad => new ModuleLoadNotificationData(exceptionInformation[1]),
            NotificationType_1.ModuleUnload => new ModuleUnloadNotificationData(exceptionInformation[1]),
            NotificationType_1.Jit2 => new JitNotificationData(exceptionInformation[1], exceptionInformation[2]),
            NotificationType_1.Exception => new ExceptionNotificationData(exceptionInformation[1]),
            NotificationType_1.Gc => ParseGcNotification(exceptionInformation),
            NotificationType_1.ExceptionCatcherEnter => new ExceptionCatcherEnterNotificationData(exceptionInformation[1], (uint)exceptionInformation[2].Value),
            _ => null,
        };

        return notification is not null;
    }

    private static GcNotificationData ParseGcNotification(ReadOnlySpan<TargetPointer> exceptionInformation)
    {
        GcEventType eventType = (GcEventType)(uint)exceptionInformation[1].Value;
        GcEventData eventData = new(eventType, (int)(uint)exceptionInformation[2].Value);
        return new GcNotificationData(eventData, IsSupportedEvent: eventType == GcEventType.MarkEnd);
    }
}