_methodCodeNode.InitializeDebugLocInfos(_debugLocInfos);
_methodCodeNode.InitializeDebugVarInfos(_debugVarInfos);
#if READYTORUN
- _methodCodeNode.InitializeInliningInfo(_inlinedMethods.ToArray());
+ _methodCodeNode.InitializeInliningInfo(_inlinedMethods.ToArray(), _compilation.NodeFactory);
// Detect cases where the instruction set support used is a superset of the baseline instruction set specification
var baselineSupport = _compilation.InstructionSetSupport;
namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
- public class InstanceEntryPointTableNode : HeaderTableNode
+ public class InstanceEntryPointTableNode : HeaderTableNode, ISignatureEmitter
{
private readonly NodeFactory _factory;
+ private bool _materializedSignature;
public InstanceEntryPointTableNode(NodeFactory factory)
: base(factory.Target)
{
_factory = factory;
+ _factory.ManifestMetadataTable.RegisterEmitter(this);
}
-
+
+ public void MaterializeSignature()
+ {
+ if (!_materializedSignature)
+ {
+ if (_factory.CompilationModuleGroup.IsInputBubble)
+ {
+ foreach (MethodWithGCInfo method in _factory.EnumerateCompiledMethods(null, CompiledMethodCategory.Instantiated))
+ {
+ BuildSignatureForMethod(method, _factory);
+ }
+ }
+
+ _materializedSignature = true;
+ }
+ }
+
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix);
sb.Append("__ReadyToRunInstanceEntryPointTable");
}
+ private ArraySignatureBuilder BuildSignatureForMethod(MethodWithGCInfo method, NodeFactory factory)
+ {
+ // In composite R2R format, always enforce owning type to let us share generic instantiations among modules
+
+ EcmaMethod typicalMethod = (EcmaMethod)method.Method.GetTypicalMethodDefinition();
+ ModuleToken moduleToken = new ModuleToken(typicalMethod.Module, typicalMethod.Handle);
+
+ ArraySignatureBuilder signatureBuilder = new ArraySignatureBuilder();
+ signatureBuilder.EmitMethodSignature(
+ new MethodWithToken(method.Method, moduleToken, constrainedType: null, unboxing: false, context: null),
+ enforceDefEncoding: true,
+ enforceOwningType: _factory.CompilationModuleGroup.EnforceOwningType(moduleToken.Module),
+ factory.SignatureContext,
+ isInstantiatingStub: false);
+
+ return signatureBuilder;
+ }
+
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
if (relocsOnly)
int methodIndex = factory.RuntimeFunctionsTable.GetIndex(method);
- // In composite R2R format, always enforce owning type to let us share generic instantiations among modules
- EcmaMethod typicalMethod = (EcmaMethod)method.Method.GetTypicalMethodDefinition();
- ModuleToken moduleToken = new ModuleToken(typicalMethod.Module, typicalMethod.Handle);
-
- ArraySignatureBuilder signatureBuilder = new ArraySignatureBuilder();
- signatureBuilder.EmitMethodSignature(
- new MethodWithToken(method.Method, moduleToken, constrainedType: null, unboxing: false, context: null),
- enforceDefEncoding: true,
- enforceOwningType: _factory.CompilationModuleGroup.EnforceOwningType(moduleToken.Module),
- factory.SignatureContext,
- isInstantiatingStub: false);
+ ArraySignatureBuilder signatureBuilder = BuildSignatureForMethod(method, factory);
byte[] signature = signatureBuilder.ToArray();
BlobVertex signatureBlob;
if (!uniqueSignatures.TryGetValue(signature, out signatureBlob))
using System;
using System.Collections.Generic;
+using System.Collections.Concurrent;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
private int _nextModuleId;
/// <summary>
+ /// Modules which need to exist in set of modules visible
+ /// </summary>
+ private ConcurrentBag<EcmaModule> _modulesWhichMustBeIndexable = new ConcurrentBag<EcmaModule>();
+
+ /// <summary>
/// Set to true after GetData has been called. After that, ModuleToIndex may be called no more.
/// </summary>
private bool _emissionCompleted;
return ModuleToIndexInternal(module);
}
+ public void EnsureModuleIndexable(ModuleDesc module)
+ {
+ if (_emissionCompleted)
+ {
+ throw new InvalidOperationException("Adding a new assembly after signatures have been materialized.");
+ }
+
+ if (module is EcmaModule ecmaModule && _nodeFactory.CompilationModuleGroup.VersionsWithModule(ecmaModule))
+ {
+ _modulesWhichMustBeIndexable.Add(ecmaModule);
+ }
+ }
+
private int ModuleToIndexInternal(EcmaModule module)
{
AssemblyName assemblyName = module.Assembly.GetName();
sb.Append("ManifestMetadataTableNode");
}
- public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
+ private void ComputeLastSetOfModuleIndices()
{
- if (relocsOnly)
- {
- return new ObjectData(Array.Empty<byte>(), null, 1, null);
- }
-
if (!_emissionCompleted)
{
foreach (ISignatureEmitter emitter in _signatureEmitters)
emitter.MaterializeSignature();
}
+ EcmaModule [] moduleArray = _modulesWhichMustBeIndexable.ToArray();
+ Array.Sort(moduleArray, (EcmaModule moduleA, EcmaModule moduleB) => moduleA.CompareTo(moduleB));
+ foreach (var module in moduleArray)
+ {
+ ModuleToIndex(module);
+ }
+
_emissionCompleted = true;
}
+ }
+
+ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
+ {
+ if (relocsOnly)
+ {
+ return new ObjectData(Array.Empty<byte>(), null, 1, null);
+ }
+
+ ComputeLastSetOfModuleIndices();
MetadataBuilder metadataBuilder = new MetadataBuilder();
internal byte[] GetManifestAssemblyMvidTableData()
{
+ ComputeLastSetOfModuleIndices();
+
byte[] manifestAssemblyMvidTable = new byte[ManifestAssemblyMvidTableSize];
for (int i = 0; i < _manifestAssemblyMvids.Count; i++)
{
using Internal.JitInterface;
using Internal.Text;
using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
InitializeFrameInfos(Array.Empty<FrameInfo>());
}
_lateTriggeredCompilation = context.CompilationCurrentPhase != 0;
+ RegisterInlineeModuleIndices(context);
+ }
+
+ private void RegisterInlineeModuleIndices(NodeFactory factory)
+ {
+ if (_inlinedMethods != null)
+ {
+ foreach (var inlinee in _inlinedMethods)
+ {
+ MethodDesc inlineeDefinition = inlinee.GetTypicalMethodDefinition();
+ if (!(inlineeDefinition is EcmaMethod ecmaInlineeDefinition))
+ {
+ // We don't record non-ECMA methods because they don't have tokens that
+ // diagnostic tools could reason about anyway.
+ continue;
+ }
+
+ if (!factory.CompilationModuleGroup.VersionsWithMethodBody(inlinee))
+ {
+ // We cannot record inlining info across version bubble as cross-bubble assemblies
+ // are not guaranteed to preserve token values. Only non-versionable methods may be
+ // inlined across the version bubble.
+ Debug.Assert(inlinee.IsNonVersionable());
+ continue;
+ }
+ factory.ManifestMetadataTable.EnsureModuleIndexable(ecmaInlineeDefinition.Module);
+ }
+ }
}
public override int DependencyPhaseForDeferredStaticComputation => _lateTriggeredCompilation ? 2 : 0;
return comparer.Compare(_method, otherNode._method);
}
- public void InitializeInliningInfo(MethodDesc[] inlinedMethods)
+ public void InitializeInliningInfo(MethodDesc[] inlinedMethods, NodeFactory factory)
{
Debug.Assert(_inlinedMethods == null);
_inlinedMethods = inlinedMethods;
+ if (this.Marked)
+ RegisterInlineeModuleIndices(factory);
}
public int Offset => 0;