Skip to content
This repository was archived by the owner on Nov 1, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public CompilationBuilder UsePreinitializationManager(PreinitializationManager m
protected PreinitializationManager GetPreinitializationManager()
{
if (_preinitializationManager == null)
return new PreinitializationManager(_context, _compilationGroup, GetILProvider());
return new PreinitializationManager(_context, _compilationGroup, GetILProvider(), enableInterpreter: false);
return _preinitializationManager;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,27 @@ namespace ILCompiler
{
internal class CompilerMetadataFieldLayoutAlgorithm : MetadataFieldLayoutAlgorithm
{
// GC statics start with a pointer to the "EEType" that signals the size and GCDesc to the GC
public static LayoutInt GetGCStaticFieldOffset(TypeSystemContext context) => context.Target.LayoutPointerSize;

protected override void PrepareRuntimeSpecificStaticFieldLayout(TypeSystemContext context, ref ComputedStaticFieldLayout layout)
{
// GC statics start with a pointer to the "EEType" that signals the size and GCDesc to the GC
layout.GcStatics.Size = context.Target.LayoutPointerSize;
layout.ThreadGcStatics.Size = context.Target.LayoutPointerSize;
LayoutInt offset = GetGCStaticFieldOffset(context);
layout.GcStatics.Size = offset;
layout.ThreadGcStatics.Size = offset;
}

protected override void FinalizeRuntimeSpecificStaticFieldLayout(TypeSystemContext context, ref ComputedStaticFieldLayout layout)
{
LayoutInt offset = GetGCStaticFieldOffset(context);

// If the size of GCStatics is equal to the size set in PrepareRuntimeSpecificStaticFieldLayout, we
// don't have any GC statics
if (layout.GcStatics.Size == context.Target.LayoutPointerSize)
if (layout.GcStatics.Size == offset)
{
layout.GcStatics.Size = LayoutInt.Zero;
}
if (layout.ThreadGcStatics.Size == context.Target.LayoutPointerSize)
if (layout.ThreadGcStatics.Size == offset)
{
layout.ThreadGcStatics.Size = LayoutInt.Zero;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,32 @@
// 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 System.Diagnostics;

using Internal.Text;
using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;

namespace ILCompiler.DependencyAnalysis
{
/// <summary>
/// Represents a frozen array
/// Represents a frozen object that is statically preallocated within the data section
/// of the executable instead of on the GC heap.
/// </summary>
public class FrozenArrayNode : EmbeddedObjectNode, ISymbolDefinitionNode
public class FrozenObjectNode : EmbeddedObjectNode, ISymbolDefinitionNode
{
private PreInitFieldInfo _preInitFieldInfo;
private readonly FieldDesc _field;
private readonly TypePreinit.ISerializableReference _data;

public FrozenArrayNode(PreInitFieldInfo preInitFieldInfo)
public FrozenObjectNode(FieldDesc field, TypePreinit.ISerializableReference data)
{
_preInitFieldInfo = preInitFieldInfo;
_field = field;
_data = data;
}

public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix).Append("__FrozenArr_")
.Append(nameMangler.GetMangledFieldName(_preInitFieldInfo.Field));
sb.Append(nameMangler.CompilationUnitPrefix).Append("__FrozenObj_")
.Append(nameMangler.GetMangledFieldName(_field));
}

public override bool StaticDependenciesAreComputed => true;
Expand All @@ -38,41 +38,18 @@ int ISymbolDefinitionNode.Offset
{
get
{
// The frozen array symbol points at the EEType portion of the object, skipping over the sync block
return OffsetFromBeginningOfArray + _preInitFieldInfo.Field.Context.Target.PointerSize;
// The frozen object symbol points at the EEType portion of the object, skipping over the sync block
return OffsetFromBeginningOfArray + _field.Context.Target.PointerSize;
}
}

private IEETypeNode GetEETypeNode(NodeFactory factory)
{
var fieldType = _preInitFieldInfo.Type;
var node = factory.ConstructedTypeSymbol(fieldType);
Debug.Assert(!node.RepresentsIndirectionCell); // Array are always local
return node;
}

public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly)
{
// Sync Block
dataBuilder.EmitZeroPointer();

// EEType
dataBuilder.EmitPointerReloc(GetEETypeNode(factory));

// numComponents
dataBuilder.EmitInt(_preInitFieldInfo.Length);

int pointerSize = _preInitFieldInfo.Field.Context.Target.PointerSize;
Debug.Assert(pointerSize == 8 || pointerSize == 4);

if (pointerSize == 8)
{
// padding numComponents in 64-bit
dataBuilder.EmitInt(0);
}

// byte contents
_preInitFieldInfo.WriteData(ref dataBuilder, factory, relocsOnly);
_data.WriteContent(ref dataBuilder, factory);
}

protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
Expand Down Expand Up @@ -105,7 +82,7 @@ protected override void OnMarked(NodeFactory factory)

public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return _preInitFieldInfo.CompareTo(((FrozenArrayNode)other)._preInitFieldInfo, comparer);
return comparer.Compare(((FrozenObjectNode)other)._field, _field);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ namespace ILCompiler.DependencyAnalysis
{
public class GCStaticsNode : ObjectNode, IExportableSymbolNode, ISortableSymbolNode, ISymbolNodeWithDebugInfo
{
private MetadataType _type;
private List<PreInitFieldInfo> _preInitFieldInfos;
private readonly MetadataType _type;
private readonly TypePreinit.PreinitializationInfo _preinitializationInfo;

public GCStaticsNode(MetadataType type)
public GCStaticsNode(MetadataType type, PreinitializationManager preinitManager)
{
Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Specific));
_type = type;
_preInitFieldInfos = PreInitFieldInfo.GetPreInitFieldInfos(_type, hasGCStaticBase: true);

if (preinitManager.IsPreinitialized(type))
_preinitializationInfo = preinitManager.GetPreinitializationInfo(_type);
}

protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
Expand Down Expand Up @@ -51,8 +53,8 @@ private ISymbolNode GetGCStaticEETypeNode(NodeFactory factory)

public GCStaticsPreInitDataNode NewPreInitDataNode()
{
Debug.Assert(_preInitFieldInfos != null);
return new GCStaticsPreInitDataNode(_type, _preInitFieldInfos);
Debug.Assert(_preinitializationInfo != null && _preinitializationInfo.IsPreinitialized);
return new GCStaticsPreInitDataNode(_preinitializationInfo);
}

protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
Expand All @@ -65,9 +67,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
}

dependencyList.Add(factory.GCStaticsRegion, "GCStatics Region");
dependencyList.Add(GetGCStaticEETypeNode(factory), "GCStatic EEType");
if (_preInitFieldInfos != null)
dependencyList.Add(factory.GCStaticsPreInitDataNode(_type), "PreInitData node");

dependencyList.Add(factory.GCStaticIndirection(_type), "GC statics indirection");
EETypeNode.AddDependenciesForStaticsNode(factory, _type, ref dependencyList);
Expand All @@ -82,47 +81,25 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact

public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
if (factory.Target.Abi == TargetAbi.CoreRT || factory.Target.Abi == TargetAbi.CppCodegen)
{
ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);
ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

builder.RequireInitialPointerAlignment();
builder.RequireInitialPointerAlignment();

int delta = GCStaticRegionConstants.Uninitialized;
int delta = GCStaticRegionConstants.Uninitialized;

// Set the flag that indicates next pointer following EEType is the preinit data
if (_preInitFieldInfos != null)
delta |= GCStaticRegionConstants.HasPreInitializedData;
// Set the flag that indicates next pointer following EEType is the preinit data
bool isPreinitialized = _preinitializationInfo != null && _preinitializationInfo.IsPreinitialized;
if (isPreinitialized)
delta |= GCStaticRegionConstants.HasPreInitializedData;

builder.EmitPointerReloc(GetGCStaticEETypeNode(factory), delta);

if (_preInitFieldInfos != null)
builder.EmitPointerReloc(factory.GCStaticsPreInitDataNode(_type));
builder.EmitPointerReloc(GetGCStaticEETypeNode(factory), delta);

builder.AddSymbol(this);
if (isPreinitialized)
builder.EmitPointerReloc(factory.GCStaticsPreInitDataNode(_type));

return builder.ToObjectData();
}
else
{
if (_preInitFieldInfos == null)
{
ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);
builder.AddSymbol(this);

builder.RequireInitialPointerAlignment();

builder.EmitZeros(_type.GCStaticFieldSize.AsInt);

builder.AddSymbol(this);

return builder.ToObjectData();
}
else
{
_preInitFieldInfos.Sort(PreInitFieldInfo.FieldDescCompare);
return GCStaticsPreInitDataNode.GetDataForPreInitDataField(this, _type, _preInitFieldInfos, 0, factory, relocsOnly);
}
}
return builder.ToObjectData();
}

public override int ClassCode => -522346696;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// 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 Internal.Text;
using Internal.TypeSystem;

Expand All @@ -19,28 +17,23 @@ namespace ILCompiler.DependencyAnalysis
/// </summary>
public class GCStaticsPreInitDataNode : ObjectNode, ISymbolDefinitionNode
{
private MetadataType _type;
private List<PreInitFieldInfo> _sortedPreInitFields;
private TypePreinit.PreinitializationInfo _preinitializationInfo;

public GCStaticsPreInitDataNode(MetadataType type, List<PreInitFieldInfo> preInitFields)
public GCStaticsPreInitDataNode(TypePreinit.PreinitializationInfo preinitializationInfo)
{
Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Specific));
_type = type;

// sort the PreInitFieldInfo to appear in increasing offset order for easier emitting
_sortedPreInitFields = new List<PreInitFieldInfo>(preInitFields);
_sortedPreInitFields.Sort(PreInitFieldInfo.FieldDescCompare);
Debug.Assert(!preinitializationInfo.Type.IsCanonicalSubtype(CanonicalFormKind.Specific));
_preinitializationInfo = preinitializationInfo;
}

protected override string GetName(NodeFactory factory) => GetMangledName(_type, factory.NameMangler);
protected override string GetName(NodeFactory factory) => GetMangledName(_preinitializationInfo.Type, factory.NameMangler);

public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(GetMangledName(_type, nameMangler));
sb.Append(GetMangledName(_preinitializationInfo.Type, nameMangler));
}

public int Offset => 0;
public MetadataType Type => _type;
public MetadataType Type => _preinitializationInfo.Type;

public static string GetMangledName(TypeDesc type, NameMangler nameMangler)
{
Expand All @@ -49,66 +42,52 @@ public static string GetMangledName(TypeDesc type, NameMangler nameMangler)

public override bool StaticDependenciesAreComputed => true;

public override ObjectNodeSection Section => ObjectNodeSection.ReadOnlyDataSection;
public override bool IsShareable => EETypeNode.IsTypeNodeShareable(_type);

public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
public override ObjectNodeSection Section
{
// We only need this for CoreRT (at least for now) as we emit static field value directly in GCStaticsNode for N
Debug.Assert(factory.Target.Abi == TargetAbi.CoreRT);

return GetDataForPreInitDataField(
this, _type, _sortedPreInitFields,
factory.Target.PointerSize, // CoreRT static size calculation includes EEType - skip it
factory, relocsOnly);
get
{
if (Type.Context.Target.IsWindows)
return ObjectNodeSection.ReadOnlyDataSection;
else
return ObjectNodeSection.DataSection;
}
}
public override bool IsShareable => EETypeNode.IsTypeNodeShareable(_preinitializationInfo.Type);

public static ObjectData GetDataForPreInitDataField(
ISymbolDefinitionNode node,
MetadataType _type, List<PreInitFieldInfo> sortedPreInitFields,
int startOffset,
NodeFactory factory, bool relocsOnly = false)
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);

builder.RequireInitialAlignment(_type.GCStaticFieldAlignment.AsInt);
MetadataType type = _preinitializationInfo.Type;

int staticOffset = startOffset;
int staticOffsetEnd = _type.GCStaticFieldSize.AsInt;
int idx = 0;
builder.RequireInitialAlignment(factory.Target.PointerSize);

while (staticOffset < staticOffsetEnd)
// GC static fields don't begin at offset 0, need to subtract that.
int initialOffset = CompilerMetadataFieldLayoutAlgorithm.GetGCStaticFieldOffset(factory.TypeSystemContext).AsInt;

foreach (FieldDesc field in type.GetFields())
{
PreInitFieldInfo fieldInfo = idx < sortedPreInitFields.Count ? sortedPreInitFields[idx] : null;
int writeTo = staticOffsetEnd;
if (fieldInfo != null)
writeTo = fieldInfo.Field.Offset.AsInt;

// Emit the zero before the next preinitField
builder.EmitZeros(writeTo - staticOffset);
staticOffset = writeTo;

if (fieldInfo != null)
{
int count = builder.CountBytes;

if (fieldInfo.Field.FieldType.IsValueType)
{
// Emit inlined data for value types
fieldInfo.WriteData(ref builder, factory);
}
else
{
// Emit a pointer reloc to the frozen data for reference types
builder.EmitPointerReloc(factory.SerializedFrozenArray(fieldInfo));
}

staticOffset += builder.CountBytes - count;
idx++;
}
if (!field.IsStatic || field.HasRva || field.IsLiteral || field.IsThreadStatic || !field.HasGCStaticBase)
continue;

int padding = field.Offset.AsInt - initialOffset - builder.CountBytes;
Debug.Assert(padding >= 0);
builder.EmitZeros(padding);

TypePreinit.ISerializableValue val = _preinitializationInfo.GetFieldValue(field);
int currentOffset = builder.CountBytes;
if (val != null)
val.WriteFieldData(ref builder, field, factory);
else
builder.EmitZeroPointer();
Debug.Assert(builder.CountBytes - currentOffset == field.FieldType.GetElementSize().AsInt);
}

builder.AddSymbol(node);
int pad = _preinitializationInfo.Type.GCStaticFieldSize.AsInt - builder.CountBytes - initialOffset;
Debug.Assert(pad >= 0);
builder.EmitZeros(pad);

builder.AddSymbol(this);

return builder.ToObjectData();
}
Expand All @@ -117,7 +96,7 @@ public static ObjectData GetDataForPreInitDataField(

public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_type, ((GCStaticsPreInitDataNode)other)._type);
return comparer.Compare(_preinitializationInfo.Type, ((GCStaticsPreInitDataNode)other)._preinitializationInfo.Type);
}
}
}
Loading