diff options
22 files changed, 263 insertions, 55 deletions
diff --git a/src/Common/src/System/Runtime/CompilerServices/__BlockReflectionAttribute.cs b/src/Common/src/System/Runtime/CompilerServices/__BlockReflectionAttribute.cs new file mode 100644 index 000000000..fbb490403 --- /dev/null +++ b/src/Common/src/System/Runtime/CompilerServices/__BlockReflectionAttribute.cs @@ -0,0 +1,17 @@ +// 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. + +/* + Providing a definition for __BlockReflectionAttribute in an assembly is a signal to the .NET Native toolchain + to remove the metadata for all non-public APIs. This both reduces size and disables private reflection on those + APIs in libraries that include this. +*/ + +using System; + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.All)] + internal class __BlockReflectionAttribute : Attribute { } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/BlockedInternalsBlockingPolicy.cs b/src/ILCompiler.Compiler/src/Compiler/BlockedInternalsBlockingPolicy.cs new file mode 100644 index 000000000..5da9253bd --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/BlockedInternalsBlockingPolicy.cs @@ -0,0 +1,132 @@ +// 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. + +using System; + +using Internal.TypeSystem; +using Internal.TypeSystem.Ecma; + +using Debug = System.Diagnostics.Debug; +using TypeAttributes = System.Reflection.TypeAttributes; +using MethodAttributes = System.Reflection.MethodAttributes; +using FieldAttributes = System.Reflection.FieldAttributes; + +namespace ILCompiler +{ + /// <summary> + /// Represents a metadata policy that blocks implementations details. + /// </summary> + public sealed class BlockedInternalsBlockingPolicy : MetadataBlockingPolicy + { + private class BlockingState + { + public EcmaType Type { get; } + public bool IsBlocked { get; } + public BlockingState(EcmaType type, bool isBlocked) + { + Type = type; + IsBlocked = isBlocked; + } + } + + private class BlockedTypeHashtable : LockFreeReaderHashtable<EcmaType, BlockingState> + { + protected override int GetKeyHashCode(EcmaType key) => key.GetHashCode(); + protected override int GetValueHashCode(BlockingState value) => value.Type.GetHashCode(); + protected override bool CompareKeyToValue(EcmaType key, BlockingState value) => Object.ReferenceEquals(key, value.Type); + protected override bool CompareValueToValue(BlockingState value1, BlockingState value2) => Object.ReferenceEquals(value1.Type, value2.Type); + protected override BlockingState CreateValueFromKey(EcmaType type) + { + bool isBlocked = false; + bool moduleHasBlockingPolicy = type.Module.GetType("System.Runtime.CompilerServices", "__BlockReflectionAttribute", false) != null; + if (moduleHasBlockingPolicy) + { + isBlocked = ComputeIsBlocked(type); + } + + return new BlockingState(type, isBlocked); + } + + private bool ComputeIsBlocked(EcmaType type) + { + // <Module> type always gets metadata + if (type.IsModuleType) + return false; + + // The various SR types used in Resource Manager always get metadata + if (type.Name == "SR") + return false; + + var typeDefinition = type.MetadataReader.GetTypeDefinition(type.Handle); + DefType containingType = type.ContainingType; + if (containingType == null) + { + if ((typeDefinition.Attributes & TypeAttributes.Public) == 0) + { + return true; + } + } + else + { + if ((typeDefinition.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic) + { + return ComputeIsBlocked((EcmaType)containingType); + } + else + { + return true; + } + } + + return false; + } + } + private BlockedTypeHashtable _blockedTypes = new BlockedTypeHashtable(); + + public override bool IsBlocked(MetadataType type) + { + Debug.Assert(type.IsTypeDefinition); + + var ecmaType = type as EcmaType; + if (ecmaType == null) + return true; + + return _blockedTypes.GetOrCreateValue(ecmaType).IsBlocked; + } + + public override bool IsBlocked(MethodDesc method) + { + Debug.Assert(method.IsTypicalMethodDefinition); + + var ecmaMethod = method as EcmaMethod; + if (ecmaMethod == null) + return true; + + if (_blockedTypes.GetOrCreateValue((EcmaType)ecmaMethod.OwningType).IsBlocked) + return true; + + if ((ecmaMethod.Attributes & MethodAttributes.Public) != MethodAttributes.Public) + return true; + + return false; + } + + public override bool IsBlocked(FieldDesc field) + { + Debug.Assert(field.IsTypicalFieldDefinition); + + var ecmaField = field as EcmaField; + if (ecmaField == null) + return true; + + if (_blockedTypes.GetOrCreateValue((EcmaType)ecmaField.OwningType).IsBlocked) + return true; + + if ((ecmaField.Attributes & FieldAttributes.Public) != FieldAttributes.Public) + return true; + + return false; + } + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedMetadataManager.cs index 495b837f7..d3aa1ee92 100644 --- a/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedMetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedMetadataManager.cs @@ -152,6 +152,9 @@ namespace ILCompiler continue; } + if (IsReflectionBlocked(method.Instantiation) || IsReflectionBlocked(method.OwningType.Instantiation)) + continue; + MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition()); if (record != null) @@ -174,6 +177,9 @@ namespace ILCompiler foreach (FieldDesc field in eetypeGenerated.GetFields()) { + if (IsReflectionBlocked(field.OwningType.Instantiation)) + continue; + Field record = transformed.GetTransformedFieldDefinition(field.GetTypicalFieldDefinition()); if (record != null) fieldMappings.Add(new MetadataMapping<FieldDesc>(field, writer.GetRecordHandle(record))); @@ -246,7 +252,8 @@ namespace ILCompiler public bool GeneratesMetadata(FieldDesc fieldDef) { - return _factory.TypeMetadata((MetadataType)fieldDef.OwningType).Marked; + return _factory.TypeMetadata((MetadataType)fieldDef.OwningType).Marked && + !_parent._blockingPolicy.IsBlocked(fieldDef); } public bool GeneratesMetadata(MethodDesc methodDef) @@ -264,6 +271,11 @@ namespace ILCompiler return _parent._blockingPolicy.IsBlocked(typeDef); } + public bool IsBlocked(MethodDesc methodDef) + { + return _parent._blockingPolicy.IsBlocked(methodDef); + } + public ModuleDesc GetModuleOfType(MetadataType typeDef) { return _explicitScopeMixin.GetModuleOfType(typeDef); diff --git a/src/ILCompiler.Compiler/src/Compiler/MetadataBlockingPolicy.cs b/src/ILCompiler.Compiler/src/Compiler/MetadataBlockingPolicy.cs index 3a2591a28..a00cfd734 100644 --- a/src/ILCompiler.Compiler/src/Compiler/MetadataBlockingPolicy.cs +++ b/src/ILCompiler.Compiler/src/Compiler/MetadataBlockingPolicy.cs @@ -4,8 +4,6 @@ using Internal.TypeSystem; -using Debug = System.Diagnostics.Debug; - namespace ILCompiler { /// <summary> @@ -29,34 +27,4 @@ namespace ILCompiler /// </summary> public abstract bool IsBlocked(FieldDesc field); } - - /// <summary> - /// Represents a metadata policy that blocks implementations details. - /// </summary> - public sealed class BlockedInternalsBlockingPolicy : MetadataBlockingPolicy - { - public override bool IsBlocked(MetadataType type) - { - Debug.Assert(type.IsTypeDefinition); - - // TODO: Make this also respect System.Runtime.CompilerServices.DisablePrivateReflectionAttribute - return !(type is Internal.TypeSystem.Ecma.EcmaType); - } - - public override bool IsBlocked(MethodDesc method) - { - Debug.Assert(method.IsTypicalMethodDefinition); - - // TODO: Make this also respect System.Runtime.CompilerServices.DisablePrivateReflectionAttribute - return !(method is Internal.TypeSystem.Ecma.EcmaMethod); - } - - public override bool IsBlocked(FieldDesc field) - { - Debug.Assert(field.IsTypicalFieldDefinition); - - // TODO: Make this also respect System.Runtime.CompilerServices.DisablePrivateReflectionAttribute - return !(field is Internal.TypeSystem.Ecma.EcmaField); - } - } } diff --git a/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs index d5021c29c..3807de4bf 100644 --- a/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs +++ b/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs @@ -608,16 +608,22 @@ namespace ILCompiler } } + protected bool IsReflectionBlocked(Instantiation instantiation) + { + foreach (TypeDesc type in instantiation) + { + if (IsReflectionBlocked(type)) + return true; + } + return false; + } + public bool IsReflectionBlocked(FieldDesc field) { FieldDesc typicalFieldDefinition = field.GetTypicalFieldDefinition(); - if (typicalFieldDefinition != field) + if (typicalFieldDefinition != field && IsReflectionBlocked(field.OwningType.Instantiation)) { - foreach (TypeDesc type in field.OwningType.Instantiation) - { - if (IsReflectionBlocked(type)) - return true; - } + return true; } return _blockingPolicy.IsBlocked(typicalFieldDefinition); @@ -626,23 +632,15 @@ namespace ILCompiler public bool IsReflectionBlocked(MethodDesc method) { MethodDesc methodDefinition = method.GetMethodDefinition(); - if (method != methodDefinition) + if (method != methodDefinition && IsReflectionBlocked(method.Instantiation)) { - foreach (TypeDesc type in method.Instantiation) - { - if (IsReflectionBlocked(type)) - return true; - } + return true; } MethodDesc typicalMethodDefinition = methodDefinition.GetTypicalMethodDefinition(); - if (typicalMethodDefinition != methodDefinition) + if (typicalMethodDefinition != methodDefinition && IsReflectionBlocked(method.OwningType.Instantiation)) { - foreach (TypeDesc type in method.OwningType.Instantiation) - { - if (IsReflectionBlocked(type)) - return true; - } + return true; } return _blockingPolicy.IsBlocked(typicalMethodDefinition); diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj index 954d0dc89..9ea569b71 100644 --- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj +++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj @@ -107,6 +107,7 @@ <Compile Include="..\..\JitInterface\src\JitConfigProvider.cs"> <Link>JitInterface\JitConfigProvider.cs</Link> </Compile> + <Compile Include="Compiler\BlockedInternalsBlockingPolicy.cs" /> <Compile Include="Compiler\CompilerGeneratedType.cs" /> <Compile Include="Compiler\CompilerGeneratedType.Sorting.cs" /> <Compile Include="Compiler\CompilerTypeSystemContext.BoxedTypes.cs" /> diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/IMetadataPolicy.cs b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/IMetadataPolicy.cs index 48c3474ae..d0dde5804 100644 --- a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/IMetadataPolicy.cs +++ b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/IMetadataPolicy.cs @@ -44,6 +44,8 @@ namespace ILCompiler.Metadata /// </summary> bool IsBlocked(Cts.MetadataType typeDef); + bool IsBlocked(Cts.MethodDesc methodDef); + /// <summary> /// Return the Module that should be treated as defining the type. Typically implementations /// will return typeDef.Module, but in some circumstances it may return a different value. diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Type.cs b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Type.cs index 326cda3b0..ea95f9c50 100644 --- a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Type.cs +++ b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.Type.cs @@ -322,7 +322,13 @@ namespace ILCompiler.Metadata Ecma.MethodImplementation miDef = reader.GetMethodImplementation(miHandle); Cts.MethodDesc methodBody = (Cts.MethodDesc)ecmaEntity.EcmaModule.GetObject(miDef.MethodBody); + if (_policy.IsBlocked(methodBody)) + continue; + Cts.MethodDesc methodDecl = (Cts.MethodDesc)ecmaEntity.EcmaModule.GetObject(miDef.MethodDeclaration); + if (_policy.IsBlocked(methodDecl.GetTypicalMethodDefinition())) + continue; + MethodImpl methodImplRecord = new MethodImpl { MethodBody = HandleQualifiedMethod(methodBody), diff --git a/src/ILCompiler.MetadataTransform/tests/MockPolicy.cs b/src/ILCompiler.MetadataTransform/tests/MockPolicy.cs index c87ce5f8b..217cfbd98 100644 --- a/src/ILCompiler.MetadataTransform/tests/MockPolicy.cs +++ b/src/ILCompiler.MetadataTransform/tests/MockPolicy.cs @@ -57,6 +57,11 @@ namespace MetadataTransformTests return false; } + public bool IsBlocked(MethodDesc method) + { + return IsBlocked((MetadataType)method.OwningType); + } + public ModuleDesc GetModuleOfType(MetadataType typeDef) { if (_moduleOfType != null) diff --git a/src/ILCompiler.MetadataTransform/tests/MultifileMetadataPolicy.cs b/src/ILCompiler.MetadataTransform/tests/MultifileMetadataPolicy.cs index ac4d25775..18a585f93 100644 --- a/src/ILCompiler.MetadataTransform/tests/MultifileMetadataPolicy.cs +++ b/src/ILCompiler.MetadataTransform/tests/MultifileMetadataPolicy.cs @@ -52,6 +52,11 @@ namespace MetadataTransformTests return false; } + public bool IsBlocked(MethodDesc method) + { + return IsBlocked((MetadataType)method.OwningType); + } + public ModuleDesc GetModuleOfType(MetadataType typeDef) { return _explicitScopePolicyMixin.GetModuleOfType(typeDef); diff --git a/src/ILCompiler.MetadataTransform/tests/SingleFileMetadataPolicy.cs b/src/ILCompiler.MetadataTransform/tests/SingleFileMetadataPolicy.cs index c8fab721e..16c3bd2b5 100644 --- a/src/ILCompiler.MetadataTransform/tests/SingleFileMetadataPolicy.cs +++ b/src/ILCompiler.MetadataTransform/tests/SingleFileMetadataPolicy.cs @@ -40,6 +40,11 @@ namespace MetadataTransformTests return false; } + public bool IsBlocked(MethodDesc method) + { + return IsBlocked((MetadataType)method.OwningType); + } + public ModuleDesc GetModuleOfType(MetadataType typeDef) { if (_explicitScopePolicyMixin == null) diff --git a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj index 8315ce057..61f9f54f9 100644 --- a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -730,6 +730,9 @@ <Compile Include="..\..\Common\src\System\Numerics\Hashing\HashHelpers.cs"> <Link>System\Numerics\Hashing\HashHelpers.cs</Link> </Compile> + <Compile Include="..\..\Common\src\System\Runtime\CompilerServices\__BlockReflectionAttribute.cs" Condition="'$(IsProjectNLibrary)' != 'true'"> + <Link>System\Runtime\CompilerServices\__BlockReflectionAttribute.cs</Link> + </Compile> <Compile Include="..\..\Common\src\System\Runtime\InteropServices\McgIntrinsicsAttribute.cs"> <Link>System\Runtime\InteropServices\McgIntrinsicsAttribute.cs</Link> </Compile> diff --git a/src/System.Private.DeveloperExperience.Console/src/System.Private.DeveloperExperience.Console.csproj b/src/System.Private.DeveloperExperience.Console/src/System.Private.DeveloperExperience.Console.csproj index cb2037028..63e8a67c2 100644 --- a/src/System.Private.DeveloperExperience.Console/src/System.Private.DeveloperExperience.Console.csproj +++ b/src/System.Private.DeveloperExperience.Console/src/System.Private.DeveloperExperience.Console.csproj @@ -34,6 +34,9 @@ <Compile Include="Internal\DeveloperExperience\DeveloperExperienceConnector.cs" /> <Compile Include="Internal\DeveloperExperience\DeveloperExperienceConsole.cs" /> <Compile Include="Internal\Runtime\CompilerHelpers\LibraryInitializer.cs" /> + <Compile Include="..\..\Common\src\System\Runtime\CompilerServices\__BlockReflectionAttribute.cs" Condition="'$(IsProjectNLibrary)' != 'true'"> + <Link>System\Runtime\CompilerServices\__BlockReflectionAttribute.cs</Link> + </Compile> </ItemGroup> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> diff --git a/src/System.Private.Interop/src/System.Private.Interop.csproj b/src/System.Private.Interop/src/System.Private.Interop.csproj index 431cc60e2..aa08ccddc 100644 --- a/src/System.Private.Interop/src/System.Private.Interop.csproj +++ b/src/System.Private.Interop/src/System.Private.Interop.csproj @@ -146,6 +146,9 @@ <Compile Include="..\..\Common\src\Internal\Runtime\MetadataBlob.cs"> <Link>MetadataBlob.cs</Link> </Compile> + <Compile Include="..\..\Common\src\System\Runtime\CompilerServices\__BlockReflectionAttribute.cs"> + <Link>System\Runtime\CompilerServices\__BlockReflectionAttribute.cs</Link> + </Compile> </ItemGroup> <ItemGroup> <Compile Include="System\Runtime\InteropServices\ComTypes\advf.cs" /> diff --git a/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj b/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj index 9ce0ef1c4..3c735e8a4 100644 --- a/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj +++ b/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj @@ -251,6 +251,9 @@ <Compile Include="..\..\Common\src\System\Runtime\CompilerServices\DeveloperExperienceState.cs"> <Link>System\Runtime\CompilerServices\DeveloperExperienceState.cs</Link> </Compile> + <Compile Include="..\..\Common\src\System\Runtime\CompilerServices\__BlockReflectionAttribute.cs" Condition="'$(IsProjectNLibrary)' != 'true'"> + <Link>System\Runtime\CompilerServices\__BlockReflectionAttribute.cs</Link> + </Compile> </ItemGroup> <ItemGroup> <EmbeddedResource Include="Resources\System.Private.Reflection.Core.rd.xml" /> diff --git a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs index 45dde7c41..c87ae2814 100644 --- a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs +++ b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs @@ -124,8 +124,6 @@ namespace Internal.Reflection.Execution // public unsafe sealed override bool IsReflectionBlocked(RuntimeTypeHandle runtimeTypeHandle) { - // CORERT-TODO: reflection blocking -#if !CORERT // For generic types, use the generic type definition runtimeTypeHandle = GetTypeDefinition(runtimeTypeHandle); @@ -151,7 +149,6 @@ namespace Internal.Reflection.Execution return true; } // Entry not found, must not be blocked -#endif return false; } diff --git a/src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj b/src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj index cbd6f9ddd..a8d369995 100644 --- a/src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj +++ b/src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj @@ -138,6 +138,9 @@ <Compile Include="..\..\Common\src\System\Collections\Generic\Empty.cs" > <Link>System\Collections\Generic\Empty.cs</Link> </Compile> + <Compile Include="..\..\Common\src\System\Runtime\CompilerServices\__BlockReflectionAttribute.cs" Condition="'$(IsProjectNLibrary)' != 'true'"> + <Link>System\Runtime\CompilerServices\__BlockReflectionAttribute.cs</Link> + </Compile> </ItemGroup> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> </Project> diff --git a/src/System.Private.Reflection.Metadata/src/System.Private.Reflection.Metadata.csproj b/src/System.Private.Reflection.Metadata/src/System.Private.Reflection.Metadata.csproj index 08d3fbeee..b02e524c0 100644 --- a/src/System.Private.Reflection.Metadata/src/System.Private.Reflection.Metadata.csproj +++ b/src/System.Private.Reflection.Metadata/src/System.Private.Reflection.Metadata.csproj @@ -34,6 +34,11 @@ <Compile Include="$(MetadataCommonPath)\NativeMetadataReader.cs" /> <Compile Include="$(MetadataCommonPath)\NativeFormatReaderGen.cs" /> </ItemGroup> + <ItemGroup> + <Compile Include="..\..\Common\src\System\Runtime\CompilerServices\__BlockReflectionAttribute.cs" Condition="'$(IsProjectNLibrary)' != 'true'"> + <Link>System\Runtime\CompilerServices\__BlockReflectionAttribute.cs</Link> + </Compile> + </ItemGroup> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> </Project> diff --git a/src/System.Private.StackTraceGenerator/src/System.Private.StackTraceGenerator.csproj b/src/System.Private.StackTraceGenerator/src/System.Private.StackTraceGenerator.csproj index 9decba91a..77e9568df 100644 --- a/src/System.Private.StackTraceGenerator/src/System.Private.StackTraceGenerator.csproj +++ b/src/System.Private.StackTraceGenerator/src/System.Private.StackTraceGenerator.csproj @@ -32,6 +32,9 @@ <Compile Include="..\..\Common\src\System\Runtime\InteropServices\McgIntrinsicsAttribute.cs" > <Link>System\Runtime\InteropServices\McgIntrinsicsAttribute.cs</Link> </Compile> + <Compile Include="..\..\Common\src\System\Runtime\CompilerServices\__BlockReflectionAttribute.cs" Condition="'$(IsProjectNLibrary)' != 'true'"> + <Link>System\Runtime\CompilerServices\__BlockReflectionAttribute.cs</Link> + </Compile> </ItemGroup> <ItemGroup Condition="'$(TargetsWindows)'!='true'"> diff --git a/src/System.Private.Threading/src/System.Private.Threading.csproj b/src/System.Private.Threading/src/System.Private.Threading.csproj index 57925bd34..002200834 100644 --- a/src/System.Private.Threading/src/System.Private.Threading.csproj +++ b/src/System.Private.Threading/src/System.Private.Threading.csproj @@ -24,6 +24,9 @@ <Compile Include="Internal\Threading\TaskTraceCallbacksImplementation.cs" /> <Compile Include="System\Threading\CDSsyncETWBCLProvider.cs" /> <Compile Include="System\Threading\Tasks\TPLETWProvider.cs" /> + <Compile Include="..\..\Common\src\System\Runtime\CompilerServices\__BlockReflectionAttribute.cs" Condition="'$(IsProjectNLibrary)' != 'true'"> + <Link>System\Runtime\CompilerServices\__BlockReflectionAttribute.cs</Link> + </Compile> </ItemGroup> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> </Project> diff --git a/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj b/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj index c04db2716..7ff7bebc0 100644 --- a/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj +++ b/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj @@ -472,6 +472,9 @@ <Compile Include="..\..\Common\src\TypeSystem\NativeFormat\MetadataExtensions.cs"> <Link>NativeFormat\MetadataExtensions.cs</Link> </Compile> + <Compile Include="..\..\Common\src\System\Runtime\CompilerServices\__BlockReflectionAttribute.cs" Condition="'$(IsProjectNLibrary)' != 'true'"> + <Link>System\Runtime\CompilerServices\__BlockReflectionAttribute.cs</Link> + </Compile> </ItemGroup> <ItemGroup Condition="'$(METADATA_TYPE_LOADER)' != ''"> <Compile Include="..\..\Common\src\TypeSystem\NativeFormat\NativeFormatField.cs"> diff --git a/tests/src/Simple/PInvoke/PInvoke.cs b/tests/src/Simple/PInvoke/PInvoke.cs index e5b8f942f..fef465840 100644 --- a/tests/src/Simple/PInvoke/PInvoke.cs +++ b/tests/src/Simple/PInvoke/PInvoke.cs @@ -564,7 +564,7 @@ namespace PInvokeTests ssa[i].f1 = 0; ssa[i].f1 = i; ssa[i].f2 = i*i; - ssa[i].f3 = i.ToString(); + ssa[i].f3 = i.LowLevelToString(); } ThrowIfNotEquals(true, StructTest_Array(ssa, ssa.Length), "Array of struct marshalling failed"); @@ -640,4 +640,35 @@ namespace PInvokeTests } } //end of SafeMemoryHandle class + public static class LowLevelExtensions + { + // Int32.ToString() calls into glob/loc garbage that hits CppCodegen limitations + public static string LowLevelToString(this int i) + { + char[] digits = new char[11]; + int numDigits = 0; + + if (i == int.MinValue) + return "-2147483648"; + + bool negative = i < 0; + if (negative) + i = -i; + + do + { + digits[numDigits] = (char)('0' + (i % 10)); + numDigits++; + i /= 10; + } + while (i != 0); + if (negative) + { + digits[numDigits] = '-'; + numDigits++; + } + Array.Reverse(digits); + return new string(digits, digits.Length - numDigits, numDigits); + } + } } |