diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index ba1e1480ed8e6f..967359e64cb15c 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -244,6 +244,7 @@ The .NET Foundation licenses this file to you under the MIT license. + diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs index 8d596f87e43f31..694a95620550d7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilationBuilder.Aot.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; namespace ILCompiler { @@ -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()); return _preinitializationManager; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/PreinitializationManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/PreinitializationManager.cs index 59aa509360464e..17494cd874f6dc 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/PreinitializationManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/PreinitializationManager.cs @@ -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; @@ -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 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); } /// @@ -137,13 +138,15 @@ private sealed class PreinitializationInfoHashtable : LockFreeReaderHashtable _featureSwitches; - public PreinitializationInfoHashtable(CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinit.TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy) + public PreinitializationInfoHashtable(CompilationModuleGroup compilationGroup, ILProvider ilProvider, TypePreinit.TypePreinitializationPolicy policy, ReadOnlyFieldPolicy readOnlyPolicy, IReadOnlyDictionary featureSwitches) { _compilationGroup = compilationGroup; _ilProvider = ilProvider; _policy = policy; _readOnlyPolicy = readOnlyPolicy; + _featureSwitches = featureSwitches; } protected override bool CompareKeyToValue(MetadataType key, TypePreinit.PreinitializationInfo value) => key == value.Type; @@ -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 diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index 6f5fa941b6a1ca..c82b866f2c4c98 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -39,14 +39,16 @@ public class TypePreinit private readonly Dictionary _fieldValues = new Dictionary(); private readonly Dictionary _internedStrings = new Dictionary(); private readonly Dictionary _internedTypes = new Dictionary(); + private readonly IReadOnlyDictionary _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 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()) @@ -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 featureSwitches, MetadataType type) { Debug.Assert(type.HasStaticConstructor); Debug.Assert(!type.IsGenericDefinition); @@ -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 _); } @@ -351,7 +353,7 @@ private Status TryScanMethod(MethodIL methodIL, Value[] parameters, Stack(); recursionProtect.Push(methodIL.OwningMethod); @@ -466,7 +468,7 @@ private Status TryScanMethod(MethodIL methodIL, Value[] parameters, Stack(); recursionProtect.Push(methodIL.OwningMethod); @@ -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; @@ -2623,11 +2635,11 @@ public override bool GetRawData(NodeFactory factory, out object data) return false; } - private ReadOnlySpan AsExactByteCount(int count) + private Span AsExactByteCount(int count) { if (PointedToOffset + count > PointedToBytes.Length) ThrowHelper.ThrowInvalidProgramException(); - return new ReadOnlySpan(PointedToBytes, PointedToOffset, count); + return new Span(PointedToBytes, PointedToOffset, count); } public sbyte DereferenceAsSByte() => (sbyte)AsExactByteCount(1)[0]; @@ -2636,6 +2648,7 @@ private ReadOnlySpan 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 @@ -2904,7 +2917,7 @@ private sealed class StringInstance : ReferenceTypeValue, IHasInstanceFields { private readonly byte[] _value; - private string ValueAsString + public string ValueAsString { get { diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs index 66df76365d8d28..29dab15fb50e3b 100644 --- a/src/coreclr/tools/aot/ILCompiler/Program.cs +++ b/src/coreclr/tools/aot/ILCompiler/Program.cs @@ -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); @@ -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); } diff --git a/src/tests/nativeaot/SmokeTests/FrameworkStrings/UseSystemResourceKeys.csproj b/src/tests/nativeaot/SmokeTests/FrameworkStrings/UseSystemResourceKeys.csproj index 752d76b2687c3c..59c74f6a222ea0 100644 --- a/src/tests/nativeaot/SmokeTests/FrameworkStrings/UseSystemResourceKeys.csproj +++ b/src/tests/nativeaot/SmokeTests/FrameworkStrings/UseSystemResourceKeys.csproj @@ -3,6 +3,8 @@ Exe 0 $(DefineConstants);RESOURCE_KEYS + + true true @@ -10,10 +12,6 @@ true - - - -