| File: Compiler\ReadyToRunExternalTypeMapNode.cs | Web Access |
| Project: ILCompiler.ReadyToRun.csproj (ILCompiler.ReadyToRun) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Diagnostics; using System.Text; using ILCompiler.DependencyAnalysis; using ILCompiler.DependencyAnalysisFramework; using Internal; using Internal.NativeFormat; using Internal.TypeSystem; namespace ILCompiler.ReadyToRun { internal class ReadyToRunExternalTypeMapNode(ModuleDesc triggeringModule, TypeDesc group, TypeMapMetadata.IExternalTypeMap map, ImportReferenceProvider importProvider) : SortableDependencyNode, IExternalTypeMapNode { public TypeDesc TypeMapGroup => group; public override int ClassCode => 565222977; public override bool InterestingForDynamicDependencyAnalysis => false; public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => false; public override bool StaticDependenciesAreComputed => true; private ModuleDesc TriggeringModule { get; } = triggeringModule; public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) { ReadyToRunExternalTypeMapNode otherNode = (ReadyToRunExternalTypeMapNode)other; int result = comparer.Compare(TypeMapGroup, otherNode.TypeMapGroup); if (result != 0) return result; return comparer.Compare(TriggeringModule, otherNode.TriggeringModule); } public Vertex CreateTypeMap(NodeFactory factory, NativeWriter writer, Section section, INativeFormatTypeReferenceProvider externalReferences) { Vertex typeMapGroupVertex = externalReferences.EncodeReferenceToType(writer, TypeMapGroup, TriggeringModule); if (map.ThrowingMethodStub is not null) { // We don't write out the throwing method stub for R2R // as emitting loose methods is not supported/very expensive. // Instead, we defer to the runtime to generate the type map // and throw on error cases. return section.Place(writer.GetTuple( typeMapGroupVertex, writer.GetUnsignedConstant(ReadyToRunTypeMapEncoding.RuntimeAttributeFallback))); } VertexHashtable typeMapHashTable = new(); VertexSequence namedEntries = new(); bool hasNamedEntries = false; Section typeMapEntriesSection = writer.NewSection(); foreach ((string key, TypeMapMetadata.ExternalTypeMapEntry mapEntry) in map.TypeMap) { if (ReadyToRunTypeMapEncoding.IsTypeDescEncodable(factory, TriggeringModule, mapEntry.Type)) { Vertex entry = writer.GetTuple( writer.GetStringConstant(key), externalReferences.EncodeReferenceToType(writer, mapEntry.Type, TriggeringModule)); typeMapHashTable.Append((uint)VersionResilientHashCode.NameHashCode(Encoding.UTF8.GetBytes(key)), typeMapEntriesSection.Place(entry)); } else { Debug.Assert(TriggeringModule.Assembly == mapEntry.DeclaringModule.Assembly); namedEntries.Append(writer.GetTuple( writer.GetStringConstant(key), writer.GetStringConstant(mapEntry.SerializedTypeName))); hasNamedEntries = true; } } uint typeMapState = hasNamedEntries ? ReadyToRunTypeMapEncoding.PrecomputedFixupsAndTypeNames : ReadyToRunTypeMapEncoding.PrecomputedFixups; Vertex typeMapStateVertex = writer.GetUnsignedConstant(typeMapState); Vertex typeMapData = hasNamedEntries ? writer.GetTuple(typeMapHashTable, namedEntries) : typeMapHashTable; Vertex tuple = writer.GetTuple(typeMapGroupVertex, typeMapStateVertex, typeMapData); return section.Place(tuple); } public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context) => []; public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context) { yield return new DependencyListEntry(importProvider.GetImportToType(TypeMapGroup, TriggeringModule), $"Type map '{TypeMapGroup}' key type"); if (map.ThrowingMethodStub is not null) { yield break; } foreach (var entry in map.TypeMap) { if (ReadyToRunTypeMapEncoding.IsTypeDescEncodable(context, TriggeringModule, entry.Value.Type)) { yield return new DependencyListEntry(importProvider.GetImportToType(entry.Value.Type, TriggeringModule), $"External type map entry target for key '{entry.Key}'"); } } } public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => []; protected override string GetName(NodeFactory context) => $"ExternalTypeMap {TypeMapGroup} entries in assembly {TriggeringModule.GetDisplayName()}"; } }