Skip to content

Commit

Permalink
Initial hot cold splitting support for crossgen2/VM
Browse files Browse the repository at this point in the history
  • Loading branch information
cshung committed Jun 18, 2022
1 parent 8b3be89 commit 5280674
Show file tree
Hide file tree
Showing 22 changed files with 418 additions and 20 deletions.
1 change: 1 addition & 0 deletions src/coreclr/inc/readytorun.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ enum class ReadyToRunSectionType : uint32_t
OwnerCompositeExecutable = 116, // Added in V4.1
PgoInstrumentationData = 117, // Added in V5.2
ManifestAssemblyMvids = 118, // Added in V5.3
Scratch = 119, // This is meant to be a scratch area just for prototyping

// If you add a new section consider whether it is a breaking or non-breaking change.
// Usually it is non-breaking, but if it is preferable to have older runtimes fail
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public enum ReadyToRunSectionType
OwnerCompositeExecutable = 116, // Added in 4.1
PgoInstrumentationData = 117, // Added in 5.2
ManifestAssemblyMvids = 118, // Added in 5.3
Scratch = 119, // This is meant to be a scratch area for prototyping only

//
// NativeAOT ReadyToRun sections
Expand Down
56 changes: 49 additions & 7 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#if READYTORUN
using System.Reflection.Metadata.Ecma335;
using ILCompiler.DependencyAnalysis.ReadyToRun;
using Internal.Text;
#endif

namespace Internal.JitInterface
Expand Down Expand Up @@ -422,6 +423,20 @@ private void PublishCode()
, isFoldable: (_compilation._compilationOptions & RyuJitCompilationOptions.MethodBodyFolding) != 0
#endif
);
#if READYTORUN
if (_methodColdCodeNode != null)
{
// TODO, Study how this work.
var relocs2 = _coldCodeRelocs.ToArray();
Array.Sort(relocs2, (x, y) => (x.Offset - y.Offset));
var coldObjectData = new ObjectNode.ObjectData(_coldCode,
relocs2,
alignment,
new ISymbolDefinitionNode[] { _methodColdCodeNode });
_methodColdCodeNode.SetCode(coldObjectData);
_methodCodeNode.SetColdCodeNode(_methodColdCodeNode);
}
#endif

_methodCodeNode.InitializeFrameInfos(_frameInfos);
_methodCodeNode.InitializeDebugEHClauseInfos(debugEHClauseInfos);
Expand Down Expand Up @@ -563,7 +578,9 @@ private void CompileMethodCleanup()
}

_methodCodeNode = null;

#if READYTORUN
_methodColdCodeNode = null;
#endif
_code = null;
_coldCode = null;

Expand All @@ -572,7 +589,9 @@ private void CompileMethodCleanup()

_codeRelocs = new ArrayBuilder<Relocation>();
_roDataRelocs = new ArrayBuilder<Relocation>();

#if READYTORUN
_coldCodeRelocs = new ArrayBuilder<Relocation>();
#endif
_numFrameInfos = 0;
_usedFrameInfos = 0;
_frameInfos = null;
Expand Down Expand Up @@ -3396,6 +3415,10 @@ private void allocMem(ref AllocMemArgs args)

if (args.coldCodeSize != 0)
{

#if READYTORUN
this._methodColdCodeNode = new MethodColdCodeNode(MethodBeingCompiled);
#endif
args.coldCodeBlock = (void*)GetPin(_coldCode = new byte[args.coldCodeSize]);
args.coldCodeBlockRW = args.coldCodeBlock;
}
Expand Down Expand Up @@ -3443,7 +3466,10 @@ private void allocMem(ref AllocMemArgs args)

private void reserveUnwindInfo(bool isFunclet, bool isColdCode, uint unwindSize)
{
_numFrameInfos++;
if (!isColdCode)
{
_numFrameInfos++;
}
}

private void allocUnwindInfo(byte* pHotCode, byte* pColdCode, uint startOffset, uint endOffset, uint unwindSize, byte* pUnwindBlock, CorJitFuncKind funcKind)
Expand Down Expand Up @@ -3474,8 +3500,12 @@ private void allocUnwindInfo(byte* pHotCode, byte* pColdCode, uint startOffset,
blobData = CompressARM64CFI(blobData);
}
#endif

_frameInfos[_usedFrameInfos++] = new FrameInfo(flags, (int)startOffset, (int)endOffset, blobData);
#if READYTORUN
if (blobData.Length > 0)
#endif
{
_frameInfos[_usedFrameInfos++] = new FrameInfo(flags, (int)startOffset, (int)endOffset, blobData);
}
}

private void* allocGCInfo(UIntPtr size)
Expand Down Expand Up @@ -3510,7 +3540,9 @@ private void recordCallSite(uint instrOffset, CORINFO_SIG_INFO* callSig, CORINFO

private ArrayBuilder<Relocation> _codeRelocs;
private ArrayBuilder<Relocation> _roDataRelocs;

#if READYTORUN
private ArrayBuilder<Relocation> _coldCodeRelocs;
#endif

/// <summary>
/// Various type of block.
Expand Down Expand Up @@ -3588,6 +3620,11 @@ private ref ArrayBuilder<Relocation> findRelocBlock(BlockType blockType, out int
case BlockType.ROData:
length = _roData.Length;
return ref _roDataRelocs;
#if READYTORUN
case BlockType.ColdCode:
length = _coldCode.Length;
return ref _coldCodeRelocs;
#endif
default:
throw new NotImplementedException("Arbitrary relocs");
}
Expand Down Expand Up @@ -3640,8 +3677,13 @@ private void recordRelocation(void* location, void* locationRW, void* target, us
break;

case BlockType.ColdCode:
// TODO: Arbitrary relocs
#if READYTORUN
Debug.Assert(_methodColdCodeNode != null);
relocTarget = _methodColdCodeNode;
break;
#else
throw new NotImplementedException("ColdCode relocs");
#endif

case BlockType.ROData:
relocTarget = _roDataBlob;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ public void BuildCFIMap(NodeFactory factory, ObjectNode node)

int start = frameInfo.StartOffset;
int end = frameInfo.EndOffset;

int len = frameInfo.BlobData.Length;
byte[] blob = frameInfo.BlobData;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// 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 System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.InteropServices;

using Internal.IL;
using Internal.IL.Stubs;
using Internal.Text;
using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
using Internal.TypeSystem.Interop;
using Internal.CorConstants;
using Internal.Pgo;
using Internal.ReadyToRunConstants;

using ILCompiler;
using ILCompiler.DependencyAnalysis;
using ILCompiler.DependencyAnalysis.ReadyToRun;
using System.Text;

namespace ILCompiler.DependencyAnalysis.ReadyToRun
{
public class MethodColdCodeNode : ObjectNode, ISymbolDefinitionNode
{
private ObjectData _methodColdCode;
private MethodDesc _owningMethod;

public MethodColdCodeNode(MethodDesc owningMethod)
{
_owningMethod = owningMethod;
}

public int Offset => 0;

public override ObjectNodeSection Section
{
get
{
// TODO, Unix
return ObjectNodeSection.ManagedCodeWindowsContentSection;
}
}

public override bool IsShareable => false;

// This ClassCode must be larger than that of MethodCodeNode to ensure it got sorted at the end of the code
public override int ClassCode => 788492408;

public override bool StaticDependenciesAreComputed => _methodColdCode != null;

public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append("__coldcode_" + nameMangler.GetMangledMethodName(_owningMethod));
}

public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
MethodColdCodeNode otherNode = (MethodColdCodeNode)other;
return comparer.Compare(_owningMethod, otherNode._owningMethod);
}

public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) => _methodColdCode;

protected override string GetName(NodeFactory context) => throw new NotImplementedException();

public void SetCode(ObjectData data)
{
Debug.Assert(_methodColdCode == null);
_methodColdCode = data;
}

public int GetColdCodeSize()
{
return _methodColdCode.Data.Length;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ protected override void OnMarked(NodeFactory factory)

public int[] CalculateFuncletOffsets(NodeFactory factory)
{
int[] offsets = new int[_methodNode.FrameInfos.Length];
int coldCodeUnwindInfoCount = 0;
if (_methodNode.GetColdCodeNode() != null)
{
coldCodeUnwindInfoCount = 1;
}
int[] offsets = new int[_methodNode.FrameInfos.Length + coldCodeUnwindInfoCount];
if (!factory.RuntimeFunctionsGCInfo.Deduplicator.TryGetValue(this, out var deduplicatedResult))
{
throw new Exception("Did not properly initialize deduplicator");
Expand All @@ -60,6 +65,10 @@ public int[] CalculateFuncletOffsets(NodeFactory factory)
offset += (-offset & 3); // 4-alignment after GC info in 1st funclet
}
}
if (coldCodeUnwindInfoCount == 1)
{
offsets[_methodNode.FrameInfos.Length] = offset;
}
return offsets;
}

Expand Down Expand Up @@ -164,6 +173,22 @@ private IEnumerable<GCInfoComponent> EncodeDataCore(NodeFactory factory)
yield return new GCInfoComponent(_methodNode.GCInfo);
}
}
#if READYTORUN
if (_methodNode.GetColdCodeNode() != null)
{
byte[] header = new byte[4];
int i = 0;
header[i++] = 1 + (4 << 3); // Version = 1, UNW_FLAG_CHAININFO
header[i++] = 0; // SizeOfProlog = 0
header[i++] = 0; // CountOfCode = 0
header[i++] = 0; // Frame = 0
yield return new GCInfoComponent(header);
yield return new GCInfoComponent(_methodNode, 0);
yield return new GCInfoComponent(_methodNode, _methodNode.Size);
// TODO: Is this correct?
yield return new GCInfoComponent(factory.RuntimeFunctionsGCInfo.StartSymbol, this.OffsetFromBeginningOfArray);
}
#endif
}

class MethodGCInfoNodeDeduplicatingComparer : IEqualityComparer<MethodGCInfoNode>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;

using System.Linq;
using System.Reflection.Metadata.Ecma335;
using Internal.JitInterface;
using Internal.Text;
using Internal.TypeSystem;
Expand All @@ -19,6 +20,9 @@ public class MethodWithGCInfo : ObjectNode, IMethodBodyNode, ISymbolDefinitionNo
private readonly MethodDesc _method;

private ObjectData _methodCode;
#if READYTORUN
private MethodColdCodeNode _methodColdCodeNode;
#endif
private FrameInfo[] _frameInfos;
private byte[] _gcInfo;
private ObjectData _ehInfo;
Expand Down Expand Up @@ -129,11 +133,27 @@ public int Compare(FixupCell a, FixupCell b)
}
}

public MethodColdCodeNode GetColdCodeNode() => _methodColdCodeNode;

public byte[] GetFixupBlob(NodeFactory factory)
{
Relocation[] relocations = GetData(factory, relocsOnly: true).Relocs;

#if READYTORUN
if (_methodColdCodeNode != null)
{
Relocation[] coldRelocations = _methodColdCodeNode.GetData(factory, relocsOnly: true).Relocs;
if (relocations == null)
{
relocations = coldRelocations;
}
else if (coldRelocations != null)
{
relocations = Enumerable.Concat(relocations, coldRelocations).ToArray();
}
}
#endif

if (relocations == null)
{
return null;
Expand Down Expand Up @@ -249,6 +269,10 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
{
dependencyList.Add(node, "classMustBeLoadedBeforeCodeIsRun");
}
if (_methodColdCodeNode != null)
{
dependencyList.Add(_methodColdCodeNode, "cold");
}

return dependencyList;
}
Expand Down Expand Up @@ -358,5 +382,12 @@ public void InitializeInliningInfo(MethodDesc[] inlinedMethods, NodeFactory fact
public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => IsEmpty;

public override string ToString() => _method.ToString();

#if READYTORUN
public void SetColdCodeNode(MethodColdCodeNode methodColdCodeNode)
{
_methodColdCodeNode = methodColdCodeNode;
}
#endif
}
}
Loading

0 comments on commit 5280674

Please sign in to comment.