|
// 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 Internal.Text;
using System.Diagnostics;
using System.Reflection.Metadata;
using Internal.TypeSystem.Ecma;
namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
public class MethodIsGenericMapNode : ModuleSpecificHeaderTableNode
{
private MetadataReader _metadata;
public MethodIsGenericMapNode(EcmaModule module) : base(module)
{
_metadata = module.MetadataReader;
}
public static bool IsSupported(MetadataReader metadata)
{
// Only support this map with R2R images of some size
return metadata.MethodDefinitions.Count > 32;
}
public override int ClassCode => 606284890;
protected override string ModuleSpecificName => "__MethodIsGenericMap__";
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
// This node does not trigger generation of other nodes.
if (relocsOnly)
return new ObjectData(Array.Empty<byte>(), Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });
ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);
builder.AddSymbol(this);
builder.EmitInt(_metadata.MethodDefinitions.Count);
int usedBits = 0;
byte curByte = 0;
foreach (var methodDefinitionHandle in _metadata.MethodDefinitions)
{
var methodDefinition = _metadata.GetMethodDefinition(methodDefinitionHandle);
bool isGeneric = methodDefinition.GetGenericParameters().Count > 0;
curByte |= isGeneric ? (byte)1 : (byte)0;
usedBits++;
if (usedBits == 8)
{
builder.EmitByte(curByte);
usedBits = 0;
curByte = 0;
}
else
{
curByte <<= 1;
}
}
if (usedBits != 0)
builder.EmitByte((byte)(curByte << (7 - usedBits)));
return builder.ToObjectData();
}
}
}
|