Build header tables using metadata manager (#6222)

* Build header tables using metadata manager

* Enable MetadataManager to track use of types / methods

* Introduce `AvailableType` which replaces the CoreRT EETypeNode.
Ready-to-run doesn't emit types directly into the image but records
their use and fills a table of available types used for type resolution
between ready-to-run modules by the runtime.

* Add dependency tracking in a few existing places where references to
types are being made. In library compilation mode, the non-private types
will be rooted so they always end up in the available types table.

* Use a single NodeCache for method entrypoints instead of a separate
dictionary for ready-to-run entrypoints. To smooth over the API
differences between the base `NodeFactory` and
`ReadyToRunCodegenNodeFactory`, allow a custom GetOrAdd method that
takes a creator callback.

* Switch over `RuntimeFunctionsTable`, `TypesTable`,
`MethodEntryPointTable` to use metadata manager for the list of types /
methods to emit entries for.
This commit is contained in:
Simon Nattress 2018-08-14 12:44:10 -07:00 коммит произвёл GitHub
Родитель ee5bc9f6ff
Коммит 3d56b11db6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
18 изменённых файлов: 424 добавлений и 118 удалений

Просмотреть файл

@ -149,60 +149,18 @@ namespace ILCompiler.DependencyAnalysis
{
return _cache.GetOrAdd(key, _creator);
}
public TValue GetOrAdd(TKey key, Func<TKey, TValue> creator)
{
return _cache.GetOrAdd(key, creator);
}
}
private void CreateNodeCaches()
{
_typeSymbols = new NodeCache<TypeDesc, IEETypeNode>((TypeDesc type) =>
{
Debug.Assert(!_compilationModuleGroup.ShouldReferenceThroughImportTable(type));
if (_compilationModuleGroup.ContainsType(type))
{
if (type.IsGenericDefinition)
{
return new GenericDefinitionEETypeNode(this, type);
}
else if (type.IsCanonicalDefinitionType(CanonicalFormKind.Any))
{
return new CanonicalDefinitionEETypeNode(this, type);
}
else if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
{
return new NecessaryCanonicalEETypeNode(this, type);
}
else
{
return new EETypeNode(this, type);
}
}
else
{
return new ExternEETypeSymbolNode(this, type);
}
});
_typeSymbols = new NodeCache<TypeDesc, IEETypeNode>(CreateNecessaryTypeNode);
_constructedTypeSymbols = new NodeCache<TypeDesc, IEETypeNode>((TypeDesc type) =>
{
// Canonical definition types are *not* constructed types (call NecessaryTypeSymbol to get them)
Debug.Assert(!type.IsCanonicalDefinitionType(CanonicalFormKind.Any));
Debug.Assert(!_compilationModuleGroup.ShouldReferenceThroughImportTable(type));
if (_compilationModuleGroup.ContainsType(type))
{
if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
{
return new CanonicalEETypeNode(this, type);
}
else
{
return new ConstructedEETypeNode(this, type);
}
}
else
{
return new ExternEETypeSymbolNode(this, type);
}
});
_constructedTypeSymbols = new NodeCache<TypeDesc, IEETypeNode>(CreateConstructedTypeNode);
_clonedTypeSymbols = new NodeCache<TypeDesc, IEETypeNode>((TypeDesc type) =>
{
@ -483,6 +441,57 @@ namespace ILCompiler.DependencyAnalysis
WindowsDebugData = new WindowsDebugDataHelper(this);
}
protected virtual IEETypeNode CreateNecessaryTypeNode(TypeDesc type)
{
Debug.Assert(!_compilationModuleGroup.ShouldReferenceThroughImportTable(type));
if (_compilationModuleGroup.ContainsType(type))
{
if (type.IsGenericDefinition)
{
return new GenericDefinitionEETypeNode(this, type);
}
else if (type.IsCanonicalDefinitionType(CanonicalFormKind.Any))
{
return new CanonicalDefinitionEETypeNode(this, type);
}
else if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
{
return new NecessaryCanonicalEETypeNode(this, type);
}
else
{
return new EETypeNode(this, type);
}
}
else
{
return new ExternEETypeSymbolNode(this, type);
}
}
protected virtual IEETypeNode CreateConstructedTypeNode(TypeDesc type)
{
// Canonical definition types are *not* constructed types (call NecessaryTypeSymbol to get them)
Debug.Assert(!type.IsCanonicalDefinitionType(CanonicalFormKind.Any));
Debug.Assert(!_compilationModuleGroup.ShouldReferenceThroughImportTable(type));
if (_compilationModuleGroup.ContainsType(type))
{
if (type.IsCanonicalSubtype(CanonicalFormKind.Any))
{
return new CanonicalEETypeNode(this, type);
}
else
{
return new ConstructedEETypeNode(this, type);
}
}
else
{
return new ExternEETypeSymbolNode(this, type);
}
}
protected abstract IMethodNode CreateMethodEntrypointNode(MethodDesc method);
protected abstract IMethodNode CreateUnboxingStubNode(MethodDesc method);
@ -721,7 +730,7 @@ namespace ILCompiler.DependencyAnalysis
return _stringAllocators.GetOrAdd(stringConstructor);
}
private NodeCache<MethodDesc, IMethodNode> _methodEntrypoints;
protected NodeCache<MethodDesc, IMethodNode> _methodEntrypoints;
private NodeCache<MethodDesc, IMethodNode> _unboxingStubs;
private NodeCache<IMethodNode, MethodAssociatedDataNode> _methodAssociatedData;

Просмотреть файл

@ -45,8 +45,8 @@ namespace ILCompiler
protected readonly ManifestResourceBlockingPolicy _resourceBlockingPolicy;
private List<NonGCStaticsNode> _cctorContextsGenerated = new List<NonGCStaticsNode>();
private HashSet<TypeDesc> _typesWithEETypesGenerated = new HashSet<TypeDesc>();
private HashSet<TypeDesc> _typesWithConstructedEETypesGenerated = new HashSet<TypeDesc>();
private readonly HashSet<TypeDesc> _typesWithEETypesGenerated = new HashSet<TypeDesc>();
private readonly HashSet<TypeDesc> _typesWithConstructedEETypesGenerated = new HashSet<TypeDesc>();
private HashSet<MethodDesc> _methodsGenerated = new HashSet<MethodDesc>();
private HashSet<GenericDictionaryNode> _genericDictionariesGenerated = new HashSet<GenericDictionaryNode>();
private HashSet<IMethodBodyNode> _methodBodiesGenerated = new HashSet<IMethodBodyNode>();
@ -560,7 +560,7 @@ namespace ILCompiler
return _genericDictionariesGenerated;
}
internal IEnumerable<MethodDesc> GetCompiledMethods()
public IEnumerable<MethodDesc> GetCompiledMethods()
{
return _methodsGenerated;
}

Просмотреть файл

@ -72,14 +72,6 @@ namespace ILCompiler.DependencyAnalysis
_rdataSectionIndex = sectionBuilder.AddSection(".rdata", SectionCharacteristics.ContainsInitializedData | SectionCharacteristics.MemRead, 512);
_dataSectionIndex = sectionBuilder.AddSection(".data", SectionCharacteristics.ContainsInitializedData | SectionCharacteristics.MemWrite | SectionCharacteristics.MemRead, 512);
foreach (var depNode in _nodes)
{
if (depNode is EETypeNode eeTypeNode)
{
_nodeFactory.TypesTable.Add(eeTypeNode);
}
}
int nodeIndex = -1;
foreach (var depNode in _nodes)
{

Просмотреть файл

@ -0,0 +1,62 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using ILCompiler.DependencyAnalysisFramework;
using Internal.Text;
using Internal.TypeSystem;
namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
class ExternalTypeNode : DependencyNodeCore<NodeFactory>, IEETypeNode
{
private readonly TypeDesc _type;
public ExternalTypeNode(NodeFactory factory, TypeDesc type)
{
_type = type;
//
// This check encodes rules specific to CoreRT. Ie, no function pointer classes allowed.
// Eventually we will hit situations where this check fails when it shouldn't and we'll need to
// split the logic. It's a good sanity check for the time being though.
//
EETypeNode.CheckCanGenerateEEType(factory, type);
}
public TypeDesc Type => _type;
public int Offset => 0;
public bool RepresentsIndirectionCell => false;
public int ClassCode => -1044459;
public override bool InterestingForDynamicDependencyAnalysis => false;
public override bool HasDynamicDependencies => false;
public override bool HasConditionalStaticDependencies => false;
public override bool StaticDependenciesAreComputed => true;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.GetMangledTypeName(_type));
}
public int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(Type, ((AvailableType)other).Type);
}
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context) => null;
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context) => null;
protected override string GetName(NodeFactory factory) => $"Externally referenced type {Type.ToString()}";
}
}

Просмотреть файл

@ -0,0 +1,62 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using ILCompiler.DependencyAnalysisFramework;
using Internal.Text;
using Internal.TypeSystem;
namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
public class AvailableType : DependencyNodeCore<NodeFactory>, IEETypeNode
{
private readonly TypeDesc _type;
public AvailableType(NodeFactory factory, TypeDesc type)
{
_type = type;
//
// This check encodes rules specific to CoreRT. Ie, no function pointer classes allowed.
// Eventually we will hit situations where this check fails when it shouldn't and we'll need to
// split the logic. It's a good sanity check for the time being though.
//
EETypeNode.CheckCanGenerateEEType(factory, type);
}
public TypeDesc Type => _type;
public int Offset => 0;
public bool RepresentsIndirectionCell => false;
public int ClassCode => 345483495;
public override bool InterestingForDynamicDependencyAnalysis => false;
public override bool HasDynamicDependencies => false;
public override bool HasConditionalStaticDependencies => false;
public override bool StaticDependenciesAreComputed => true;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.GetMangledTypeName(_type));
}
public int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(Type, ((AvailableType)other).Type);
}
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context) => null;
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context) => null;
protected override string GetName(NodeFactory factory) => $"Available type {Type.ToString()}";
}
}

Просмотреть файл

@ -32,6 +32,7 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
}
public MethodDesc Method => _methodDesc;
public MethodWithGCInfo MethodCodeNode => _localMethod;
public override int ClassCode => 458823351;

Просмотреть файл

@ -66,7 +66,7 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
}
}
List<EntryPoint> _ridToEntryPoint;
private List<EntryPoint> _ridToEntryPoint;
public MethodEntryPointTableNode(TargetDetails target)
: base(target)
@ -200,6 +200,19 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
return new ObjectData(Array.Empty<byte>(), Array.Empty<Relocation>(), 1, Array.Empty<ISymbolDefinitionNode>());
}
foreach (MethodDesc method in factory.MetadataManager.GetCompiledMethods())
{
MethodWithGCInfo methodCodeNode = factory.MethodEntrypoint(method) as MethodWithGCInfo;
if (methodCodeNode == null)
{
methodCodeNode = ((ExternalMethodImport)factory.MethodEntrypoint(method))?.MethodCodeNode;
if (methodCodeNode == null)
continue;
}
Add(methodCodeNode, ((ReadyToRunCodegenNodeFactory)factory).RuntimeFunctionsTable.GetIndex(methodCodeNode));
}
NativeWriter writer = new NativeWriter();
Section arraySection = writer.NewSection();

Просмотреть файл

@ -2,9 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics;
using ILCompiler.DependencyAnalysisFramework;
using Internal.Text;
using Internal.TypeSystem;
@ -43,10 +44,7 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
protected override void OnMarked(NodeFactory factory)
{
ReadyToRunCodegenNodeFactory r2rFactory = (ReadyToRunCodegenNodeFactory)factory;
// Marked method - add runtime & entry point table entry
r2rFactory.RuntimeFunctionsGCInfo.AddEmbeddedObject(GCInfoNode);
int index = r2rFactory.RuntimeFunctionsTable.Add(this);
r2rFactory.MethodEntryPointTable.Add(this, index);
}
public override ObjectData GetData(NodeFactory factory, bool relocsOnly)

Просмотреть файл

@ -44,5 +44,12 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
return _typeToken.CompareTo(((NewArrayFixupSignature)other)._typeToken);
}
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
{
DependencyList dependencies = new DependencyList();
dependencies.Add(factory.NecessaryTypeSymbol(_arrayType.ElementType), "Type used as array element");
return dependencies;
}
}
}

Просмотреть файл

@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using ILCompiler.DependencyAnalysisFramework;
using Internal.Text;
using Internal.TypeSystem;
@ -44,5 +45,12 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
return _typeToken.CompareTo(((NewObjectFixupSignature)other)._typeToken);
}
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
{
DependencyList dependencies = new DependencyList();
dependencies.Add(factory.ConstructedTypeSymbol(_typeDesc), "Type constructed through new object fixup");
return dependencies;
}
}
}

Просмотреть файл

@ -2,20 +2,26 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using Internal.Text;
using Internal.TypeSystem;
using Debug = System.Diagnostics.Debug;
namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
public class RuntimeFunctionsTableNode : HeaderTableNode
{
private readonly List<MethodWithGCInfo> _methodNodes;
private List<MethodWithGCInfo> _methodNodes;
private Dictionary<MethodWithGCInfo, int> _insertedMethodNodes;
private readonly NodeFactory _nodeFactory;
public RuntimeFunctionsTableNode(TargetDetails target)
: base(target)
public RuntimeFunctionsTableNode(NodeFactory nodeFactory)
: base(nodeFactory.Target)
{
_methodNodes = new List<MethodWithGCInfo>();
_nodeFactory = nodeFactory;
}
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
@ -24,14 +30,47 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
sb.Append("__ReadyToRunRuntimeFunctionsTable");
}
public int Add(MethodWithGCInfo method)
public int GetIndex(MethodWithGCInfo method)
{
_methodNodes.Add(method);
return _methodNodes.Count - 1;
#if DEBUG
Debug.Assert(_nodeFactory.MarkingComplete);
Debug.Assert(method.Marked);
#endif
if (_methodNodes == null)
LayoutRuntimeFunctions();
return _insertedMethodNodes[method];
}
private void LayoutRuntimeFunctions()
{
_methodNodes = new List<MethodWithGCInfo>();
_insertedMethodNodes = new Dictionary<MethodWithGCInfo, int>();
foreach (MethodDesc method in _nodeFactory.MetadataManager.GetCompiledMethods())
{
MethodWithGCInfo methodCodeNode = _nodeFactory.MethodEntrypoint(method) as MethodWithGCInfo;
if (methodCodeNode == null)
{
methodCodeNode = ((ExternalMethodImport)_nodeFactory.MethodEntrypoint(method))?.MethodCodeNode;
if (methodCodeNode == null)
continue;
}
_methodNodes.Add(methodCodeNode);
_insertedMethodNodes[methodCodeNode] = _methodNodes.Count - 1;
}
}
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 });
if (_methodNodes == null)
LayoutRuntimeFunctions();
ObjectDataBuilder runtimeFunctionsBuilder = new ObjectDataBuilder(factory, relocsOnly);
// Add the symbol representing this object node

Просмотреть файл

@ -50,5 +50,12 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
return _typeToken.CompareTo(((TypeFixupSignature)other)._typeToken);
}
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
{
DependencyList dependencies = new DependencyList();
dependencies.Add(factory.NecessaryTypeSymbol(_typeDesc), "Type referenced in a fixup signature");
return dependencies;
}
}
}

Просмотреть файл

@ -17,13 +17,8 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
public class TypesTableNode : HeaderTableNode
{
List<(int Rid, EETypeNode Node)> _eeTypeNodes;
public TypesTableNode(TargetDetails target)
: base(target)
{
_eeTypeNodes = new List<(int Rid, EETypeNode Node)>();
}
: base(target) {}
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
@ -31,34 +26,33 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
sb.Append("__ReadyToRunAvailableTypesTable");
}
public int Add(EETypeNode eeTypeNode)
{
if (eeTypeNode.Type is EcmaType ecmaType)
{
int rid = MetadataTokens.GetToken(ecmaType.Handle) & 0x00FFFFFF;
Debug.Assert(rid != 0);
int eeTypeIndex = _eeTypeNodes.Count;
_eeTypeNodes.Add((Rid: rid, Node: eeTypeNode));
return eeTypeIndex;
}
else
{
throw new NotImplementedException();
}
}
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 });
NativeWriter writer = new NativeWriter();
Section section = writer.NewSection();
VertexHashtable typesHashtable = new VertexHashtable();
section.Place(typesHashtable);
foreach ((int Rid, EETypeNode Node) eeTypeNode in _eeTypeNodes)
foreach (TypeDesc type in ((ReadyToRunTableManager)factory.MetadataManager).GetTypesWithAvailableTypes())
{
int hashCode = eeTypeNode.Node.Type.GetHashCode();
typesHashtable.Append(unchecked((uint)hashCode), section.Place(new UnsignedConstant((uint)eeTypeNode.Rid << 1)));
int rid = 0;
if (type is EcmaType ecmaType)
{
rid = MetadataTokens.GetToken(ecmaType.Handle) & 0x00FFFFFF;
Debug.Assert(rid != 0);
}
else
{
throw new NotImplementedException();
}
int hashCode = type.GetHashCode();
typesHashtable.Append(unchecked((uint)hashCode), section.Place(new UnsignedConstant((uint)rid << 1)));
}
MemoryStream writerContent = new MemoryStream();

Просмотреть файл

@ -74,17 +74,12 @@ namespace ILCompiler.DependencyAnalysis
public ImportSectionNode PrecodeImports;
Dictionary<MethodDesc, IMethodNode> _methodMap = new Dictionary<MethodDesc, IMethodNode>();
public IMethodNode MethodEntrypoint(MethodDesc method, ModuleToken token, bool isUnboxingStub = false)
{
IMethodNode methodNode;
if (!_methodMap.TryGetValue(method, out methodNode))
return _methodEntrypoints.GetOrAdd(method, (m) =>
{
methodNode = CreateMethodEntrypointNode(method, token, isUnboxingStub);
_methodMap.Add(method, methodNode);
}
return methodNode;
return CreateMethodEntrypointNode(method, token, isUnboxingStub);
});
}
private IMethodNode CreateMethodEntrypointNode(MethodDesc method, ModuleToken token, bool isUnboxingStub = false)
@ -589,7 +584,7 @@ namespace ILCompiler.DependencyAnalysis
var compilerIdentifierNode = new CompilerIdentifierNode(Target);
Header.Add(Internal.Runtime.ReadyToRunSectionType.CompilerIdentifier, compilerIdentifierNode, compilerIdentifierNode);
RuntimeFunctionsTable = new RuntimeFunctionsTableNode(Target);
RuntimeFunctionsTable = new RuntimeFunctionsTableNode(this);
Header.Add(Internal.Runtime.ReadyToRunSectionType.RuntimeFunctions, RuntimeFunctionsTable, RuntimeFunctionsTable);
RuntimeFunctionsGCInfo = new RuntimeFunctionsGCInfoNode();
@ -660,6 +655,8 @@ namespace ILCompiler.DependencyAnalysis
graph.AddRoot(PrecodeImports, "Precode imports are always generated");
graph.AddRoot(StringImports, "String imports are always generated");
graph.AddRoot(Header, "ReadyToRunHeader is always generated");
MetadataManager.AttachToDependencyGraph(graph);
}
public IMethodNode ImportedMethodNode(MethodDesc method, bool unboxingStub, ModuleToken token, MethodWithGCInfo localMethod)
@ -717,6 +714,33 @@ namespace ILCompiler.DependencyAnalysis
return MethodEntrypoint(method, token, isUnboxingStub);
}
protected override IEETypeNode CreateNecessaryTypeNode(TypeDesc type)
{
if (CompilationModuleGroup.ContainsType(type))
{
return new AvailableType(this, type);
}
else
{
return new ExternalTypeNode(this, type);
}
}
protected override IEETypeNode CreateConstructedTypeNode(TypeDesc type)
{
// Canonical definition types are *not* constructed types (call NecessaryTypeSymbol to get them)
Debug.Assert(!type.IsCanonicalDefinitionType(CanonicalFormKind.Any));
if (CompilationModuleGroup.ContainsType(type))
{
return new AvailableType(this, type);
}
else
{
return new ExternalTypeNode(this, type);
}
}
protected override IMethodNode CreateMethodEntrypointNode(MethodDesc method)
{
if (!CompilationModuleGroup.ContainsMethodBody(method, unboxingStub: false))

Просмотреть файл

@ -0,0 +1,57 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using ILCompiler.DependencyAnalysis;
using ILCompiler.DependencyAnalysis.ReadyToRun;
using ILCompiler.DependencyAnalysisFramework;
using Internal.TypeSystem;
using Debug = System.Diagnostics.Debug;
namespace ILCompiler
{
public class ReadyToRunTableManager : MetadataManager
{
private readonly HashSet<TypeDesc> _typesWithAvailableTypesGenerated = new HashSet<TypeDesc>();
public ReadyToRunTableManager(CompilerTypeSystemContext typeSystemContext)
: base(typeSystemContext, new NoMetadataBlockingPolicy(), new NoManifestResourceBlockingPolicy()) {}
public override void AddToReadyToRunHeader(ReadyToRunHeaderNode header, NodeFactory nodeFactory, ExternalReferencesTableNode commonFixupsTableNode)
{
// We don't attach any metadata blobs.
}
protected override void Graph_NewMarkedNode(DependencyNodeCore<NodeFactory> obj)
{
base.Graph_NewMarkedNode(obj);
var eetypeNode = obj as AvailableType;
if (eetypeNode != null)
{
_typesWithAvailableTypesGenerated.Add(eetypeNode.Type);
return;
}
}
public IEnumerable<TypeDesc> GetTypesWithAvailableTypes()
{
return _typesWithAvailableTypesGenerated;
}
public override MethodDesc GetCanonicalReflectionInvokeStub(MethodDesc method) => throw new NotImplementedException();
public override IEnumerable<ModuleDesc> GetCompilationModulesWithMetadata() => throw new NotImplementedException();
public override bool HasReflectionInvokeStubForInvokableMethod(MethodDesc method) => throw new NotImplementedException();
public override bool WillUseMetadataTokenToReferenceField(FieldDesc field) => throw new NotImplementedException();
public override bool WillUseMetadataTokenToReferenceMethod(MethodDesc method) => throw new NotImplementedException();
protected override void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, out List<MetadataMapping<MetadataType>> typeMappings, out List<MetadataMapping<MethodDesc>> methodMappings, out List<MetadataMapping<FieldDesc>> fieldMappings, out List<MetadataMapping<MethodDesc>> stackTraceMapping) => throw new NotImplementedException();
protected override MetadataCategory GetMetadataCategory(MethodDesc method) => throw new NotImplementedException();
protected override MetadataCategory GetMetadataCategory(TypeDesc type) => throw new NotImplementedException();
protected override MetadataCategory GetMetadataCategory(FieldDesc field) => throw new NotImplementedException();
}
}

Просмотреть файл

@ -28,7 +28,9 @@
<ItemGroup>
<Compile Include="CodeGen\ReadyToRunObjectWriter.cs" />
<Compile Include="Compiler\DependencyAnalysis\ExternalTypeNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRunCodegenNodeFactory.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\AvailableType.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\ByteArrayComparer.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\CompilerIdentifierNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\DelayLoadHelperImport.cs" />
@ -72,6 +74,7 @@
<Compile Include="Compiler\ReadyToRunMetadataFieldLayoutAlgorithm.cs" />
<Compile Include="Compiler\ReadyToRunNodeMangler.cs" />
<Compile Include="Compiler\ReadyToRunSingleAssemblyCompilationModuleGroup.cs" />
<Compile Include="Compiler\ReadyToRunTableManager.cs" />
<Compile Include="JitInterface\CorInfoImpl.ReadyToRun.cs" />
<Compile Include="ObjectWriter\SectionBuilder.cs" />
<Compile Include="ObjectWriter\R2RPEBuilder.cs" />

Просмотреть файл

@ -491,7 +491,16 @@ namespace ILCompiler
bool supportsReflection = !_isReadyToRunCodeGen && !_isWasmCodegen && !_isCppCodegen && _systemModuleName == DefaultSystemModule;
MetadataManager compilationMetadataManager = supportsReflection ? metadataManager : (MetadataManager)new EmptyMetadataManager(typeSystemContext);
MetadataManager compilationMetadataManager;
if (_isReadyToRunCodeGen)
{
compilationMetadataManager = new ReadyToRunTableManager(typeSystemContext);
}
else
{
compilationMetadataManager = supportsReflection ? metadataManager : (MetadataManager)new EmptyMetadataManager(typeSystemContext);
}
ILScanResults scanResults = null;
if (useScanner)
{

Просмотреть файл

@ -261,6 +261,25 @@ internal class Program
return true;
}
private static bool CreateLocalClassInstance()
{
var testClass = new TestClass(1234);
Console.WriteLine("Successfully constructed TestClass");
return testClass.A == 1234;
}
private class TestClass
{
private int _a;
public TestClass(int a)
{
_a = a;
}
public int A => _a;
}
public static int Main(string[] args)
{
if (args.Length > 0)
@ -290,6 +309,8 @@ internal class Program
RunTest("ManipulateListOfString", ManipulateListOfString());
RunTest("EmptyArray", EmptyArray());
RunTest("CreateLocalClassInstance", CreateLocalClassInstance());
// TODO: RunTest("EnumerateEmptyArray", EnumerateEmptyArray());
Console.WriteLine($@"{_passedTests.Count} tests pass:");