| File: Compiler\ReachabilityInstrumentationFilter.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler) |
// 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 System.IO; using System.Reflection.Metadata.Ecma335; using System.Runtime.InteropServices; using Internal.IL; using Internal.IL.Stubs; using Internal.TypeSystem; using Internal.TypeSystem.Ecma; namespace ILCompiler { /// <summary> /// An <see cref="ILProvider"/> that filters methods based on a filter in a file. Methods not specified in /// the filter are replaced with a failfast call. /// </summary> public class ReachabilityInstrumentationFilter : ILProvider { private readonly Dictionary<Guid, bool[]> _reachabilityInfo = new Dictionary<Guid, bool[]>(); private readonly ILProvider _nestedProvider; public ReachabilityInstrumentationFilter(string profileDataFileName, ILProvider nestedProvider) { _nestedProvider = nestedProvider; // Read the file using BinaryReader reader = new BinaryReader(File.OpenRead(profileDataFileName)); int length = reader.ReadInt32(); if (length != (int)reader.BaseStream.Length) throw new IOException("Invalid header"); Span<byte> guidBytes = stackalloc byte[16]; while (true) { if (reader.Read(guidBytes) != guidBytes.Length) break; int numTokens = reader.ReadInt32(); bool[] tokenStates = new bool[numTokens]; if (reader.Read(MemoryMarshal.Cast<bool, byte>(tokenStates.AsSpan())) != numTokens) throw new IOException("Unexpected end of file"); _reachabilityInfo.Add(new Guid(guidBytes), tokenStates); } } public override MethodIL GetMethodIL(MethodDesc method) { MethodIL nestedIL = _nestedProvider.GetMethodIL(method); if (method is not EcmaMethod ecmaMethod || nestedIL is null) { return nestedIL; } Guid mvid = ecmaMethod.MetadataReader.GetGuid(ecmaMethod.MetadataReader.GetModuleDefinition().Mvid); int rowNumber = MetadataTokens.GetRowNumber(ecmaMethod.Handle); if (!_reachabilityInfo.TryGetValue(mvid, out bool[] tokenStates) || rowNumber >= tokenStates.Length) //throw new Exception("Mismatched profile data"); return nestedIL; // Method is present in the profile, return unmodified if (tokenStates[rowNumber]) return nestedIL; // Method not present: stub it out var emit = new ILEmitter(); ILCodeStream codeStream = emit.NewCodeStream(); codeStream.EmitCallThrowHelper(emit, method.Context.SystemModule.GetKnownType("System.Runtime"u8, "InternalCalls"u8).GetKnownMethod("RhpFallbackFailFast"u8, null)); return emit.Link(method); } } }