Skip to content
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 @@ -118,7 +118,7 @@ public CompilationBuilder UseDwarf5(bool value)
protected PreinitializationManager GetPreinitializationManager()
{
if (_preinitializationManager == null)
return new PreinitializationManager(_context, _compilationGroup, GetILProvider(), enableInterpreter: false);
return new PreinitializationManager(_context, _compilationGroup, GetILProvider(), new TypePreinit.DisabledPreinitializationPolicy());
return _preinitializationManager;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,10 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
Section nativeSection = nativeWriter.NewSection();
nativeSection.Place(hashtable);

foreach (TypeDesc type in factory.MetadataManager.GetTypesWithConstructedEETypes())
foreach (TypeDesc type in factory.MetadataManager.GetTypeTemplates())
{
if (!IsEligibleToHaveATemplate(type))
continue;

// Type's native layout info
NativeLayoutTemplateTypeLayoutVertexNode templateNode = factory.NativeLayout.TemplateTypeLayout(type);

// If this template isn't considered necessary, don't emit it.
if (!templateNode.Marked)
continue;
Vertex nativeLayout = templateNode.SavedVertex;

// Hashtable Entry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,8 @@ public sealed class NativeLayoutTemplateTypeLayoutVertexNode : NativeLayoutSaved
private TypeDesc _type;
private bool _isUniversalCanon;

public TypeDesc CanonType => _type.ConvertToCanonForm(CanonicalFormKind.Specific);

protected override string GetName(NodeFactory factory) => "NativeLayoutTemplateTypeLayoutVertexNode_" + factory.NameMangler.GetMangledTypeName(_type);

public NativeLayoutTemplateTypeLayoutVertexNode(NodeFactory factory, TypeDesc type)
Expand Down Expand Up @@ -989,7 +991,7 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
}
}

if (context.PreinitializationManager.HasLazyStaticConstructor(_type))
if (context.PreinitializationManager.HasLazyStaticConstructor(_type.ConvertToCanonForm(CanonicalFormKind.Specific)))
{
yield return new DependencyListEntry(context.MethodEntrypoint(_type.GetStaticConstructor().GetCanonMethodTarget(CanonicalFormKind.Specific)), "cctor for template");
}
Expand Down Expand Up @@ -1188,7 +1190,7 @@ public override Vertex WriteVertex(NodeFactory factory)
layoutInfo.Append(BagElementKind.DictionaryLayout, dictionaryLayout.WriteVertex(factory));
}

if (factory.PreinitializationManager.HasLazyStaticConstructor(_type))
if (factory.PreinitializationManager.HasLazyStaticConstructor(_type.ConvertToCanonForm(CanonicalFormKind.Specific)))
{
MethodDesc cctorMethod = _type.GetStaticConstructor();
MethodDesc canonCctorMethod = cctorMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public NonGCStaticsNode(MetadataType type, PreinitializationManager preinitializ

protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory)
{
if (_preinitializationManager.HasLazyStaticConstructor(_type)
if (HasCCtorContext
|| _preinitializationManager.IsPreinitialized(_type))
{
// We have data to be emitted so this needs to be in an initialized data section
Expand Down Expand Up @@ -63,7 +63,7 @@ int ISymbolDefinitionNode.Offset
get
{
// Make sure the NonGCStatics symbol always points to the beginning of the data.
if (_preinitializationManager.HasLazyStaticConstructor(_type))
if (HasCCtorContext)
{
return GetClassConstructorContextStorageSize(_type.Context.Target, _type);
}
Expand All @@ -74,7 +74,25 @@ int ISymbolDefinitionNode.Offset
}
}

public bool HasCCtorContext => _preinitializationManager.HasLazyStaticConstructor(_type);
public static bool TypeHasCctorContext(PreinitializationManager preinitializationManager, MetadataType type)
{
// If the type has a lazy static constructor, we need the cctor context.
if (preinitializationManager.HasLazyStaticConstructor(type))
return true;

// If the type has a canonical form and accessing the base from a canonical
// context requires a cctor check, we need the cctor context.
TypeDesc canonType = type.ConvertToCanonForm(CanonicalFormKind.Specific);
if (canonType != type && preinitializationManager.HasLazyStaticConstructor(canonType))
return true;

// Otherwise no cctor context needed.
return false;
}

public bool HasCCtorContext => TypeHasCctorContext(_preinitializationManager, _type);

public bool HasLazyStaticConstructor => _preinitializationManager.HasLazyStaticConstructor(_type);

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

Expand Down Expand Up @@ -124,7 +142,7 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo

// If the type has a class constructor, its non-GC statics section is prefixed
// by System.Runtime.CompilerServices.StaticClassConstructionContext struct.
if (factory.PreinitializationManager.HasLazyStaticConstructor(_type))
if (HasCCtorContext)
{
int alignmentRequired = Math.Max(_type.NonGCStaticFieldAlignment.AsInt, GetClassConstructorContextAlignment(_type.Context.Target));
int classConstructorContextStorageSize = GetClassConstructorContextStorageSize(factory.Target, _type);
Expand All @@ -138,7 +156,24 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo
// Emit the actual StaticClassConstructionContext
MethodDesc cctorMethod = _type.GetStaticConstructor();
builder.EmitPointerReloc(factory.ExactCallableAddress(cctorMethod));
builder.EmitZeroPointer();

// If we're emitting the cctor context, but the type is actually preinitialized, emit the
// cctor context as already executed.
if (!HasLazyStaticConstructor)
{
// Constructor executed
// TODO-NICE: introduce a named constant and also use it in the runner in CoreLib
builder.EmitInt(1);
}
else
{
// Constructor didn't execute
builder.EmitInt(0);
}

// Emit padding if needed
if (builder.TargetPointerSize == 8)
builder.EmitInt(0);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ protected sealed override void OnMarked(NodeFactory factory)
layout.EnsureEntry(_lookupSignature);

if ((_id == ReadyToRunHelperId.GetGCStaticBase || _id == ReadyToRunHelperId.GetThreadStaticBase) &&
factory.PreinitializationManager.HasLazyStaticConstructor((TypeDesc)_target))
TriggersLazyStaticConstructor(factory))
{
// If the type has a lazy static constructor, we also need the non-GC static base
// because that's where the class constructor context is.
Expand All @@ -116,6 +116,12 @@ protected sealed override void OnMarked(NodeFactory factory)
}
}

private bool TriggersLazyStaticConstructor(NodeFactory factory)
{
TypeDesc type = (TypeDesc)_target;
return factory.PreinitializationManager.HasLazyStaticConstructor(type.ConvertToCanonForm(CanonicalFormKind.Specific));
}

public IEnumerable<DependencyListEntry> InstantiateDependencies(NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation)
{
DependencyList result = new DependencyList();
Expand All @@ -129,13 +135,11 @@ public IEnumerable<DependencyListEntry> InstantiateDependencies(NodeFactory fact
{
// If the type has a lazy static constructor, we also need the non-GC static base
// because that's where the class constructor context is.
TypeDesc type = (TypeDesc)_target;

if (factory.PreinitializationManager.HasLazyStaticConstructor(type))
if (TriggersLazyStaticConstructor(factory))
{
result.Add(
new DependencyListEntry(
factory.GenericLookup.TypeNonGCStaticBase(type).GetTarget(factory, lookupContext),
factory.GenericLookup.TypeNonGCStaticBase((TypeDesc)_target).GetTarget(factory, lookupContext),
"Dictionary dependency"));
}
}
Expand Down Expand Up @@ -250,7 +254,7 @@ public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDep
// a template dictionary node.
TypeDesc type = (TypeDesc)_target;
Debug.Assert(templateLayout != null);
if (factory.PreinitializationManager.HasLazyStaticConstructor(type))
if (TriggersLazyStaticConstructor(factory))
{
GenericLookupResult nonGcRegionLookup = factory.GenericLookup.TypeNonGCStaticBase(type);
conditionalDependencies.Add(new CombinedDependencyListEntry(nonGcRegionLookup.TemplateDictionaryNode(factory),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public static void AddStaticsInfoDependencies(ref DependencyList dependencies, N
dependencies.Add(factory.TypeGCStaticsSymbol(metadataType), "GC statics indirection for StaticsInfoHashtable");
}

if (metadataType.NonGCStaticFieldSize.AsInt > 0 || factory.PreinitializationManager.HasLazyStaticConstructor(type))
if (metadataType.NonGCStaticFieldSize.AsInt > 0 || NonGCStaticsNode.TypeHasCctorContext(factory.PreinitializationManager, metadataType))
{
// The entry in the StaticsInfoHashtable points at the beginning of the static fields data, rather than the cctor
// context offset.
Expand Down Expand Up @@ -98,7 +98,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
bag.AppendUnsigned(BagElementKind.GcStaticData, _nativeStaticsReferences.GetIndex(factory.TypeGCStaticsSymbol(metadataType)));
}
if (metadataType.NonGCStaticFieldSize.AsInt > 0 || factory.PreinitializationManager.HasLazyStaticConstructor(type))
if (metadataType.NonGCStaticFieldSize.AsInt > 0 || NonGCStaticsNode.TypeHasCctorContext(factory.PreinitializationManager, metadataType))
{
bag.AppendUnsigned(BagElementKind.NonGcStaticData, _nativeStaticsReferences.GetIndex(factory.TypeNonGCStaticsSymbol(metadataType)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref ARMEmitter enco

EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Result, _lookupSignature, relocsOnly);

MetadataType target = (MetadataType)_target;
if (!factory.PreinitializationManager.HasLazyStaticConstructor(target))
if (!TriggersLazyStaticConstructor(factory))
{
encoder.EmitRET();
}
Expand Down Expand Up @@ -99,7 +98,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref ARMEmitter enco
encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Result);

MetadataType target = (MetadataType)_target;
if (!factory.PreinitializationManager.HasLazyStaticConstructor(target))
if (!TriggersLazyStaticConstructor(factory))
{
encoder.EmitRET();
}
Expand Down Expand Up @@ -132,7 +131,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref ARMEmitter enco
EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg1, _lookupSignature, relocsOnly);

ISymbolNode helperEntrypoint;
if (factory.PreinitializationManager.HasLazyStaticConstructor(target))
if (TriggersLazyStaticConstructor(factory))
{
// There is a lazy class constructor. We need the non-GC static base because that's where the
// class constructor context lives.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref ARM64Emitter en

EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Result, _lookupSignature, relocsOnly);

MetadataType target = (MetadataType)_target;
if (!factory.PreinitializationManager.HasLazyStaticConstructor(target))
if (!TriggersLazyStaticConstructor(factory))
{
encoder.EmitRET();
}
Expand Down Expand Up @@ -111,7 +110,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref ARM64Emitter en
encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Result);

MetadataType target = (MetadataType)_target;
if (!factory.PreinitializationManager.HasLazyStaticConstructor(target))
if (!TriggersLazyStaticConstructor(factory))
{
encoder.EmitRET();
}
Expand Down Expand Up @@ -144,7 +143,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref ARM64Emitter en
EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg1, _lookupSignature, relocsOnly);

ISymbolNode helperEntrypoint;
if (factory.PreinitializationManager.HasLazyStaticConstructor(target))
if (TriggersLazyStaticConstructor(factory))
{
// There is a lazy class constructor. We need the non-GC static base because that's where the
// class constructor context lives.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref LoongArch64Emit

EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Result, _lookupSignature, relocsOnly);

MetadataType target = (MetadataType)_target;
if (!factory.PreinitializationManager.HasLazyStaticConstructor(target))
if (!TriggersLazyStaticConstructor(factory))
{
encoder.EmitRET();
}
Expand Down Expand Up @@ -100,7 +99,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref LoongArch64Emit
encoder.EmitLD(encoder.TargetRegister.Result, encoder.TargetRegister.Result, 0);

MetadataType target = (MetadataType)_target;
if (!factory.PreinitializationManager.HasLazyStaticConstructor(target))
if (!TriggersLazyStaticConstructor(factory))
{
encoder.EmitRET();
}
Expand Down Expand Up @@ -133,7 +132,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref LoongArch64Emit
EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg1, _lookupSignature, relocsOnly);

ISymbolNode helperEntrypoint;
if (factory.PreinitializationManager.HasLazyStaticConstructor(target))
if (TriggersLazyStaticConstructor(factory))
{
// There is a lazy class constructor. We need the non-GC static base because that's where the
// class constructor context lives.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref X64Emitter enco
{
Debug.Assert(contextRegister == encoder.TargetRegister.Arg0);

MetadataType target = (MetadataType)_target;

if (!factory.PreinitializationManager.HasLazyStaticConstructor(target))
if (!TriggersLazyStaticConstructor(factory))
{
EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Result, _lookupSignature, relocsOnly);
encoder.EmitRET();
Expand Down Expand Up @@ -119,7 +117,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref X64Emitter enco
AddrMode loadFromResult = new AddrMode(encoder.TargetRegister.Result, null, 0, 0, AddrModeSize.Int64);
encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromResult);

if (!factory.PreinitializationManager.HasLazyStaticConstructor(target))
if (!TriggersLazyStaticConstructor(factory))
{
encoder.EmitRET();
}
Expand Down Expand Up @@ -153,7 +151,7 @@ protected sealed override void EmitCode(NodeFactory factory, ref X64Emitter enco
EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg1, _lookupSignature, relocsOnly);

ISymbolNode helperEntrypoint;
if (factory.PreinitializationManager.HasLazyStaticConstructor(target))
if (TriggersLazyStaticConstructor(factory))
{
// There is a lazy class constructor. We need the non-GC static base because that's where the
// class constructor context lives.
Expand Down
Loading