From 915354c880a62ecd2e29bce5f2a2bec9f250c8a9 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Thu, 21 Nov 2019 11:14:57 -0800 Subject: [PATCH 1/5] Add SkipLocalsInitAttribute This attribute supports a new compiler feature that allows a user to specify that they don't want to emit the CLR `.locals init` portion of the header in methods. This can sometimes produce a performance improvement but, in some cases, can reveal uninitialized memory to the application. Ported from https://github.com/dotnet/coreclr/pull/20093 --- .../src/System.Private.CoreLib.Shared.projitems | 1 + .../CompilerServices/SkipLocalsInitAttribute.cs | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index ac793c38fc2767..35ee6e5f18f65b 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -609,6 +609,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs new file mode 100644 index 00000000000000..2c3409357b8de1 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event, Inherited = false)] + public sealed class SkipLocalsInitAttribute : Attribute + { + public SkipLocalsInitAttribute() + { + } + } +} \ No newline at end of file From 98f1ce6ca414e7d605a7d404eb61c0c9d7dcf9e2 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Mon, 2 Dec 2019 14:25:03 -0800 Subject: [PATCH 2/5] Add doc comments and update the ref source --- .../SkipLocalsInitAttribute.cs | 21 ++++++++++++++++++- .../System.Runtime/ref/System.Runtime.cs | 7 +++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs index 2c3409357b8de1..85f65b35dd2e39 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs @@ -4,7 +4,26 @@ namespace System.Runtime.CompilerServices { - [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event, Inherited = false)] + /// + /// Used to indicate to the compiler that the `.locals init` flag should not + /// be set in nested method headers when emitting to metadata. This attribute + /// is unsafe because it may reveal uninitialized memory to the application + /// in certain instances (e.g., reading from uninitialized stackalloc'd + /// memory). If applied to a method directly, the attribute applies to that + /// method and all nested functions (lambdas, local functions) below it. If + /// applied to a type or module, it applies to all methods nested inside. + /// + /// + /// This attribute is intentionally not permitted on assemblies. Use at the + /// module level instead to apply to multiple type declarations. + /// + [AttributeUsage(AttributeTargets.Module + | AttributeTargets.Class + | AttributeTargets.Struct + | AttributeTargets.Constructor + | AttributeTargets.Method + | AttributeTargets.Property + | AttributeTargets.Event, Inherited = false)] public sealed class SkipLocalsInitAttribute : Attribute { public SkipLocalsInitAttribute() diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index d203dcc3d17be3..6b0927ae5a6995 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -6914,6 +6914,13 @@ public RuntimeWrappedException(object thrownObject) { } public object WrappedException { get { throw null; } } public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } + [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event, Inherited = false)] + public sealed class SkipLocalsInitAttribute : Attribute + { + public SkipLocalsInitAttribute() + { + } + } [System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Event | System.AttributeTargets.Field | System.AttributeTargets.Method | System.AttributeTargets.Property | System.AttributeTargets.Struct)] public sealed partial class SpecialNameAttribute : System.Attribute { From 02ba309d85b62f9829b5f4749f0643642f5db568 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Mon, 2 Dec 2019 15:42:46 -0800 Subject: [PATCH 3/5] Add test for coverage --- .../System/Runtime/CompilerServices/AttributesTests.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs index 66ba84f4353797..0ee7a7a723258f 100644 --- a/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs +++ b/src/libraries/System.Runtime/tests/System/Runtime/CompilerServices/AttributesTests.cs @@ -8,6 +8,12 @@ namespace System.Runtime.CompilerServices.Tests { public static class AttributesTests { + [Fact] + public static void SkipLocalsInitAttributeTests() + { + new SkipLocalsInitAttribute(); + } + [Fact] public static void AccessedThroughPropertyAttributeTests() { From 12a0a8ad98684470adb157782acacde963b82fd2 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Tue, 3 Dec 2019 16:47:52 -0800 Subject: [PATCH 4/5] Fully qualify, add partial --- .../CompilerServices/SkipLocalsInitAttribute.cs | 15 ++++++++------- .../System.Runtime/ref/System.Runtime.cs | 8 +++----- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs index 85f65b35dd2e39..a8afd6e1ad108b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs @@ -5,13 +5,14 @@ namespace System.Runtime.CompilerServices { /// - /// Used to indicate to the compiler that the `.locals init` flag should not - /// be set in nested method headers when emitting to metadata. This attribute - /// is unsafe because it may reveal uninitialized memory to the application - /// in certain instances (e.g., reading from uninitialized stackalloc'd - /// memory). If applied to a method directly, the attribute applies to that - /// method and all nested functions (lambdas, local functions) below it. If - /// applied to a type or module, it applies to all methods nested inside. + /// Used to indicate to the compiler that the .locals init flag should + /// not be set in nested method headers when emitting to metadata. This + /// attribute is unsafe because it may reveal uninitialized memory to the + /// application in certain instances (e.g., reading from uninitialized + /// stackalloc'd memory). If applied to a method directly, the attribute + /// applies to that method and all nested functions (lambdas, local + /// functions) below it. If applied to a type or module, it applies to all + /// methods nested inside. /// /// /// This attribute is intentionally not permitted on assemblies. Use at the diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 6b0927ae5a6995..2caba78c09e26c 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -6914,12 +6914,10 @@ public RuntimeWrappedException(object thrownObject) { } public object WrappedException { get { throw null; } } public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } - [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event, Inherited = false)] - public sealed class SkipLocalsInitAttribute : Attribute + [System.AttributeUsageAttribute(System.AttributeTargets.Module | System.AttributeTargets.Class | System.AttributeTargets.Struct | System.AttributeTargets.Constructor | System.AttributeTargets.Method | System.AttributeTargets.Property | System.AttributeTargets.Event, Inherited = false)] + public sealed partial class SkipLocalsInitAttribute : System.Attribute { - public SkipLocalsInitAttribute() - { - } + public SkipLocalsInitAttribute() { } } [System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Event | System.AttributeTargets.Field | System.AttributeTargets.Method | System.AttributeTargets.Property | System.AttributeTargets.Struct)] public sealed partial class SpecialNameAttribute : System.Attribute From 8548c63726b23b2e1a2cb182b9886882208d6216 Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 6 Dec 2019 15:28:16 -0800 Subject: [PATCH 5/5] Move excess documentation to remarks --- .../CompilerServices/SkipLocalsInitAttribute.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs index a8afd6e1ad108b..fef7f11749863f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs @@ -6,17 +6,17 @@ namespace System.Runtime.CompilerServices { /// /// Used to indicate to the compiler that the .locals init flag should - /// not be set in nested method headers when emitting to metadata. This - /// attribute is unsafe because it may reveal uninitialized memory to the - /// application in certain instances (e.g., reading from uninitialized + /// not be set in nested method headers when emitting to metadata. + /// + /// + /// This attribute is unsafe because it may reveal uninitialized memory to + /// the application in certain instances (e.g., reading from uninitialized /// stackalloc'd memory). If applied to a method directly, the attribute /// applies to that method and all nested functions (lambdas, local /// functions) below it. If applied to a type or module, it applies to all - /// methods nested inside. - /// - /// - /// This attribute is intentionally not permitted on assemblies. Use at the - /// module level instead to apply to multiple type declarations. + /// methods nested inside. This attribute is intentionally not permitted on + /// assemblies. Use at the module level instead to apply to multiple type + /// declarations. /// [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class