Skip to content

Commit 1651e0f

Browse files
committed
Early work to make it possible to call the interpreter from ReadyToRun code
1 parent dc643f2 commit 1651e0f

File tree

19 files changed

+370
-5
lines changed

19 files changed

+370
-5
lines changed

src/coreclr/inc/readytorun.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ enum class ReadyToRunSectionType : uint32_t
102102
MethodIsGenericMap = 121, // Added in V9.0
103103
EnclosingTypeMap = 122, // Added in V9.0
104104
TypeGenericInfoMap = 123, // Added in V9.0
105+
InterpreterMap = 124, // Prototype
105106

106107
// If you add a new section consider whether it is a breaking or non-breaking change.
107108
// Usually it is non-breaking, but if it is preferable to have older runtimes fail
@@ -447,6 +448,8 @@ enum ReadyToRunHelper
447448
READYTORUN_HELPER_StackProbe = 0x111,
448449

449450
READYTORUN_HELPER_GetCurrentManagedThreadId = 0x112,
451+
452+
READYTORUN_HELPER_InterpreterRoutine = 0x113,
450453
};
451454

452455
#include "readytoruninstructionset.h"

src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ enum ReadyToRunSectionType
7979
MethodIsGenericMap = 121, // Added in V9.0
8080
EnclosingTypeMap = 122, // Added in V9.0
8181
TypeGenericInfoMap = 123, // Added in V9.0
82+
InterpreterMap = 124, // Added for prototyping only
8283

8384
//
8485
// NativeAOT ReadyToRun sections

src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,9 @@ public enum ReadyToRunHelper
348348

349349
GetCurrentManagedThreadId = 0x112,
350350

351+
//Interpreter
352+
InterpreterRoutine = 0x113,
353+
351354
// **********************************************************************************************
352355
//
353356
// These are not actually part of the R2R file format. We have them here because it's convenient.

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DelayLoadMethodImport.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
4646
{
4747
yield return entry;
4848
}
49+
50+
// It is possible that an instance of DelayLoadMethodImport is constructed by never get into the graph
51+
// So we must delay the construction and rooting of the InterpreterImport
52+
53+
InterpreterImport _interpreterImport = new InterpreterImport();
54+
InterpreterStub _interpreterStub = new InterpreterStub(_interpreterImport);
55+
factory.AddInterpreterMapping(this, _interpreterImport, _interpreterStub);
56+
yield return new DependencyListEntry(_interpreterImport, "Unused reason 1");
57+
yield return new DependencyListEntry(_interpreterStub, "Unused reason 2");
58+
yield return new DependencyListEntry(factory.InterpreterMap, "Unused reason 3");
4959
if (_localMethod != null)
5060
yield return new DependencyListEntry(_localMethod, "Local method import");
5161
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Internal.JitInterface;
5+
using Internal.Text;
6+
using Internal.TypeSystem;
7+
using Internal.ReadyToRunConstants;
8+
using ILCompiler.DependencyAnalysisFramework;
9+
using System.Collections.Generic;
10+
11+
namespace ILCompiler.DependencyAnalysis.ReadyToRun
12+
{
13+
// An InterpreterImport simply a pointer sized variable that the
14+
// interpreter stub can use to reference the InterpreterMethodInfo
15+
public class InterpreterImport : ObjectNode, ISymbolDefinitionNode
16+
{
17+
public int _id;
18+
public static int id = 1;
19+
20+
public InterpreterImport()
21+
{
22+
// TODO, andrewau, we need a mechanism to identify the call sites
23+
// using a ID is not going to be deterministic
24+
_id = id++;
25+
}
26+
27+
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
28+
{
29+
return this._id - ((InterpreterImport)(other))._id;
30+
}
31+
32+
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
33+
{
34+
ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);
35+
builder.AddSymbol(this);
36+
builder.EmitZeroPointer();
37+
return builder.ToObjectData();
38+
}
39+
40+
public int Offset { get; set; }
41+
42+
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
43+
=> sb.Append(nameMangler.CompilationUnitPrefix).Append("InterpreterImport").Append(_id.ToString());
44+
45+
public override ObjectNodeSection GetSection(NodeFactory factory)
46+
{
47+
return ObjectNodeSection.DataSection;
48+
}
49+
50+
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context)
51+
{
52+
yield break;
53+
}
54+
55+
protected override string GetName(NodeFactory context) => "InterpreterImport";
56+
57+
public override int ClassCode => 46709394;
58+
59+
public override bool IsShareable => false;
60+
61+
public override bool StaticDependenciesAreComputed => true;
62+
}
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
6+
using Internal.Text;
7+
using System.Collections.Generic;
8+
using System.Diagnostics;
9+
10+
namespace ILCompiler.DependencyAnalysis.ReadyToRun
11+
{
12+
public class InterpreterMapNode : HeaderTableNode
13+
{
14+
public override int ClassCode => 25687179;
15+
16+
private List<DelayLoadMethodImport> leftItems = new List<DelayLoadMethodImport>();
17+
private List<InterpreterStub> lastItems = new List<InterpreterStub>();
18+
private List<InterpreterImport> rightItems = new List<InterpreterImport>();
19+
20+
public void AddMapping(DelayLoadMethodImport left, InterpreterImport right, InterpreterStub last)
21+
{
22+
// TODO, andrewau, this require proper locking and sorting for multithreaded compilation.
23+
// correctness and determinism
24+
leftItems.Add(left);
25+
rightItems.Add(right);
26+
lastItems.Add(last);
27+
}
28+
29+
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
30+
{
31+
sb.Append(nameMangler.CompilationUnitPrefix);
32+
sb.Append("__InterpreterMap"u8);
33+
}
34+
35+
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
36+
{
37+
ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);
38+
builder.AddSymbol(this);
39+
for (int i = 0; i < leftItems.Count; i++)
40+
{
41+
// This will emit the RVAs for these
42+
builder.EmitReloc(leftItems[i], RelocType.IMAGE_REL_FILE_ABSOLUTE);
43+
builder.EmitReloc(rightItems[i], RelocType.IMAGE_REL_FILE_ABSOLUTE);
44+
builder.EmitReloc(lastItems[i], RelocType.IMAGE_REL_FILE_ABSOLUTE);
45+
}
46+
return builder.ToObjectData();
47+
}
48+
}
49+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Internal.JitInterface;
5+
using Internal.Text;
6+
using Internal.TypeSystem;
7+
using Internal.ReadyToRunConstants;
8+
using ILCompiler.DependencyAnalysisFramework;
9+
using System.Collections.Generic;
10+
11+
// TODO, andrewau, other architectures
12+
using ILCompiler.DependencyAnalysis.X64;
13+
14+
namespace ILCompiler.DependencyAnalysis.ReadyToRun
15+
{
16+
// An InterpreterStub is a small trampoline that
17+
// 1.) Push the InterpreterMethodInfo to the stack, and
18+
// 2.) Jump to the InterpreterMethod
19+
public class InterpreterStub : ObjectNode, ISymbolDefinitionNode
20+
{
21+
public InterpreterImport _interpreterImport;
22+
23+
public InterpreterStub(InterpreterImport interpreterImport)
24+
{
25+
_interpreterImport = interpreterImport;
26+
}
27+
28+
public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
29+
{
30+
return _interpreterImport._id - ((InterpreterStub)(other))._interpreterImport._id;
31+
}
32+
33+
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
34+
{
35+
X64Emitter x64Emitter = new X64Emitter(factory, relocsOnly);
36+
x64Emitter.Builder.AddSymbol(this);
37+
x64Emitter.EmitMOV(Register.RCX, _interpreterImport);
38+
// TODO, andrewau, shouldn't have to do this if we can make node represent redirection cell
39+
AddrMode addr = new AddrMode(Register.RCX, null, 0, 0, AddrModeSize.Int64);
40+
x64Emitter.EmitMOV(Register.RCX, ref addr);
41+
x64Emitter.EmitJMP(factory.InterpreterRoutineImport);
42+
return x64Emitter.Builder.ToObjectData();
43+
}
44+
45+
public int Offset { get; set; }
46+
47+
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
48+
=> sb.Append(nameMangler.CompilationUnitPrefix).Append("InterpreterStub").Append(_interpreterImport._id.ToString());
49+
50+
public override ObjectNodeSection GetSection(NodeFactory factory)
51+
{
52+
return ObjectNodeSection.TextSection;
53+
}
54+
55+
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context)
56+
{
57+
yield break;
58+
}
59+
60+
protected override string GetName(NodeFactory context) => "InterpreterStub";
61+
62+
public override int ClassCode => 95566084;
63+
64+
public override bool IsShareable => false;
65+
66+
public override bool StaticDependenciesAreComputed => true;
67+
}
68+
}

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,16 @@ public void GenerateHotColdMap(DependencyAnalyzerBase<NodeFactory> dependencyGra
9797
dependencyGraph.AddRoot(HotColdMap, "HotColdMap is generated because there is cold code");
9898
}
9999
}
100+
101+
public void AddInterpreterMapping(DelayLoadMethodImport left, InterpreterImport right, InterpreterStub last)
102+
{
103+
if (InterpreterMap == null)
104+
{
105+
InterpreterMap = new InterpreterMapNode();
106+
Header.Add(Internal.Runtime.ReadyToRunSectionType.InterpreterMap, InterpreterMap, InterpreterMap);
107+
}
108+
InterpreterMap.AddMapping(left, right, last);
109+
}
100110

101111
public void SetMarkingComplete()
102112
{
@@ -372,6 +382,8 @@ private void CreateNodeCaches()
372382

373383
public HotColdMapNode HotColdMap;
374384

385+
public InterpreterMapNode InterpreterMap;
386+
375387
public RuntimeFunctionsGCInfoNode RuntimeFunctionsGCInfo;
376388

377389
public DelayLoadMethodCallThunkNodeRange DelayLoadMethodCallThunks;
@@ -387,6 +399,8 @@ private void CreateNodeCaches()
387399

388400
public Import ModuleImport;
389401

402+
public Import InterpreterRoutineImport;
403+
390404
public ISymbolNode PersonalityRoutine;
391405

392406
public ISymbolNode FilterFuncletPersonalityRoutine;
@@ -803,6 +817,10 @@ public void AttachToDependencyGraph(DependencyAnalyzerBase<NodeFactory> graph, I
803817
ReadyToRunHelper.Module));
804818
graph.AddRoot(ModuleImport, "Module import is required by the R2R format spec");
805819

820+
InterpreterRoutineImport = new Import(EagerImports, new ReadyToRunHelperSignature(
821+
ReadyToRunHelper.InterpreterRoutine));
822+
graph.AddRoot(InterpreterRoutineImport, "This allow ready to run code to bail to interpreter");
823+
806824
if (Target.Architecture != TargetArchitecture.X86)
807825
{
808826
Import personalityRoutineImport = new Import(EagerImports, new ReadyToRunHelperSignature(

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,8 @@ internal ReadyToRunCodegenCompilation(
348348
{
349349
_computedFixedLayoutTypesUncached = IsLayoutFixedInCurrentVersionBubbleInternal;
350350
_resilient = resilient;
351-
_parallelism = parallelism;
351+
// TODO, andrewau, until we fix the problem in InterpreterMapNode, this is required
352+
_parallelism = 1;
352353
_corInfoImpls = new CorInfoImpl[_parallelism];
353354
_generateMapFile = generateMapFile;
354355
_generateMapCsvFile = generateMapCsvFile;

src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@
193193
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\GCRefMapNode.cs" />
194194
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\GenericLookupSignature.cs" />
195195
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\ImportThunk.cs" />
196+
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\InterpreterImport.cs" />
197+
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\InterpreterMapNode.cs" />
198+
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\InterpreterStub.cs" />
196199
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\DelegateCtorSignature.cs" />
197200
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\DevirtualizationManager.cs" />
198201
<Compile Include="Compiler\DependencyAnalysis\ReadyToRun\FieldFixupSignature.cs" />

0 commit comments

Comments
 (0)