Skip to content
Closed
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 @@ -244,6 +244,7 @@ The .NET Foundation licenses this file to you under the MIT license.
<IlcArg Include="@(AutoInitializedAssemblies->'--initassembly:%(Identity)')" />
<IlcArg Include="@(DirectPInvoke->'--directpinvoke:%(Identity)')" />
<IlcArg Include="@(DirectPInvokeList->'--directpinvokelist:%(Identity)')" />
<IlcArg Include="--feature:System.Resources.UseSystemResourceKeys=false" />
<IlcArg Include="@(_TrimmerFeatureSettings->'--feature:%(Identity)=%(Value)')" />
<IlcArg Include="@(RuntimeHostConfigurationOption->'--runtimeknob:%(Identity)=%(Value)')" />
<IlcArg Include="--runtimeknob:RUNTIME_IDENTIFIER=$(RuntimeIdentifier)" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;

namespace ILCompiler
{
Expand Down Expand Up @@ -132,7 +133,7 @@ public CompilationBuilder UseDwarf5(bool value)
protected PreinitializationManager GetPreinitializationManager()
{
if (_preinitializationManager == null)
return new PreinitializationManager(_context, _compilationGroup, GetILProvider(), new TypePreinit.DisabledPreinitializationPolicy(), new StaticReadOnlyFieldPolicy());
return new PreinitializationManager(_context, _compilationGroup, GetILProvider(), new TypePreinit.DisabledPreinitializationPolicy(), new StaticReadOnlyFieldPolicy(), new Dictionary<string, bool>());
return _preinitializationManager;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Diagnostics;
using Internal.IL;
using Internal.TypeSystem;
Expand All @@ -14,10 +15,10 @@ public class PreinitializationManager
{
private readonly bool _supportsLazyCctors;

public PreinitializationManager(TypeSystemContext context, CompilationModuleGroup compilationGroup, ILProvider ilprovider, TypePreinit.TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy)
public PreinitializationManager(TypeSystemContext context, CompilationModuleGroup compilationGroup, ILProvider ilprovider, TypePreinit.TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy, IReadOnlyDictionary<string, bool> featureSwitches)
{
_supportsLazyCctors = context.SystemModule.GetType("System.Runtime.CompilerServices", "ClassConstructorRunner", throwIfNotFound: false) != null;
_preinitHashTable = new PreinitializationInfoHashtable(compilationGroup, ilprovider, policy, readOnlyPolicy);
_preinitHashTable = new PreinitializationInfoHashtable(compilationGroup, ilprovider, policy, readOnlyPolicy, featureSwitches);
}

/// <summary>
Expand Down Expand Up @@ -137,13 +138,15 @@ private sealed class PreinitializationInfoHashtable : LockFreeReaderHashtable<Me
private readonly ILProvider _ilProvider;
internal readonly TypePreinit.TypePreinitializationPolicy _policy;
private readonly ReadOnlyFieldPolicy _readOnlyPolicy;
private readonly IReadOnlyDictionary<string, bool> _featureSwitches;

public PreinitializationInfoHashtable(CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinit.TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy)
public PreinitializationInfoHashtable(CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinit.TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy, IReadOnlyDictionary<string, bool> featureSwitches)
{
_compilationGroup = compilationGroup;
_ilProvider = ilProvider;
_policy = policy;
_readOnlyPolicy = readOnlyPolicy;
_featureSwitches = featureSwitches;
}

protected override bool CompareKeyToValue(MetadataType key, TypePreinit.PreinitializationInfo value) => key == value.Type;
Expand All @@ -153,7 +156,7 @@ public PreinitializationInfoHashtable(CompilationModuleGroup compilationGroup, I

protected override TypePreinit.PreinitializationInfo CreateValueFromKey(MetadataType key)
{
var info = TypePreinit.ScanType(_compilationGroup, _ilProvider, _policy, _readOnlyPolicy, key);
var info = TypePreinit.ScanType(_compilationGroup, _ilProvider, _policy, _readOnlyPolicy, _featureSwitches, key);

// We either successfully preinitialized or
// the type doesn't have a canonical form or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,16 @@ public class TypePreinit
private readonly Dictionary<FieldDesc, Value> _fieldValues = new Dictionary<FieldDesc, Value>();
private readonly Dictionary<string, StringInstance> _internedStrings = new Dictionary<string, StringInstance>();
private readonly Dictionary<TypeDesc, RuntimeTypeValue> _internedTypes = new Dictionary<TypeDesc, RuntimeTypeValue>();
private readonly IReadOnlyDictionary<string, bool> _featureSwitches;

private TypePreinit(MetadataType owningType, CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy)
private TypePreinit(MetadataType owningType, CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy, IReadOnlyDictionary<string, bool> featureSwitches)
{
_type = owningType;
_compilationGroup = compilationGroup;
_ilProvider = ilProvider;
_policy = policy;
_readOnlyPolicy = readOnlyPolicy;
_featureSwitches = featureSwitches;

// Zero initialize all fields we model.
foreach (var field in owningType.GetFields())
Expand All @@ -58,7 +60,7 @@ private TypePreinit(MetadataType owningType, CompilationModuleGroup compilationG
}
}

public static PreinitializationInfo ScanType(CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy, MetadataType type)
public static PreinitializationInfo ScanType(CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy, IReadOnlyDictionary<string, bool> featureSwitches, MetadataType type)
{
Debug.Assert(type.HasStaticConstructor);
Debug.Assert(!type.IsGenericDefinition);
Expand All @@ -85,7 +87,7 @@ public static PreinitializationInfo ScanType(CompilationModuleGroup compilationG
Status status;
try
{
preinit = new TypePreinit(type, compilationGroup, ilProvider, policy, readOnlyPolicy);
preinit = new TypePreinit(type, compilationGroup, ilProvider, policy, readOnlyPolicy, featureSwitches);
int instructions = 0;
status = preinit.TryScanMethod(type.GetStaticConstructor(), null, null, ref instructions, out _);
}
Expand Down Expand Up @@ -351,7 +353,7 @@ private Status TryScanMethod(MethodIL methodIL, Value[] parameters, Stack<Method
&& field.OwningType.HasStaticConstructor
&& _policy.CanPreinitialize(field.OwningType))
{
TypePreinit nestedPreinit = new TypePreinit((MetadataType)field.OwningType, _compilationGroup, _ilProvider, _policy, _readOnlyPolicy);
TypePreinit nestedPreinit = new TypePreinit((MetadataType)field.OwningType, _compilationGroup, _ilProvider, _policy, _readOnlyPolicy, _featureSwitches);
recursionProtect ??= new Stack<MethodDesc>();
recursionProtect.Push(methodIL.OwningMethod);

Expand Down Expand Up @@ -466,7 +468,7 @@ private Status TryScanMethod(MethodIL methodIL, Value[] parameters, Stack<Method
}

Value retVal;
if (!method.IsIntrinsic || !TryHandleIntrinsicCall(method, methodParams, out retVal))
if (!TryHandleIntrinsicCall(method, methodParams, out retVal))
{
recursionProtect ??= new Stack<MethodDesc>();
recursionProtect.Push(methodIL.OwningMethod);
Expand Down Expand Up @@ -1886,6 +1888,16 @@ private bool TryHandleIntrinsicCall(MethodDesc method, Value[] parameters, out V
retVal = ValueTypeValue.FromSByte(parameters[0] == parameters[1] ? (sbyte)1 : (sbyte)0);
return true;
}
case "TryGetSwitch" when method.OwningType is MetadataType appContextType
&& appContextType.Name == "AppContext" && appContextType.Namespace == "System"
&& appContextType.Module == appContextType.Context.SystemModule
&& parameters[0] is StringInstance switchName && parameters[1] is ByRefValue switchValueLocation
&& _featureSwitches.TryGetValue(switchName.ValueAsString, out bool switchValue):
{
switchValueLocation.WriteAsBool(switchValue);
retVal = ValueTypeValue.FromSByte(1);
return true;
}
}

return false;
Expand Down Expand Up @@ -2623,11 +2635,11 @@ public override bool GetRawData(NodeFactory factory, out object data)
return false;
}

private ReadOnlySpan<byte> AsExactByteCount(int count)
private Span<byte> AsExactByteCount(int count)
{
if (PointedToOffset + count > PointedToBytes.Length)
ThrowHelper.ThrowInvalidProgramException();
return new ReadOnlySpan<byte>(PointedToBytes, PointedToOffset, count);
return new Span<byte>(PointedToBytes, PointedToOffset, count);
}

public sbyte DereferenceAsSByte() => (sbyte)AsExactByteCount(1)[0];
Expand All @@ -2636,6 +2648,7 @@ private ReadOnlySpan<byte> AsExactByteCount(int count)
public long DereferenceAsInt64() => BitConverter.ToInt64(AsExactByteCount(8));
public float DereferenceAsSingle() => BitConverter.ToSingle(AsExactByteCount(4));
public double DereferenceAsDouble() => BitConverter.ToDouble(AsExactByteCount(8));
public void WriteAsBool(bool value) => BitConverter.TryWriteBytes(AsExactByteCount(1), value);
}

private abstract class ReferenceTypeValue : Value
Expand Down Expand Up @@ -2904,7 +2917,7 @@ private sealed class StringInstance : ReferenceTypeValue, IHasInstanceFields
{
private readonly byte[] _value;

private string ValueAsString
public string ValueAsString
{
get
{
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/tools/aot/ILCompiler/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ public int Run()
TypePreinit.TypePreinitializationPolicy preinitPolicy = preinitStatics ?
new TypePreinit.TypeLoaderAwarePreinitializationPolicy() : new TypePreinit.DisabledPreinitializationPolicy();

var preinitManager = new PreinitializationManager(typeSystemContext, compilationGroup, ilProvider, preinitPolicy, new StaticReadOnlyFieldPolicy());
var preinitManager = new PreinitializationManager(typeSystemContext, compilationGroup, ilProvider, preinitPolicy, new StaticReadOnlyFieldPolicy(), featureSwitches);
builder
.UseILProvider(ilProvider)
.UsePreinitializationManager(preinitManager);
Expand Down Expand Up @@ -515,7 +515,7 @@ void RunScanner()
{
var readOnlyFieldPolicy = scanResults.GetReadOnlyFieldPolicy();
preinitManager = new PreinitializationManager(typeSystemContext, compilationGroup, ilProvider, scanResults.GetPreinitializationPolicy(),
readOnlyFieldPolicy);
readOnlyFieldPolicy, featureSwitches);
builder.UsePreinitializationManager(preinitManager)
.UseReadOnlyFieldPolicy(readOnlyFieldPolicy);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@
<OutputType>Exe</OutputType>
<CLRTestPriority>0</CLRTestPriority>
<DefineConstants>$(DefineConstants);RESOURCE_KEYS</DefineConstants>

<UseSystemResourceKeys>true</UseSystemResourceKeys>

<!-- Requires the framework to also be compiled with UseSystemResourceKeys -->
<CLRTestTargetUnsupported Condition="'$(IlcMultiModule)' == 'true'">true</CLRTestTargetUnsupported>
<!-- Test infra issue on apple devices: https://github.com/dotnet/runtime/issues/89917 -->
<CLRTestTargetUnsupported Condition="'$(TargetsAppleMobile)' == 'true'">true</CLRTestTargetUnsupported>
</PropertyGroup>

<ItemGroup>
<IlcArg Include="--feature:System.Resources.UseSystemResourceKeys=true" />
</ItemGroup>

<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
Expand Down