Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IsDynamicCodeSupported Feature Switch #80246

Merged
merged 6 commits into from
Jan 9, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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 @@ -208,7 +208,6 @@
<Compile Include="$(BclSourcesRoot)\System\Resources\ManifestBasedResourceGroveler.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\CastHelpers.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\ICastableHelpers.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeFeature.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeHelpers.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\ControlledExecution.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\DependentHandle.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
<linker>
<assembly fullname="System.Private.CoreLib">
<type fullname="System.Runtime.CompilerServices.RuntimeFeature" feature="System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported" featurevalue="true">
<method signature="System.Boolean get_IsDynamicCodeCompiled()" body="stub" value="true" />
<method signature="System.Boolean get_IsDynamicCodeSupported()" body="stub" value="true" />
</type>
<type fullname="System.Runtime.CompilerServices.RuntimeFeature" feature="System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported" featurevalue="false">
<method signature="System.Boolean get_IsDynamicCodeCompiled()" body="stub" value="false" />
<method signature="System.Boolean get_IsDynamicCodeSupported()" body="stub" value="false" />
</type>
<type fullname="System.StartupHookProvider" feature="System.StartupHookProvider.IsSupported" featurevalue="false">
<method signature="System.Boolean get_IsSupported()" body="stub" value="false" />
</type>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ internal AssemblyBuilder(AssemblyName name,
throw new InvalidOperationException();
}

EnsureDynamicCodeSupported();

_access = access;

_internalAssembly = CreateDynamicAssembly(assemblyLoadContext ?? AssemblyLoadContext.GetLoadContext(callingAssembly)!, name, access);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ public CustomAttributeBuilder(ConstructorInfo con, object?[] constructorArgs, Pr
ArgumentNullException.ThrowIfNull(namedFields);
ArgumentNullException.ThrowIfNull(fieldValues);

AssemblyBuilder.EnsureDynamicCodeSupported();
jkotas marked this conversation as resolved.
Show resolved Hide resolved

#pragma warning disable CA2208 // Instantiate argument exceptions correctly, combination of arguments used
if (namedProperties.Length != propertyValues.Length)
throw new ArgumentException(SR.Arg_ArrayLengthsDiffer, "namedProperties, propertyValues");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ private void Init(Module? mod)

if (m_module == null && mod != null)
throw new ArgumentException(SR.NotSupported_MustBeModuleBuilder);

AssemblyBuilder.EnsureDynamicCodeSupported();
}

[MemberNotNull(nameof(m_signature))]
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\RequiredMemberAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\RuntimeCompatibilityAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\RuntimeFeature.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\RuntimeFeature.NonNativeAot.cs" Condition="'$(FeatureNativeAot)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\RuntimeHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\RuntimeWrappedException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\SkipLocalsInitAttribute.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Runtime.CompilerServices;

namespace System.Reflection.Emit
{
Expand Down Expand Up @@ -38,5 +39,16 @@ public override string[] GetManifestResourceNames() =>

public override Stream? GetManifestResourceStream(Type type, string name) =>
throw new NotSupportedException(SR.NotSupported_DynamicAssembly);

internal static void EnsureDynamicCodeSupported()
{
if (!RuntimeFeature.IsDynamicCodeSupported)
{
ThrowDynamicCodeNotSupported();
}
}

private static void ThrowDynamicCodeNotSupported() =>
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ReflectionEmit);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ private void Init(string name,
{
ArgumentNullException.ThrowIfNull(name);

AssemblyBuilder.EnsureDynamicCodeSupported();

if (attributes != (MethodAttributes.Static | MethodAttributes.Public) || callingConvention != CallingConventions.Standard)
throw new NotSupportedException(SR.NotSupported_DynamicMethodFlags);

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

namespace System.Runtime.CompilerServices
{
public static partial class RuntimeFeature
{
public static bool IsDynamicCodeSupported { get; } =
AppContext.TryGetSwitch("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", out bool isDynamicCodeSupported) ? isDynamicCodeSupported : true;

public static bool IsDynamicCodeCompiled => IsDynamicCodeSupported;
eerhardt marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.RemoteExecutor;
using Xunit;

namespace System.Reflection.Emit.Tests
Expand Down Expand Up @@ -1069,6 +1070,28 @@ public void NamedPropertyAndPropertyValuesDifferentLengths_ThrowsArgumentExcepti
AssertExtensions.Throws<ArgumentException>(paramName, () => new CustomAttributeBuilder(con, new object[0], namedProperties, propertyValues, new FieldInfo[0], new object[0]));
}

[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
public static void ThrowsWhenDynamicCodeNotSupported()
{
RemoteInvokeOptions options = new RemoteInvokeOptions();
options.RuntimeConfigurationOptions.Add("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", false.ToString());

using RemoteInvokeHandle remoteHandle = RemoteExecutor.Invoke(static () =>
{
ConstructorInfo con = typeof(TestAttribute).GetConstructor(new Type[0]);
object[] constructorArgs = new object[0];
PropertyInfo[] namedProperties = Helpers.GetProperties(typeof(TestAttribute), nameof(TestAttribute.ObjectProperty));
object[] propertyValues = new object[] { new int[0, 0] };
FieldInfo[] namedFields = new FieldInfo[0];
object[] fieldValues = new object[0];

Assert.Throws<PlatformNotSupportedException>(() => new CustomAttributeBuilder(con, constructorArgs));
Assert.Throws<PlatformNotSupportedException>(() => new CustomAttributeBuilder(con, constructorArgs, namedFields, fieldValues));
Assert.Throws<PlatformNotSupportedException>(() => new CustomAttributeBuilder(con, constructorArgs, namedProperties, propertyValues));
Assert.Throws<PlatformNotSupportedException>(() => new CustomAttributeBuilder(con, constructorArgs, namedProperties, propertyValues, namedFields, fieldValues));
}, options);
}

private static Type CreateEnum(Type underlyingType, params object[] literalValues)
{
ModuleBuilder module = Helpers.DynamicModule();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.DotNet.RemoteExecutor;
using Xunit;

namespace System.Reflection.Emit.Tests
{
public class SignatureHelperDynamicCodeNotSupported
{
[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
public static void ThrowsWhenDynamicCodeNotSupported()
{
RemoteInvokeOptions options = new RemoteInvokeOptions();
options.RuntimeConfigurationOptions.Add("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", false.ToString());

using RemoteInvokeHandle remoteHandle = RemoteExecutor.Invoke(static () =>
{
Assert.Throws<PlatformNotSupportedException>(() => SignatureHelper.GetFieldSigHelper(null));
Assert.Throws<PlatformNotSupportedException>(() => SignatureHelper.GetLocalVarSigHelper());
Assert.Throws<PlatformNotSupportedException>(() => SignatureHelper.GetMethodSigHelper(CallingConventions.Any, typeof(int)));

// Mono always throws NotImplementedException - https://github.com/dotnet/runtime/issues/37794
if (!PlatformDetection.IsMonoRuntime)
{
Assert.Throws<PlatformNotSupportedException>(() => SignatureHelper.GetPropertySigHelper(null, typeof(string), new Type[] { typeof(string), typeof(int) }));
}
}, options);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
<TestRuntime>true</TestRuntime>
<IncludeRemoteExecutor>true</IncludeRemoteExecutor>
</PropertyGroup>
<ItemGroup>
<Compile Include="ILGenerator\DeclareLocalTests.cs" />
Expand Down Expand Up @@ -32,6 +33,7 @@
<Compile Include="SignatureHelper\SignatureHelperGetMethodSigHelper.cs" />
<Compile Include="SignatureHelper\SignatureHelperGetPropertySigHelper.cs" />
<Compile Include="SignatureHelper\SignatureHelperGetSignature.cs" />
<Compile Include="SignatureHelper\SignatureHelperDynamicCodeNotSupported.cs" />
<Compile Include="SignatureHelper\SignatureHelperToString.cs" />
<Compile Include="CustomAttributeBuilderTests.cs" />
<Compile Include="Utilities.cs" />
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 Microsoft.DotNet.RemoteExecutor;
using Xunit;

namespace System.Reflection.Emit.Tests
Expand Down Expand Up @@ -173,5 +174,30 @@ public void InvalidOwner_ThrowsArgumentException(Type owner)
AssertExtensions.Throws<ArgumentException>(null, () => new DynamicMethod("Method", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(void), new Type[0], owner, true));
AssertExtensions.Throws<ArgumentException>(null, () => new DynamicMethod("Method", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(void), new Type[0], owner, false));
}

[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
public static void ThrowsWhenDynamicCodeNotSupported()
{
RemoteInvokeOptions options = new RemoteInvokeOptions();
options.RuntimeConfigurationOptions.Add("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", false.ToString());

using RemoteInvokeHandle remoteHandle = RemoteExecutor.Invoke(static () =>
{
Module module = typeof(TestClass).GetTypeInfo().Module;
string name = "Method";
Type returnType = typeof(void);
Type[] parameterTypes = null;
Type owner = typeof(TestClass);

Assert.Throws<PlatformNotSupportedException>(() => new DynamicMethod(name, returnType, parameterTypes));
Assert.Throws<PlatformNotSupportedException>(() => new DynamicMethod(name, returnType, parameterTypes, true));
Assert.Throws<PlatformNotSupportedException>(() => new DynamicMethod(name, returnType, parameterTypes, module));
Assert.Throws<PlatformNotSupportedException>(() => new DynamicMethod(name, returnType, parameterTypes, owner));
Assert.Throws<PlatformNotSupportedException>(() => new DynamicMethod(name, returnType, parameterTypes, module, true));
Assert.Throws<PlatformNotSupportedException>(() => new DynamicMethod(name, returnType, parameterTypes, owner, true));
Assert.Throws<PlatformNotSupportedException>(() => new DynamicMethod(name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, module, true));
Assert.Throws<PlatformNotSupportedException>(() => new DynamicMethod(name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, returnType, parameterTypes, owner, true));
}, options);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
<TestRuntime>true</TestRuntime>
<IncludeRemoteExecutor>true</IncludeRemoteExecutor>
</PropertyGroup>
<ItemGroup>
<Compile Include="DynamicILInfoTests.cs" />
Expand Down
16 changes: 16 additions & 0 deletions src/libraries/System.Reflection.Emit/tests/AssemblyBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.DotNet.RemoteExecutor;
using Xunit;

namespace System.Reflection.Emit.Tests
Expand Down Expand Up @@ -442,5 +443,20 @@ public void DefineDynamicAssembly_AssemblyBuilderLocationIsEmpty_InternalAssembl
Assert.Empty(internalAssemblyBuilder.Location);
}

[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
public static void ThrowsWhenDynamicCodeNotSupported()
{
RemoteInvokeOptions options = new RemoteInvokeOptions();
options.RuntimeConfigurationOptions.Add("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", false.ToString());

using RemoteInvokeHandle remoteHandle = RemoteExecutor.Invoke(static () =>
{
var assemblyName = new AssemblyName("TestName");
AssemblyBuilderAccess access = AssemblyBuilderAccess.Run;

Assert.Throws<PlatformNotSupportedException>(() => AssemblyBuilder.DefineDynamicAssembly(assemblyName, access));
Assert.Throws<PlatformNotSupportedException>(() => AssemblyBuilder.DefineDynamicAssembly(assemblyName, access, assemblyAttributes: null));
}, options);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
<TestRuntime>true</TestRuntime>
<IncludeRemoteExecutor>true</IncludeRemoteExecutor>
</PropertyGroup>
<ItemGroup>
<Compile Include="AssemblyBuilderTests.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.DotNet.RemoteExecutor;
using Xunit;

namespace System.Runtime.CompilerServices.Tests
Expand Down Expand Up @@ -70,5 +71,26 @@ public static void StaticDataMatchesDynamicProbing(string probedValue)
{
Assert.True(RuntimeFeature.IsSupported(probedValue));
}

[ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
[InlineData(true)]
[InlineData(false)]
public static void DynamicCode_ContextSwitch(bool isDynamicCodeSupported)
{
RemoteInvokeOptions options = new RemoteInvokeOptions();
options.RuntimeConfigurationOptions.Add("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", isDynamicCodeSupported.ToString());

// IsDynamicCodeCompiled on Mono interpreter always returns false
bool isDynamicCodeCompiled = PlatformDetection.IsMonoInterpreter ? false : isDynamicCodeSupported;

using RemoteInvokeHandle remoteHandle = RemoteExecutor.Invoke(static (isDynamicCodeSupportedString, isDynamicCodeCompiledString) =>
{
bool isDynamicCodeSupported = bool.Parse(isDynamicCodeSupportedString);
Assert.Equal(isDynamicCodeSupported, RuntimeFeature.IsDynamicCodeSupported);

bool isDynamicCodeCompiled = bool.Parse(isDynamicCodeCompiledString);
Assert.Equal(isDynamicCodeCompiled, RuntimeFeature.IsDynamicCodeCompiled);
}, isDynamicCodeSupported.ToString(), isDynamicCodeCompiled.ToString(), options);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,6 @@
<Compile Include="$(BclSourcesRoot)\System\Runtime\JitInfo.Mono.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\JitHelpers.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeHelpers.Mono.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeFeature.Mono.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\GCHandle.Mono.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\Marshal.Mono.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\MemoryMarshal.Mono.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ public sealed partial class AssemblyBuilder : Assembly
[DynamicDependency(nameof(access))] // Automatically keeps all previous fields too due to StructLayout
private AssemblyBuilder(AssemblyName n, AssemblyBuilderAccess access)
{
EnsureDynamicCodeSupported();

aname = (AssemblyName)n.Clone();

if (!Enum.IsDefined(typeof(AssemblyBuilderAccess), access))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ private void Initialize(ConstructorInfo con, object?[] constructorArgs,
ArgumentNullException.ThrowIfNull(namedFields);
ArgumentNullException.ThrowIfNull(fieldValues);

AssemblyBuilder.EnsureDynamicCodeSupported();

if (con.GetParametersCount() != constructorArgs.Length)
throw new ArgumentException(SR.Argument_BadParameterCountsForConstructor);
if (namedProperties.Length != propertyValues.Length)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ internal enum SignatureHelperType
[DynamicDependency(nameof(modopts))] // Automatically keeps all previous fields too due to StructLayout
internal SignatureHelper(ModuleBuilder? module, SignatureHelperType type)
{
AssemblyBuilder.EnsureDynamicCodeSupported();

this.type = type;
this.module = module;
}
Expand Down

This file was deleted.

6 changes: 3 additions & 3 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -2606,9 +2606,9 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas
else if (in_corlib &&
!strcmp ("System.Runtime.CompilerServices", klass_name_space) &&
!strcmp ("RuntimeFeature", klass_name)) {
if (!strcmp (tm, "get_IsDynamicCodeSupported"))
*op = MINT_LDC_I4_1;
else if (!strcmp (tm, "get_IsDynamicCodeCompiled"))
// NOTE: on the interpreter, use the C# code in System.Private.CoreLib for IsDynamicCodeSupported
// and always return false for IsDynamicCodeCompiled
if (!strcmp (tm, "get_IsDynamicCodeCompiled"))
*op = MINT_LDC_I4_0;
} else if (in_corlib &&
(!strncmp ("System.Runtime.Intrinsics.Arm", klass_name_space, 29) ||
Expand Down
Loading