From ad72065e4a0f6cc8b14cf48052109aa4d9e0a14d Mon Sep 17 00:00:00 2001 From: Mitchell Hwang <16830051+mdh1418@users.noreply.github.com> Date: Fri, 30 Jul 2021 16:16:35 -0400 Subject: [PATCH 01/64] =?UTF-8?q?[libraries][iOS][tvOS]=20Skip=20Roundtrip?= =?UTF-8?q?EmptyArray=20on=20older=20tvOS=20iOS=20ver=E2=80=A6=20(#56583)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [libraries][iOS][tvOS] Skip RoundtripEmptyArray on older tvOS iOS versions * Address feedback * Use OperatingSystem API directly Co-authored-by: Mitchell Hwang --- .../AlgorithmImplementations/RSA/EncryptDecrypt.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs index 80fbbace5b58a9..85fb5c7691a9e4 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Test.Cryptography; +using Microsoft.DotNet.XUnitExtensions; using Xunit; namespace System.Security.Cryptography.Rsa.Tests @@ -336,11 +337,19 @@ private void RsaCryptRoundtrip(RSAEncryptionPadding paddingMode, bool expectSucc Assert.Equal(TestData.HelloBytes, output); } - [Fact] + [ConditionalFact] [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/52199", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void RoundtripEmptyArray() { + if (OperatingSystem.IsIOS() && !OperatingSystem.IsIOSVersionAtLeast(13, 6)) + { + throw new SkipTestException("iOS prior to 13.6 does not reliably support RSA encryption of empty data."); + } + if (OperatingSystem.IsTvOS() && !OperatingSystem.IsTvOSVersionAtLeast(14, 0)) + { + throw new SkipTestException("tvOS prior to 14.0 does not reliably support RSA encryption of empty data."); + } + using (RSA rsa = RSAFactory.Create(TestData.RSA2048Params)) { void RoundtripEmpty(RSAEncryptionPadding paddingMode) From 26572970a7fc7959c7413a6d0c90f8123ffddc3b Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Fri, 30 Jul 2021 23:17:43 +0300 Subject: [PATCH 02/64] Fix crossgen2 build on Tizen (#55789) --- Directory.Build.props | 13 +++++++++---- src/coreclr/tools/aot/crossgen2/crossgen2.csproj | 6 +----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 88779ccdac0290..2e8a20b3a0eb83 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -139,6 +139,10 @@ <_runtimeOS Condition="$(_runtimeOS.StartsWith('tizen'))">linux <_runtimeOS Condition="'$(PortableBuild)' == 'true'">$(_portableOS) + + <_packageOS Condition="'$(CrossBuild)' == 'true'">$(_hostOS.ToLowerInvariant) + <_packageOS Condition="'$(_packageOS)' == '' and '$(PortableBuild)' == 'true'">$(_portableOS) + <_packageOS Condition="'$(_packageOS)' == ''">$(_runtimeOS) @@ -163,10 +167,11 @@ linux-$(_hostArch) $(_toolRuntimeRID) - <_packageRID Condition="'$(PortableBuild)' == 'true'">$(_portableOS)-$(TargetArchitecture) - <_packageRID Condition="'$(CrossBuild)' == 'true'">$(_hostOS.ToLowerInvariant)-$(TargetArchitecture) - $(_packageRID) - $(_runtimeOS)-$(TargetArchitecture) + $(_packageOS)-$(TargetArchitecture) + + + $(_packageOS)-arm + $(PackageRID) $(PackageRID) $(_portableOS)-$(TargetArchitecture) diff --git a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj index 4b1fc1af499083..7959568995ac49 100644 --- a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj +++ b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj @@ -3,11 +3,7 @@ $(RuntimeBinDir)/crossgen2 true - - $(TargetArchitecture) - arm - - $(PackageRID) + $(Crossgen2PackageRID) From 45005830255a78caab66cef1757dcb77536f4c0d Mon Sep 17 00:00:00 2001 From: Andy Gocke Date: Fri, 30 Jul 2021 13:20:57 -0700 Subject: [PATCH 03/64] Add RequiresAssemblyFiles attribute (#56196) This PR annotates every API doc'd as having different behavior in single-file publishing with RequiresAssemblyFiles. Some APIs might be special-cased by the analyzer to produce special messages, but RAF is useful for visual inspection of the APIs. Module.Name and .FullyQualifiedName were also unannotated. --- .../System/Reflection/Emit/AssemblyBuilder.cs | 4 +- .../System/Reflection/Emit/ModuleBuilder.cs | 2 + .../src/System/Reflection/RuntimeAssembly.cs | 4 +- .../src/System/Reflection/RuntimeModule.cs | 5 ++- .../ComponentModel/LicFileLicenseProvider.cs | 44 +++++++++++-------- .../System/Configuration/ClientConfigPaths.cs | 4 ++ .../src/System/Reflection/Assembly.cs | 10 +++-- .../System/Reflection/Emit/AssemblyBuilder.cs | 4 +- .../src/System/Reflection/Module.cs | 4 ++ .../Context/Delegation/DelegatingModule.cs | 9 ++++ .../ref/System.Reflection.Emit.cs | 2 + .../Ecma/EcmaAssembly.ManifestResources.cs | 3 ++ .../Assemblies/RoAssembly.Modules.cs | 7 +++ .../TypeLoading/Assemblies/RoAssembly.cs | 6 ++- .../Modules/Ecma/EcmaModule.GetTypeCore.cs | 3 ++ .../TypeLoading/Modules/RoModule.cs | 11 ++++- .../TypeLoading/Modules/RoResourceModule.cs | 4 ++ .../src/Tests/Module/MultiModuleTests.cs | 4 +- .../System.Runtime/ref/System.Runtime.cs | 10 +++-- .../Reflection/Emit/ModuleBuilder.Mono.cs | 4 +- .../src/System/Reflection/RuntimeAssembly.cs | 4 +- .../src/System/Reflection/RuntimeModule.cs | 19 +++++--- 22 files changed, 126 insertions(+), 41 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs index 6f34f7dcef5f42..0914c0ca7600c2 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs @@ -77,11 +77,13 @@ public override string[] GetManifestResourceNames() throw new NotSupportedException(SR.NotSupported_DynamicAssembly); } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream GetFile(string name) { throw new NotSupportedException(SR.NotSupported_DynamicAssembly); } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream[] GetFiles(bool getResourceModules) { throw new NotSupportedException(SR.NotSupported_DynamicAssembly); @@ -104,7 +106,7 @@ public override FileStream[] GetFiles(bool getResourceModules) public override string Location => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override string? CodeBase => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); [RequiresUnreferencedCode("Types might be removed")] diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs index c1c243b8d02306..230bb06bd810ed 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs @@ -706,6 +706,7 @@ internal Type[] GetTypesNoLock() return GetType(parameters, baseType); } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string FullyQualifiedName => _moduleData._moduleName; [RequiresUnreferencedCode("Trimming changes metadata tokens")] @@ -785,6 +786,7 @@ public override MethodInfo[] GetMethods(BindingFlags bindingFlags) public override string ScopeName => InternalModule.ScopeName; + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string Name => InternalModule.Name; public override Assembly Assembly => _assemblyBuilder; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index cb7bd41495f6dc..5a5fd3e8b129f0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -83,7 +83,7 @@ private static extern bool GetCodeBase(QCallAssembly assembly, return null; } - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override string? CodeBase { get @@ -372,6 +372,7 @@ private static extern void InternalLoad(ObjectHandleOnStack assemblyName, // Returns the file in the File table of the manifest that matches the // given name. (Name should not include path.) + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream? GetFile(string name) { if (Location.Length == 0) @@ -389,6 +390,7 @@ private static extern void InternalLoad(ObjectHandleOnStack assemblyName, FileAccess.Read, FileShare.Read, FileStream.DefaultBufferSize, false); } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream[] GetFiles(bool getResourceModules) { if (Location.Length == 0) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs index a85a2226265b88..a5aad806bf07fa 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs @@ -441,6 +441,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont return retType; } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] internal string GetFullyQualifiedName() { string? fullyQualifiedName = null; @@ -449,9 +450,10 @@ internal string GetFullyQualifiedName() return fullyQualifiedName!; } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string FullyQualifiedName => GetFullyQualifiedName(); - [RequiresUnreferencedCode("Types might be removed")] + [RequiresUnreferencedCode("Types might be removed")] public override Type[] GetTypes() { return GetTypes(this); @@ -518,6 +520,7 @@ public override string ScopeName } } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string Name { get diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs index cd420c931a90ff..e5ce14bcb1d31a 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs @@ -3,6 +3,7 @@ using System.ComponentModel.Design; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; @@ -40,6 +41,10 @@ protected virtual string GetKey(Type type) /// /// Gets a license for the instance of the component and determines if it is valid. /// + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles", + Justification = "Only used for when Location is non-empty")] + [UnconditionalSuppressMessage("SingleFile", "IL3000:RequiresAssemblyFiles", + Justification = "Location is checked for empty")] public override License? GetLicense(LicenseContext context, Type type, object? instance, bool allowExceptions) { LicFileLicense? lic = null; @@ -69,30 +74,33 @@ protected virtual string GetKey(Type type) } } - if (modulePath == null) + if (type.Assembly.Location.Length != 0) { - modulePath = type.Module.FullyQualifiedName; - } + if (modulePath == null) + { + modulePath = type.Module.FullyQualifiedName; + } - string? moduleDir = Path.GetDirectoryName(modulePath); - string licenseFile = moduleDir + "\\" + type.FullName + ".lic"; + string? moduleDir = Path.GetDirectoryName(modulePath); + string licenseFile = moduleDir + "\\" + type.FullName + ".lic"; - Debug.WriteLine($"Looking for license in: {licenseFile}"); - if (File.Exists(licenseFile)) - { - Stream licStream = new FileStream(licenseFile, FileMode.Open, FileAccess.Read, FileShare.Read); - StreamReader sr = new StreamReader(licStream); - string? s = sr.ReadLine(); - sr.Close(); - if (IsKeyValid(s, type)) + Debug.WriteLine($"Looking for license in: {licenseFile}"); + if (File.Exists(licenseFile)) { - lic = new LicFileLicense(this, GetKey(type)); + Stream licStream = new FileStream(licenseFile, FileMode.Open, FileAccess.Read, FileShare.Read); + StreamReader sr = new StreamReader(licStream); + string? s = sr.ReadLine(); + sr.Close(); + if (IsKeyValid(s, type)) + { + lic = new LicFileLicense(this, GetKey(type)); + } } - } - if (lic != null) - { - context!.SetSavedLicenseKey(type, lic.LicenseKey); + if (lic != null) + { + context!.SetSavedLicenseKey(type, lic.LicenseKey); + } } } } diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs index a92612ca0b0f4f..747815c9f6ce9a 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs @@ -31,6 +31,8 @@ internal sealed class ClientConfigPaths [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Code handles single file case")] + [UnconditionalSuppressMessage("SingleFile", "IL3002: RequiresAssemblyFiles on Module.Name", + Justification = "Code handles single file case")] private ClientConfigPaths(string exePath, bool includeUserConfig) { _includesUserConfig = includeUserConfig; @@ -222,6 +224,8 @@ private static string CombineIfValid(string path1, string path2) // The evidence we use, in priority order, is Strong Name, Url and Exe Path. If one of // these is found, we compute a SHA1 hash of it and return a suffix based on that. // If none is found, we return null. + [UnconditionalSuppressMessage("SingleFile", "IL3002: RequiresAssemblyFiles on Module.Name", + Justification = "Code handles single file case")] private static string GetTypeAndHashSuffix(string exePath, bool isSingleFile) { Assembly assembly = Assembly.GetEntryAssembly(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs index 5b5035b2720620..3612e751aee285 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs @@ -81,7 +81,9 @@ public virtual IEnumerable ExportedTypes [RequiresUnreferencedCode("Types might be removed")] public virtual Type[] GetForwardedTypes() { throw NotImplemented.ByDesign; } - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + internal const string ThrowingMessageInRAF = "This member throws an exception for assemblies embedded in a single-file app"; + + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual string? CodeBase => throw NotImplemented.ByDesign; public virtual MethodInfo? EntryPoint => throw NotImplemented.ByDesign; public virtual string? FullName => throw NotImplemented.ByDesign; @@ -116,7 +118,7 @@ public virtual IEnumerable ExportedTypes public virtual object[] GetCustomAttributes(bool inherit) { throw NotImplemented.ByDesign; } public virtual object[] GetCustomAttributes(Type attributeType, bool inherit) { throw NotImplemented.ByDesign; } - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual string EscapedCodeBase => AssemblyName.EscapeCodeBase(CodeBase); [RequiresUnreferencedCode("Assembly.CreateInstance is not supported with trimming. Use Type.GetType instead.")] @@ -153,9 +155,11 @@ public virtual IEnumerable ExportedTypes public virtual Assembly GetSatelliteAssembly(CultureInfo culture) { throw NotImplemented.ByDesign; } public virtual Assembly GetSatelliteAssembly(CultureInfo culture, Version? version) { throw NotImplemented.ByDesign; } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual FileStream? GetFile(string name) { throw NotImplemented.ByDesign; } - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual FileStream[] GetFiles() => GetFiles(getResourceModules: false); + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual FileStream[] GetFiles(bool getResourceModules) { throw NotImplemented.ByDesign; } public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { throw NotImplemented.ByDesign; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs index dc77c941297f39..631b6ea927eded 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs @@ -8,7 +8,7 @@ namespace System.Reflection.Emit { public sealed partial class AssemblyBuilder : Assembly { - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override string? CodeBase => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); public override string Location => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); public override MethodInfo? EntryPoint => null; @@ -18,9 +18,11 @@ public sealed partial class AssemblyBuilder : Assembly public override Type[] GetExportedTypes() => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream GetFile(string name) => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream[] GetFiles(bool getResourceModules) => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs index 4fe3b9ad74747a..fc762fee949775 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs @@ -13,7 +13,11 @@ public abstract partial class Module : ICustomAttributeProvider, ISerializable protected Module() { } public virtual Assembly Assembly => throw NotImplemented.ByDesign; + + internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public virtual string FullyQualifiedName => throw NotImplemented.ByDesign; + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public virtual string Name => throw NotImplemented.ByDesign; public virtual int MDStreamVersion => throw NotImplemented.ByDesign; diff --git a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs index c1f11fcc4ba1ef..0c34b67b4cf4ee 100644 --- a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs +++ b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.Context.Delegation { @@ -22,6 +23,11 @@ public override Assembly Assembly get { return UnderlyingModule.Assembly; } } + internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; + +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] +#endif public override string FullyQualifiedName { get { return UnderlyingModule.FullyQualifiedName; } @@ -42,6 +48,9 @@ public override Guid ModuleVersionId get { return UnderlyingModule.ModuleVersionId; } } +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] +#endif public override string Name { get { return UnderlyingModule.Name; } diff --git a/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs b/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs index e823c6a25c3c0e..cbbcaa28059a5d 100644 --- a/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs +++ b/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs @@ -29,7 +29,9 @@ internal AssemblyBuilder() { } public System.Reflection.Emit.ModuleBuilder? GetDynamicModule(string name) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] public override System.Type[] GetExportedTypes() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public override System.IO.FileStream GetFile(string name) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public override System.IO.FileStream[] GetFiles(bool getResourceModules) { throw null; } public override int GetHashCode() { throw null; } public override System.Reflection.Module[] GetLoadedModules(bool getResourceModules) { throw null; } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs index 976d002039ae27..fea1363738dbb7 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.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.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection.Metadata; @@ -51,6 +52,8 @@ public sealed override string[] GetManifestResourceNames() return resourceNames; } + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles on Module.GetFile", + Justification = "ResourceLocation should never be ContainedInAnotherAssembly if embedded in a single-file")] public sealed override Stream? GetManifestResourceStream(string name) { if (name == null) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs index fe92aa504f05ac..d141c710af2e84 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs @@ -4,6 +4,7 @@ using System.IO; using System.Threading; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Collections.Generic; namespace System.Reflection.TypeLoading @@ -16,6 +17,9 @@ internal abstract partial class RoAssembly public sealed override Module? GetModule(string name) => GetRoModule(name); public sealed override Module[] GetModules(bool getResourceModules) => ComputeRoModules(getResourceModules).CloneArray(); +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(ThrowingMessageInRAF)] +#endif public sealed override FileStream? GetFile(string name) { Module? m = GetModule(name); @@ -24,6 +28,9 @@ internal abstract partial class RoAssembly return new FileStream(m.FullyQualifiedName, FileMode.Open, FileAccess.Read, FileShare.Read); } +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(ThrowingMessageInRAF)] +#endif public sealed override FileStream[] GetFiles(bool getResourceModules) { Module[] m = GetModules(getResourceModules); diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs index 114f581d06954a..4d48000d787252 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs @@ -40,16 +40,18 @@ protected RoAssembly(MetadataLoadContext loader, int assemblyFileCount) public sealed override string FullName => _lazyFullName ?? (_lazyFullName = GetName().FullName); private volatile string? _lazyFullName; + internal const string ThrowingMessageInRAF = "This member throws an exception for assemblies embedded in a single-file app"; + // Location and codebase public abstract override string Location { get; } #if NET5_0_OR_GREATER [Obsolete(Obsoletions.CodeBaseMessage, DiagnosticId = Obsoletions.CodeBaseDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override string CodeBase => throw new NotSupportedException(SR.NotSupported_AssemblyCodeBase); #if NET5_0_OR_GREATER [Obsolete(Obsoletions.CodeBaseMessage, DiagnosticId = Obsoletions.CodeBaseDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override string EscapedCodeBase => throw new NotSupportedException(SR.NotSupported_AssemblyCodeBase); diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.GetTypeCore.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.GetTypeCore.cs index 78f4d92757b4ae..cba523452ffdb9 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.GetTypeCore.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.GetTypeCore.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.Diagnostics.CodeAnalysis; using System.Reflection.Metadata; namespace System.Reflection.TypeLoading.Ecma @@ -16,6 +17,8 @@ internal sealed partial class EcmaModule /// If a type is not contained or forwarded from the assembly, this method returns null (does not throw.) /// This supports the "throwOnError: false" behavior of Module.GetType(string, bool). /// + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles on FullyQualifiedName", + Justification = "FullyQualifiedName is only used for exception message")] protected sealed override RoDefinitionType? GetTypeCoreNoCache(ReadOnlySpan ns, ReadOnlySpan name, out Exception? e) { MetadataReader reader = Reader; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs index e9727f2db0bbae..4ddd4427edbb13 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.Serialization; @@ -15,7 +16,7 @@ internal abstract partial class RoModule : Module { private readonly string _fullyQualifiedName; - internal const string FullyQualifiedNameForModulesLoadedFromByteArrays = ""; + internal const string FullyQualifiedNameForModulesLoadedFromByteArrays = ""; internal RoModule(string fullyQualifiedName) : base() @@ -30,11 +31,19 @@ internal RoModule(string fullyQualifiedName) public sealed override Assembly Assembly => GetRoAssembly(); internal abstract RoAssembly GetRoAssembly(); + internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; + +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] +#endif public sealed override string FullyQualifiedName => _fullyQualifiedName; public abstract override int MDStreamVersion { get; } public abstract override int MetadataToken { get; } public abstract override Guid ModuleVersionId { get; } +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] +#endif public sealed override string Name { get diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoResourceModule.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoResourceModule.cs index 9bff8aba7a8f19..7e2adb511c662c 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoResourceModule.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoResourceModule.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.TypeLoading { @@ -30,6 +31,9 @@ internal RoResourceModule(RoAssembly assembly, string fullyQualifiedName) public sealed override int MDStreamVersion => throw new InvalidOperationException(SR.ResourceOnlyModule); public sealed override int MetadataToken => 0x00000000; public sealed override Guid ModuleVersionId => throw new InvalidOperationException(SR.ResourceOnlyModule); + + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles on Name", + Justification = "https://github.com/dotnet/runtime/issues/56519")] public sealed override string ScopeName => Name; public sealed override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine) { diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Module/MultiModuleTests.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Module/MultiModuleTests.cs index 578d04f8d51b5d..569cc33aa70319 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Module/MultiModuleTests.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Module/MultiModuleTests.cs @@ -234,8 +234,8 @@ public static void LoadModule(string moduleName) Assert.Equal(m, m1); Assert.Equal(a, m.Assembly); - Assert.Equal("", m.FullyQualifiedName); - Assert.Equal("", m.Name); + Assert.Equal("", m.FullyQualifiedName); + Assert.Equal("", m.Name); Assert.Equal("Joe.netmodule", m.ScopeName); Assert.Equal(TestData.s_JoeNetModuleMvid, m.ModuleVersionId); } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index a94b40b28eec0a..380e0a2e7f1009 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -11060,13 +11060,13 @@ public abstract partial class Assembly : System.Reflection.ICustomAttributeProvi { protected Assembly() { } [System.ObsoleteAttribute("Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("The code will throw for assemblies embedded in a single-file app")] + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual string? CodeBase { get { throw null; } } public virtual System.Collections.Generic.IEnumerable CustomAttributes { get { throw null; } } public virtual System.Collections.Generic.IEnumerable DefinedTypes { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] get { throw null; } } public virtual System.Reflection.MethodInfo? EntryPoint { get { throw null; } } [System.ObsoleteAttribute("Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("The code will throw for assemblies embedded in a single-file app")] + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual string EscapedCodeBase { get { throw null; } } public virtual System.Collections.Generic.IEnumerable ExportedTypes { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] get { throw null; } } public virtual string? FullName { get { throw null; } } @@ -11100,9 +11100,11 @@ public virtual event System.Reflection.ModuleResolveEventHandler? ModuleResolve public static System.Reflection.Assembly GetExecutingAssembly() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] public virtual System.Type[] GetExportedTypes() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual System.IO.FileStream? GetFile(string name) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual System.IO.FileStream[] GetFiles() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual System.IO.FileStream[] GetFiles(bool getResourceModules) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] public virtual System.Type[] GetForwardedTypes() { throw null; } @@ -11867,11 +11869,13 @@ public abstract partial class Module : System.Reflection.ICustomAttributeProvide protected Module() { } public virtual System.Reflection.Assembly Assembly { get { throw null; } } public virtual System.Collections.Generic.IEnumerable CustomAttributes { get { throw null; } } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("Returns for modules with no file path")] public virtual string FullyQualifiedName { get { throw null; } } public virtual int MDStreamVersion { get { throw null; } } public virtual int MetadataToken { get { throw null; } } public System.ModuleHandle ModuleHandle { get { throw null; } } public virtual System.Guid ModuleVersionId { get { throw null; } } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("Returns for modules with no file path")] public virtual string Name { get { throw null; } } public virtual string ScopeName { get { throw null; } } public override bool Equals(object? o) { throw null; } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs index 86ba437fa10287..427767a5fbc5d0 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs @@ -106,6 +106,7 @@ internal ModuleBuilder(AssemblyBuilder assb, string name, bool emitSymbolInfo) set_wrappers_type(this, type); } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string FullyQualifiedName { get @@ -816,6 +817,7 @@ public override Assembly Assembly get { return assemblyb; } } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string Name { get { return name; } @@ -874,7 +876,7 @@ internal MemberInfo ResolveOrGetRegisteredToken(int metadataToken, Type[] generi m = GetRegisteredToken(metadataToken) as MemberInfo; if (m == null) - throw RuntimeModule.resolve_token_exception(Name, metadataToken, error, "MemberInfo"); + throw RuntimeModule.resolve_token_exception(this, metadataToken, error, "MemberInfo"); else return m; } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index d5fa9e4e31d83b..95aed378b17070 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -74,7 +74,7 @@ public extern override MethodInfo? EntryPoint public override bool ReflectionOnly => false; - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override string? CodeBase { get @@ -410,6 +410,7 @@ public override Assembly GetSatelliteAssembly(CultureInfo culture, Version? vers return res; } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream? GetFile(string name) { if (name == null) @@ -430,6 +431,7 @@ public override Assembly GetSatelliteAssembly(CultureInfo culture, Version? vers return null; } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream[] GetFiles(bool getResourceModules) { if (Location.Length == 0) diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs index 692d7ff29926c9..9b92b126780d82 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs @@ -56,6 +56,7 @@ Assembly Assembly get { return assembly; } } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override // Note: we do not ask for PathDiscovery because no path is returned here. @@ -94,6 +95,7 @@ Guid ModuleVersionId } } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string FullyQualifiedName { @@ -232,7 +234,7 @@ internal static FieldInfo ResolveField(Module module, IntPtr monoModule, int met IntPtr handle = ResolveFieldToken(monoModule, metadataToken, ptrs_from_types(genericTypeArguments), ptrs_from_types(genericMethodArguments), out error); if (handle == IntPtr.Zero) - throw resolve_token_exception(module.Name, metadataToken, error, "Field"); + throw resolve_token_exception(module, metadataToken, error, "Field"); else return FieldInfo.GetFieldFromHandle(new RuntimeFieldHandle(handle)); } @@ -251,7 +253,7 @@ internal static MemberInfo ResolveMember(Module module, IntPtr monoModule, int m MemberInfo m = ResolveMemberToken(monoModule, metadataToken, ptrs_from_types(genericTypeArguments), ptrs_from_types(genericMethodArguments), out error); if (m == null) - throw resolve_token_exception(module.Name, metadataToken, error, "MemberInfo"); + throw resolve_token_exception(module, metadataToken, error, "MemberInfo"); else return m; } @@ -270,7 +272,7 @@ internal static MethodBase ResolveMethod(Module module, IntPtr monoModule, int m IntPtr handle = ResolveMethodToken(monoModule, metadataToken, ptrs_from_types(genericTypeArguments), ptrs_from_types(genericMethodArguments), out error); if (handle == IntPtr.Zero) - throw resolve_token_exception(module.Name, metadataToken, error, "MethodBase"); + throw resolve_token_exception(module, metadataToken, error, "MethodBase"); else return RuntimeMethodInfo.GetMethodFromHandleNoGenericCheck(new RuntimeMethodHandle(handle)); } @@ -289,7 +291,7 @@ internal static string ResolveString(Module module, IntPtr monoModule, int metad string s = ResolveStringToken(monoModule, metadataToken, out error); if (s == null) - throw resolve_token_exception(module.Name, metadataToken, error, "string"); + throw resolve_token_exception(module, metadataToken, error, "string"); else return s; } @@ -308,7 +310,7 @@ internal static Type ResolveType(Module module, IntPtr monoModule, int metadataT IntPtr handle = ResolveTypeToken(monoModule, metadataToken, ptrs_from_types(genericTypeArguments), ptrs_from_types(genericMethodArguments), out error); if (handle == IntPtr.Zero) - throw resolve_token_exception(module.Name, metadataToken, error, "Type"); + throw resolve_token_exception(module, metadataToken, error, "Type"); else return Type.GetTypeFromHandle(new RuntimeTypeHandle(handle)); } @@ -327,7 +329,7 @@ internal static byte[] ResolveSignature(Module module, IntPtr monoModule, int me byte[] res = ResolveSignature(monoModule, metadataToken, out error); if (res == null) - throw resolve_token_exception(module.Name, metadataToken, error, "signature"); + throw resolve_token_exception(module, metadataToken, error, "signature"); else return res; } @@ -364,6 +366,11 @@ internal Guid GetModuleVersionId() return new Guid(guid); } + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles", + Justification = "Module Name is used only for diagnostic reporting message")] + internal static Exception resolve_token_exception(Module module, int metadataToken, ResolveTokenError error, string tokenType) + => resolve_token_exception(module.Name, metadataToken, error, tokenType); + internal static Exception resolve_token_exception(string name, int metadataToken, ResolveTokenError error, string tokenType) { if (error == ResolveTokenError.OutOfRange) From dcacebb9edba8f08f56679029982c7765101da15 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang <16830051+mdh1418@users.noreply.github.com> Date: Fri, 30 Jul 2021 17:17:27 -0400 Subject: [PATCH 04/64] [libraries][Android] Reenable tests failing from feature switches being improperly set (#56635) Fixes #50576 Fixes #50881 Fixes #50916 Fixes #50917 Fixes #50918 Fixes #50919 Fixes #50927 Fixes #50928 Fixes #50944 Fixes #50945 Fixes #50946 Fixes #50947 Fixes #50948 Fixes #50999 When setting up functional tests for mobile, the feature switches being used for the tests were misplaced in a broader project, affecting the library tests and causing failures. After moving the feature switches to the scope of functional tests as done in #53253, these test suites no longer fail and can be re-enabled. --- .../tests/BlockingCollectionCancellationTests.cs | 1 - .../ComponentModel/CategoryAttributeTests.cs | 5 ----- .../InvalidEnumArgumentExceptionTests.cs | 1 - .../Hosting/Core/CompositionDependencyTests.cs | 1 - .../Hosting/Core/ExportDescriptorPromiseTests.cs | 1 - .../Hosting/Core/CompositionContractTests.cs | 1 - .../System.Composition/tests/CardinalityTests.cs | 2 -- .../System.Composition/tests/ContractTests.cs | 1 - .../System.Composition/tests/DiscoveryTests.cs | 3 --- .../tests/ErrorMessageQualityTests.cs | 5 ----- .../tests/MetadataViewGenerationTests.cs | 2 -- .../System.Composition/tests/OpenGenericsTests.cs | 2 -- .../System.Composition/tests/SharingTests.cs | 1 - .../tests/FlushAsyncCompletionTests.cs | 1 - .../System.IO.Pipelines/tests/FlushAsyncTests.cs | 1 - .../tests/PipeReaderWriterFacts.cs | 3 --- .../tests/ReadAsyncCompletionTests.cs | 1 - .../tests/Functional/LoggingTest.cs | 1 - .../tests/Functional/SmtpExceptionTest.cs | 2 -- .../tests/FunctionalTests/LoggingTest.cs | 4 ---- .../tests/FunctionalTests/TelemetryTest.cs | 1 - .../tests/xNodeBuilder/CommonTests.cs | 3 --- .../tests/XmlReader/Tests/ReaderEncodingTests.cs | 7 ------- src/libraries/tests.proj | 15 --------------- 24 files changed, 65 deletions(-) diff --git a/src/libraries/System.Collections.Concurrent/tests/BlockingCollectionCancellationTests.cs b/src/libraries/System.Collections.Concurrent/tests/BlockingCollectionCancellationTests.cs index a3d366927137d7..14fa6d8d487467 100644 --- a/src/libraries/System.Collections.Concurrent/tests/BlockingCollectionCancellationTests.cs +++ b/src/libraries/System.Collections.Concurrent/tests/BlockingCollectionCancellationTests.cs @@ -97,7 +97,6 @@ public static void ExternalCancel_Negative() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50576", TestPlatforms.Android)] public static void ExternalCancel_AddToAny() { for (int test = 0; test < 3; test++) diff --git a/src/libraries/System.ComponentModel.Primitives/tests/System/ComponentModel/CategoryAttributeTests.cs b/src/libraries/System.ComponentModel.Primitives/tests/System/ComponentModel/CategoryAttributeTests.cs index a14dd422fbd684..5c87bba93b893f 100644 --- a/src/libraries/System.ComponentModel.Primitives/tests/System/ComponentModel/CategoryAttributeTests.cs +++ b/src/libraries/System.ComponentModel.Primitives/tests/System/ComponentModel/CategoryAttributeTests.cs @@ -9,7 +9,6 @@ namespace System.ComponentModel.Tests public class CategoryAttributeTests { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50881", TestPlatforms.Android)] public void Ctor_Default() { var attribute = new CategoryAttribute(); @@ -24,7 +23,6 @@ public void Ctor_Default() [InlineData("Misc", true)] [InlineData("misc", false)] [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, ".NET Framework throws a NullReferenceException")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50881", TestPlatforms.Android)] public void Ctor_String(string category, bool expectedIsDefaultAttribute) { var attribute = new CategoryAttribute(category); @@ -61,7 +59,6 @@ public static IEnumerable Equals_TestData() [Theory] [MemberData(nameof(Equals_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50881", TestPlatforms.Android)] public void Equals_Object_ReturnsExpected(CategoryAttribute attribute, object other, bool expected) { Assert.Equal(expected, attribute.Equals(other)); @@ -90,7 +87,6 @@ public static IEnumerable Properties_TestData() [Theory] [MemberData(nameof(Properties_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50881", TestPlatforms.Android)] public void Properties_Get_ReturnsExpected(Func attributeThunk, string expectedCategory) { CategoryAttribute attribute = attributeThunk(); @@ -129,7 +125,6 @@ public void GetLocalizedString_InvokeValueExists_ReturnsNonEmpty(string value) [InlineData(null)] [InlineData("")] [InlineData("value")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50881", TestPlatforms.Android)] public void GetLocalizedString_InvokeNoSuchValue_ReturnsNull(string value) { var attribute = new SubCategoryAttribute(); diff --git a/src/libraries/System.ComponentModel.Primitives/tests/System/ComponentModel/InvalidEnumArgumentExceptionTests.cs b/src/libraries/System.ComponentModel.Primitives/tests/System/ComponentModel/InvalidEnumArgumentExceptionTests.cs index a993c3f81d6765..4b6187edc248df 100644 --- a/src/libraries/System.ComponentModel.Primitives/tests/System/ComponentModel/InvalidEnumArgumentExceptionTests.cs +++ b/src/libraries/System.ComponentModel.Primitives/tests/System/ComponentModel/InvalidEnumArgumentExceptionTests.cs @@ -88,7 +88,6 @@ public void Ctor_NullEnumClass_ThrowsArgumentNulException() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBinaryFormatterSupported))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50881", TestPlatforms.Android)] public void Ctor_SerializationInfo_StreamingContext() { using (var stream = new MemoryStream()) diff --git a/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/CompositionDependencyTests.cs b/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/CompositionDependencyTests.cs index cfa0fc3fc2708a..eb9fb2192704d8 100644 --- a/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/CompositionDependencyTests.cs +++ b/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/CompositionDependencyTests.cs @@ -37,7 +37,6 @@ public void Missing_NullSite_ThrowsArgumentNullException() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50917", TestPlatforms.Android)] public void Satisfied_Invoke_ReturnsExpected() { var contract = new CompositionContract(typeof(int)); diff --git a/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/ExportDescriptorPromiseTests.cs b/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/ExportDescriptorPromiseTests.cs index 2883082f94a70d..082eca388e478d 100644 --- a/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/ExportDescriptorPromiseTests.cs +++ b/src/libraries/System.Composition.Hosting/tests/System/Composition/Hosting/Core/ExportDescriptorPromiseTests.cs @@ -252,7 +252,6 @@ public void GetDescriptor_CycleMetadataBroken_HasExpectedProperties() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50917", TestPlatforms.Android)] public void ToString_Invoke_ReturnsExpected() { var promise = new ExportDescriptorPromise(new CompositionContract(typeof(int)), "Origin", true, () => Enumerable.Empty(), depdendencies => diff --git a/src/libraries/System.Composition.Runtime/tests/System/Composition/Hosting/Core/CompositionContractTests.cs b/src/libraries/System.Composition.Runtime/tests/System/Composition/Hosting/Core/CompositionContractTests.cs index 04088a747177c8..7784bad7ba48f3 100644 --- a/src/libraries/System.Composition.Runtime/tests/System/Composition/Hosting/Core/CompositionContractTests.cs +++ b/src/libraries/System.Composition.Runtime/tests/System/Composition/Hosting/Core/CompositionContractTests.cs @@ -279,7 +279,6 @@ public static IEnumerable ToString_TestData() [Theory] [MemberData(nameof(ToString_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50918", TestPlatforms.Android)] public void ToString_Get_ReturnsExpected(CompositionContract contract, string expected) { Assert.Equal(expected, contract.ToString()); diff --git a/src/libraries/System.Composition/tests/CardinalityTests.cs b/src/libraries/System.Composition/tests/CardinalityTests.cs index 87723ebf69acb7..149287cfa8721d 100644 --- a/src/libraries/System.Composition/tests/CardinalityTests.cs +++ b/src/libraries/System.Composition/tests/CardinalityTests.cs @@ -31,7 +31,6 @@ public UsesLog(ILog log) { } } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void RequestingOneWhereMultipleArePresentFails() { var c = CreateContainer(typeof(LogA), typeof(LogB)); @@ -42,7 +41,6 @@ public void RequestingOneWhereMultipleArePresentFails() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void ImportingOneWhereMultipleArePresentFails() { var c = CreateContainer(typeof(LogA), typeof(LogB), typeof(UsesLog)); diff --git a/src/libraries/System.Composition/tests/ContractTests.cs b/src/libraries/System.Composition/tests/ContractTests.cs index b0c3fbc46f6318..746cd56641f372 100644 --- a/src/libraries/System.Composition/tests/ContractTests.cs +++ b/src/libraries/System.Composition/tests/ContractTests.cs @@ -67,7 +67,6 @@ public void ConstraintsWithEquivalentKeysAndValuesHaveTheSameHashCode() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void FormattingTheContractPrintsConstraintKeysAndValues() { var mcd = new CompositionContract(typeof(AType), null, new Dictionary { { "A", 1 }, { "B", "C" } }); diff --git a/src/libraries/System.Composition/tests/DiscoveryTests.cs b/src/libraries/System.Composition/tests/DiscoveryTests.cs index 8087e3d9384365..833001774e4e0b 100644 --- a/src/libraries/System.Composition/tests/DiscoveryTests.cs +++ b/src/libraries/System.Composition/tests/DiscoveryTests.cs @@ -56,7 +56,6 @@ public void DiscoversCustomExportAttributesUnderConventions() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void InstanceExportsOfIncompatibleContractsAreDetected() { var x = Assert.Throws(() => CreateContainer(typeof(IncompatibleRule))); @@ -64,7 +63,6 @@ public void InstanceExportsOfIncompatibleContractsAreDetected() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void PropertyExportsOfIncompatibleContractsAreDetected() { var x = Assert.Throws(() => CreateContainer(typeof(IncompatibleRuleProperty))); @@ -124,7 +122,6 @@ public class MultipleImportsOnProperty } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void MultipleImportAttributesAreDetected() { var c = new ContainerConfiguration() diff --git a/src/libraries/System.Composition/tests/ErrorMessageQualityTests.cs b/src/libraries/System.Composition/tests/ErrorMessageQualityTests.cs index f53e79612eb10d..f0918e392c29c3 100644 --- a/src/libraries/System.Composition/tests/ErrorMessageQualityTests.cs +++ b/src/libraries/System.Composition/tests/ErrorMessageQualityTests.cs @@ -63,7 +63,6 @@ public class RequiresOnlyOne } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void MissingTopLevelExportMessageIsInformative() { var cc = CreateContainer(); @@ -72,7 +71,6 @@ public void MissingTopLevelExportMessageIsInformative() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void MissingTopLevelNamedExportMessageIsInformative() { var cc = CreateContainer(); @@ -81,7 +79,6 @@ public void MissingTopLevelNamedExportMessageIsInformative() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void MissingDependencyMessageIsInformative() { var cc = CreateContainer(typeof(UserOfUnregistered)); @@ -92,7 +89,6 @@ public void MissingDependencyMessageIsInformative() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void CycleMessageIsInformative() { var cc = CreateContainer(typeof(CycleA), typeof(CycleB), typeof(CycleC)); @@ -106,7 +102,6 @@ public void CycleMessageIsInformative() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void CardinalityViolationMessageIsInformative() { var cc = CreateContainer(typeof(ShouldBeOne), typeof(ButThereIsAnother), typeof(RequiresOnlyOne)); diff --git a/src/libraries/System.Composition/tests/MetadataViewGenerationTests.cs b/src/libraries/System.Composition/tests/MetadataViewGenerationTests.cs index e2561e916ee054..9786a7db1ae4fc 100644 --- a/src/libraries/System.Composition/tests/MetadataViewGenerationTests.cs +++ b/src/libraries/System.Composition/tests/MetadataViewGenerationTests.cs @@ -77,7 +77,6 @@ public InvalidConcreteView(string unsupported) { } } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void AConcreteTypeWithUnsupportedConstructorsCannotBeUsedAsAMetadataView() { var cc = new ContainerConfiguration() @@ -102,7 +101,6 @@ public class ImportsWithMetadataInterface } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void UnsupportedMetadataViewMessageIsInformative() { var cc = new ContainerConfiguration().WithParts(typeof(ImportsWithMetadataInterface), typeof(ExportsWithMetadata)).CreateContainer(); diff --git a/src/libraries/System.Composition/tests/OpenGenericsTests.cs b/src/libraries/System.Composition/tests/OpenGenericsTests.cs index 8462c5aa6f67fc..a7eec57c15b096 100644 --- a/src/libraries/System.Composition/tests/OpenGenericsTests.cs +++ b/src/libraries/System.Composition/tests/OpenGenericsTests.cs @@ -123,7 +123,6 @@ public void MultipleGenericExportsCanBeSpecifiedAtTheClassLevel() // In future, the set of allowable generic type mappings will be expanded (see // ignored tests above). [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void TypesWithMismatchedGenericParameterListsAreDetectedDuringDiscovery() { var x = Assert.Throws(() => CreateContainer(typeof(RepositoryWithKey<,>))); @@ -131,7 +130,6 @@ public void TypesWithMismatchedGenericParameterListsAreDetectedDuringDiscovery() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void TypesWithNonGenericExportsAreDetectedDuringDiscovery() { var x = Assert.Throws(() => CreateContainer(typeof(RepositoryWithNonGenericExport<>))); diff --git a/src/libraries/System.Composition/tests/SharingTests.cs b/src/libraries/System.Composition/tests/SharingTests.cs index 22cd14fa417135..826881f349c5df 100644 --- a/src/libraries/System.Composition/tests/SharingTests.cs +++ b/src/libraries/System.Composition/tests/SharingTests.cs @@ -318,7 +318,6 @@ public class SharingTest : ContainerTests /// we fail only when we create instance of B.. is that correct. /// [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50919", TestPlatforms.Android)] public void BoundaryExposedBoundaryButNoneImported() { try diff --git a/src/libraries/System.IO.Pipelines/tests/FlushAsyncCompletionTests.cs b/src/libraries/System.IO.Pipelines/tests/FlushAsyncCompletionTests.cs index 6169d1e05684b2..5b56222f819e5f 100644 --- a/src/libraries/System.IO.Pipelines/tests/FlushAsyncCompletionTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/FlushAsyncCompletionTests.cs @@ -10,7 +10,6 @@ namespace System.IO.Pipelines.Tests public class FlushAsyncCompletionTests : PipeTest { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50927", TestPlatforms.Android)] public void AwaitingFlushAsyncAwaitableTwiceCompletesReaderWithException() { async Task Await(ValueTask a) diff --git a/src/libraries/System.IO.Pipelines/tests/FlushAsyncTests.cs b/src/libraries/System.IO.Pipelines/tests/FlushAsyncTests.cs index fa3db4c91ae4da..afa1f318937a4d 100644 --- a/src/libraries/System.IO.Pipelines/tests/FlushAsyncTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/FlushAsyncTests.cs @@ -71,7 +71,6 @@ public async Task CallingFlushAsyncMultipleTimesAllowsFirstToComplete() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50927", TestPlatforms.Android)] public async Task DoubleFlushAsyncThrows() { Pipe.Writer.WriteEmpty(65); diff --git a/src/libraries/System.IO.Pipelines/tests/PipeReaderWriterFacts.cs b/src/libraries/System.IO.Pipelines/tests/PipeReaderWriterFacts.cs index dc4593bfeb0db2..f4b41418a6afc4 100644 --- a/src/libraries/System.IO.Pipelines/tests/PipeReaderWriterFacts.cs +++ b/src/libraries/System.IO.Pipelines/tests/PipeReaderWriterFacts.cs @@ -150,7 +150,6 @@ public async Task CompleteReaderAfterFlushWithoutAdvancingDoesNotThrow() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50927", TestPlatforms.Android)] public async Task AdvanceAfterCompleteThrows() { await _pipe.Writer.WriteAsync(new byte[1]); @@ -621,7 +620,6 @@ public async Task WritingDataMakesDataReadableViaPipeline() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50927", TestPlatforms.Android)] public async Task DoubleAsyncReadThrows() { ValueTask readTask1 = _pipe.Reader.ReadAsync(); @@ -658,7 +656,6 @@ public async Task CompleteAfterAdvanceCommits() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50927", TestPlatforms.Android)] public async Task AdvanceWithoutReadThrows() { await _pipe.Writer.WriteAsync(new byte[3]); diff --git a/src/libraries/System.IO.Pipelines/tests/ReadAsyncCompletionTests.cs b/src/libraries/System.IO.Pipelines/tests/ReadAsyncCompletionTests.cs index 2abc58534071c0..f15da4024d67ec 100644 --- a/src/libraries/System.IO.Pipelines/tests/ReadAsyncCompletionTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/ReadAsyncCompletionTests.cs @@ -9,7 +9,6 @@ namespace System.IO.Pipelines.Tests public class ReadAsyncCompletionTests : PipeTest { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50927", TestPlatforms.Android)] public void AwaitingReadAsyncAwaitableTwiceCompletesWriterWithException() { async Task Await(ValueTask a) diff --git a/src/libraries/System.Net.Mail/tests/Functional/LoggingTest.cs b/src/libraries/System.Net.Mail/tests/Functional/LoggingTest.cs index 95f952e6635369..c4c9e801fd78c6 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/LoggingTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/LoggingTest.cs @@ -13,7 +13,6 @@ namespace System.Net.Mail.Tests public class LoggingTest { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50999", TestPlatforms.Android)] public void EventSource_ExistsWithCorrectId() { Type esType = typeof(SmtpClient).Assembly.GetType("System.Net.NetEventSource", throwOnError: true, ignoreCase: false); diff --git a/src/libraries/System.Net.Mail/tests/Functional/SmtpExceptionTest.cs b/src/libraries/System.Net.Mail/tests/Functional/SmtpExceptionTest.cs index a10bed3e1684f2..d97d147413cf7e 100644 --- a/src/libraries/System.Net.Mail/tests/Functional/SmtpExceptionTest.cs +++ b/src/libraries/System.Net.Mail/tests/Functional/SmtpExceptionTest.cs @@ -54,7 +54,6 @@ public void TestConstructorWithStatusCodeArgument() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50999", TestPlatforms.Android)] public void TestConstructorWithStringArgument() { string msg; @@ -92,7 +91,6 @@ public void TestConstructorWithStringArgument() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50999", TestPlatforms.Android)] public void TestConstructorWithStatusCodeAndStringArgument() { string msg; diff --git a/src/libraries/System.Net.NameResolution/tests/FunctionalTests/LoggingTest.cs b/src/libraries/System.Net.NameResolution/tests/FunctionalTests/LoggingTest.cs index e4d4fcc9aa6a4e..915067acffbbfc 100644 --- a/src/libraries/System.Net.NameResolution/tests/FunctionalTests/LoggingTest.cs +++ b/src/libraries/System.Net.NameResolution/tests/FunctionalTests/LoggingTest.cs @@ -17,7 +17,6 @@ namespace System.Net.NameResolution.Tests public class LoggingTest { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50928", TestPlatforms.Android)] public static void EventSource_ExistsWithCorrectId() { Type esType = typeof(Dns).Assembly.GetType("System.Net.NetEventSource", throwOnError: true, ignoreCase: false); @@ -30,7 +29,6 @@ public static void EventSource_ExistsWithCorrectId() } [ConditionalFact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50928", TestPlatforms.Android)] public void GetHostEntry_InvalidHost_LogsError() { using (var listener = new TestEventListener("Private.InternalDiagnostics.System.Net.NameResolution", EventLevel.Error)) @@ -65,7 +63,6 @@ public void GetHostEntry_InvalidHost_LogsError() } [ConditionalFact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50928", TestPlatforms.Android)] public async Task GetHostEntryAsync_InvalidHost_LogsError() { using (var listener = new TestEventListener("Private.InternalDiagnostics.System.Net.NameResolution", EventLevel.Error)) @@ -115,7 +112,6 @@ static async Task WaitForErrorEventAsync(ConcurrentQueue } [ConditionalFact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50928", TestPlatforms.Android)] public void GetHostEntry_ValidName_NoErrors() { using (var listener = new TestEventListener("Private.InternalDiagnostics.System.Net.NameResolution", EventLevel.Verbose)) diff --git a/src/libraries/System.Net.NameResolution/tests/FunctionalTests/TelemetryTest.cs b/src/libraries/System.Net.NameResolution/tests/FunctionalTests/TelemetryTest.cs index a3ee6418d903bd..55d0e3ac08f36f 100644 --- a/src/libraries/System.Net.NameResolution/tests/FunctionalTests/TelemetryTest.cs +++ b/src/libraries/System.Net.NameResolution/tests/FunctionalTests/TelemetryTest.cs @@ -17,7 +17,6 @@ namespace System.Net.NameResolution.Tests public class TelemetryTest { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50928", TestPlatforms.Android)] public static void EventSource_ExistsWithCorrectId() { Type esType = typeof(Dns).Assembly.GetType("System.Net.NameResolutionTelemetry", throwOnError: true, ignoreCase: false); diff --git a/src/libraries/System.Private.Xml.Linq/tests/xNodeBuilder/CommonTests.cs b/src/libraries/System.Private.Xml.Linq/tests/xNodeBuilder/CommonTests.cs index 86f73206626209..772f9b87ab9080 100644 --- a/src/libraries/System.Private.Xml.Linq/tests/xNodeBuilder/CommonTests.cs +++ b/src/libraries/System.Private.Xml.Linq/tests/xNodeBuilder/CommonTests.cs @@ -3403,7 +3403,6 @@ private void CData_4() //[Variation(Id = 5, Desc = "WriteCData with ]]>", Priority = 1)] [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50944", TestPlatforms.Android)] public void WriteCDataWithTwoClosingBrackets_5() { XDocument doc = new XDocument(); @@ -3599,7 +3598,6 @@ private void comment_5() //[Variation(Id = 6, Desc = "WriteComment with -- in value", Priority = 1)] [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50944", TestPlatforms.Android)] public void WriteCommentWithDoubleHyphensInValue() { XDocument doc = new XDocument(); @@ -4205,7 +4203,6 @@ private void pi_10() //[Variation(Id = 11, Desc = "Include PI end tag ?> as part of the text value", Priority = 1)] [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50944", TestPlatforms.Android)] public void IncludePIEndTagAsPartOfTextValue() { XDocument doc = new XDocument(); diff --git a/src/libraries/System.Private.Xml/tests/XmlReader/Tests/ReaderEncodingTests.cs b/src/libraries/System.Private.Xml/tests/XmlReader/Tests/ReaderEncodingTests.cs index c89b48447c37af..0c91c2b2e27b3e 100644 --- a/src/libraries/System.Private.Xml/tests/XmlReader/Tests/ReaderEncodingTests.cs +++ b/src/libraries/System.Private.Xml/tests/XmlReader/Tests/ReaderEncodingTests.cs @@ -17,7 +17,6 @@ public class ReaderEncodingTests private static string _invalidCharInThisEncoding = "Invalid character in the given encoding"; [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void ReadWithSurrogateCharAndInvalidChar() { // {60, 0, 0, 0} is a normal char, {0, 34, 1, 0} is a surrogate char {62, 100, 60, 47} is an invalid char @@ -30,7 +29,6 @@ public static void ReadWithSurrogateCharAndInvalidChar() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void ReadWithNormalCharAndInvalidChar() { // {60, 0, 0, 0, 65, 0, 0, 0} are normal chars, {62, 100, 60, 47} is an invalid char, similar bytes used below tests @@ -43,7 +41,6 @@ public static void ReadWithNormalCharAndInvalidChar() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void ReadWithSurrogateCharAndInvalidChar_ValidXmlStructure() { var bytes = new byte[] { 60, 0, 0, 0, 97, 0, 0, 0, 62, 0, 0, 0, 0, 34, 1, 0, 62, 100, 60, 47, 60, 0, 0, 0, 47, 0, 0, 0, 97, 0, 0, 0, 62, 0, 0, 0 }; @@ -55,7 +52,6 @@ public static void ReadWithSurrogateCharAndInvalidChar_ValidXmlStructure() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void ReadWithSurrogateCharAsElementName() { var bytes = new byte[] { 60, 0, 0, 0, 0, 34, 1, 0, 65, 0, 0, 0, 97, 0, 0, 0 }; @@ -88,7 +84,6 @@ public static void BytesEndingWithSurrogateChar() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void BytesStartingWithInvalidChar() { var bytes = new byte[] { 62, 100, 60, 47, 60, 0, 0, 0, 0, 34, 1, 0, 65, 0, 0, 0, 97, 0, 0, 0 }; @@ -99,7 +94,6 @@ public static void BytesStartingWithInvalidChar() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void BytesEndingWithInvalidChar() { var bytes = new byte[] { 60, 0, 0, 0, 97, 0, 0, 0, 62, 0, 0, 0, 65, 0, 0, 0, 65, 0, 0, 0, 97, 0, 0, 0, 62, 100, 60, 47}; @@ -120,7 +114,6 @@ public static void ReadWithSurrogateChar_ValidXmlStructure() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50945", TestPlatforms.Android)] public static void ReadWithIncompleteBytes() { var bytes = new byte[] { 60, 0, 0, 0, 97, 0, 0, 0, 65, 0, 0, 0, 97, 62, 10}; diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index e319549502ea3e..73f74bcc65bddd 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -74,9 +74,6 @@ - - - @@ -86,18 +83,6 @@ - - - - - - - - - - - - From 3bd0acf30587c88a1448a51a852871e3407aff5f Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Fri, 30 Jul 2021 23:20:59 +0200 Subject: [PATCH 05/64] Fix Win arm GC barrier stuff (#56585) My recent change to enable using LLD on Unix inadvertedly broken Windows ARM GC barriers. This change makes part of that change Unix specific. --- src/coreclr/vm/arm/stubs.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/coreclr/vm/arm/stubs.cpp b/src/coreclr/vm/arm/stubs.cpp index 6b4f71f2455308..6e32957944d136 100644 --- a/src/coreclr/vm/arm/stubs.cpp +++ b/src/coreclr/vm/arm/stubs.cpp @@ -281,8 +281,13 @@ void StubLinkerCPU::Init(void) // value of the global into a register. struct WriteBarrierDescriptor { - DWORD m_pFuncStart; // Offset to the start of the barrier function relative to this struct address - DWORD m_pFuncEnd; // Offset to the end of the barrier function relative to this struct address +#ifdef TARGET_UNIX + DWORD m_funcStartOffset; // Offset to the start of the barrier function relative to this struct address + DWORD m_funcEndOffset; // Offset to the end of the barrier function relative to this struct address +#else // TARGET_UNIX + BYTE * m_pFuncStart; // Pointer to the start of the barrier function + BYTE * m_pFuncEnd; // Pointer to the end of the barrier function +#endif // TARGET_UNIX DWORD m_dw_g_lowest_address_offset; // Offset of the instruction reading g_lowest_address DWORD m_dw_g_highest_address_offset; // Offset of the instruction reading g_highest_address DWORD m_dw_g_ephemeral_low_offset; // Offset of the instruction reading g_ephemeral_low @@ -436,18 +441,28 @@ void UpdateGCWriteBarriers(bool postGrow = false) // Iterate through the write barrier patch table created in the .clrwb section // (see write barrier asm code) WriteBarrierDescriptor * pDesc = &g_rgWriteBarrierDescriptors; +#ifdef TARGET_UNIX + while (pDesc->m_funcStartOffset) +#else // TARGET_UNIX while (pDesc->m_pFuncStart) +#endif // TARGET_UNIX { // If the write barrier is being currently used (as in copied over to the patchable site) // then read the patch location from the table and use the offset to patch the target asm code - PBYTE to = FindWBMapping((BYTE *)pDesc + pDesc->m_pFuncStart); +#ifdef TARGET_UNIX + PBYTE to = FindWBMapping((BYTE *)pDesc + pDesc->m_funcStartOffset); + size_t barrierSize = pDesc->m_funcEndOffset - pDesc->m_funcStartOffset; +#else // TARGET_UNIX + PBYTE to = FindWBMapping(pDesc->m_pFuncStart); + size_t barrierSize = pDesc->m_pFuncEnd - pDesc->m_pFuncStart; +#endif // TARGET_UNIX if(to) { to = (PBYTE)PCODEToPINSTR((PCODE)GetWriteBarrierCodeLocation(to)); ExecutableWriterHolder barrierWriterHolder; if (IsWriteBarrierCopyEnabled()) { - barrierWriterHolder = ExecutableWriterHolder(to, pDesc->m_pFuncEnd - pDesc->m_pFuncStart); + barrierWriterHolder = ExecutableWriterHolder(to, barrierSize); to = barrierWriterHolder.GetRW(); } GWB_PATCH_OFFSET(g_lowest_address); From ab92a77b4e1218bf69195b9218571fed4045bd12 Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Fri, 30 Jul 2021 16:56:35 -0700 Subject: [PATCH 06/64] Add test case for deleting custom attributes using ApplyUpdate (#56644) * Add test case for deleting custom attributes using ApplyUpdate Issue: https://github.com/dotnet/runtime/issues/54284 * Fix mono failures --- .../System.Runtime.Loader.sln | 716 +++++++++--------- .../CustomAttributeDelete.cs | 35 + .../CustomAttributeDelete_v1.cs | 31 + ...lyUpdate.Test.CustomAttributeDelete.csproj | 11 + .../deltascript.json | 6 + .../tests/ApplyUpdateTest.cs | 40 + .../tests/System.Runtime.Loader.Tests.csproj | 42 +- 7 files changed, 507 insertions(+), 374 deletions(-) create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete.cs create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete_v1.cs create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete.csproj create mode 100644 src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/deltascript.json diff --git a/src/libraries/System.Runtime.Loader/System.Runtime.Loader.sln b/src/libraries/System.Runtime.Loader/System.Runtime.Loader.sln index 7a8d6cf7361210..f9468b7e1fd665 100644 --- a/src/libraries/System.Runtime.Loader/System.Runtime.Loader.sln +++ b/src/libraries/System.Runtime.Loader/System.Runtime.Loader.sln @@ -1,4 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31515.178 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{D6D16FFD-FD76-4700-B456-1DC4D093D1B5}" @@ -47,55 +51,102 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{C75ECE17-3CF EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6963C709-FD2F-45A7-9A9D-431B1E9A4796}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete", "tests\ApplyUpdate\System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete\System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete.csproj", "{EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}" +EndProject Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{64ddd2af-bf90-4dd8-ac24-d2084db8d558}*SharedItemsImports = 5 + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution + Checked|Any CPU = Checked|Any CPU + Checked|x64 = Checked|x64 + Checked|x86 = Checked|x86 Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 - Checked|Any CPU = Checked|Any CPU - Checked|x64 = Checked|x64 - Checked|x86 = Checked|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|Any CPU.Build.0 = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x64.ActiveCfg = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x64.Build.0 = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x86.ActiveCfg = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x86.Build.0 = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|Any CPU.ActiveCfg = Release|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|Any CPU.Build.0 = Release|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x64.ActiveCfg = Release|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x64.Build.0 = Release|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x86.ActiveCfg = Release|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x86.Build.0 = Release|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|Any CPU.Build.0 = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x64.ActiveCfg = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x64.Build.0 = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x86.ActiveCfg = Debug|Any CPU - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x86.Build.0 = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x64.ActiveCfg = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x64.Build.0 = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x86.ActiveCfg = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x86.Build.0 = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|Any CPU.Build.0 = Release|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x64.ActiveCfg = Release|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x64.Build.0 = Release|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x86.ActiveCfg = Release|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x86.Build.0 = Release|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|Any CPU.Build.0 = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x64.ActiveCfg = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x64.Build.0 = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x86.ActiveCfg = Debug|Any CPU - {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x86.Build.0 = Debug|Any CPU + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|Any CPU.ActiveCfg = Checked|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|Any CPU.Build.0 = Checked|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x64.ActiveCfg = Checked|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x64.Build.0 = Checked|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x86.ActiveCfg = Checked|x86 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x86.Build.0 = Checked|x86 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|Any CPU.ActiveCfg = Debug|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|Any CPU.Build.0 = Debug|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x64.ActiveCfg = Debug|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x64.Build.0 = Debug|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x86.ActiveCfg = Debug|x86 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x86.Build.0 = Debug|x86 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|Any CPU.ActiveCfg = Release|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|Any CPU.Build.0 = Release|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x64.ActiveCfg = Release|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x64.Build.0 = Release|x64 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x86.ActiveCfg = Release|x86 + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x86.Build.0 = Release|x86 + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|Any CPU.Build.0 = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x64.ActiveCfg = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x64.Build.0 = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x86.ActiveCfg = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x86.Build.0 = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x64.ActiveCfg = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x64.Build.0 = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x86.ActiveCfg = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x86.Build.0 = Debug|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|Any CPU.Build.0 = Release|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x64.ActiveCfg = Release|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x64.Build.0 = Release|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x86.ActiveCfg = Release|Any CPU + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x86.Build.0 = Release|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|Any CPU.Build.0 = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x64.ActiveCfg = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x64.Build.0 = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x86.ActiveCfg = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x86.Build.0 = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x64.ActiveCfg = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x64.Build.0 = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x86.ActiveCfg = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x86.Build.0 = Debug|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|Any CPU.Build.0 = Release|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x64.ActiveCfg = Release|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x64.Build.0 = Release|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x86.ActiveCfg = Release|Any CPU + {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x86.Build.0 = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|Any CPU.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x64.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x64.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x86.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x86.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x64.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x64.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x86.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x86.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|Any CPU.Build.0 = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x64.ActiveCfg = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x64.Build.0 = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x86.ActiveCfg = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x86.Build.0 = Release|Any CPU + {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|Any CPU.Build.0 = Debug|Any CPU + {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x64.ActiveCfg = Debug|Any CPU + {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x64.Build.0 = Debug|Any CPU + {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x86.ActiveCfg = Debug|Any CPU + {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x86.Build.0 = Debug|Any CPU {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Debug|Any CPU.Build.0 = Debug|Any CPU {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -108,30 +159,12 @@ Global {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Release|x64.Build.0 = Release|Any CPU {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Release|x86.ActiveCfg = Release|Any CPU {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Release|x86.Build.0 = Release|Any CPU - {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|Any CPU.Build.0 = Debug|Any CPU - {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x64.ActiveCfg = Debug|Any CPU - {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x64.Build.0 = Debug|Any CPU - {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x86.ActiveCfg = Debug|Any CPU - {95B66B14-BCC7-407A-930C-4B34D4F7EC98}.Checked|x86.Build.0 = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x64.ActiveCfg = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x64.Build.0 = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x86.ActiveCfg = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x86.Build.0 = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|Any CPU.Build.0 = Release|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x64.ActiveCfg = Release|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x64.Build.0 = Release|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x86.ActiveCfg = Release|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x86.Build.0 = Release|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|Any CPU.Build.0 = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x64.ActiveCfg = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x64.Build.0 = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x86.ActiveCfg = Debug|Any CPU - {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x86.Build.0 = Debug|Any CPU + {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|Any CPU.Build.0 = Debug|Any CPU + {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x64.ActiveCfg = Debug|Any CPU + {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x64.Build.0 = Debug|Any CPU + {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x86.ActiveCfg = Debug|Any CPU + {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x86.Build.0 = Debug|Any CPU {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Debug|Any CPU.Build.0 = Debug|Any CPU {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -144,156 +177,102 @@ Global {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Release|x64.Build.0 = Release|Any CPU {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Release|x86.ActiveCfg = Release|Any CPU {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Release|x86.Build.0 = Release|Any CPU - {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|Any CPU.Build.0 = Debug|Any CPU - {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x64.ActiveCfg = Debug|Any CPU - {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x64.Build.0 = Debug|Any CPU - {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x86.ActiveCfg = Debug|Any CPU - {B8F22D73-B183-4F17-9D5E-04B80699E56A}.Checked|x86.Build.0 = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|Any CPU.Build.0 = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x64.ActiveCfg = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x64.Build.0 = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x86.ActiveCfg = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x86.Build.0 = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Release|Any CPU.ActiveCfg = Release|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Release|Any CPU.Build.0 = Release|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x64.ActiveCfg = Release|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x64.Build.0 = Release|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x86.ActiveCfg = Release|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x86.Build.0 = Release|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|Any CPU.Build.0 = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x64.ActiveCfg = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x64.Build.0 = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x86.ActiveCfg = Debug|Any CPU - {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x86.Build.0 = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x64.ActiveCfg = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x64.Build.0 = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x86.ActiveCfg = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Debug|x86.Build.0 = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|Any CPU.Build.0 = Release|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x64.ActiveCfg = Release|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x64.Build.0 = Release|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x86.ActiveCfg = Release|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Release|x86.Build.0 = Release|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|Any CPU.Build.0 = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x64.ActiveCfg = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x64.Build.0 = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x86.ActiveCfg = Debug|Any CPU - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5}.Checked|x86.Build.0 = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x64.ActiveCfg = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x64.Build.0 = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x86.ActiveCfg = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x86.Build.0 = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|Any CPU.Build.0 = Release|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x64.ActiveCfg = Release|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x64.Build.0 = Release|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x86.ActiveCfg = Release|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x86.Build.0 = Release|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|Any CPU.Build.0 = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x64.ActiveCfg = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x64.Build.0 = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x86.ActiveCfg = Debug|Any CPU - {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x86.Build.0 = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x64.ActiveCfg = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x64.Build.0 = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x86.ActiveCfg = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x86.Build.0 = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|Any CPU.Build.0 = Release|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x64.ActiveCfg = Release|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x64.Build.0 = Release|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x86.ActiveCfg = Release|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x86.Build.0 = Release|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|Any CPU.Build.0 = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x64.ActiveCfg = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x64.Build.0 = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x86.ActiveCfg = Debug|Any CPU - {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x86.Build.0 = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x64.ActiveCfg = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x64.Build.0 = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x86.ActiveCfg = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x86.Build.0 = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|Any CPU.Build.0 = Release|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x64.ActiveCfg = Release|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x64.Build.0 = Release|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x86.ActiveCfg = Release|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x86.Build.0 = Release|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|Any CPU.Build.0 = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x64.ActiveCfg = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x64.Build.0 = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x86.ActiveCfg = Debug|Any CPU - {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x86.Build.0 = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x64.ActiveCfg = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x64.Build.0 = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x86.ActiveCfg = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x86.Build.0 = Debug|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|Any CPU.Build.0 = Release|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x64.ActiveCfg = Release|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x64.Build.0 = Release|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x86.ActiveCfg = Release|Any CPU - {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x86.Build.0 = Release|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|Any CPU.Build.0 = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x64.ActiveCfg = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x64.Build.0 = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x86.ActiveCfg = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x86.Build.0 = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x64.ActiveCfg = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x64.Build.0 = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x86.ActiveCfg = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x86.Build.0 = Debug|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|Any CPU.Build.0 = Release|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x64.ActiveCfg = Release|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x64.Build.0 = Release|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x86.ActiveCfg = Release|Any CPU + {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x86.Build.0 = Release|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|Any CPU.Build.0 = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x64.ActiveCfg = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x64.Build.0 = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x86.ActiveCfg = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x86.Build.0 = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x64.ActiveCfg = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x64.Build.0 = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x86.ActiveCfg = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x86.Build.0 = Debug|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|Any CPU.Build.0 = Release|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x64.ActiveCfg = Release|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x64.Build.0 = Release|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x86.ActiveCfg = Release|Any CPU + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x86.Build.0 = Release|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|Any CPU.Build.0 = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x64.ActiveCfg = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x64.Build.0 = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x86.ActiveCfg = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x86.Build.0 = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x64.ActiveCfg = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x64.Build.0 = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x86.ActiveCfg = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x86.Build.0 = Debug|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|Any CPU.Build.0 = Release|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x64.ActiveCfg = Release|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x64.Build.0 = Release|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x86.ActiveCfg = Release|Any CPU + {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x86.Build.0 = Release|Any CPU {76BE0621-CDAD-4808-8537-ADC9F028286B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU {76BE0621-CDAD-4808-8537-ADC9F028286B}.Checked|Any CPU.Build.0 = Debug|Any CPU {76BE0621-CDAD-4808-8537-ADC9F028286B}.Checked|x64.ActiveCfg = Debug|Any CPU {76BE0621-CDAD-4808-8537-ADC9F028286B}.Checked|x64.Build.0 = Debug|Any CPU {76BE0621-CDAD-4808-8537-ADC9F028286B}.Checked|x86.ActiveCfg = Debug|Any CPU {76BE0621-CDAD-4808-8537-ADC9F028286B}.Checked|x86.Build.0 = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x64.ActiveCfg = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x64.Build.0 = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x86.ActiveCfg = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x86.Build.0 = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|Any CPU.Build.0 = Release|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x64.ActiveCfg = Release|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x64.Build.0 = Release|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x86.ActiveCfg = Release|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x86.Build.0 = Release|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|Any CPU.Build.0 = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x64.ActiveCfg = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x64.Build.0 = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x86.ActiveCfg = Debug|Any CPU - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x86.Build.0 = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x64.ActiveCfg = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x64.Build.0 = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x86.ActiveCfg = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x86.Build.0 = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|Any CPU.Build.0 = Release|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x64.ActiveCfg = Release|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x64.Build.0 = Release|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x86.ActiveCfg = Release|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x86.Build.0 = Release|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|Any CPU.Build.0 = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x64.ActiveCfg = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x64.Build.0 = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x86.ActiveCfg = Debug|Any CPU - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x86.Build.0 = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x64.ActiveCfg = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x64.Build.0 = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x86.ActiveCfg = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Debug|x86.Build.0 = Debug|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|Any CPU.Build.0 = Release|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x64.ActiveCfg = Release|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x64.Build.0 = Release|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x86.ActiveCfg = Release|Any CPU + {76BE0621-CDAD-4808-8537-ADC9F028286B}.Release|x86.Build.0 = Release|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|Any CPU.Build.0 = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x64.ActiveCfg = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x64.Build.0 = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x86.ActiveCfg = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Checked|x86.Build.0 = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x64.ActiveCfg = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x64.Build.0 = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x86.ActiveCfg = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Debug|x86.Build.0 = Debug|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|Any CPU.Build.0 = Release|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x64.ActiveCfg = Release|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x64.Build.0 = Release|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x86.ActiveCfg = Release|Any CPU + {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159}.Release|x86.Build.0 = Release|Any CPU + {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|Any CPU.Build.0 = Debug|Any CPU + {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x64.ActiveCfg = Debug|Any CPU + {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x64.Build.0 = Debug|Any CPU + {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x86.ActiveCfg = Debug|Any CPU + {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x86.Build.0 = Debug|Any CPU {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Debug|Any CPU.Build.0 = Debug|Any CPU {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -306,12 +285,12 @@ Global {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Release|x64.Build.0 = Release|Any CPU {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Release|x86.ActiveCfg = Release|Any CPU {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Release|x86.Build.0 = Release|Any CPU - {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|Any CPU.Build.0 = Debug|Any CPU - {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x64.ActiveCfg = Debug|Any CPU - {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x64.Build.0 = Debug|Any CPU - {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x86.ActiveCfg = Debug|Any CPU - {78BC94E5-2E23-40EF-863E-52AFCE838C96}.Checked|x86.Build.0 = Debug|Any CPU + {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|Any CPU.Build.0 = Debug|Any CPU + {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x64.ActiveCfg = Debug|Any CPU + {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x64.Build.0 = Debug|Any CPU + {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x86.ActiveCfg = Debug|Any CPU + {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x86.Build.0 = Debug|Any CPU {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Debug|Any CPU.Build.0 = Debug|Any CPU {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -324,146 +303,195 @@ Global {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Release|x64.Build.0 = Release|Any CPU {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Release|x86.ActiveCfg = Release|Any CPU {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Release|x86.Build.0 = Release|Any CPU - {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|Any CPU.Build.0 = Debug|Any CPU - {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x64.ActiveCfg = Debug|Any CPU - {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x64.Build.0 = Debug|Any CPU - {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x86.ActiveCfg = Debug|Any CPU - {7E785A7B-6ED6-4459-A07D-28DE1830C186}.Checked|x86.Build.0 = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|Any CPU.Build.0 = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x64.ActiveCfg = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x64.Build.0 = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x86.ActiveCfg = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Debug|x86.Build.0 = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|Any CPU.ActiveCfg = Release|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|Any CPU.Build.0 = Release|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x64.ActiveCfg = Release|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x64.Build.0 = Release|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x86.ActiveCfg = Release|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Release|x86.Build.0 = Release|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|Any CPU.Build.0 = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x64.ActiveCfg = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x64.Build.0 = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x86.ActiveCfg = Debug|Any CPU - {71B8CD61-839D-445C-8E7D-F0F67CE00527}.Checked|x86.Build.0 = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x64.ActiveCfg = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x64.Build.0 = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x86.ActiveCfg = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Debug|x86.Build.0 = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|Any CPU.Build.0 = Release|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x64.ActiveCfg = Release|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x64.Build.0 = Release|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x86.ActiveCfg = Release|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Release|x86.Build.0 = Release|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|Any CPU.Build.0 = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x64.ActiveCfg = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x64.Build.0 = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x86.ActiveCfg = Debug|Any CPU - {BCE10255-8B2B-4F66-914D-7B685BC98198}.Checked|x86.Build.0 = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x64.ActiveCfg = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x64.Build.0 = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x86.ActiveCfg = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Debug|x86.Build.0 = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|Any CPU.Build.0 = Release|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x64.ActiveCfg = Release|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x64.Build.0 = Release|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x86.ActiveCfg = Release|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Release|x86.Build.0 = Release|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|Any CPU.Build.0 = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x64.ActiveCfg = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x64.Build.0 = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x86.ActiveCfg = Debug|Any CPU - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5}.Checked|x86.Build.0 = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|Any CPU.Build.0 = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x64.ActiveCfg = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x64.Build.0 = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x86.ActiveCfg = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x86.Build.0 = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|Any CPU.ActiveCfg = Release|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|Any CPU.Build.0 = Release|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x64.ActiveCfg = Release|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x64.Build.0 = Release|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x86.ActiveCfg = Release|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x86.Build.0 = Release|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|Any CPU.Build.0 = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x64.ActiveCfg = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x64.Build.0 = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x86.ActiveCfg = Debug|Any CPU - {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x86.Build.0 = Debug|Any CPU - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|Any CPU.ActiveCfg = Debug|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|Any CPU.Build.0 = Debug|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x64.ActiveCfg = Debug|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x64.Build.0 = Debug|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x86.ActiveCfg = Debug|x86 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Debug|x86.Build.0 = Debug|x86 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|Any CPU.ActiveCfg = Release|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|Any CPU.Build.0 = Release|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x64.ActiveCfg = Release|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x64.Build.0 = Release|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x86.ActiveCfg = Release|x86 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Release|x86.Build.0 = Release|x86 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|Any CPU.ActiveCfg = Checked|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|Any CPU.Build.0 = Checked|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x64.ActiveCfg = Checked|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x64.Build.0 = Checked|x64 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x86.ActiveCfg = Checked|x86 - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558}.Checked|x86.Build.0 = Checked|x86 - {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x64.ActiveCfg = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x64.Build.0 = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x86.ActiveCfg = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Debug|x86.Build.0 = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|Any CPU.Build.0 = Release|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x64.ActiveCfg = Release|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x64.Build.0 = Release|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x86.ActiveCfg = Release|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Release|x86.Build.0 = Release|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|Any CPU.Build.0 = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x64.ActiveCfg = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x64.Build.0 = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x86.ActiveCfg = Debug|Any CPU - {8D19CD03-08EE-4574-B798-C658502C0A42}.Checked|x86.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|Any CPU.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x64.ActiveCfg = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x64.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x86.ActiveCfg = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Checked|x86.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x64.ActiveCfg = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x64.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x86.ActiveCfg = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Debug|x86.Build.0 = Debug|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|Any CPU.Build.0 = Release|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x64.ActiveCfg = Release|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x64.Build.0 = Release|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x86.ActiveCfg = Release|Any CPU + {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902}.Release|x86.Build.0 = Release|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|Any CPU.Build.0 = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x64.ActiveCfg = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x64.Build.0 = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x86.ActiveCfg = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Checked|x86.Build.0 = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x64.ActiveCfg = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x64.Build.0 = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x86.ActiveCfg = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Debug|x86.Build.0 = Debug|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|Any CPU.Build.0 = Release|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x64.ActiveCfg = Release|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x64.Build.0 = Release|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x86.ActiveCfg = Release|Any CPU + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD}.Release|x86.Build.0 = Release|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|Any CPU.Build.0 = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x64.ActiveCfg = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x64.Build.0 = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x86.ActiveCfg = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Checked|x86.Build.0 = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x64.ActiveCfg = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x64.Build.0 = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x86.ActiveCfg = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Debug|x86.Build.0 = Debug|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|Any CPU.Build.0 = Release|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x64.ActiveCfg = Release|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x64.Build.0 = Release|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x86.ActiveCfg = Release|Any CPU + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD}.Release|x86.Build.0 = Release|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|Any CPU.Build.0 = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x64.ActiveCfg = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x64.Build.0 = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x86.ActiveCfg = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Checked|x86.Build.0 = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x64.ActiveCfg = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x64.Build.0 = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x86.ActiveCfg = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Debug|x86.Build.0 = Debug|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|Any CPU.Build.0 = Release|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x64.ActiveCfg = Release|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x64.Build.0 = Release|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x86.ActiveCfg = Release|Any CPU + {44B22827-B9F0-4ADC-969C-7EC647D0B82A}.Release|x86.Build.0 = Release|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|Any CPU.Build.0 = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x64.ActiveCfg = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x64.Build.0 = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x86.ActiveCfg = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Checked|x86.Build.0 = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x64.ActiveCfg = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x64.Build.0 = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x86.ActiveCfg = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Debug|x86.Build.0 = Debug|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Release|Any CPU.ActiveCfg = Release|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Release|Any CPU.Build.0 = Release|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x64.ActiveCfg = Release|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x64.Build.0 = Release|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x86.ActiveCfg = Release|Any CPU + {49B0A873-5834-45A4-9495-E1063005CB82}.Release|x86.Build.0 = Release|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|Any CPU.Build.0 = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x64.ActiveCfg = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x64.Build.0 = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x86.ActiveCfg = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Checked|x86.Build.0 = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x64.ActiveCfg = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x64.Build.0 = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x86.ActiveCfg = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Debug|x86.Build.0 = Debug|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|Any CPU.Build.0 = Release|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x64.ActiveCfg = Release|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x64.Build.0 = Release|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x86.ActiveCfg = Release|Any CPU + {E60DD367-D1D7-4F6C-919B-DC68E8445E97}.Release|x86.Build.0 = Release|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|Any CPU.Build.0 = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x64.ActiveCfg = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x64.Build.0 = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x86.ActiveCfg = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Checked|x86.Build.0 = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x64.ActiveCfg = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x64.Build.0 = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x86.ActiveCfg = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Debug|x86.Build.0 = Debug|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|Any CPU.Build.0 = Release|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x64.ActiveCfg = Release|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x64.Build.0 = Release|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x86.ActiveCfg = Release|Any CPU + {9AD657ED-396B-4BE7-BCB6-BCA130825418}.Release|x86.Build.0 = Release|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|Any CPU.Build.0 = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x64.ActiveCfg = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x64.Build.0 = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x86.ActiveCfg = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Checked|x86.Build.0 = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|Any CPU.Build.0 = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x64.ActiveCfg = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x64.Build.0 = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x86.ActiveCfg = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Debug|x86.Build.0 = Debug|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|Any CPU.ActiveCfg = Release|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|Any CPU.Build.0 = Release|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x64.ActiveCfg = Release|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x64.Build.0 = Release|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x86.ActiveCfg = Release|Any CPU + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562}.Release|x86.Build.0 = Release|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Checked|Any CPU.Build.0 = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Checked|x64.ActiveCfg = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Checked|x64.Build.0 = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Checked|x86.ActiveCfg = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Checked|x86.Build.0 = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Debug|x64.ActiveCfg = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Debug|x64.Build.0 = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Debug|x86.ActiveCfg = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Debug|x86.Build.0 = Debug|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Release|Any CPU.Build.0 = Release|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Release|x64.ActiveCfg = Release|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Release|x64.Build.0 = Release|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Release|x86.ActiveCfg = Release|Any CPU + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {29E02AA9-E3D5-400C-B2C5-970B6E6D8562} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558} = {6963C709-FD2F-45A7-9A9D-431B1E9A4796} + {D6D16FFD-FD76-4700-B456-1DC4D093D1B5} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {8D19CD03-08EE-4574-B798-C658502C0A42} = {C75ECE17-3CF5-409D-B26F-E2F5053DD5B9} + {04BA3E3C-6979-4792-B19E-C797AD607F42} = {6963C709-FD2F-45A7-9A9D-431B1E9A4796} + {95B66B14-BCC7-407A-930C-4B34D4F7EC98} = {C75ECE17-3CF5-409D-B26F-E2F5053DD5B9} + {B8F22D73-B183-4F17-9D5E-04B80699E56A} = {6963C709-FD2F-45A7-9A9D-431B1E9A4796} + {BCE10255-8B2B-4F66-914D-7B685BC98198} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {71B8CD61-839D-445C-8E7D-F0F67CE00527} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {76BE0621-CDAD-4808-8537-ADC9F028286B} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} {8EB6F6F0-FD8C-44C8-A9D8-18854C3C2159} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {78BC94E5-2E23-40EF-863E-52AFCE838C96} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {7E785A7B-6ED6-4459-A07D-28DE1830C186} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} {F0CEA7EB-E8B5-482A-AB6C-3E12992F2902} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {44B22827-B9F0-4ADC-969C-7EC647D0B82A} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} {49B0A873-5834-45A4-9495-E1063005CB82} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {D6D16FFD-FD76-4700-B456-1DC4D093D1B5} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} {E60DD367-D1D7-4F6C-919B-DC68E8445E97} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} {9AD657ED-396B-4BE7-BCB6-BCA130825418} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {44B22827-B9F0-4ADC-969C-7EC647D0B82A} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {76BE0621-CDAD-4808-8537-ADC9F028286B} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {CA8B6E49-5EAF-4B7C-A141-6D83DD8D8AFD} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {10699CE6-A1B3-4C14-93E0-CB5CF3292BDD} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {78BC94E5-2E23-40EF-863E-52AFCE838C96} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {7E785A7B-6ED6-4459-A07D-28DE1830C186} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {71B8CD61-839D-445C-8E7D-F0F67CE00527} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {BCE10255-8B2B-4F66-914D-7B685BC98198} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {78C4F407-C2E0-46BA-A4A0-EE04D89A2EB5} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} - {95B66B14-BCC7-407A-930C-4B34D4F7EC98} = {C75ECE17-3CF5-409D-B26F-E2F5053DD5B9} - {8D19CD03-08EE-4574-B798-C658502C0A42} = {C75ECE17-3CF5-409D-B26F-E2F5053DD5B9} - {B8F22D73-B183-4F17-9D5E-04B80699E56A} = {6963C709-FD2F-45A7-9A9D-431B1E9A4796} - {04BA3E3C-6979-4792-B19E-C797AD607F42} = {6963C709-FD2F-45A7-9A9D-431B1E9A4796} - {64DDD2AF-BF90-4DD8-AC24-D2084DB8D558} = {6963C709-FD2F-45A7-9A9D-431B1E9A4796} + {29E02AA9-E3D5-400C-B2C5-970B6E6D8562} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} + {EEAE2A15-E2AE-4421-8D30-AAB17AC805F8} = {F36F0790-5CF7-4CAD-B903-4A3EE0DC1345} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {73D0667D-A181-41CA-B57B-DD177166E019} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete.cs new file mode 100644 index 00000000000000..1781dcfe3db184 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; + + +namespace System.Reflection.Metadata.ApplyUpdate.Test +{ + [AttributeUsage (AttributeTargets.Method, AllowMultiple=true)] + public class MyDeleteAttribute : Attribute + { + public MyDeleteAttribute (string stringValue) { StringValue = stringValue; } + + public MyDeleteAttribute (Type typeValue) { TypeValue = typeValue; } + + public MyDeleteAttribute (int x) { IntValue = x; } + + public string StringValue { get; set; } + public Type TypeValue {get; set; } + public int IntValue {get; set; } + } + + public class ClassWithCustomAttributeDelete + { + [MyDeleteAttribute ("abcd")] + public static string Method1 () => null; + + [MyDeleteAttribute (typeof(Exception))] + public static string Method2 () => null; + + [MyDeleteAttribute (42, StringValue = "hijkl", TypeValue = typeof(Type))] + [MyDeleteAttribute (17, StringValue = "", TypeValue = typeof(object))] + public static string Method3 () => null; + + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete_v1.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete_v1.cs new file mode 100644 index 00000000000000..db85640bb538dc --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/CustomAttributeDelete_v1.cs @@ -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 System; + + +namespace System.Reflection.Metadata.ApplyUpdate.Test +{ + [AttributeUsage (AttributeTargets.Method, AllowMultiple=true)] + public class MyDeleteAttribute : Attribute + { + public MyDeleteAttribute (string stringValue) { StringValue = stringValue; } + + public MyDeleteAttribute (Type typeValue) { TypeValue = typeValue; } + + public MyDeleteAttribute (int x) { IntValue = x; } + + public string StringValue { get; set; } + public Type TypeValue {get; set; } + public int IntValue {get; set; } + } + + public class ClassWithCustomAttributeDelete + { + public static string Method1 () => null; + + public static string Method2 () => null; + + [MyDeleteAttribute (17, StringValue = "Not Deleted", TypeValue = typeof(object))] + public static string Method3 () => null; + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete.csproj b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete.csproj new file mode 100644 index 00000000000000..fa4dec5c554d76 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete.csproj @@ -0,0 +1,11 @@ + + + System.Runtime.Loader.Tests + $(NetCoreAppCurrent) + true + deltascript.json + + + + + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/deltascript.json b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/deltascript.json new file mode 100644 index 00000000000000..ffddaad9069e39 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.CustomAttributeDelete/deltascript.json @@ -0,0 +1,6 @@ +{ + "changes": [ + {"document": "CustomAttributeDelete.cs", "update": "CustomAttributeDelete_v1.cs"}, + ] +} + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs index 6976f8a6f77729..c8cf4b47e5e280 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs @@ -112,6 +112,46 @@ public void CustomAttributeUpdates() }); } + [ActiveIssue("https://github.com/dotnet/runtime/issues/52993", TestRuntimes.Mono)] + [ConditionalFact(typeof(ApplyUpdateUtil), nameof (ApplyUpdateUtil.IsSupported))] + public void CustomAttributeDelete() + { + // Test that deleting custom attribute on constructor/property works as expected. + ApplyUpdateUtil.TestCase(static () => + { + var assm = typeof(System.Reflection.Metadata.ApplyUpdate.Test.ClassWithCustomAttributeDelete).Assembly; + + ApplyUpdateUtil.ApplyUpdate(assm); + ApplyUpdateUtil.ClearAllReflectionCaches(); + + // Just check the updated value on one method + + Type attrType = typeof(System.Reflection.Metadata.ApplyUpdate.Test.MyDeleteAttribute); + Type ty = assm.GetType("System.Reflection.Metadata.ApplyUpdate.Test.ClassWithCustomAttributeDelete"); + Assert.NotNull(ty); + + MethodInfo mi1 = ty.GetMethod(nameof(System.Reflection.Metadata.ApplyUpdate.Test.ClassWithCustomAttributeDelete.Method1), BindingFlags.Public | BindingFlags.Static); + Assert.NotNull(mi1); + Attribute[] cattrs = Attribute.GetCustomAttributes(mi1, attrType); + Assert.NotNull(cattrs); + Assert.Equal(0, cattrs.Length); + + MethodInfo mi2 = ty.GetMethod(nameof(System.Reflection.Metadata.ApplyUpdate.Test.ClassWithCustomAttributeDelete.Method2), BindingFlags.Public | BindingFlags.Static); + Assert.NotNull(mi2); + cattrs = Attribute.GetCustomAttributes(mi2, attrType); + Assert.NotNull(cattrs); + Assert.Equal(0, cattrs.Length); + + MethodInfo mi3 = ty.GetMethod(nameof(System.Reflection.Metadata.ApplyUpdate.Test.ClassWithCustomAttributeDelete.Method3), BindingFlags.Public | BindingFlags.Static); + Assert.NotNull(mi3); + cattrs = Attribute.GetCustomAttributes(mi3, attrType); + Assert.NotNull(cattrs); + Assert.Equal(1, cattrs.Length); + string p = (cattrs[0] as System.Reflection.Metadata.ApplyUpdate.Test.MyDeleteAttribute).StringValue; + Assert.Equal("Not Deleted", p); + }); + } + class NonRuntimeAssembly : Assembly { } diff --git a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj index a5f2b3b0cce7bc..714d83d65fabea 100644 --- a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj +++ b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj @@ -23,15 +23,10 @@ - - - + + + + @@ -48,35 +43,22 @@ - + - - - + + + - + - - - + + + From 32056a71c13efaace94af03ad7b672612283ab80 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Fri, 30 Jul 2021 17:46:53 -0700 Subject: [PATCH 07/64] JIT: spill exception-causing entries from stack for finalizable newobj (#56636) Fix a long-standing issue where in some rare cases an object could be finalized even though its constructor was never called. The problem was that the jit was allocating the object before evaluating any of the arguments to the constructor, so that if an argument evaluation threw, a default-initialized version of the object still lived on the heap. The fix is to spill any side-effecting stack entry if the jit is going to create a finalizable object. This improves on previous attempts by only spilling for the finalizable case. Closes #4871. --- src/coreclr/jit/importer.cpp | 12 +++++ .../JitBlue/Runtime_4781/Runtime_4781.cs | 52 +++++++++++++++++++ .../JitBlue/Runtime_4781/Runtime_4781.csproj | 12 +++++ .../JitBlue/Runtime_4781/Runtime_4781_1.cs | 49 +++++++++++++++++ .../Runtime_4781/Runtime_4781_1.csproj | 12 +++++ 5 files changed, 137 insertions(+) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.csproj create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.csproj diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 3517306b959a7f..da396f145bfe05 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -14497,6 +14497,18 @@ void Compiler::impImportBlockCode(BasicBlock* block) } else { + // If we're newing up a finalizable object, spill anything that can cause exceptions. + // + bool hasSideEffects = false; + CorInfoHelpFunc newHelper = + info.compCompHnd->getNewHelper(&resolvedToken, info.compMethodHnd, &hasSideEffects); + + if (hasSideEffects) + { + JITDUMP("\nSpilling stack for finalizable newobj\n"); + impSpillSideEffects(true, (unsigned)CHECK_SPILL_ALL DEBUGARG("finalizable newobj spill")); + } + const bool useParent = true; op1 = gtNewAllocObjNode(&resolvedToken, useParent); if (op1 == nullptr) diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.cs b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.cs new file mode 100644 index 00000000000000..8d2221fb2280ca --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +// Test for proper ordering of exception-causing ctor args and +// the newobj allocation + +class Foo : IDisposable +{ + public bool IsConstructed { get; } = true; + public Foo(int ignored) { } + + ~Foo() + { + if (!IsConstructed) + { + Console.WriteLine("Finalizing a non-constructed object?!"); + Runtime_4781.Fail(); + } + } + + public void Dispose() => GC.SuppressFinalize(this); +} + +class Runtime_4781 +{ + private static int Throw() => throw new NotSupportedException(); + private static bool failed = false; + public static void Fail() { failed = true; } + + private static IDisposable Test() + { + try + { + int x = Throw(); + return new Foo(x); + } + catch + { + } + return new Foo(2); + } + + static int Main(string[] args) + { + Test().Dispose(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + return failed ? -1 : 100; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.csproj new file mode 100644 index 00000000000000..f3e1cbd44b4041 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.cs b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.cs new file mode 100644 index 00000000000000..a7cf8fe4a455e8 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +// Test for proper ordering of a gc safepoint inducing arg and +// the newobj allocation + +class Bar +{ + public Bar() + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + } +} + +static class Observer +{ + public static bool failed; +} + +class Foo : IDisposable +{ + + public Foo(Bar b) + { + Console.WriteLine($"new Foo"); + } + + ~Foo() + { + Console.WriteLine($"~Foo"); + Observer.failed = true; + } + + public void Dispose() => GC.SuppressFinalize(this); +} + +class Runtime_4781_1 +{ + static Bar s_bar = new Bar(); + + static int Main(string[] args) + { + var f = new Foo(s_bar); + return Observer.failed ? -1 : 100; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.csproj new file mode 100644 index 00000000000000..f3e1cbd44b4041 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + + From 99d1bf8e5996b2e39f9c24c4719daaa80f9027a7 Mon Sep 17 00:00:00 2001 From: Tarek Mahmoud Sayed Date: Fri, 30 Jul 2021 18:06:08 -0700 Subject: [PATCH 08/64] Fix String.LastIndexOf with string has zero sort weights characters (#56504) * Fix String.LastIndexOf with string has zero sort weights characters --- .../pal_collation.c | 32 ++++++++++++++++--- .../CompareInfoTests.LastIndexOf.cs | 8 ++++- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.c b/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.c index 4a8d5bcd72153d..0e0a46c5b1c599 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.c +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_collation.c @@ -839,11 +839,35 @@ int32_t GlobalizationNative_LastIndexOf( result = usearch_last(pSearch, &err); - // if the search was successful, - // we'll try to get the matched string length. - if (result != USEARCH_DONE && pMatchedLength != NULL) + // if the search was successful, we'll try to get the matched string length. + if (result != USEARCH_DONE) { - *pMatchedLength = usearch_getMatchedLength(pSearch); + int32_t matchLength = -1; + + if (pMatchedLength != NULL) + { + matchLength = usearch_getMatchedLength(pSearch); + *pMatchedLength = matchLength; + } + + // In case the search result is pointing at the last character (including Surrogate case) of the source string, we need to check if the target string + // was constructed with characters which have no sort weights. The way we do that is to check that the matched length is 0. + // We need to update the returned index to have consistent behavior with Ordinal and NLS operations, and satisfy the condition: + // index = source.LastIndexOf(value, comparisonType); + // originalString.Substring(index).StartsWith(value, comparisonType) == true. + // https://github.com/dotnet/runtime/issues/13383 + if (result >= cwSourceLength - 2) + { + if (pMatchedLength == NULL) + { + matchLength = usearch_getMatchedLength(pSearch); + } + + if (matchLength == 0) + { + result = cwSourceLength; + } + } } RestoreSearchHandle(pSortHandle, pSearch, searchCacheSlot); diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.LastIndexOf.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.LastIndexOf.cs index 060648e8185b25..a400dedbdca66a 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.LastIndexOf.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.LastIndexOf.cs @@ -92,7 +92,13 @@ public static IEnumerable LastIndexOf_TestData() // ICU matches weightless characters at 1 index prior to the end of the string yield return new object[] { s_invariantCompare, "", "\u200d", 0, 0, CompareOptions.None, 0, 0 }; yield return new object[] { s_invariantCompare, "", "\u200d", -1, 0, CompareOptions.None, 0, 0 }; - yield return new object[] { s_invariantCompare, "hello", "\u200d", 4, 5, CompareOptions.IgnoreCase, useNls ? 5 : 4 , 0}; + yield return new object[] { s_invariantCompare, "hello", "\u200d", 4, 5, CompareOptions.IgnoreCase, 5, 0}; + yield return new object[] { s_invariantCompare, "hello", "\0", 4, 5, CompareOptions.None, useNls ? -1 : 5, 0}; + + yield return new object[] { s_invariantCompare, "A\u0303", "\u200d", 1, 2, CompareOptions.None, 2, 0}; // A + ̃ = Ã + yield return new object[] { s_invariantCompare, "A\u0303\u200D", "\u200d", 2, 3, CompareOptions.None, 3, 0}; // A + ̃ = Ã + yield return new object[] { s_invariantCompare, "\u0001F601", "\u200d", 1, 2, CompareOptions.None, 2, 0}; // \u0001F601 is GRINNING FACE WITH SMILING EYES surrogate character + yield return new object[] { s_invariantCompare, "AA\u200DA", "\u200d", 3, 4, CompareOptions.None, 4, 0}; // Ignore symbols yield return new object[] { s_invariantCompare, "More Test's", "Tests", 10, 11, CompareOptions.IgnoreSymbols, 5, 6 }; From 3afb043770d705200a1d2418c30bc15066aca6ad Mon Sep 17 00:00:00 2001 From: Tomas Weinfurt Date: Fri, 30 Jul 2021 19:26:53 -0700 Subject: [PATCH 09/64] fix deadlock in Quic (#56600) * fix deadlock in Quic * feedback from review --- .../MsQuic/MsQuicConnection.cs | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs index d909514ea0f820..82638fc605f6bc 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs @@ -150,6 +150,7 @@ public MsQuicConnection(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, Saf try { + Debug.Assert(!Monitor.IsEntered(_state)); MsQuicApi.Api.SetCallbackHandlerDelegate( _state.Handle, s_connectionDelegate, @@ -184,6 +185,7 @@ public MsQuicConnection(QuicClientConnectionOptions options) _state.StateGCHandle = GCHandle.Alloc(_state); try { + Debug.Assert(!Monitor.IsEntered(_state)); uint status = MsQuicApi.Api.ConnectionOpenDelegate( MsQuicApi.Api.Registration, s_connectionDelegate, @@ -220,7 +222,7 @@ private static uint HandleEventConnected(State state, ref ConnectionEvent connec if (!state.Connected) { // Connected will already be true for connections accepted from a listener. - + Debug.Assert(!Monitor.IsEntered(state)); SOCKADDR_INET inetAddress = MsQuicParameterHelpers.GetINetParam(MsQuicApi.Api, state.Handle, QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.LOCAL_ADDRESS); Debug.Assert(state.Connection != null); @@ -459,6 +461,10 @@ internal override ValueTask WaitForAvailableUnidirectionalStreamsAsync(Cancellat TaskCompletionSource? tcs = _state.NewUnidirectionalStreamsAvailable; if (tcs is null) { + // We need to avoid calling MsQuic under lock. + // This is not atomic but it won't be anyway as counts can change between when task is completed + // and before somebody may try to allocate new stream. + int count = GetRemoteAvailableUnidirectionalStreamCount(); lock (_state) { if (_state.NewUnidirectionalStreamsAvailable is null) @@ -468,13 +474,14 @@ internal override ValueTask WaitForAvailableUnidirectionalStreamsAsync(Cancellat throw new QuicOperationAbortedException(); } - if (GetRemoteAvailableUnidirectionalStreamCount() > 0) + if (count > 0) { return ValueTask.CompletedTask; } _state.NewUnidirectionalStreamsAvailable = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); } + tcs = _state.NewUnidirectionalStreamsAvailable; } } @@ -487,6 +494,10 @@ internal override ValueTask WaitForAvailableBidirectionalStreamsAsync(Cancellati TaskCompletionSource? tcs = _state.NewBidirectionalStreamsAvailable; if (tcs is null) { + // We need to avoid calling MsQuic under lock. + // This is not atomic but it won't be anyway as counts can change between when task is completed + // and before somebody may try to allocate new stream. + int count = GetRemoteAvailableBidirectionalStreamCount(); lock (_state) { if (_state.NewBidirectionalStreamsAvailable is null) @@ -496,7 +507,7 @@ internal override ValueTask WaitForAvailableBidirectionalStreamsAsync(Cancellati throw new QuicOperationAbortedException(); } - if (GetRemoteAvailableBidirectionalStreamCount() > 0) + if (count > 0) { return ValueTask.CompletedTask; } @@ -526,11 +537,13 @@ internal override QuicStreamProvider OpenBidirectionalStream() internal override int GetRemoteAvailableUnidirectionalStreamCount() { + Debug.Assert(!Monitor.IsEntered(_state)); return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.LOCAL_UNIDI_STREAM_COUNT); } internal override int GetRemoteAvailableBidirectionalStreamCount() { + Debug.Assert(!Monitor.IsEntered(_state)); return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.LOCAL_BIDI_STREAM_COUNT); } @@ -563,6 +576,7 @@ internal override ValueTask ConnectAsync(CancellationToken cancellationToken = d SOCKADDR_INET address = MsQuicAddressHelpers.IPEndPointToINet((IPEndPoint)_remoteEndPoint); unsafe { + Debug.Assert(!Monitor.IsEntered(_state)); status = MsQuicApi.Api.SetParamDelegate(_state.Handle, QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.REMOTE_ADDRESS, (uint)sizeof(SOCKADDR_INET), (byte*)&address); QuicExceptionHelpers.ThrowIfFailed(status, "Failed to connect to peer."); } @@ -587,6 +601,7 @@ internal override ValueTask ConnectAsync(CancellationToken cancellationToken = d try { + Debug.Assert(!Monitor.IsEntered(_state)); status = MsQuicApi.Api.ConnectionStartDelegate( _state.Handle, _configuration, @@ -620,6 +635,7 @@ private ValueTask ShutdownAsync( try { + Debug.Assert(!Monitor.IsEntered(_state)); MsQuicApi.Api.ConnectionShutdownDelegate( _state.Handle, Flags, @@ -747,6 +763,7 @@ private void Dispose(bool disposing) if (_state.Handle != null) { // Handle can be null if outbound constructor failed and we are called from finalizer. + Debug.Assert(!Monitor.IsEntered(_state)); MsQuicApi.Api.ConnectionShutdownDelegate( _state.Handle, QUIC_CONNECTION_SHUTDOWN_FLAGS.SILENT, From fe671e1da1bd22ff320009654ceed076adb447f5 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Fri, 30 Jul 2021 23:24:28 -0400 Subject: [PATCH 10/64] Return null from GetManifestResourceInfo and GetManifestResourceStream when the resource is not found (#56602) --- .../Ecma/EcmaAssembly.ManifestResources.cs | 13 ++++++++++- .../TypeLoading/Assemblies/RoAssembly.cs | 2 +- .../TypeLoading/Assemblies/RoStubAssembly.cs | 2 +- .../tests/src/Tests/Assembly/AssemblyTests.cs | 22 +++++++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs index fea1363738dbb7..9cfdf5b19d9354 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs @@ -12,7 +12,7 @@ namespace System.Reflection.TypeLoading.Ecma /// internal sealed partial class EcmaAssembly { - public sealed override ManifestResourceInfo GetManifestResourceInfo(string resourceName) + public sealed override ManifestResourceInfo? GetManifestResourceInfo(string resourceName) { if (resourceName == null) throw new ArgumentNullException(nameof(resourceName)); @@ -21,6 +21,11 @@ public sealed override ManifestResourceInfo GetManifestResourceInfo(string resou InternalManifestResourceInfo internalManifestResourceInfo = GetEcmaManifestModule().GetInternalManifestResourceInfo(resourceName); + if (!internalManifestResourceInfo.Found) + { + return null; + } + if (internalManifestResourceInfo.ResourceLocation == ResourceLocation.ContainedInAnotherAssembly) { // Must get resource info from other assembly, and OR in the contained in another assembly information @@ -62,6 +67,12 @@ public sealed override string[] GetManifestResourceNames() throw new ArgumentException(nameof(name)); InternalManifestResourceInfo internalManifestResourceInfo = GetEcmaManifestModule().GetInternalManifestResourceInfo(name); + + if (!internalManifestResourceInfo.Found) + { + return null; + } + if ((internalManifestResourceInfo.ResourceLocation & ResourceLocation.Embedded) != 0) { unsafe diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs index 4d48000d787252..43609a2f3eb869 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs @@ -166,7 +166,7 @@ public sealed override AssemblyName[] GetReferencedAssemblies() public abstract override MethodInfo? EntryPoint { get; } // Manifest resource support. - public abstract override ManifestResourceInfo GetManifestResourceInfo(string resourceName); + public abstract override ManifestResourceInfo? GetManifestResourceInfo(string resourceName); public abstract override string[] GetManifestResourceNames(); public abstract override Stream? GetManifestResourceStream(string name); public sealed override Stream? GetManifestResourceStream(Type type, string name) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoStubAssembly.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoStubAssembly.cs index 3807a905adbf47..315efba1b9849f 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoStubAssembly.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoStubAssembly.cs @@ -17,7 +17,7 @@ internal RoStubAssembly() : base(null!, 0) { } public sealed override bool IsDynamic => throw null!; public sealed override event ModuleResolveEventHandler? ModuleResolve { add { throw null!; } remove { throw null!; } } public sealed override IEnumerable CustomAttributes => throw null!; - public sealed override ManifestResourceInfo GetManifestResourceInfo(string resourceName) => throw null!; + public sealed override ManifestResourceInfo? GetManifestResourceInfo(string resourceName) => throw null!; public sealed override string[] GetManifestResourceNames() => throw null!; public sealed override Stream GetManifestResourceStream(string name) => throw null!; protected sealed override AssemblyNameData[] ComputeAssemblyReferences() => throw null!; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Assembly/AssemblyTests.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Assembly/AssemblyTests.cs index 43179d98a0a56a..2dc40fa00d1c94 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Assembly/AssemblyTests.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Assembly/AssemblyTests.cs @@ -602,5 +602,27 @@ public static void CrossAssemblyTypeRefToNestedType() Assert.Equal(expected, bt); } } + + [Fact] + public static void ResourceDoesNotExist_GetManifestResourceInfo_ReturnsNull() + { + using (MetadataLoadContext lc = new MetadataLoadContext(new SimpleAssemblyResolver())) + { + Assembly a = lc.LoadFromByteArray(TestData.s_AssemblyWithEmbeddedResourcesImage); + ManifestResourceInfo? r = a.GetManifestResourceInfo("ResourceThatDoesNotExist"); + Assert.Null(r); + } + } + + [Fact] + public static void ResourceDoesNotExist_GetManifestResourceStream_ReturnsNull() + { + using (MetadataLoadContext lc = new MetadataLoadContext(new SimpleAssemblyResolver())) + { + Assembly a = lc.LoadFromByteArray(TestData.s_AssemblyWithEmbeddedResourcesImage); + Stream? r = a.GetManifestResourceStream("ResourceThatDoesNotExist"); + Assert.Null(r); + } + } } } From 9d22ab7810f888338f952316a15228082d85d2d1 Mon Sep 17 00:00:00 2001 From: Dan Moseley Date: Fri, 30 Jul 2021 22:14:51 -0600 Subject: [PATCH 11/64] Stabilize TestToString_OnExitedProcess (#56652) --- src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs index f275db05e48eed..e4f52b617096a2 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs @@ -489,7 +489,7 @@ public void TestToString_OnExitedProcess() // Ensure ToString does not throw an exception, but still returns // a representation of the object. - Assert.Equal("System.Diagnostics.Process", p.ToString()); + Assert.Contains("System.Diagnostics.Process", p.ToString()); } [Fact] From b0cb96e5caa95d3eeeffd3ed1ffa5b2c7f1d5785 Mon Sep 17 00:00:00 2001 From: Maoni Stephens Date: Fri, 30 Jul 2021 22:28:40 -0700 Subject: [PATCH 12/64] exclusive_sync check should failfast when hitting an error (#56660) --- src/coreclr/gc/gc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index b768bc2a588a25..9d285b64a38f8d 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -1146,7 +1146,7 @@ class exclusive_sync { if (alloc_objects [i] != (uint8_t*)0) { - GCToOSInterface::DebugBreak(); + FATAL_GC_ERROR(); } } } From 0f04d34ac4254f2ede46840300d1251ac65354d9 Mon Sep 17 00:00:00 2001 From: CW2 Date: Sat, 31 Jul 2021 07:54:03 +0200 Subject: [PATCH 13/64] Added Visual Studio build tools (#55629) (#56234) * Added Visual Studio build tools (#55629) Added description of build tools (CMake, Ninja and Python) installation as Visual Studio Individual Components. Added emphasis (bold) of Visual Studio installer sections and components (replaces previously used different styles of quotes). * Removed Python 32-bit VS component Python 64-bit component is enough for building x86 and x64 target architectures. Co-authored-by: Juan Hoyos --- .../requirements/windows-requirements.md | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/docs/workflow/requirements/windows-requirements.md b/docs/workflow/requirements/windows-requirements.md index 2629df320d2887..4430e47d7853cb 100644 --- a/docs/workflow/requirements/windows-requirements.md +++ b/docs/workflow/requirements/windows-requirements.md @@ -22,21 +22,28 @@ git config --system core.longpaths true - Install [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/). The Community edition is available free of charge. Visual Studio 2019 installation process: -- It's recommended to use 'Workloads' installation approach. The following are the minimum requirements: - - .NET Desktop Development with all default components. - - Desktop Development with C++ with all default components. -- To build for Arm32 or Arm64, make sure that you have the right architecture-specific compilers installed. In the "Individual components" window, in the "Compilers, build tools, and runtimes" section: - - For Arm32, check the box for "MSVC v142 - VS 2019 C++ ARM build tools (v14.23 or newer)". - - For Arm64, check the box for "MSVC v142 - VS 2019 C++ ARM64 build tools (v14.23 or newer)". +- It's recommended to use **Workloads** installation approach. The following are the minimum requirements: + - **.NET Desktop Development** with all default components, + - **Desktop Development with C++** with all default components. +- The build tools (CMake, Ninja and Python) can be downloaded and installed separately (see detailed instructions in the [section below](#build-tools)) or by selecting the following **Individual Components**: + - **C++ CMake tools for Windows** (includes Ninja), + - **Python 3 64-bit** (3.7.4 or newer). +- To build for Arm32 or Arm64, make sure that you have the right architecture-specific compilers installed. In the **Individual components** window, in the **Compilers, build tools, and runtimes** section: + - For Arm32, check the box for **MSVC v142 - VS 2019 C++ ARM build tools (Latest)** (v14.23 or newer), + - For Arm64, check the box for **MSVC v142 - VS 2019 C++ ARM64 build tools (Latest)** (v14.23 or newer). - To build the tests, you will need some additional components: - - Windows 10 SDK component version 10.0.18362 or newer. This component is installed by default as a part of 'Desktop Development with C++' workload. - - C++/CLI support for v142 build tools (v14.23 or newer) + - **Windows 10 SDK (10.0.18362)** or newer. This component is installed by default as a part of **Desktop Development with C++** workload. + - **C++/CLI support for v142 build tools (Latest)** (v14.23 or newer). A `.vsconfig` file is included in the root of the dotnet/runtime repository that includes all components needed to build the dotnet/runtime repository. You can [import `.vsconfig` in your Visual Studio installer](https://docs.microsoft.com/en-us/visualstudio/install/import-export-installation-configurations?view=vs-2019#import-a-configuration) to install all necessary components. Visual Studio 2019 16.6 or later is required for building the repository. Visual Studio 2019 16.10 is required to work with the libraries projects inside the Visual Studio IDE. -## CMake +## Build Tools + +These steps are required only in case the tools have not been installed as Visual Studio **Individual Components** (described above). + +### CMake - Install [CMake](https://cmake.org/download) for Windows. - Add its location (e.g. C:\Program Files (x86)\CMake\bin) to the PATH environment variable. @@ -44,13 +51,13 @@ Visual Studio 2019 16.6 or later is required for building the repository. Visual The dotnet/runtime repository recommends using CMake 3.16.4 or newer, but it may work with CMake 3.15.5. -## Ninja +### Ninja - Install Ninja in one of the two following ways - [Download the executable](https://github.com/ninja-build/ninja/releases) and add its location to [the Default PATH variable](#adding-to-the-default-path-variable). - [Install via a package manager](https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages), which should automatically add it to the PATH environment variable. -## Python +### Python - Install [Python](https://www.python.org/downloads/) for Windows. - Add its location (e.g. C:\Python*\) to the PATH environment variable. From 3ec2f6771416270f1a37b74b6afc375d068d20bc Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Sat, 31 Jul 2021 09:10:17 -0400 Subject: [PATCH 14/64] Enable skipped Runtime.Extensions tests on Android (#56586) 1. AppDomain TestingCreateInstanceFromObjectHandle and TestingCreateInstanceFromObjectHandleFullSignature were failing because the assembly file to load has to be case sensitive and wasn't. 2. AppDomain TargetFrameworkTest was permanently skipped 3. StringComparerTests CreateFromCultureAndOptions, CreateFromCultureAndOptionsStringSort, and CreateWithCulturesTest skips testing the turkish culture as it's problematic on Android 4. Environment.Exit ExitCode_VoidMainAppReturnsSetValue was permanently skipped Fixes https://github.com/dotnet/runtime/issues/49868 --- .../TestUtilities/System/PlatformDetection.cs | 3 ++ .../tests/System/AppDomainTests.cs | 50 +++++++++++------- .../tests/System/Environment.Exit.cs | 3 +- .../tests/System/StringComparer.cs | 52 ++++++++++--------- 4 files changed, 62 insertions(+), 46 deletions(-) diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index c1bb1854ff1ba1..d44f9bcfdd6614 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -54,6 +54,9 @@ public static partial class PlatformDetection public static bool Is64BitProcess => IntPtr.Size == 8; public static bool IsNotWindows => !IsWindows; + public static bool IsCaseInsensitiveOS => IsWindows || IsOSX; + public static bool IsCaseSensitiveOS => !IsCaseInsensitiveOS; + public static bool IsThreadingSupported => !IsBrowser; public static bool IsBinaryFormatterSupported => IsNotMobile; diff --git a/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.cs b/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.cs index 7360975078abae..ce88bd71623004 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.cs @@ -44,9 +44,7 @@ public void RelativeSearchPath_Is_Null() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "throws pNSE")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49868", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36896", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.Android | TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst, "The dotnet sdk will not be available on these platforms")] public void TargetFrameworkTest() { const int ExpectedExitCode = 0; @@ -800,9 +798,9 @@ public static void GetPermissionSet() } [Theory] - [ActiveIssue("https://github.com/dotnet/runtime/issues/34030", TestPlatforms.Linux | TestPlatforms.Browser | TestPlatforms.Android, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [MemberData(nameof(TestingCreateInstanceFromObjectHandleData))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/34030", TestPlatforms.Linux | TestPlatforms.Browser, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] [ActiveIssue("https://github.com/dotnet/runtime/issues/36896", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] + [MemberData(nameof(TestingCreateInstanceFromObjectHandleData))] public static void TestingCreateInstanceFromObjectHandle(string physicalFileName, string assemblyFile, string type, string returnedFullNameType, Type exceptionType) { ObjectHandle oh = null; @@ -838,18 +836,29 @@ public static void TestingCreateInstanceFromObjectHandle(string physicalFileName Assert.True(File.Exists(physicalFileName)); } - public static TheoryData TestingCreateInstanceFromObjectHandleData => new TheoryData + public static IEnumerable TestingCreateInstanceFromObjectHandleData() { + Type exceptionType; + + if (PlatformDetection.IsCaseSensitiveOS && PlatformDetection.IsMonoRuntime) + { + exceptionType = typeof(FileNotFoundException); + } + else + { + exceptionType = typeof(TypeLoadException); + } + // string physicalFileName, string assemblyFile, string typeName, returnedFullNameType, expectedException - { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", "AssemblyResolveTestApp.PublicClassSample", null }, - { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", "AssemblyResolveTestApp.PublicClassSample", typeof(TypeLoadException) }, + yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", "AssemblyResolveTestApp.PublicClassSample", null }; + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", "AssemblyResolveTestApp.PublicClassSample", exceptionType }; - { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", "AssemblyResolveTestApp.PrivateClassSample", null }, - { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", "AssemblyResolveTestApp.PrivateClassSample", typeof(TypeLoadException) }, + yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", "AssemblyResolveTestApp.PrivateClassSample", null }; + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", "AssemblyResolveTestApp.PrivateClassSample", exceptionType }; - { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(MissingMethodException) }, - { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclassnodefaultconstructorsample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(TypeLoadException) } - }; + yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", typeof(MissingMethodException) }; + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclassnodefaultconstructorsample", "AssemblyResolveTestApp.PublicClassNoDefaultConstructorSample", exceptionType }; + } [Theory] [MemberData(nameof(TestingCreateInstanceObjectHandleData))] @@ -901,7 +910,7 @@ public static void TestingCreateInstanceObjectHandle(string assemblyName, string }; [Theory] - [ActiveIssue("https://github.com/dotnet/runtime/issues/34030", TestPlatforms.Linux | TestPlatforms.Browser | TestPlatforms.Android, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/34030", TestPlatforms.Linux | TestPlatforms.Browser, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] [MemberData(nameof(TestingCreateInstanceFromObjectHandleFullSignatureData))] [ActiveIssue("https://github.com/dotnet/runtime/issues/36896", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public static void TestingCreateInstanceFromObjectHandleFullSignature(string physicalFileName, string assemblyFile, string type, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, string returnedFullNameType) @@ -919,14 +928,17 @@ public static IEnumerable TestingCreateInstanceFromObjectHandleFullSig { // string physicalFileName, string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes, returnedFullNameType yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" }; - yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" }; yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PublicClassSample", false, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" }; - yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" }; - yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" }; - yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" }; yield return new object[] { "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.dll", "AssemblyResolveTestApp.PrivateClassSample", false, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" }; - yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" }; + + if (PlatformDetection.IsCaseInsensitiveOS) + { + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" }; + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.publicclasssample", true, BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PublicClassSample" }; + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[0], CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" }; + yield return new object[] { "AssemblyResolveTestApp.dll", "assemblyresolvetestapp.dll", "assemblyresolvetestapp.privateclasssample", true, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, Type.DefaultBinder, new object[1] { 1 }, CultureInfo.InvariantCulture, null, "AssemblyResolveTestApp.PrivateClassSample" }; + } } [Theory] diff --git a/src/libraries/System.Runtime.Extensions/tests/System/Environment.Exit.cs b/src/libraries/System.Runtime.Extensions/tests/System/Environment.Exit.cs index f6ef6cef9f4637..ed187de932e90e 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/Environment.Exit.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/Environment.Exit.cs @@ -41,8 +41,7 @@ public static void ExitCode_Roundtrips(int exitCode) [InlineData(1)] // setting ExitCode and exiting Main [InlineData(2)] // setting ExitCode both from Main and from an Unloading event handler. [InlineData(3)] // using Exit(exitCode) - [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49868", TestPlatforms.Android)] + [SkipOnPlatform(TestPlatforms.Android | TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on Android, Browser, iOS, MacCatalyst, or tvOS.")] public static void ExitCode_VoidMainAppReturnsSetValue(int mode) { int expectedExitCode = 123; diff --git a/src/libraries/System.Runtime.Extensions/tests/System/StringComparer.cs b/src/libraries/System.Runtime.Extensions/tests/System/StringComparer.cs index ef8cd8945e38e3..f4e28a34b8dfb0 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/StringComparer.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/StringComparer.cs @@ -87,7 +87,7 @@ public static IEnumerable UpperLowerCasing_TestData() yield return new object[] { "abcd", "ABCD", "en-US" }; yield return new object[] { "latin i", "LATIN I", "en-US" }; - if (PlatformDetection.IsNotInvariantGlobalization) + if (PlatformDetection.IsNotInvariantGlobalization && !PlatformDetection.IsAndroid) { yield return new object[] { "turky \u0131", "TURKY I", "tr-TR" }; yield return new object[] { "turky i", "TURKY \u0130", "tr-TR" }; @@ -96,7 +96,6 @@ public static IEnumerable UpperLowerCasing_TestData() [Theory] [MemberData(nameof(UpperLowerCasing_TestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49868", TestPlatforms.Android)] public static void CreateWithCulturesTest(string lowerForm, string upperForm, string cultureName) { CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); @@ -164,28 +163,33 @@ public static void FromComparisonInvalidTest() AssertExtensions.Throws("comparisonType", () => StringComparer.FromComparison(maxInvalid)); } - public static TheoryData CreateFromCultureAndOptionsData => - new TheoryData + public static IEnumerable CreateFromCultureAndOptionsData() + { + yield return new object[] { "abcd", "ABCD", "en-US", CompareOptions.None, false}; + yield return new object[] { "latin i", "LATIN I", "en-US", CompareOptions.None, false}; + yield return new object[] { "turky \u0131", "TURKY I", "tr-TR", CompareOptions.None, false}; + yield return new object[] { "turky i", "TURKY \u0130", "tr-TR", CompareOptions.None, false}; + yield return new object[] { "abcd", "ABCD", "en-US", CompareOptions.IgnoreCase, true}; + yield return new object[] { "latin i", "LATIN I", "en-US", CompareOptions.IgnoreCase, true}; + + // Android has its own ICU, which doesn't work well with tr + if (!PlatformDetection.IsAndroid) { - { "abcd", "ABCD", "en-US", CompareOptions.None, false}, - { "latin i", "LATIN I", "en-US", CompareOptions.None, false}, - { "turky \u0131", "TURKY I", "tr-TR", CompareOptions.None, false}, - { "turky i", "TURKY \u0130", "tr-TR", CompareOptions.None, false}, - { "abcd", "ABCD", "en-US", CompareOptions.IgnoreCase, true}, - { "latin i", "LATIN I", "en-US", CompareOptions.IgnoreCase, true}, - { "turky \u0131", "TURKY I", "tr-TR", CompareOptions.IgnoreCase, true}, - { "turky i", "TURKY \u0130", "tr-TR", CompareOptions.IgnoreCase, true}, - { "abcd", "ab cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "abcd", "ab+cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "abcd", "ab%cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "abcd", "ab&cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "a-bcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "abcd*", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }, - { "ab$dd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, false }, - { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }, - }; + yield return new object[] { "turky \u0131", "TURKY I", "tr-TR", CompareOptions.IgnoreCase, true}; + yield return new object[] { "turky i", "TURKY \u0130", "tr-TR", CompareOptions.IgnoreCase, true}; + } + + yield return new object[] { "abcd", "ab cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "abcd", "ab+cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "abcd", "ab%cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "abcd", "ab&cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "a-bcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "abcd*", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }; + yield return new object[] { "ab$dd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, false }; + yield return new object[] { "abcd", "ab$cd", "en-US", CompareOptions.IgnoreSymbols, true }; + } public static TheoryData CreateFromCultureAndOptionsStringSortData => new TheoryData { @@ -196,7 +200,6 @@ public static void FromComparisonInvalidTest() [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInvariantGlobalization))] [MemberData(nameof(CreateFromCultureAndOptionsData))] [MemberData(nameof(CreateFromCultureAndOptionsStringSortData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49868", TestPlatforms.Android)] public static void CreateFromCultureAndOptions(string actualString, string expectedString, string cultureName, CompareOptions options, bool result) { CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); @@ -208,7 +211,6 @@ public static void CreateFromCultureAndOptions(string actualString, string expec [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInvariantGlobalization))] [MemberData(nameof(CreateFromCultureAndOptionsData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49868", TestPlatforms.Android)] public static void CreateFromCultureAndOptionsStringSort(string actualString, string expectedString, string cultureName, CompareOptions options, bool result) { CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); From 65f04b9f299bc0f57788dd4124b3748fbc92ef84 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Sat, 31 Jul 2021 08:46:27 -0600 Subject: [PATCH 15/64] Resolve MakeGenericType ILLink warning in DependencyInjection (#55102) * Resolve MakeGenericType ILLink warning in DependencyInjection Resolve the ILLink warning in DependencyInjection by adding a runtime check that is behind a new AppContext switch 'Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability'. The runtime check ensures the trimming annotations on the open generic types are compatible between the service and implementation types. The check is enabled by default when PublishTrimmed=true. * Make VerifyOpenGenericServiceTrimmability a full feature switch --- docs/workflow/trimming/feature-switches.md | 1 + ...ns.DependencyInjection.Abstractions.csproj | 2 +- .../src/ILLink/ILLink.Substitutions.xml | 7 ++ .../src/ILLink/ILLink.Suppressions.xml | 11 --- ...soft.Extensions.DependencyInjection.csproj | 9 ++- .../src/Resources/Strings.resx | 8 +- .../src/ServiceLookup/CallSiteFactory.cs | 75 ++++++++++++++++++- .../src/ServiceProvider.cs | 3 + ...xtensions.DependencyInjection.Tests.csproj | 11 ++- .../ServiceLookup/CallSiteFactoryTest.cs | 62 +++++++++++++++ 10 files changed, 171 insertions(+), 18 deletions(-) create mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Substitutions.xml delete mode 100644 src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Suppressions.xml diff --git a/docs/workflow/trimming/feature-switches.md b/docs/workflow/trimming/feature-switches.md index e7aa6be63cf979..5a693bd7bc00e4 100644 --- a/docs/workflow/trimming/feature-switches.md +++ b/docs/workflow/trimming/feature-switches.md @@ -25,6 +25,7 @@ configurations but their defaults might vary as any SDK can set the defaults dif | EnableCppCLIHostActivation | System.Runtime.InteropServices.EnableCppCLIHostActivation | C++/CLI host activation code is disabled when set to false and related functionality can be trimmed. | | MetadataUpdaterSupport | System.Reflection.Metadata.MetadataUpdater.IsSupported | Metadata update related code to be trimmed when set to false | | _EnableConsumingManagedCodeFromNativeHosting | System.Runtime.InteropServices.EnableConsumingManagedCodeFromNativeHosting | Getting a managed function from native hosting is disabled when set to false and related functionality can be trimmed. | +| VerifyDependencyInjectionOpenGenericServiceTrimmability | Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability | When set to true, DependencyInjection will verify trimming annotations applied to open generic services are correct | | NullabilityInfoContextSupport | System.Reflection.NullabilityInfoContext.IsSupported | Nullable attributes can be trimmed when set to false | | _AggressiveAttributeTrimming | System.AggressiveAttributeTrimming | When set to true, aggressively trims attributes to allow for the most size savings possible, even if it could result in runtime behavior changes | diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj index b275c71c780c76..dc32454f1759ac 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent);netstandard2.1;netstandard2.0;net461 diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Substitutions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Substitutions.xml new file mode 100644 index 00000000000000..eb381de19d6153 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Substitutions.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Suppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Suppressions.xml deleted file mode 100644 index 3a09880ba32d15..00000000000000 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ILLink/ILLink.Suppressions.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - ILLink - IL2055 - member - M:Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateOpenGeneric(Microsoft.Extensions.DependencyInjection.ServiceDescriptor,System.Type,Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain,System.Int32,System.Boolean) - - - \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj index b93c0a8e61e66b..7ee51306d042d5 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent);netstandard2.1;netstandard2.0;net461 @@ -19,6 +19,10 @@ $(DefineConstants);SAVE_ASSEMBLIES + + + + @@ -32,7 +36,7 @@ - + @@ -41,7 +45,6 @@ Link="Common\src\Extensions\ParameterDefaultValue\ParameterDefaultValue.cs" /> - diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx index e76446a526b4fc..efbb7cc4a7451f 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/Resources/Strings.resx @@ -174,4 +174,10 @@ Call site type {0} is not supported - \ No newline at end of file + + Generic implementation type '{0}' has a DynamicallyAccessedMembers attribute applied to a generic argument type, but the service type '{1}' doesn't have a matching DynamicallyAccessedMembers attribute on its generic argument type. + + + Generic implementation type '{0}' has a DefaultConstructorConstraint ('new()' constraint), but the generic service type '{1}' doesn't. + + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs index a2e02ce4f50010..06bcdf632879ca 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs @@ -51,11 +51,18 @@ private void Populate() SR.Format(SR.TypeCannotBeActivated, implementationType, serviceType)); } - if (serviceType.GetGenericArguments().Length != implementationType.GetGenericArguments().Length) + Type[] serviceTypeGenericArguments = serviceType.GetGenericArguments(); + Type[] implementationTypeGenericArguments = implementationType.GetGenericArguments(); + if (serviceTypeGenericArguments.Length != implementationTypeGenericArguments.Length) { throw new ArgumentException( SR.Format(SR.ArityOfOpenGenericServiceNotEqualArityOfOpenGenericImplementation, serviceType, implementationType), "descriptors"); } + + if (ServiceProvider.VerifyOpenGenericServiceTrimmability) + { + ValidateTrimmingAnnotations(serviceType, serviceTypeGenericArguments, implementationType, implementationTypeGenericArguments); + } } else if (descriptor.ImplementationInstance == null && descriptor.ImplementationFactory == null) { @@ -77,6 +84,68 @@ private void Populate() } } + /// + /// Validates that two generic type definitions have compatible trimming annotations on their generic arguments. + /// + /// + /// When open generic types are used in DI, there is an error when the concrete implementation type + /// has [DynamicallyAccessedMembers] attributes on a generic argument type, but the interface/service type + /// doesn't have matching annotations. The problem is that the trimmer doesn't see the members that need to + /// be preserved on the type being passed to the generic argument. But when the interface/service type also has + /// the annotations, the trimmer will see which members need to be preserved on the closed generic argument type. + /// + private static void ValidateTrimmingAnnotations( + Type serviceType, + Type[] serviceTypeGenericArguments, + Type implementationType, + Type[] implementationTypeGenericArguments) + { + Debug.Assert(serviceTypeGenericArguments.Length == implementationTypeGenericArguments.Length); + + for (int i = 0; i < serviceTypeGenericArguments.Length; i++) + { + Type serviceGenericType = serviceTypeGenericArguments[i]; + Type implementationGenericType = implementationTypeGenericArguments[i]; + + DynamicallyAccessedMemberTypes serviceDynamicallyAccessedMembers = GetDynamicallyAccessedMemberTypes(serviceGenericType); + DynamicallyAccessedMemberTypes implementationDynamicallyAccessedMembers = GetDynamicallyAccessedMemberTypes(implementationGenericType); + + if (!AreCompatible(serviceDynamicallyAccessedMembers, implementationDynamicallyAccessedMembers)) + { + throw new ArgumentException(SR.Format(SR.TrimmingAnnotationsDoNotMatch, implementationType.FullName, serviceType.FullName)); + } + + bool serviceHasNewConstraint = serviceGenericType.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint); + bool implementationHasNewConstraint = implementationGenericType.GenericParameterAttributes.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint); + if (implementationHasNewConstraint && !serviceHasNewConstraint) + { + throw new ArgumentException(SR.Format(SR.TrimmingAnnotationsDoNotMatch_NewConstraint, implementationType.FullName, serviceType.FullName)); + } + } + } + + private static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypes(Type serviceGenericType) + { + foreach (CustomAttributeData attributeData in serviceGenericType.GetCustomAttributesData()) + { + if (attributeData.AttributeType.FullName == "System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute" && + attributeData.ConstructorArguments.Count == 1 && + attributeData.ConstructorArguments[0].ArgumentType.FullName == "System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes") + { + return (DynamicallyAccessedMemberTypes)(int)attributeData.ConstructorArguments[0].Value; + } + } + + return DynamicallyAccessedMemberTypes.None; + } + + private static bool AreCompatible(DynamicallyAccessedMemberTypes serviceDynamicallyAccessedMembers, DynamicallyAccessedMemberTypes implementationDynamicallyAccessedMembers) + { + // The DynamicallyAccessedMemberTypes don't need to exactly match. + // The service type needs to preserve a superset of the members required by the implementation type. + return serviceDynamicallyAccessedMembers.HasFlag(implementationDynamicallyAccessedMembers); + } + // For unit testing internal int? GetSlot(ServiceDescriptor serviceDescriptor) { @@ -273,6 +342,10 @@ private ServiceCallSite TryCreateExact(ServiceDescriptor descriptor, Type servic return null; } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:MakeGenericType", + Justification = "MakeGenericType here is used to create a closed generic implementation type given the closed service type. " + + "Trimming annotations on the generic types are verified when 'Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability' is set, which is set by default when PublishTrimmed=true. " + + "That check informs developers when these generic types don't have compatible trimming annotations.")] private ServiceCallSite TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, int slot, bool throwOnConstraintViolation) { if (serviceType.IsConstructedGenericType && diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs index afe118acf79093..a05e82f8a44986 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs @@ -30,6 +30,9 @@ public sealed class ServiceProvider : IServiceProvider, IDisposable, IAsyncDispo internal ServiceProviderEngineScope Root { get; } + internal static bool VerifyOpenGenericServiceTrimmability { get; } = + AppContext.TryGetSwitch("Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability", out bool verifyOpenGenerics) ? verifyOpenGenerics : false; + internal ServiceProvider(IEnumerable serviceDescriptors, ServiceProviderOptions options) { // note that Root needs to be set before calling GetEngine(), because the engine may need to access Root diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/Microsoft.Extensions.DependencyInjection.Tests.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/Microsoft.Extensions.DependencyInjection.Tests.csproj index 073451c2cd9f08..698e3ec3dd659c 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/Microsoft.Extensions.DependencyInjection.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/Microsoft.Extensions.DependencyInjection.Tests.csproj @@ -1,8 +1,11 @@ - + $(NetCoreAppCurrent);net461 true + true + + $(NoWarn);CS0436 @@ -11,6 +14,12 @@ Link="Shared\SingleThreadedSynchronizationContext.cs" /> + + + + + + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs index 8d6a78029fefff..da24dca4e92cf9 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceLookup/CallSiteFactoryTest.cs @@ -3,9 +3,11 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Threading.Tasks; +using Microsoft.DotNet.RemoteExecutor; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Specification.Fakes; using Xunit; @@ -849,6 +851,51 @@ public void CallSitesAreUniquePerServiceTypeAndSlotWithOpenGenericInGraph() } } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] // RuntimeConfigurationOptions are not supported on .NET Framework (and neither is trimming) + public void VerifyOpenGenericTrimmabilityChecks() + { + RemoteInvokeOptions options = new RemoteInvokeOptions(); + options.RuntimeConfigurationOptions.Add("Microsoft.Extensions.DependencyInjection.VerifyOpenGenericServiceTrimmability", "true"); + + using RemoteInvokeHandle remoteHandle = RemoteExecutor.Invoke(() => + { + (Type, Type)[] invalidTestCases = new[] + { + (typeof(IFakeOpenGenericService<>), typeof(ClassWithNewConstraint<>)), + (typeof(IServiceWithoutTrimmingAnnotations<>), typeof(ServiceWithTrimmingAnnotations<>)), + (typeof(IServiceWithPublicConstructors<>), typeof(ServiceWithPublicProperties<>)), + (typeof(IServiceWithTwoGenerics<,>), typeof(ServiceWithTwoGenericsInvalid<,>)), + }; + foreach ((Type serviceType, Type implementationType) in invalidTestCases) + { + ServiceDescriptor[] serviceDescriptors = new[] + { + new ServiceDescriptor(serviceType, implementationType, ServiceLifetime.Singleton) + }; + + Assert.Throws(() => new CallSiteFactory(serviceDescriptors)); + } + + (Type, Type)[] validTestCases = new[] + { + (typeof(IFakeOpenGenericService<>), typeof(FakeOpenGenericService<>)), + (typeof(IServiceWithPublicConstructors<>), typeof(ServiceWithPublicConstructors<>)), + (typeof(IServiceWithTwoGenerics<,>), typeof(ServiceWithTwoGenericsValid<,>)), + (typeof(IServiceWithMoreMemberTypes<>), typeof(ServiceWithLessMemberTypes<>)), + }; + foreach ((Type serviceType, Type implementationType) in validTestCases) + { + ServiceDescriptor[] serviceDescriptors = new[] + { + new ServiceDescriptor(serviceType, implementationType, ServiceLifetime.Singleton) + }; + + Assert.NotNull(new CallSiteFactory(serviceDescriptors)); + } + }, options); + } + private static Func GetCallSiteFactory(params ServiceDescriptor[] descriptors) { var collection = new ServiceCollection(); @@ -887,5 +934,20 @@ private class ClassB { public ClassB(ClassC cc) { } } private class ClassC { } private class ClassD { public ClassD(ClassC cd) { } } private class ClassE { public ClassE(ClassB cb) { } } + + // Open generic with trimming annotations + private interface IServiceWithoutTrimmingAnnotations { } + private class ServiceWithTrimmingAnnotations<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T> : IServiceWithoutTrimmingAnnotations { } + + private interface IServiceWithPublicConstructors<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T> { } + private class ServiceWithPublicProperties<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>: IServiceWithPublicConstructors { } + private class ServiceWithPublicConstructors<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>: IServiceWithPublicConstructors { } + + private interface IServiceWithTwoGenerics { } + private class ServiceWithTwoGenericsInvalid : IServiceWithTwoGenerics { } + private class ServiceWithTwoGenericsValid : IServiceWithTwoGenerics { } + + private interface IServiceWithMoreMemberTypes<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties)] T> { } + private class ServiceWithLessMemberTypes<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T> : IServiceWithMoreMemberTypes { } } } From 7d9a08cd372ac957a4ce24f005b2a9c88cb19dea Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Sat, 31 Jul 2021 12:13:43 -0400 Subject: [PATCH 16/64] Enable trimming TLS arrays in ArrayPool.Shared (#56316) * Enable trimming TLS arrays in ArrayPool.Shared Today arrays stored in `ArrayPool.Shared`'s per-core buckets have trimming applied, but arrays stored in the per-thread buckets are only trimmed when there's high memory pressure. This change enables all buffers to be trimmed (eventually). Every time our gen2 callback runs, it ensures any non-timestamped buffers have a timestamp, and also ensures that any timestamped buffers are still timely... if any aren't, they're eligible for trimming. The timestamp is reset for TLS arrays when they're stored, and for per-core buckets when they transition from empty to non-empty; the latter is just a tweak on the current behavior, which incurs the cost of Environment.TickCount upon that transition, whereas now we only pay it as part of the trimming pass. * Address PR feedback * Work around bad linker transform --- .../tests/ArrayPool/CollectionTests.cs | 78 ++++-- .../TlsOverPerCoreLockedStacksArrayPool.cs | 229 ++++++++++++------ 2 files changed, 208 insertions(+), 99 deletions(-) diff --git a/src/libraries/System.Buffers/tests/ArrayPool/CollectionTests.cs b/src/libraries/System.Buffers/tests/ArrayPool/CollectionTests.cs index 6b39f5409bdea6..b4b9685ff887a9 100644 --- a/src/libraries/System.Buffers/tests/ArrayPool/CollectionTests.cs +++ b/src/libraries/System.Buffers/tests/ArrayPool/CollectionTests.cs @@ -23,48 +23,51 @@ public void BuffersAreCollectedWhenStale() const int BufferCount = 8; const int BufferSize = 1025; - // Get the pool and check our trim setting - var pool = ArrayPool.Shared; - List rentedBuffers = new List(); // Rent and return a set of buffers for (int i = 0; i < BufferCount; i++) { - rentedBuffers.Add(pool.Rent(BufferSize)); + rentedBuffers.Add(ArrayPool.Shared.Rent(BufferSize)); } for (int i = 0; i < BufferCount; i++) { - pool.Return(rentedBuffers[i]); + ArrayPool.Shared.Return(rentedBuffers[i]); } // Rent what we returned and ensure they are the same for (int i = 0; i < BufferCount; i++) { - var buffer = pool.Rent(BufferSize); + var buffer = ArrayPool.Shared.Rent(BufferSize); Assert.Contains(rentedBuffers, item => ReferenceEquals(item, buffer)); } for (int i = 0; i < BufferCount; i++) { - pool.Return(rentedBuffers[i]); + ArrayPool.Shared.Return(rentedBuffers[i]); + } + + // Trigger a few Gen2 GCs to make sure the pool has appropriately time stamped buffers. + for (int i = 0; i < 2; i++) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); } // Now wait a little over a minute and force a GC to get some buffers returned Console.WriteLine("Waiting a minute for buffers to go stale..."); Thread.Sleep(61 * 1000); - GC.Collect(2); + GC.Collect(); GC.WaitForPendingFinalizers(); bool foundNewBuffer = false; for (int i = 0; i < BufferCount; i++) { - var buffer = pool.Rent(BufferSize); + var buffer = ArrayPool.Shared.Rent(BufferSize); if (!rentedBuffers.Any(item => ReferenceEquals(item, buffer))) { foundNewBuffer = true; } } - // Should only have found a new buffer if we're trimming Assert.True(foundNewBuffer); }, 3 * 60 * 1000); // This test has to wait for the buffers to go stale (give it three minutes) } @@ -78,21 +81,18 @@ public unsafe void ThreadLocalIsCollectedUnderHighPressure() { RemoteInvokeWithTrimming(() => { - // Get the pool and check our trim setting - var pool = ArrayPool.Shared; - // Create our buffer, return it, re-rent it and ensure we have the same one const int BufferSize = 4097; - var buffer = pool.Rent(BufferSize); - pool.Return(buffer); - Assert.Same(buffer, pool.Rent(BufferSize)); + byte[] buffer = ArrayPool.Shared.Rent(BufferSize); + ArrayPool.Shared.Return(buffer); + Assert.Same(buffer, ArrayPool.Shared.Rent(BufferSize)); // Return it and put memory pressure on to get it cleared - pool.Return(buffer); + ArrayPool.Shared.Return(buffer); const int AllocSize = 1024 * 1024 * 64; int PageSize = Environment.SystemPageSize; - var pressureMethod = pool.GetType().GetMethod("GetMemoryPressure", BindingFlags.Static | BindingFlags.NonPublic); + var pressureMethod = ArrayPool.Shared.GetType().GetMethod("GetMemoryPressure", BindingFlags.Static | BindingFlags.NonPublic); do { Span native = new Span(Marshal.AllocHGlobal(AllocSize).ToPointer(), AllocSize); @@ -109,10 +109,45 @@ public unsafe void ThreadLocalIsCollectedUnderHighPressure() GC.WaitForPendingFinalizers(); // Should have a new buffer now - Assert.NotSame(buffer, pool.Rent(BufferSize)); + Assert.NotSame(buffer, ArrayPool.Shared.Rent(BufferSize)); }); } + // This test can cause problems for other tests run in parallel (from other assemblies) as + // it pushes the physical memory usage above 80% temporarily. + [OuterLoop("This is a long running test (over 2 minutes)")] + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public unsafe void ThreadLocalIsCollectedUnderNormalPressure() + { + RemoteInvokeWithTrimming(() => + { + // Create our buffer, return it, re-rent it and ensure we have the same one + const int BufferSize = 4097; + byte[] buffer = ArrayPool.Shared.Rent(BufferSize); + ArrayPool.Shared.Return(buffer); + Assert.Same(buffer, ArrayPool.Shared.Rent(BufferSize)); + + // Return it and put memory pressure on to get it cleared + ArrayPool.Shared.Return(buffer); + + // Make sure buffer gets time stamped + for (int i = 0; i < 2; i++) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + + // Now wait for enough time to pass and force a GC to get buffers dropped + Console.WriteLine("Waiting a minute for buffers to go stale..."); + Thread.Sleep(61 * 1000); + GC.Collect(); + GC.WaitForPendingFinalizers(); + + // Should have a new buffer now + Assert.NotSame(buffer, ArrayPool.Shared.Rent(BufferSize)); + }, 3 * 60 * 1000); // This test has to wait for the buffers to go stale (give it three minutes) + } + private static bool IsPreciseGcSupportedAndRemoteExecutorSupported => PlatformDetection.IsPreciseGcSupported && RemoteExecutor.IsSupported; [ActiveIssue("https://github.com/dotnet/runtime/issues/44037")] @@ -121,9 +156,8 @@ public void PollingEventFires() { RemoteInvokeWithTrimming(() => { - var pool = ArrayPool.Shared; bool pollEventFired = false; - var buffer = pool.Rent(10); + float[] buffer = ArrayPool.Shared.Rent(10); // Polling doesn't start until the thread locals are created for a pool. // Try before the return then after. @@ -141,7 +175,7 @@ public void PollingEventFires() }); Assert.False(pollEventFired, "collection isn't hooked up until the first item is returned"); - pool.Return(buffer); + ArrayPool.Shared.Return(buffer); RunWithListener(() => { diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs index fd4d242463c321..d38bda960e7528 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs @@ -21,12 +21,6 @@ namespace System.Buffers /// internal sealed partial class TlsOverPerCoreLockedStacksArrayPool : ArrayPool { - // TODO https://github.com/dotnet/coreclr/pull/7747: "Investigate optimizing ArrayPool heuristics" - // - Explore caching in TLS more than one array per size per thread, and moving stale buffers to the global queue. - // - Explore changing the size of each per-core bucket, potentially dynamically or based on other factors like array size. - // - Investigate whether false sharing is causing any issues, in particular on LockedStack's count and the contents of its array. - // ... - /// The number of buckets (array sizes) in the pool, one for each array length, starting from length 16. private const int NumBuckets = 27; // Utilities.SelectBucketIndex(1024 * 1024 * 1024 + 1) /// Maximum number of per-core stacks to use per array size. @@ -36,9 +30,9 @@ internal sealed partial class TlsOverPerCoreLockedStacksArrayPool : ArrayPool /// A per-thread array of arrays, to cache one array per array size per thread. [ThreadStatic] - private static T[]?[]? t_tlsBuckets; + private static ThreadLocalArray[]? t_tlsBuckets; /// Used to keep track of all thread local buckets for trimming if needed. - private readonly ConditionalWeakTable _allTlsBuckets = new ConditionalWeakTable(); + private readonly ConditionalWeakTable _allTlsBuckets = new ConditionalWeakTable(); /// /// An array of per-core array stacks. The slots are lazily initialized to avoid creating /// lots of overhead for unused array sizes. @@ -67,13 +61,13 @@ public override T[] Rent(int minimumLength) int bucketIndex = Utilities.SelectBucketIndex(minimumLength); // First, try to get an array from TLS if possible. - T[]?[]? tlsBuckets = t_tlsBuckets; + ThreadLocalArray[]? tlsBuckets = t_tlsBuckets; if (tlsBuckets is not null && (uint)bucketIndex < (uint)tlsBuckets.Length) { - buffer = tlsBuckets[bucketIndex]; + buffer = tlsBuckets[bucketIndex].Array; if (buffer is not null) { - tlsBuckets[bucketIndex] = null; + tlsBuckets[bucketIndex].Array = null; if (log.IsEnabled()) { log.BufferRented(buffer.GetHashCode(), buffer.Length, Id, bucketIndex); @@ -143,7 +137,7 @@ public override void Return(T[] array, bool clearArray = false) // this if the array being returned is erroneous or too large for the pool, but the // former condition is an error we don't need to optimize for, and the latter is incredibly // rare, given a max size of 1B elements. - T[]?[] tlsBuckets = t_tlsBuckets ?? InitializeTlsBucketsAndTrimming(); + ThreadLocalArray[] tlsBuckets = t_tlsBuckets ?? InitializeTlsBucketsAndTrimming(); bool haveBucket = false; bool returned = true; @@ -166,8 +160,9 @@ public override void Return(T[] array, bool clearArray = false) // Store the array into the TLS bucket. If there's already an array in it, // push that array down into the per-core stacks, preferring to keep the latest // one in TLS for better locality. - T[]? prev = tlsBuckets[bucketIndex]; - tlsBuckets[bucketIndex] = array; + ref ThreadLocalArray tla = ref tlsBuckets[bucketIndex]; + T[]? prev = tla.Array; + tla = new ThreadLocalArray(array); if (prev is not null) { PerCoreLockedStacks stackBucket = _buckets[bucketIndex] ?? CreatePerCoreLockedStacks(bucketIndex); @@ -191,58 +186,110 @@ public override void Return(T[] array, bool clearArray = false) public bool Trim() { - int milliseconds = Environment.TickCount; + int currentMilliseconds = Environment.TickCount; Utilities.MemoryPressure pressure = Utilities.GetMemoryPressure(); + // Log that we're trimming. ArrayPoolEventSource log = ArrayPoolEventSource.Log; if (log.IsEnabled()) { - log.BufferTrimPoll(milliseconds, (int)pressure); + log.BufferTrimPoll(currentMilliseconds, (int)pressure); } + // Trim each of the per-core buckets. PerCoreLockedStacks?[] perCoreBuckets = _buckets; for (int i = 0; i < perCoreBuckets.Length; i++) { - perCoreBuckets[i]?.Trim((uint)milliseconds, Id, pressure, Utilities.GetMaxSizeForBucket(i)); + perCoreBuckets[i]?.Trim(currentMilliseconds, Id, pressure, Utilities.GetMaxSizeForBucket(i)); } + // Trim each of the TLS buckets. Note that threads may be modifying their TLS slots concurrently with + // this trimming happening. We do not force synchronization with those operations, so we accept the fact + // that we may end up firing a trimming event even if an array wasn't trimmed, and potentially + // trim an array we didn't need to. Both of these should be rare occurrences. + + // Under high pressure, release all thread locals. if (pressure == Utilities.MemoryPressure.High) { - // Under high pressure, release all thread locals +#if !MONO // TODO https://github.com/mono/linker/issues/2181: Remove !MONO ifdefs in this method once is fixed if (log.IsEnabled()) { - foreach (KeyValuePair tlsBuckets in _allTlsBuckets) + foreach (KeyValuePair tlsBuckets in _allTlsBuckets) { - T[]?[] buckets = tlsBuckets.Key; + ThreadLocalArray[] buckets = tlsBuckets.Key; for (int i = 0; i < buckets.Length; i++) { - T[]? buffer = Interlocked.Exchange(ref buckets[i], null); - if (buffer is not null) + if (Interlocked.Exchange(ref buckets[i].Array, null) is T[] buffer) { - // As we don't want to take a perf hit in the rent path it - // is possible that a buffer could be rented as we "free" it. log.BufferTrimmed(buffer.GetHashCode(), buffer.Length, Id); } } } } else +#endif { - foreach (KeyValuePair tlsBuckets in _allTlsBuckets) + foreach (KeyValuePair tlsBuckets in _allTlsBuckets) { Array.Clear(tlsBuckets.Key); } } } + else + { + // Otherwise, release thread locals based on how long we've observed them to be stored. This time is + // approximate, with the time set not when the array is stored but when we see it during a Trim, so it + // takes at least two Trim calls (and thus two gen2 GCs) to drop an array, unless we're in high memory + // pressure. These values have been set arbitrarily; we could tune them in the future. + uint millisecondsThreshold = pressure switch + { + Utilities.MemoryPressure.Medium => 15_000, + _ => 30_000, + }; + + foreach (KeyValuePair tlsBuckets in _allTlsBuckets) + { + ThreadLocalArray[] buckets = tlsBuckets.Key; + for (int i = 0; i < buckets.Length; i++) + { + if (buckets[i].Array is null) + { + continue; + } + + // We treat 0 to mean it hasn't yet been seen in a Trim call. In the very rare case where Trim records 0, + // it'll take an extra Trim call to remove the array. + int lastSeen = buckets[i].MillisecondsTimeStamp; + if (lastSeen == 0) + { + buckets[i].MillisecondsTimeStamp = currentMilliseconds; + } + else if ((currentMilliseconds - lastSeen) >= millisecondsThreshold) + { + // Time noticeably wrapped, or we've surpassed the threshold. + // Clear out the array, and log its being trimmed if desired. + if (Interlocked.Exchange(ref buckets[i].Array, null) is T[] buffer) + { +#if !MONO + if (log.IsEnabled()) + { + log.BufferTrimmed(buffer.GetHashCode(), buffer.Length, Id); + } +#endif + } + } + } + } + } return true; } - private T[]?[] InitializeTlsBucketsAndTrimming() + private ThreadLocalArray[] InitializeTlsBucketsAndTrimming() { - Debug.Assert(t_tlsBuckets is null); + Debug.Assert(t_tlsBuckets is null, $"Non-null {nameof(t_tlsBuckets)}"); - T[]?[]? tlsBuckets = new T[NumBuckets][]; + var tlsBuckets = new ThreadLocalArray[NumBuckets]; t_tlsBuckets = tlsBuckets; _allTlsBuckets.Add(tlsBuckets, null); @@ -307,12 +354,12 @@ public bool TryPush(T[] array) return null; } - public void Trim(uint tickCount, int id, Utilities.MemoryPressure pressure, int bucketSize) + public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure pressure, int bucketSize) { LockedStack[] stacks = _perCoreStacks; for (int i = 0; i < stacks.Length; i++) { - stacks[i].Trim(tickCount, id, pressure, bucketSize); + stacks[i].Trim(currentMilliseconds, id, pressure, bucketSize); } } } @@ -320,9 +367,12 @@ public void Trim(uint tickCount, int id, Utilities.MemoryPressure pressure, int /// Provides a simple, bounded stack of arrays, protected by a lock. private sealed class LockedStack { + /// The arrays in the stack. private readonly T[]?[] _arrays = new T[MaxBuffersPerArraySizePerCore][]; + /// Number of arrays stored in . private int _count; - private uint _firstStackItemMS; + /// Timestamp set by Trim when it sees this as 0. + private int _millisecondsTimestamp; [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryPush(T[] array) @@ -335,8 +385,9 @@ public bool TryPush(T[] array) { if (count == 0) { - // Stash the time the bottom of the stack was filled - _firstStackItemMS = (uint)Environment.TickCount; + // Reset the time stamp now that we're transitioning from empty to non-empty. + // Trim will see this as 0 and initialize it to the current time when Trim is called. + _millisecondsTimestamp = 0; } arrays[count] = array; @@ -364,11 +415,10 @@ public bool TryPush(T[] array) return arr; } - public void Trim(uint tickCount, int id, Utilities.MemoryPressure pressure, int bucketSize) + public void Trim(int currentMilliseconds, int id, Utilities.MemoryPressure pressure, int bucketSize) { - const uint StackTrimAfterMS = 60 * 1000; // Trim after 60 seconds for low/moderate pressure - const uint StackHighTrimAfterMS = 10 * 1000; // Trim after 10 seconds for high pressure - const uint StackRefreshMS = StackTrimAfterMS / 4; // Time bump after trimming (1/4 trim time) + const int StackTrimAfterMS = 60 * 1000; // Trim after 60 seconds for low/moderate pressure + const int StackHighTrimAfterMS = 10 * 1000; // Trim after 10 seconds for high pressure const int StackLowTrimCount = 1; // Trim one item when pressure is low const int StackMediumTrimCount = 2; // Trim two items when pressure is moderate const int StackHighTrimCount = MaxBuffersPerArraySizePerCore; // Trim all items when pressure is high @@ -381,63 +431,88 @@ public void Trim(uint tickCount, int id, Utilities.MemoryPressure pressure, int return; } - uint trimTicks = pressure == Utilities.MemoryPressure.High ? StackHighTrimAfterMS : StackTrimAfterMS; + int trimMilliseconds = pressure == Utilities.MemoryPressure.High ? StackHighTrimAfterMS : StackTrimAfterMS; lock (this) { - if (_count > 0 && _firstStackItemMS > tickCount || (tickCount - _firstStackItemMS) > trimTicks) + if (_count == 0) { - // We've wrapped the tick count or elapsed enough time since the - // first item went into the stack. Drop the top item so it can - // be collected and make the stack look a little newer. + return; + } - ArrayPoolEventSource log = ArrayPoolEventSource.Log; - int trimCount = StackLowTrimCount; - switch (pressure) - { - case Utilities.MemoryPressure.High: - trimCount = StackHighTrimCount; + if (_millisecondsTimestamp == 0) + { + _millisecondsTimestamp = currentMilliseconds; + return; + } - // When pressure is high, aggressively trim larger arrays. - if (bucketSize > StackLargeBucket) - { - trimCount++; - } - if (Unsafe.SizeOf() > StackModerateTypeSize) - { - trimCount++; - } - if (Unsafe.SizeOf() > StackLargeTypeSize) - { - trimCount++; - } - break; + if ((currentMilliseconds - _millisecondsTimestamp) <= trimMilliseconds) + { + return; + } - case Utilities.MemoryPressure.Medium: - trimCount = StackMediumTrimCount; - break; - } + // We've elapsed enough time since the first item went into the stack. + // Drop the top item so it can be collected and make the stack look a little newer. - while (_count > 0 && trimCount-- > 0) - { - T[]? array = _arrays[--_count]; - Debug.Assert(array is not null, "No nulls should have been present in slots < _count."); - _arrays[_count] = null; + ArrayPoolEventSource log = ArrayPoolEventSource.Log; + int trimCount = StackLowTrimCount; + switch (pressure) + { + case Utilities.MemoryPressure.High: + trimCount = StackHighTrimCount; - if (log.IsEnabled()) + // When pressure is high, aggressively trim larger arrays. + if (bucketSize > StackLargeBucket) { - log.BufferTrimmed(array.GetHashCode(), array.Length, id); + trimCount++; } - } + if (Unsafe.SizeOf() > StackModerateTypeSize) + { + trimCount++; + } + if (Unsafe.SizeOf() > StackLargeTypeSize) + { + trimCount++; + } + break; + + case Utilities.MemoryPressure.Medium: + trimCount = StackMediumTrimCount; + break; + } - if (_count > 0 && _firstStackItemMS < uint.MaxValue - StackRefreshMS) + while (_count > 0 && trimCount-- > 0) + { + T[]? array = _arrays[--_count]; + Debug.Assert(array is not null, "No nulls should have been present in slots < _count."); + _arrays[_count] = null; + + if (log.IsEnabled()) { - // Give the remaining items a bit more time - _firstStackItemMS += StackRefreshMS; + log.BufferTrimmed(array.GetHashCode(), array.Length, id); } } + + _millisecondsTimestamp = _count > 0 ? + _millisecondsTimestamp + (trimMilliseconds / 4) : // Give the remaining items a bit more time + 0; } } } + + /// Wrapper for arrays stored in ThreadStatic buckets. + private struct ThreadLocalArray + { + /// The stored array. + public T[]? Array; + /// Environment.TickCount timestamp for when this array was observed by Trim. + public int MillisecondsTimeStamp; + + public ThreadLocalArray(T[] array) + { + Array = array; + MillisecondsTimeStamp = 0; + } + } } } From e176fdf6437121471cb0ca11c545d831feea5950 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Sun, 1 Aug 2021 01:37:23 +0200 Subject: [PATCH 17/64] Update position before ReadAsync starts, but fix it after incomplete read (#56531) * move CanRead and CanWrite checks to FileStream * don't check IsClosed twice_(FileHandle.CanSeek already contains a IsClosed check) * add a failing test * handle incomplete async reads * don't try to cache file length when file is opened for writing, as updating file position before performing async write can lead to invalid cached length value * maybe Win 7 & 8 fix --- .../tests/FileStream/ReadAsync.cs | 34 ++++++++++ ...andle.OverlappedValueTaskSource.Windows.cs | 20 +++++- .../src/System/IO/FileStream.cs | 36 ++++++++--- .../src/System/IO/RandomAccess.Windows.cs | 15 ++++- .../AsyncWindowsFileStreamStrategy.cs | 64 ++++++------------- .../IO/Strategies/OSFileStreamStrategy.cs | 36 ++--------- .../IO/Strategies/UnixFileStreamStrategy.cs | 47 ++++++-------- 7 files changed, 139 insertions(+), 113 deletions(-) diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs index da429bbad21874..e5b8ecdfab992a 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Linq; +using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using Xunit; @@ -92,6 +94,38 @@ public async Task ReadAsyncCanceledFile() } } } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + [InlineData(FileShare.None, FileOptions.Asynchronous)] // FileShare.None: exclusive access + [InlineData(FileShare.ReadWrite, FileOptions.Asynchronous)] // FileShare.ReadWrite: others can write to the file, the length can't be cached + [InlineData(FileShare.None, FileOptions.None)] + [InlineData(FileShare.ReadWrite, FileOptions.None)] + public async Task IncompleteReadCantSetPositionBeyondEndOfFile(FileShare fileShare, FileOptions options) + { + const int fileSize = 10_000; + string filePath = GetTestFilePath(); + byte[] content = RandomNumberGenerator.GetBytes(fileSize); + File.WriteAllBytes(filePath, content); + + byte[][] buffers = Enumerable.Repeat(Enumerable.Repeat(byte.MaxValue, fileSize * 2).ToArray(), 10).ToArray(); + + using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, fileShare, bufferSize: 0, options)) + { + Task[] reads = buffers.Select(buffer => fs.ReadAsync(buffer, 0, buffer.Length)).ToArray(); + + // the reads were not awaited, it's an anti-pattern and Position can be (0, buffersLength) now: + Assert.InRange(fs.Position, 0, buffers.Sum(buffer => buffer.Length)); + + await Task.WhenAll(reads); + // but when they are finished, the first buffer should contain valid data: + Assert.Equal(fileSize, reads.First().Result); + AssertExtensions.SequenceEqual(content, buffers.First().AsSpan(0, fileSize)); + // and other reads should return 0: + Assert.All(reads.Skip(1), read => Assert.Equal(0, read.Result)); + // and the Position must be correct: + Assert.Equal(fileSize, fs.Position); + } + } } [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs index 367184e9a455ea..26e17f1d161d82 100644 --- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs @@ -5,6 +5,7 @@ using System.Buffers; using System.Diagnostics; using System.IO; +using System.IO.Strategies; using System.Threading; using System.Threading.Tasks.Sources; @@ -45,7 +46,9 @@ internal sealed unsafe class OverlappedValueTaskSource : IValueTaskSource, internal readonly PreAllocatedOverlapped _preallocatedOverlapped; internal readonly SafeFileHandle _fileHandle; + private AsyncWindowsFileStreamStrategy? _strategy; internal MemoryHandle _memoryHandle; + private int _bufferSize; internal ManualResetValueTaskSourceCore _source; // mutable struct; do not make this readonly private NativeOverlapped* _overlapped; private CancellationTokenRegistration _cancellationRegistration; @@ -74,9 +77,11 @@ internal static Exception GetIOError(int errorCode, string? path) ? ThrowHelper.CreateEndOfFileException() : Win32Marshal.GetExceptionForWin32Error(errorCode, path); - internal NativeOverlapped* PrepareForOperation(ReadOnlyMemory memory, long fileOffset) + internal NativeOverlapped* PrepareForOperation(ReadOnlyMemory memory, long fileOffset, AsyncWindowsFileStreamStrategy? strategy = null) { _result = 0; + _strategy = strategy; + _bufferSize = memory.Length; _memoryHandle = memory.Pin(); _overlapped = _fileHandle.ThreadPoolBinding!.AllocateNativeOverlapped(_preallocatedOverlapped); _overlapped->OffsetLow = (int)fileOffset; @@ -132,8 +137,9 @@ internal void RegisterForCancellation(CancellationToken cancellationToken) } } - internal void ReleaseResources() + private void ReleaseResources() { + _strategy = null; // Unpin any pinned buffer. _memoryHandle.Dispose(); @@ -187,11 +193,19 @@ private static void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* internal void Complete(uint errorCode, uint numBytes) { + Debug.Assert(errorCode == Interop.Errors.ERROR_SUCCESS || numBytes == 0, $"Callback returned {errorCode} error and {numBytes} bytes"); + + AsyncWindowsFileStreamStrategy? strategy = _strategy; ReleaseResources(); + if (strategy is not null && _bufferSize != numBytes) // true only for incomplete reads + { + strategy.OnIncompleteRead(_bufferSize, (int)numBytes); + } + switch (errorCode) { - case 0: + case Interop.Errors.ERROR_SUCCESS: case Interop.Errors.ERROR_BROKEN_PIPE: case Interop.Errors.ERROR_NO_DATA: case Interop.Errors.ERROR_HANDLE_EOF: // logically success with 0 bytes read (read at end of file) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs index a2be26fa231030..6a94ad202fa190 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs @@ -280,9 +280,14 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel { return Task.FromCanceled(cancellationToken); } - else if (_strategy.IsClosed) + else if (!_strategy.CanRead) { - ThrowHelper.ThrowObjectDisposedException_FileClosed(); + if (_strategy.IsClosed) + { + ThrowHelper.ThrowObjectDisposedException_FileClosed(); + } + + ThrowHelper.ThrowNotSupportedException_UnreadableStream(); } return _strategy.ReadAsync(buffer, offset, count, cancellationToken); @@ -294,9 +299,14 @@ public override ValueTask ReadAsync(Memory buffer, CancellationToken { return ValueTask.FromCanceled(cancellationToken); } - else if (_strategy.IsClosed) + else if (!_strategy.CanRead) { - ThrowHelper.ThrowObjectDisposedException_FileClosed(); + if (_strategy.IsClosed) + { + ThrowHelper.ThrowObjectDisposedException_FileClosed(); + } + + ThrowHelper.ThrowNotSupportedException_UnreadableStream(); } return _strategy.ReadAsync(buffer, cancellationToken); @@ -319,9 +329,14 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati { return Task.FromCanceled(cancellationToken); } - else if (_strategy.IsClosed) + else if (!_strategy.CanWrite) { - ThrowHelper.ThrowObjectDisposedException_FileClosed(); + if (_strategy.IsClosed) + { + ThrowHelper.ThrowObjectDisposedException_FileClosed(); + } + + ThrowHelper.ThrowNotSupportedException_UnwritableStream(); } return _strategy.WriteAsync(buffer, offset, count, cancellationToken); @@ -333,9 +348,14 @@ public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationTo { return ValueTask.FromCanceled(cancellationToken); } - else if (_strategy.IsClosed) + else if (!_strategy.CanWrite) { - ThrowHelper.ThrowObjectDisposedException_FileClosed(); + if (_strategy.IsClosed) + { + ThrowHelper.ThrowObjectDisposedException_FileClosed(); + } + + ThrowHelper.ThrowNotSupportedException_UnwritableStream(); } return _strategy.WriteAsync(buffer, cancellationToken); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs index 8711ce23e9d2c6..2bb8d46706dccd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs @@ -242,21 +242,23 @@ internal static ValueTask ReadAtOffsetAsync(SafeFileHandle handle, Memory buffer, long fileOffset, CancellationToken cancellationToken) + internal static unsafe (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) QueueAsyncReadFile(SafeFileHandle handle, Memory buffer, long fileOffset, + CancellationToken cancellationToken, AsyncWindowsFileStreamStrategy? strategy = null) { handle.EnsureThreadPoolBindingInitialized(); SafeFileHandle.OverlappedValueTaskSource vts = handle.GetOverlappedValueTaskSource(); + int errorCode = 0; try { - NativeOverlapped* nativeOverlapped = vts.PrepareForOperation(buffer, fileOffset); + NativeOverlapped* nativeOverlapped = vts.PrepareForOperation(buffer, fileOffset, strategy); Debug.Assert(vts._memoryHandle.Pointer != null); // Queue an async ReadFile operation. if (Interop.Kernel32.ReadFile(handle, (byte*)vts._memoryHandle.Pointer, buffer.Length, IntPtr.Zero, nativeOverlapped) == 0) { // The operation failed, or it's pending. - int errorCode = FileStreamHelpers.GetLastWin32ErrorAndDisposeHandleIfInvalid(handle); + errorCode = FileStreamHelpers.GetLastWin32ErrorAndDisposeHandleIfInvalid(handle); switch (errorCode) { case Interop.Errors.ERROR_IO_PENDING: @@ -286,6 +288,13 @@ internal static unsafe (SafeFileHandle.OverlappedValueTaskSource? vts, int error vts.Dispose(); throw; } + finally + { + if (errorCode != Interop.Errors.ERROR_IO_PENDING && errorCode != Interop.Errors.ERROR_SUCCESS) + { + strategy?.OnIncompleteRead(buffer.Length, 0); + } + } // Completion handled by callback. vts.FinishedScheduling(); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/AsyncWindowsFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/AsyncWindowsFileStreamStrategy.cs index 913ce597be00a7..9bc49658bfa991 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/AsyncWindowsFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/AsyncWindowsFileStreamStrategy.cs @@ -27,40 +27,29 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel public override ValueTask ReadAsync(Memory destination, CancellationToken cancellationToken = default) => ReadAsyncInternal(destination, cancellationToken); - private unsafe ValueTask ReadAsyncInternal(Memory destination, CancellationToken cancellationToken) + private ValueTask ReadAsyncInternal(Memory destination, CancellationToken cancellationToken) { - if (!CanRead) + if (!CanSeek) { - ThrowHelper.ThrowNotSupportedException_UnreadableStream(); + return RandomAccess.ReadAtOffsetAsync(_fileHandle, destination, fileOffset: -1, cancellationToken); } - long positionBefore = _filePosition; - if (CanSeek) + if (LengthCachingSupported && _length >= 0 && Volatile.Read(ref _filePosition) >= _length) { - long len = Length; - if (positionBefore + destination.Length > len) - { - destination = positionBefore <= len ? - destination.Slice(0, (int)(len - positionBefore)) : - default; - } - - // When using overlapped IO, the OS is not supposed to - // touch the file pointer location at all. We will adjust it - // ourselves, but only in memory. This isn't threadsafe. - _filePosition += destination.Length; - - // We know for sure that there is nothing to read, so we just return here and avoid a sys-call. - if (destination.IsEmpty && LengthCachingSupported) - { - return ValueTask.FromResult(0); - } + // We know for sure that the file length can be safely cached and it has already been obtained. + // If we have reached EOF we just return here and avoid a sys-call. + return ValueTask.FromResult(0); } - (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) = RandomAccess.QueueAsyncReadFile(_fileHandle, destination, positionBefore, cancellationToken); + // This implementation updates the file position before the operation starts and updates it after incomplete read. + // This is done to keep backward compatibility for concurrent reads. + // It uses Interlocked as there can be multiple concurrent incomplete reads updating position at the same time. + long readOffset = Interlocked.Add(ref _filePosition, destination.Length) - destination.Length; + + (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) = RandomAccess.QueueAsyncReadFile(_fileHandle, destination, readOffset, cancellationToken, this); return vts != null ? new ValueTask(vts, vts.Version) - : (errorCode == 0) ? ValueTask.FromResult(0) : ValueTask.FromException(HandleIOError(positionBefore, errorCode)); + : (errorCode == 0) ? ValueTask.FromResult(0) : ValueTask.FromException(HandleIOError(readOffset, errorCode)); } public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) @@ -69,35 +58,22 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) => WriteAsyncInternal(buffer, cancellationToken); - private unsafe ValueTask WriteAsyncInternal(ReadOnlyMemory source, CancellationToken cancellationToken) + private ValueTask WriteAsyncInternal(ReadOnlyMemory source, CancellationToken cancellationToken) { - if (!CanWrite) - { - ThrowHelper.ThrowNotSupportedException_UnwritableStream(); - } - - long positionBefore = _filePosition; - if (CanSeek) - { - // When using overlapped IO, the OS is not supposed to - // touch the file pointer location at all. We will adjust it - // ourselves, but only in memory. This isn't threadsafe. - _filePosition += source.Length; - UpdateLengthOnChangePosition(); - } + long writeOffset = CanSeek ? Interlocked.Add(ref _filePosition, source.Length) - source.Length : -1; - (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) = RandomAccess.QueueAsyncWriteFile(_fileHandle, source, positionBefore, cancellationToken); + (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) = RandomAccess.QueueAsyncWriteFile(_fileHandle, source, writeOffset, cancellationToken); return vts != null ? new ValueTask(vts, vts.Version) - : (errorCode == 0) ? ValueTask.CompletedTask : ValueTask.FromException(HandleIOError(positionBefore, errorCode)); + : (errorCode == 0) ? ValueTask.CompletedTask : ValueTask.FromException(HandleIOError(writeOffset, errorCode)); } private Exception HandleIOError(long positionBefore, int errorCode) { - if (!_fileHandle.IsClosed && CanSeek) + if (_fileHandle.CanSeek) { // Update Position... it could be anywhere. - _filePosition = positionBefore; + Interlocked.Exchange(ref _filePosition, positionBefore); } return SafeFileHandle.OverlappedValueTaskSource.GetIOError(errorCode, _fileHandle.Path); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs index 226765ff8f0ee5..2faf4c2e47ae8a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs @@ -15,9 +15,9 @@ internal abstract class OSFileStreamStrategy : FileStreamStrategy private readonly FileAccess _access; // What file was opened for. protected long _filePosition; + protected long _length = -1; // negative means that hasn't been fetched. private long _appendStart; // When appending, prevent overwriting file. - private long _length = -1; // When the file is locked for writes on Windows ((share & FileShare.Write) == 0) cache file length in-memory, negative means that hasn't been fetched. - private bool _lengthCanBeCached; // SafeFileHandle hasn't been exposed and FileShare.Write was not specified when the handle was opened. + private bool _lengthCanBeCached; // SafeFileHandle hasn't been exposed, file has been opened for reading and not shared for writing. internal OSFileStreamStrategy(SafeFileHandle handle, FileAccess access) { @@ -44,7 +44,7 @@ internal OSFileStreamStrategy(string path, FileMode mode, FileAccess access, Fil string fullPath = Path.GetFullPath(path); _access = access; - _lengthCanBeCached = (share & FileShare.Write) == 0; + _lengthCanBeCached = (share & FileShare.Write) == 0 && (access & FileAccess.Write) == 0; _fileHandle = SafeFileHandle.Open(fullPath, mode, access, share, options, preallocationSize); @@ -96,21 +96,9 @@ public unsafe sealed override long Length } } - protected void UpdateLengthOnChangePosition() - { - // Do not update the cached length if the file is not locked - // or if the length hasn't been fetched. - if (!LengthCachingSupported || _length < 0) - { - Debug.Assert(_length < 0); - return; - } - - if (_filePosition > _length) - { - _length = _filePosition; - } - } + // in case of concurrent incomplete reads, there can be multiple threads trying to update the position + // at the same time. That is why we are using Interlocked here. + internal void OnIncompleteRead(int expectedBytesRead, int actualBytesRead) => Interlocked.Add(ref _filePosition, actualBytesRead - expectedBytesRead); protected bool LengthCachingSupported => OperatingSystem.IsWindows() && _lengthCanBeCached; @@ -287,18 +275,8 @@ public sealed override void Write(ReadOnlySpan buffer) ThrowHelper.ThrowNotSupportedException_UnwritableStream(); } - try - { - RandomAccess.WriteAtOffset(_fileHandle, buffer, _filePosition); - } - catch - { - _length = -1; // invalidate cached length - throw; - } - + RandomAccess.WriteAtOffset(_fileHandle, buffer, _filePosition); _filePosition += buffer.Length; - UpdateLengthOnChangePosition(); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs index e9f00f254ad290..e1a64a6e123323 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.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.Diagnostics; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Sources; @@ -34,20 +35,16 @@ public override Task ReadAsync(byte[] buffer, int offset, int count, Cancel public override ValueTask ReadAsync(Memory destination, CancellationToken cancellationToken) { - if (!CanRead) + if (!CanSeek) { - ThrowHelper.ThrowNotSupportedException_UnreadableStream(); + return RandomAccess.ReadAtOffsetAsync(_fileHandle, destination, fileOffset: -1, cancellationToken); } - if (CanSeek) - { - // This implementation updates the file position after the operation completes, rather than before. - // Also, unlike the Net5CompatFileStreamStrategy implementation, this implementation doesn't serialize operations. - ReadAsyncTaskSource rats = Interlocked.Exchange(ref _readAsyncTaskSource, null) ?? new ReadAsyncTaskSource(this); - return rats.QueueRead(destination, cancellationToken); - } - - return RandomAccess.ReadAtOffsetAsync(_fileHandle, destination, fileOffset: -1, cancellationToken); + // This implementation updates the file position before the operation starts and updates it after incomplete read. + // Also, unlike the Net5CompatFileStreamStrategy implementation, this implementation doesn't serialize operations. + long readOffset = Interlocked.Add(ref _filePosition, destination.Length) - destination.Length; + ReadAsyncTaskSource rats = Interlocked.Exchange(ref _readAsyncTaskSource, null) ?? new ReadAsyncTaskSource(this); + return rats.QueueRead(destination, readOffset, cancellationToken); } public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => @@ -61,19 +58,8 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati public override ValueTask WriteAsync(ReadOnlyMemory source, CancellationToken cancellationToken) { - if (!CanWrite) - { - ThrowHelper.ThrowNotSupportedException_UnwritableStream(); - } - - long filePositionBefore = -1; - if (CanSeek) - { - filePositionBefore = _filePosition; - _filePosition += source.Length; - } - - return RandomAccess.WriteAtOffsetAsync(_fileHandle, source, filePositionBefore, cancellationToken); + long writeOffset = CanSeek ? Interlocked.Add(ref _filePosition, source.Length) - source.Length : -1; + return RandomAccess.WriteAtOffsetAsync(_fileHandle, source, writeOffset, cancellationToken); } /// Provides a reusable ValueTask-backing object for implementing ReadAsync. @@ -83,14 +69,16 @@ private sealed class ReadAsyncTaskSource : IValueTaskSource, IThreadPoolWor private ManualResetValueTaskSourceCore _source; private Memory _destination; + private long _readOffset; private ExecutionContext? _context; private CancellationToken _cancellationToken; public ReadAsyncTaskSource(UnixFileStreamStrategy stream) => _stream = stream; - public ValueTask QueueRead(Memory destination, CancellationToken cancellationToken) + public ValueTask QueueRead(Memory destination, long readOffset, CancellationToken cancellationToken) { _destination = destination; + _readOffset = readOffset; _cancellationToken = cancellationToken; _context = ExecutionContext.Capture(); @@ -123,7 +111,7 @@ private void Read() } else { - result = _stream.Read(_destination.Span); + result = RandomAccess.ReadAtOffset(_stream._fileHandle, _destination.Span, _readOffset); } } catch (Exception e) @@ -132,7 +120,14 @@ private void Read() } finally { + // if the read was incomplete, we need to update the file position: + if (result != _destination.Length) + { + _stream.OnIncompleteRead(_destination.Length, result); + } + _destination = default; + _readOffset = -1; _cancellationToken = default; _context = null; } From ea4a3b6e203673526dfa5056fa2149a47137d9ea Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Sat, 31 Jul 2021 20:39:22 -0500 Subject: [PATCH 18/64] Enable tests marked with https://github.com/dotnet/runtime/issues/51911 (#56673) --- .../Xslt/XslCompiledTransformApi/XslCompiledTransform.cs | 4 ---- .../tests/Xslt/XslCompiledTransformApi/XsltSettings.cs | 2 -- 2 files changed, 6 deletions(-) diff --git a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs index 568072314f34ca..201ee241005997 100644 --- a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs +++ b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs @@ -544,7 +544,6 @@ public void XmlResolver2(XslInputType xslInputType, ReaderType readerType) } //[Variation(id = 3, Desc = "Default XmlResolver, load style sheet with document function, should resolve during transform", Pri = 1, Param = "DefaultResolver.txt")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51911", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)] [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)] [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)] @@ -2409,7 +2408,6 @@ public void XmlResolver1(XslInputType xslInputType , ReaderType readerType, Outp } //[Variation("Pass null XmlResolver, load style sheet with document function, should not resolve during transform", Param = "xmlResolver_document_function.txt")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51911", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData("xmlResolver_document_function.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)] [InlineData("xmlResolver_document_function.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)] [InlineData("xmlResolver_document_function.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)] @@ -2445,7 +2443,6 @@ public void XmlResolver2(object param, XslInputType xslInputType, ReaderType rea } //[Variation("Default XmlResolver, load style sheet with document function, should resolve during transform", Param = "DefaultResolver.txt")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51911", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)] [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Writer, NavType.XPathDocument)] [InlineData("DefaultResolver.txt", XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.TextWriter, NavType.XPathDocument)] @@ -2973,7 +2970,6 @@ public void TransformStrStrResolver1(XslInputType xslInputType, ReaderType reade } //[Variation("Pass null XmlResolver, load style sheet with document function, should not resolve during transform")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51911", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData(XslInputType.Reader, ReaderType.XmlValidatingReader)] [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader)] [InlineData(XslInputType.Navigator, ReaderType.XmlValidatingReader)] diff --git a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltSettings.cs b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltSettings.cs index 5074facbfc0d09..c736fe09811fb5 100644 --- a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltSettings.cs +++ b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XsltSettings.cs @@ -78,7 +78,6 @@ public void XsltSettings1_2_ContainsScript(object param0, object param1, object } //[Variation(id = 5, Desc = "Test the document function with EnableDocumentFunction, should work", Pri = 0, Params = new object[] { "XsltSettings.xml", "XsltSettings2.xsl", true, false })] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51911", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData(5, "XsltSettings.xml", "XsltSettings2.xsl", true, false)] //[Variation(id = 8, Desc = "Test the document function with TrustedXslt, should work", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings2.xsl", true, true })] [InlineData(8, "XsltSettings.xml", "XsltSettings2.xsl", true, true)] @@ -91,7 +90,6 @@ public void XsltSettings1_1_ExternalURI(object param0, object param1, object par } //[Variation(id = 18, Desc = "Test 6 with EnableDocumentFunction override, should work", Pri = 1, Params = new object[] { "XsltSettings.xml", "XsltSettings2.xsl", false, false, true, false })] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51911", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData(18, "XsltSettings.xml", "XsltSettings2.xsl", false, false, true, false)] [Theory] public void XsltSettings1_2_ExternalURI(object param0, object param1, object param2, object param3, object param4, object param5, object param6) From 833d34a6a861385d628591620d5cdc499cf592df Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Sat, 31 Jul 2021 22:49:32 -0400 Subject: [PATCH 19/64] Try again to fix AsyncMethodsDropsStateMachineAndExecutionContextUponCompletion test --- .../AsyncTaskMethodBuilderTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs b/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs index d762f2b639fc9d..d90c0685451f3a 100644 --- a/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs +++ b/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs @@ -560,6 +560,7 @@ async Task YieldOnceAsync(object s) { GC.Collect(); GC.WaitForPendingFinalizers(); + await Task.Yield(); } if (!Volatile.Read(ref finalized)) From 30a1a3a4214ee098d63b986bf6d148880b6e15be Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Sat, 31 Jul 2021 22:17:37 -0500 Subject: [PATCH 20/64] Enable #59244 on wasm (#56675) --- .../tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs index 201ee241005997..e8cf2496e07aec 100644 --- a/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs +++ b/src/libraries/System.Private.Xml/tests/Xslt/XslCompiledTransformApi/XslCompiledTransform.cs @@ -3332,7 +3332,6 @@ public CTransformRegressionTest(ITestOutputHelper output) : base(output) } //[Variation("Bug398968 - Globalization is broken for document() function")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51244", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] [InlineData(XslInputType.URI, ReaderType.XmlValidatingReader, OutputType.Stream, NavType.XPathDocument)] [Theory] public void RegressionTest1(XslInputType xslInputType, ReaderType readerType, OutputType outputType, NavType navType) From 48f0271c22b12a15847ba92b134cecea2a1dead0 Mon Sep 17 00:00:00 2001 From: imhameed Date: Sat, 31 Jul 2021 20:29:41 -0700 Subject: [PATCH 21/64] [mono] Unconditionally enable NEON/AdvSimd for arm64 with LLVM (#56323) * [mono] Unconditionally enable NEON/AdvSimd for arm64 with LLVM * Remove `mattr=neon` from the Mono AOT command line arguments for LLVM AOT tests This is now enabled by default when using LLVM. --- src/mono/mono/mini/mini.c | 7 ++++++- src/tests/run.proj | 1 - 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/mini/mini.c b/src/mono/mono/mini/mini.c index 7d24fe6374b6c5..28ce38aa7b6b7f 100644 --- a/src/mono/mono/mini/mini.c +++ b/src/mono/mono/mini/mini.c @@ -4450,7 +4450,12 @@ mini_get_cpu_features (MonoCompile* cfg) #if defined(TARGET_ARM64) // All Arm64 devices have this set - features |= MONO_CPU_ARM64_BASE; + features |= MONO_CPU_ARM64_BASE; + + // This is a standard part of ARMv8-A; see A1.5 in "ARM + // Architecture Reference Manual ARMv8, for ARMv8-A + // architecture profile" + features |= MONO_CPU_ARM64_NEON; #endif // apply parameters passed via -mattr diff --git a/src/tests/run.proj b/src/tests/run.proj index 3289e9c9ee6453..4f17417636d840 100644 --- a/src/tests/run.proj +++ b/src/tests/run.proj @@ -601,7 +601,6 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). - From 26ddd7a44eef96509596fd60b908f0948732cd79 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang <16830051+mdh1418@users.noreply.github.com> Date: Sun, 1 Aug 2021 04:53:22 -0400 Subject: [PATCH 22/64] [libraries][Android] Reenable System.Linq.Expression.Tests for Android (#56646) Co-authored-by: Mitchell Hwang --- .../tests/Dynamic/InvokeMemberBindingTests.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libraries/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs b/src/libraries/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs index ee4962af5ff1c8..a9a77a61e7f9d5 100644 --- a/src/libraries/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs @@ -245,7 +245,6 @@ public void NonIndexerParameterizedDirectAccess() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/37474", TestPlatforms.Android)] public void NonIndexerParameterizedGetterAndSetterIndexAccess() { dynamic d = GetObjectWithNonIndexerParameterProperty(true, true); @@ -256,7 +255,6 @@ public void NonIndexerParameterizedGetterAndSetterIndexAccess() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/37474", TestPlatforms.Android)] public void NonIndexerParameterizedGetterOnlyIndexAccess() { dynamic d = GetObjectWithNonIndexerParameterProperty(true, false); @@ -267,7 +265,6 @@ public void NonIndexerParameterizedGetterOnlyIndexAccess() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/37474", TestPlatforms.Android)] public void NonIndexerParameterizedSetterOnlyIndexAccess() { dynamic d = GetObjectWithNonIndexerParameterProperty(false, true); From a190d44159e9a2c3bee90757fe3ced4365376426 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Sun, 1 Aug 2021 21:18:49 +0200 Subject: [PATCH 23/64] Enable ICU trimming for Invariant=true and PredefinedCulturesOnly unspecified (#56667) * Enable ICU trimming for Invariant=true and PredefinedCulturesOnly unspecified * Update comments --- .../src/System/Globalization/GlobalizationMode.Unix.cs | 9 ++++++--- .../src/System/Globalization/GlobalizationMode.cs | 6 ++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs index 2cc6fd74b8201c..a0dad9398590f6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs @@ -8,12 +8,15 @@ internal static partial class GlobalizationMode private static partial class Settings { /// - /// Load ICU (when not in Invariant mode) in a static cctor to ensure it is loaded early in the process. - /// Other places, e.g. CompareInfo.GetSortKey, rely on ICU already being loaded before they are called. + /// Load ICU (when not in Invariant mode) in a static cctor to ensure it is loaded as side-effect of + /// the GlobalizationMode.Invariant check. Globalization P/Invokes, e.g. in CompareInfo.GetSortKey, + /// rely on ICU already being loaded before they are called. /// static Settings() { - if (!Invariant) + // Use GlobalizationMode.Invariant to allow ICU initialization to be trimmed when Invariant=false + // and PredefinedCulturesOnly is unspecified. + if (!GlobalizationMode.Invariant) { if (TryGetAppLocalIcuSwitchValue(out string? icuSuffixAndVersion)) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs index d611ea2b5e13f8..4f69f980150412 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.cs @@ -8,11 +8,12 @@ namespace System.Globalization { internal static partial class GlobalizationMode { - // split from GlobalizationMode so the whole class can be trimmed when Invariant=true. + // Split from GlobalizationMode so the whole class can be trimmed when Invariant=true. Trimming tests + // validate this implementation detail. private static partial class Settings { internal static bool Invariant { get; } = AppContextConfigHelper.GetBooleanConfig("System.Globalization.Invariant", "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"); - internal static bool PredefinedCulturesOnly { get; } = AppContextConfigHelper.GetBooleanConfig("System.Globalization.PredefinedCulturesOnly", "DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY", Invariant); + internal static bool PredefinedCulturesOnly { get; } = AppContextConfigHelper.GetBooleanConfig("System.Globalization.PredefinedCulturesOnly", "DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY", GlobalizationMode.Invariant); } // Note: Invariant=true and Invariant=false are substituted at different levels in the ILLink.Substitutions file. @@ -20,6 +21,7 @@ private static partial class Settings // static cctor (on Unix) to be preserved when Invariant=false. internal static bool Invariant => Settings.Invariant; internal static bool PredefinedCulturesOnly => Settings.PredefinedCulturesOnly; + private static bool TryGetAppLocalIcuSwitchValue([NotNullWhen(true)] out string? value) => TryGetStringValue("System.Globalization.AppLocalIcu", "DOTNET_SYSTEM_GLOBALIZATION_APPLOCALICU", out value); private static bool TryGetStringValue(string switchName, string envVariable, [NotNullWhen(true)] out string? value) From d90f6b6c86be7001dc839e147ab229dfd1c7d20d Mon Sep 17 00:00:00 2001 From: Noah Falk Date: Sun, 1 Aug 2021 23:47:20 -0700 Subject: [PATCH 24/64] Instrument MemTracker (#56648) We are seeing some likely memory corruption in https://github.com/dotnet/runtime/issues/54469 and these changes hopefully will help better diagnose it --- src/coreclr/utilcode/loaderheap.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/coreclr/utilcode/loaderheap.cpp b/src/coreclr/utilcode/loaderheap.cpp index b3b381b2f9bef4..4b6bd668033202 100644 --- a/src/coreclr/utilcode/loaderheap.cpp +++ b/src/coreclr/utilcode/loaderheap.cpp @@ -2181,6 +2181,21 @@ AllocMemTracker::~AllocMemTracker() } } +// We have seen evidence of memory corruption in this data structure. +// https://github.com/dotnet/runtime/issues/54469 +// m_pFirstBlock is intended to be a linked list terminating with +// &m_FirstBlock but we are finding a nullptr in the list before +// that point. In order to investigate further we need to observe +// the corrupted memory block(s) before they are deleted below +#ifdef _DEBUG + AllocMemTrackerBlock* pDebugBlock = m_pFirstBlock; + for (int i = 0; pDebugBlock != &m_FirstBlock; i++) + { + CONSISTENCY_CHECK_MSGF(i < 10000, ("Linked list is much longer than expected, memory corruption likely\n")); + CONSISTENCY_CHECK_MSGF(pDebugBlock != nullptr, ("Linked list pointer == NULL, memory corruption likely\n")); + pDebugBlock = pDebugBlock->m_pNext; + } +#endif AllocMemTrackerBlock *pBlock = m_pFirstBlock; while (pBlock != &m_FirstBlock) From f915301e7181758302e7c9af264923543256e06f Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Mon, 2 Aug 2021 09:02:22 +0200 Subject: [PATCH 25/64] Fix comment (#56709) --- .../src/System/Globalization/GlobalizationMode.Unix.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs index a0dad9398590f6..dc5a71d3935a54 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs @@ -14,7 +14,7 @@ private static partial class Settings /// static Settings() { - // Use GlobalizationMode.Invariant to allow ICU initialization to be trimmed when Invariant=false + // Use GlobalizationMode.Invariant to allow ICU initialization to be trimmed when Invariant=true // and PredefinedCulturesOnly is unspecified. if (!GlobalizationMode.Invariant) { From 7ed6714cd4c78c693177c6bbac17d44e758aaecb Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Mon, 2 Aug 2021 00:57:03 -0700 Subject: [PATCH 26/64] [8/21 Infra rollout] update sdk to preview6 (#56161) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update sdk to preview6 to check whether an arm64 bug is the root cause of NRE on macos. * Remove invalid Castle.DynamicProxy.Internal.AbstractInvocation from ILLink descriptor files The type is actually in the `Castle.DynamicProxy` namespace, not the `.Internal` one. This causes an error with newer linker versions. The whole `Castle.DynamicProxy` namespace is already preserved so we can remove the entry for AbstractInvocation. Co-authored-by: Alexander Köplinger --- global.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/global.json b/global.json index f0a10200a5103b..18f1604a2e5cd5 100644 --- a/global.json +++ b/global.json @@ -1,11 +1,11 @@ { "sdk": { - "version": "6.0.100-preview.5.21302.13", + "version": "6.0.100-preview.6.21355.2", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "6.0.100-preview.5.21302.13" + "dotnet": "6.0.100-preview.6.21355.2" }, "native-tools": { "cmake": "3.16.4", From 11b293f79367ff587b93a1da1795a815256c526f Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Mon, 2 Aug 2021 10:34:05 +0200 Subject: [PATCH 27/64] [wasm] Improve console.log in unit tests (#56616) --- src/mono/wasm/runtime-test.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/mono/wasm/runtime-test.js b/src/mono/wasm/runtime-test.js index 89b9c5d70cc7e8..e661a5423a0d2d 100644 --- a/src/mono/wasm/runtime-test.js +++ b/src/mono/wasm/runtime-test.js @@ -18,15 +18,21 @@ globalThis.testConsole = console; function proxyMethod (prefix, func, asJson) { return function() { - var args = [...arguments]; + const args = [...arguments]; + var payload= args[0]; + if(payload === undefined) payload = 'undefined'; + else if(payload === null) payload = 'null'; + else if(typeof payload === 'function') payload = payload.toString(); + else if(typeof payload !== 'string') payload = JSON.stringify(payload); + if (asJson) { func (JSON.stringify({ method: prefix, - payload: args[0], + payload: payload, arguments: args })); } else { - func([prefix + args[0], ...args.slice(1)]); + func([prefix + payload, ...args.slice(1)]); } }; }; From 95ef79a599b02a41b9300ccc33d83f2eed928b09 Mon Sep 17 00:00:00 2001 From: Petr Onderka Date: Mon, 2 Aug 2021 10:40:30 +0200 Subject: [PATCH 28/64] Corrected terminology in SequencePosition documentation (#56693) --- src/libraries/System.Memory/src/System/SequencePosition.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Memory/src/System/SequencePosition.cs b/src/libraries/System.Memory/src/System/SequencePosition.cs index 117131d0ad6d39..574fb767d4ed2e 100644 --- a/src/libraries/System.Memory/src/System/SequencePosition.cs +++ b/src/libraries/System.Memory/src/System/SequencePosition.cs @@ -8,7 +8,7 @@ namespace System { /// /// Represents position in non-contiguous set of memory. - /// Properties of this type should not be interpreted by anything but the type that created it. + /// Parts of this type should not be interpreted by anything but the type that created it. /// public readonly struct SequencePosition : IEquatable { From 79c4144f174754bf4fa18827a292549214f86581 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 2 Aug 2021 05:03:53 -0400 Subject: [PATCH 29/64] Use UnixFileStream's ReadAsync implementation on Windows as well (#56682) UnixFileStream's ReadAsync implementation uses a reusable IValueTaskSource implementation to avoid allocating a new work item on every read. We can push that implementation down to OSFileStreamStrategy, and then use it for the Windows implementation of ReadAsync as well when IsAsync==false, rather than delegating to the base Stream implementation. This PR almost entirely just moves code around. The only change to logic is in RandomAccess.Windows.cs, to only set an offset into the NativeOverlapped if the SafeFileHandle is seekable; otherwise, it fails when used with pipes. --- .../src/System/IO/RandomAccess.Windows.cs | 7 +- .../AsyncWindowsFileStreamStrategy.cs | 26 +-- .../IO/Strategies/OSFileStreamStrategy.cs | 144 +++++++++++++++++ .../SyncWindowsFileStreamStrategy.cs | 43 ----- .../IO/Strategies/UnixFileStreamStrategy.cs | 148 ------------------ 5 files changed, 151 insertions(+), 217 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs index 2bb8d46706dccd..09f7a69552ef20 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Windows.cs @@ -695,8 +695,11 @@ private static NativeOverlapped GetNativeOverlappedForSyncHandle(SafeFileHandle Debug.Assert(!handle.IsAsync); NativeOverlapped result = default; - result.OffsetLow = unchecked((int)fileOffset); - result.OffsetHigh = (int)(fileOffset >> 32); + if (handle.CanSeek) + { + result.OffsetLow = unchecked((int)fileOffset); + result.OffsetHigh = (int)(fileOffset >> 32); + } return result; } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/AsyncWindowsFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/AsyncWindowsFileStreamStrategy.cs index 9bc49658bfa991..12af993b617f65 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/AsyncWindowsFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/AsyncWindowsFileStreamStrategy.cs @@ -21,13 +21,7 @@ internal AsyncWindowsFileStreamStrategy(string path, FileMode mode, FileAccess a internal override bool IsAsync => true; - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - => ReadAsyncInternal(new Memory(buffer, offset, count), cancellationToken).AsTask(); - public override ValueTask ReadAsync(Memory destination, CancellationToken cancellationToken = default) - => ReadAsyncInternal(destination, cancellationToken); - - private ValueTask ReadAsyncInternal(Memory destination, CancellationToken cancellationToken) { if (!CanSeek) { @@ -52,17 +46,11 @@ private ValueTask ReadAsyncInternal(Memory destination, CancellationT : (errorCode == 0) ? ValueTask.FromResult(0) : ValueTask.FromException(HandleIOError(readOffset, errorCode)); } - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - => WriteAsyncInternal(new ReadOnlyMemory(buffer, offset, count), cancellationToken).AsTask(); - public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) - => WriteAsyncInternal(buffer, cancellationToken); - - private ValueTask WriteAsyncInternal(ReadOnlyMemory source, CancellationToken cancellationToken) { - long writeOffset = CanSeek ? Interlocked.Add(ref _filePosition, source.Length) - source.Length : -1; + long writeOffset = CanSeek ? Interlocked.Add(ref _filePosition, buffer.Length) - buffer.Length : -1; - (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) = RandomAccess.QueueAsyncWriteFile(_fileHandle, source, writeOffset, cancellationToken); + (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) = RandomAccess.QueueAsyncWriteFile(_fileHandle, buffer, writeOffset, cancellationToken); return vts != null ? new ValueTask(vts, vts.Version) : (errorCode == 0) ? ValueTask.CompletedTask : ValueTask.FromException(HandleIOError(writeOffset, errorCode)); @@ -120,15 +108,5 @@ await FileStreamHelpers } } } - - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => - TaskToApm.Begin(ReadAsync(buffer, offset, count), callback, state); - - public override int EndRead(IAsyncResult asyncResult) => TaskToApm.End(asyncResult); - - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => - TaskToApm.Begin(WriteAsync(buffer, offset, count), callback, state); - - public override void EndWrite(IAsyncResult asyncResult) => TaskToApm.End(asyncResult); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs index 2faf4c2e47ae8a..260624bf93416c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; +using System.Threading.Tasks.Sources; using Microsoft.Win32.SafeHandles; namespace System.IO.Strategies @@ -13,6 +14,7 @@ internal abstract class OSFileStreamStrategy : FileStreamStrategy { protected readonly SafeFileHandle _fileHandle; // only ever null if ctor throws private readonly FileAccess _access; // What file was opened for. + private ReadAsyncTaskSource? _readAsyncTaskSource; // Cached IValueTaskSource used for async-over-sync reads protected long _filePosition; protected long _length = -1; // negative means that hasn't been fetched. @@ -69,6 +71,8 @@ internal OSFileStreamStrategy(string path, FileMode mode, FileAccess access, Fil } } + internal override bool IsAsync => _fileHandle.IsAsync; + public sealed override bool CanSeek => _fileHandle.CanSeek; public sealed override bool CanRead => !_fileHandle.IsClosed && (_access & FileAccess.Read) != 0; @@ -278,5 +282,145 @@ public sealed override void Write(ReadOnlySpan buffer) RandomAccess.WriteAtOffset(_fileHandle, buffer, _filePosition); _filePosition += buffer.Length; } + + public sealed override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => + TaskToApm.Begin(WriteAsync(buffer, offset, count), callback, state); + + public sealed override void EndWrite(IAsyncResult asyncResult) => + TaskToApm.End(asyncResult); + + public sealed override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + WriteAsync(new ReadOnlyMemory(buffer, offset, count), cancellationToken).AsTask(); + + public override ValueTask WriteAsync(ReadOnlyMemory source, CancellationToken cancellationToken) + { + long writeOffset = CanSeek ? Interlocked.Add(ref _filePosition, source.Length) - source.Length : -1; + return RandomAccess.WriteAtOffsetAsync(_fileHandle, source, writeOffset, cancellationToken); + } + + public sealed override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => + TaskToApm.Begin(ReadAsync(buffer, offset, count), callback, state); + + public sealed override int EndRead(IAsyncResult asyncResult) => + TaskToApm.End(asyncResult); + + public sealed override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => + ReadAsync(new Memory(buffer, offset, count), cancellationToken).AsTask(); + + public override ValueTask ReadAsync(Memory destination, CancellationToken cancellationToken) + { + if (!CanSeek) + { + return RandomAccess.ReadAtOffsetAsync(_fileHandle, destination, fileOffset: -1, cancellationToken); + } + + // This implementation updates the file position before the operation starts and updates it after incomplete read. + // Also, unlike the Net5CompatFileStreamStrategy implementation, this implementation doesn't serialize operations. + long readOffset = Interlocked.Add(ref _filePosition, destination.Length) - destination.Length; + ReadAsyncTaskSource rats = Interlocked.Exchange(ref _readAsyncTaskSource, null) ?? new ReadAsyncTaskSource(this); + return rats.QueueRead(destination, readOffset, cancellationToken); + } + + /// Provides a reusable ValueTask-backing object for implementing ReadAsync. + private sealed class ReadAsyncTaskSource : IValueTaskSource, IThreadPoolWorkItem + { + private readonly OSFileStreamStrategy _stream; + private ManualResetValueTaskSourceCore _source; + + private Memory _destination; + private long _readOffset; + private ExecutionContext? _context; + private CancellationToken _cancellationToken; + + public ReadAsyncTaskSource(OSFileStreamStrategy stream) => _stream = stream; + + public ValueTask QueueRead(Memory destination, long readOffset, CancellationToken cancellationToken) + { + _destination = destination; + _readOffset = readOffset; + _cancellationToken = cancellationToken; + _context = ExecutionContext.Capture(); + + ThreadPool.UnsafeQueueUserWorkItem(this, preferLocal: true); + return new ValueTask(this, _source.Version); + } + + void IThreadPoolWorkItem.Execute() + { + if (_context is null || _context.IsDefault) + { + Read(); + } + else + { + ExecutionContext.RunForThreadPoolUnsafe(_context, static x => x.Read(), this); + } + } + + private void Read() + { + Exception? error = null; + int result = 0; + + try + { + if (_cancellationToken.IsCancellationRequested) + { + error = new OperationCanceledException(_cancellationToken); + } + else + { + result = RandomAccess.ReadAtOffset(_stream._fileHandle, _destination.Span, _readOffset); + } + } + catch (Exception e) + { + error = e; + } + finally + { + // if the read was incomplete, we need to update the file position: + if (result != _destination.Length) + { + _stream.OnIncompleteRead(_destination.Length, result); + } + + _destination = default; + _readOffset = -1; + _cancellationToken = default; + _context = null; + } + + if (error is not null) + { + _source.SetException(error); + } + else + { + _source.SetResult(result); + } + } + + int IValueTaskSource.GetResult(short token) + { + try + { + return _source.GetResult(token); + } + finally + { + _source.Reset(); +#pragma warning disable CS0197 + Volatile.Write(ref _stream._readAsyncTaskSource, this); +#pragma warning restore CS0197 + } + } + + ValueTaskSourceStatus IValueTaskSource.GetStatus(short token) => + _source.GetStatus(token); + + void IValueTaskSource.OnCompleted(Action continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags) => + _source.OnCompleted(continuation, state, token, flags); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/SyncWindowsFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/SyncWindowsFileStreamStrategy.cs index d25fcd65db3dfc..5e2513252a510b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/SyncWindowsFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/SyncWindowsFileStreamStrategy.cs @@ -1,9 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; using Microsoft.Win32.SafeHandles; namespace System.IO.Strategies @@ -20,45 +17,5 @@ internal SyncWindowsFileStreamStrategy(string path, FileMode mode, FileAccess ac } internal override bool IsAsync => false; - - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - // If we weren't opened for asynchronous I/O, we still call to the base implementation so that - // Read is invoked asynchronously. But we can do so using the base Stream's internal helper - // that bypasses delegating to BeginRead, since we already know this is FileStream rather - // than something derived from it and what our BeginRead implementation is going to do. - return BeginReadInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false); - } - - public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) - { - // If we weren't opened for asynchronous I/O, we still call to the base implementation so that - // Read is invoked asynchronously. But if we have a byte[], we can do so using the base Stream's - // internal helper that bypasses delegating to BeginRead, since we already know this is FileStream - // rather than something derived from it and what our BeginRead implementation is going to do. - return MemoryMarshal.TryGetArray(buffer, out ArraySegment segment) ? - new ValueTask(BeginReadInternal(segment.Array!, segment.Offset, segment.Count, null, null, serializeAsynchronously: true, apm: false)) : - base.ReadAsync(buffer, cancellationToken); - } - - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - // If we weren't opened for asynchronous I/O, we still call to the base implementation so that - // Write is invoked asynchronously. But we can do so using the base Stream's internal helper - // that bypasses delegating to BeginWrite, since we already know this is FileStream rather - // than something derived from it and what our BeginWrite implementation is going to do. - return BeginWriteInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false); - } - - public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) - { - // If we weren't opened for asynchronous I/O, we still call to the base implementation so that - // Write is invoked asynchronously. But if we have a byte[], we can do so using the base Stream's - // internal helper that bypasses delegating to BeginWrite, since we already know this is FileStream - // rather than something derived from it and what our BeginWrite implementation is going to do. - return MemoryMarshal.TryGetArray(buffer, out ArraySegment segment) ? - new ValueTask(BeginWriteInternal(segment.Array!, segment.Offset, segment.Count, null, null, serializeAsynchronously: true, apm: false)) : - base.WriteAsync(buffer, cancellationToken); - } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs index e1a64a6e123323..3c54f1b23a476f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/UnixFileStreamStrategy.cs @@ -1,18 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; -using System.Threading; -using System.Threading.Tasks; -using System.Threading.Tasks.Sources; using Microsoft.Win32.SafeHandles; namespace System.IO.Strategies { internal sealed partial class UnixFileStreamStrategy : OSFileStreamStrategy { - private ReadAsyncTaskSource? _readAsyncTaskSource; - internal UnixFileStreamStrategy(SafeFileHandle handle, FileAccess access) : base(handle, access) { } @@ -21,147 +15,5 @@ internal UnixFileStreamStrategy(string path, FileMode mode, FileAccess access, F base(path, mode, access, share, options, preallocationSize) { } - - internal override bool IsAsync => _fileHandle.IsAsync; - - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => - TaskToApm.Begin(ReadAsync(buffer, offset, count), callback, state); - - public override int EndRead(IAsyncResult asyncResult) => - TaskToApm.End(asyncResult); - - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => - ReadAsync(new Memory(buffer, offset, count), cancellationToken).AsTask(); - - public override ValueTask ReadAsync(Memory destination, CancellationToken cancellationToken) - { - if (!CanSeek) - { - return RandomAccess.ReadAtOffsetAsync(_fileHandle, destination, fileOffset: -1, cancellationToken); - } - - // This implementation updates the file position before the operation starts and updates it after incomplete read. - // Also, unlike the Net5CompatFileStreamStrategy implementation, this implementation doesn't serialize operations. - long readOffset = Interlocked.Add(ref _filePosition, destination.Length) - destination.Length; - ReadAsyncTaskSource rats = Interlocked.Exchange(ref _readAsyncTaskSource, null) ?? new ReadAsyncTaskSource(this); - return rats.QueueRead(destination, readOffset, cancellationToken); - } - - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) => - TaskToApm.Begin(WriteAsync(buffer, offset, count), callback, state); - - public override void EndWrite(IAsyncResult asyncResult) => - TaskToApm.End(asyncResult); - - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => - WriteAsync(new ReadOnlyMemory(buffer, offset, count), cancellationToken).AsTask(); - - public override ValueTask WriteAsync(ReadOnlyMemory source, CancellationToken cancellationToken) - { - long writeOffset = CanSeek ? Interlocked.Add(ref _filePosition, source.Length) - source.Length : -1; - return RandomAccess.WriteAtOffsetAsync(_fileHandle, source, writeOffset, cancellationToken); - } - - /// Provides a reusable ValueTask-backing object for implementing ReadAsync. - private sealed class ReadAsyncTaskSource : IValueTaskSource, IThreadPoolWorkItem - { - private readonly UnixFileStreamStrategy _stream; - private ManualResetValueTaskSourceCore _source; - - private Memory _destination; - private long _readOffset; - private ExecutionContext? _context; - private CancellationToken _cancellationToken; - - public ReadAsyncTaskSource(UnixFileStreamStrategy stream) => _stream = stream; - - public ValueTask QueueRead(Memory destination, long readOffset, CancellationToken cancellationToken) - { - _destination = destination; - _readOffset = readOffset; - _cancellationToken = cancellationToken; - _context = ExecutionContext.Capture(); - - ThreadPool.UnsafeQueueUserWorkItem(this, preferLocal: true); - return new ValueTask(this, _source.Version); - } - - void IThreadPoolWorkItem.Execute() - { - if (_context is null || _context.IsDefault) - { - Read(); - } - else - { - ExecutionContext.RunForThreadPoolUnsafe(_context, static x => x.Read(), this); - } - } - - private void Read() - { - Exception? error = null; - int result = 0; - - try - { - if (_cancellationToken.IsCancellationRequested) - { - error = new OperationCanceledException(_cancellationToken); - } - else - { - result = RandomAccess.ReadAtOffset(_stream._fileHandle, _destination.Span, _readOffset); - } - } - catch (Exception e) - { - error = e; - } - finally - { - // if the read was incomplete, we need to update the file position: - if (result != _destination.Length) - { - _stream.OnIncompleteRead(_destination.Length, result); - } - - _destination = default; - _readOffset = -1; - _cancellationToken = default; - _context = null; - } - - if (error is not null) - { - _source.SetException(error); - } - else - { - _source.SetResult(result); - } - } - - int IValueTaskSource.GetResult(short token) - { - try - { - return _source.GetResult(token); - } - finally - { - _source.Reset(); -#pragma warning disable CS0197 - Volatile.Write(ref _stream._readAsyncTaskSource, this); -#pragma warning restore CS0197 - } - } - - ValueTaskSourceStatus IValueTaskSource.GetStatus(short token) => - _source.GetStatus(token); - - void IValueTaskSource.OnCompleted(Action continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags) => - _source.OnCompleted(continuation, state, token, flags); - } } } From 749fa1381f122f7a0bb23374a9e220f834ccbbb3 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 2 Aug 2021 14:23:15 +0200 Subject: [PATCH 30/64] [main] Update dependencies from dotnet/runtime dnceng/internal/dotnet-optimization dotnet/arcade dotnet/xharness dotnet/roslyn-analyzers dotnet/emsdk (#56211) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dependencies from https://github.com/dotnet/xharness build 20210722.1 Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 1.0.0-prerelease.21370.1 -> To Version 1.0.0-prerelease.21372.1 * Update dependencies from https://github.com/dotnet/arcade build 20210723.11 Microsoft.DotNet.XUnitExtensions , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.ApiCompat , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.GenFacades , Microsoft.DotNet.GenAPI , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.SharedFramework.Sdk From Version 6.0.0-beta.21370.12 -> To Version 6.0.0-beta.21373.11 * Update dependencies from https://github.com/dotnet/xharness build 20210723.1 Microsoft.DotNet.XHarness.CLI , Microsoft.DotNet.XHarness.TestRunners.Xunit From Version 1.0.0-prerelease.21370.1 -> To Version 1.0.0-prerelease.21373.1 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20210723.2 Microsoft.CodeAnalysis.NetAnalyzers From Version 6.0.0-rc1.21366.2 -> To Version 6.0.0-rc1.21373.2 * Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-optimization build 20210724.3 optimization.linux-x64.MIBC.Runtime , optimization.windows_nt-x64.MIBC.Runtime , optimization.windows_nt-x86.MIBC.Runtime , optimization.PGO.CoreCLR From Version 1.0.0-prerelease.21371.3 -> To Version 1.0.0-prerelease.21374.3 * Update dependencies from https://github.com/dotnet/roslyn-analyzers build 20210725.2 Microsoft.CodeAnalysis.NetAnalyzers From Version 6.0.0-rc1.21366.2 -> To Version 6.0.0-rc1.21375.2 * Revert SDK bump It will be done in https://github.com/dotnet/runtime/pull/56161 * Update dependencies from https://github.com/dotnet/runtime build 20210725.2 Microsoft.NETCore.DotNetHost , Microsoft.NETCore.DotNetHostPolicy , Microsoft.NETCore.ILAsm , runtime.native.System.IO.Ports , Microsoft.NET.Sdk.IL , System.Text.Json , System.Runtime.CompilerServices.Unsafe From Version 6.0.0-rc.1.21369.2 -> To Version 6.0.0-rc.1.21375.2 * Update dependencies from https://github.com/dotnet/arcade build 20210723.11 Microsoft.DotNet.XUnitExtensions , Microsoft.DotNet.VersionTools.Tasks , Microsoft.DotNet.Build.Tasks.Workloads , Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk , Microsoft.DotNet.Build.Tasks.Packaging , Microsoft.DotNet.Build.Tasks.Installers , Microsoft.DotNet.Build.Tasks.Feed , Microsoft.DotNet.Build.Tasks.Archives , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.ApiCompat , Microsoft.DotNet.CodeAnalysis , Microsoft.DotNet.XUnitConsoleRunner , Microsoft.DotNet.GenFacades , Microsoft.DotNet.GenAPI , Microsoft.DotNet.RemoteExecutor , Microsoft.DotNet.PackageTesting , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.SharedFramework.Sdk From Version 6.0.0-beta.21370.12 -> To Version 6.0.0-beta.21373.11 * Revert SDK bump * Update dependencies from https://github.com/dotnet/emsdk build 20210726.1 Microsoft.NET.Workload.Emscripten.Manifest-6.0.100 From Version 6.0.0-rc.1.21369.1 -> To Version 6.0.0-rc.1.21376.1 * Update dependencies from https://github.com/dotnet/emsdk build 20210726.4 Microsoft.NET.Workload.Emscripten.Manifest-6.0.100 From Version 6.0.0-rc.1.21369.1 -> To Version 6.0.0-rc.1.21376.4 Co-authored-by: dotnet-maestro[bot] Co-authored-by: Alexander Köplinger --- .config/dotnet-tools.json | 2 +- eng/Version.Details.xml | 132 ++++++++++---------- eng/Versions.props | 56 ++++----- eng/common/templates/steps/source-build.yml | 6 + global.json | 10 +- 5 files changed, 106 insertions(+), 100 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index b0ca8df7b5fef8..37cc0681fbf9db 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "1.0.0-prerelease.21370.1", + "version": "1.0.0-prerelease.21373.1", "commands": [ "xharness" ] diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 05e276bfa18d91..57e52dc79db2be 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -8,79 +8,79 @@ https://github.com/dotnet/msquic d7db669b70f4dd67ec001c192f9809c218cab88b - + https://github.com/dotnet/emsdk - 70549df51ec4b2561e2d11caa542e0b2a2903e0a + 7a7664b07a1625bc1682e0735019178e69fcfbec - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 6224d1b573b73caaa84176bd83dabe75f202cdc7 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 https://github.com/microsoft/vstest @@ -158,65 +158,65 @@ https://github.com/dotnet/runtime 38017c3935de95d0335bac04f4901ddfc2718656 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 - + https://github.com/dotnet/runtime - f7e4c261815c66fde2c1e750b744f193e236c17e + 95863758cd16c345d0b8fca067d5db5d6901e498 https://github.com/mono/linker 0cb9250a903cfc90cbac602ed79c0cbc588d8d3f - + https://github.com/dotnet/xharness - aa0da55569eaa42c2c735dd89abd2843fba4fe01 + ccb49ae05b6d98b29871a1779408d4579e16d6e5 - + https://github.com/dotnet/xharness - aa0da55569eaa42c2c735dd89abd2843fba4fe01 + ccb49ae05b6d98b29871a1779408d4579e16d6e5 - + https://github.com/dotnet/arcade - 89806f0b9e93ad2bbe32c654412835c0801a2032 + c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 2e172488a9ee56619a08c8303a708e69dc82503e + f8742ac0820e98221e7eec5f13989d9538579399 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 2e172488a9ee56619a08c8303a708e69dc82503e + f8742ac0820e98221e7eec5f13989d9538579399 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 2e172488a9ee56619a08c8303a708e69dc82503e + f8742ac0820e98221e7eec5f13989d9538579399 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - 2e172488a9ee56619a08c8303a708e69dc82503e + f8742ac0820e98221e7eec5f13989d9538579399 https://github.com/dotnet/hotreload-utils @@ -226,9 +226,9 @@ https://github.com/dotnet/runtime-assets bcfd1993de3767c54c6d8a522bf63770fba3c98d - + https://github.com/dotnet/roslyn-analyzers - 7e82240306d8a7a83ebbbc1894381393cebf9fb2 + 19af44783ceecc31842d7028e3b0ce83095ea166 diff --git a/eng/Versions.props b/eng/Versions.props index b13cc449379c09..b03ef6f33987fb 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -50,31 +50,31 @@ 3.10.0 3.10.0 - 6.0.0-rc1.21366.2 + 6.0.0-rc1.21375.2 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 2.5.1-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21372.16 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 - 6.0.0-beta.21370.12 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 2.5.1-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 + 6.0.0-beta.21373.11 6.0.0-preview.1.102 6.0.0-alpha.1.20612.4 - 6.0.0-rc.1.21369.2 - 6.0.0-rc.1.21369.2 + 6.0.0-rc.1.21375.2 + 6.0.0-rc.1.21375.2 3.1.0 - 6.0.0-rc.1.21369.2 + 6.0.0-rc.1.21375.2 5.0.0 4.3.0 @@ -108,11 +108,11 @@ 5.0.0 5.0.0 4.8.1 - 6.0.0-rc.1.21369.2 - 6.0.0-rc.1.21369.2 + 6.0.0-rc.1.21375.2 + 6.0.0-rc.1.21375.2 4.5.4 4.5.0 - 6.0.0-rc.1.21369.2 + 6.0.0-rc.1.21375.2 6.0.0-beta.21371.1 6.0.0-beta.21371.1 @@ -125,10 +125,10 @@ 6.0.0-beta.21371.1 6.0.0-beta.21371.1 - 1.0.0-prerelease.21371.3 - 1.0.0-prerelease.21371.3 - 1.0.0-prerelease.21371.3 - 1.0.0-prerelease.21371.3 + 1.0.0-prerelease.21374.3 + 1.0.0-prerelease.21374.3 + 1.0.0-prerelease.21374.3 + 1.0.0-prerelease.21374.3 16.9.0-beta1.21055.5 2.0.0-beta1.20253.1 @@ -152,8 +152,8 @@ 1.0.1-prerelease-00006 16.9.0-preview-20201201-01 - 1.0.0-prerelease.21370.1 - 1.0.0-prerelease.21370.1 + 1.0.0-prerelease.21373.1 + 1.0.0-prerelease.21373.1 1.0.1-alpha.0.21369.1 2.4.1 2.4.2 @@ -182,7 +182,7 @@ 11.1.0-alpha.1.21369.1 11.1.0-alpha.1.21369.1 - 6.0.0-rc.1.21369.1 + 6.0.0-rc.1.21376.4 $(MicrosoftNETWorkloadEmscriptenManifest60100Version) 1.1.87-gba258badda diff --git a/eng/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml index e20637ed6a177d..705b7a1c847b99 100644 --- a/eng/common/templates/steps/source-build.yml +++ b/eng/common/templates/steps/source-build.yml @@ -29,6 +29,11 @@ steps: officialBuildArgs='/p:DotNetPublishUsingPipelines=true /p:OfficialBuildId=$(BUILD.BUILDNUMBER)' fi + internalRuntimeDownloadArgs= + if [ '$(dotnetclimsrc-read-sas-token-base64)' != '$''(dotnetclimsrc-read-sas-token-base64)' ]; then + internalRuntimeDownloadArgs='--runtimesourcefeed https://dotnetclimsrc.blob.core.windows.net/dotnet --runtimesourcefeedkey $(dotnetclimsrc-read-sas-token-base64)' + fi + targetRidArgs= if [ '${{ parameters.platform.targetRID }}' != '' ]; then targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' @@ -43,6 +48,7 @@ steps: --configuration $buildConfig \ --restore --build --pack $publishArgs -bl \ $officialBuildArgs \ + $internalRuntimeDownloadArgs \ $targetRidArgs \ /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ /p:ArcadeBuildFromSource=true diff --git a/global.json b/global.json index 18f1604a2e5cd5..ad51e8c2d4275c 100644 --- a/global.json +++ b/global.json @@ -12,13 +12,13 @@ "python3": "3.7.1" }, "msbuild-sdks": { - "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21370.12", + "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21373.11", "Microsoft.DotNet.PackageValidation": "1.0.0-preview.7.21352.4", - "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21370.12", - "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21370.12", - "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21370.12", + "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21373.11", + "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21373.11", + "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21373.11", "Microsoft.Build.NoTargets": "3.0.4", "Microsoft.Build.Traversal": "3.0.23", - "Microsoft.NET.Sdk.IL": "6.0.0-rc.1.21369.2" + "Microsoft.NET.Sdk.IL": "6.0.0-rc.1.21375.2" } } From aa4290f3f0aadf86882a439d124db3215851760b Mon Sep 17 00:00:00 2001 From: Gleb Balykov Date: Mon, 2 Aug 2021 17:13:40 +0300 Subject: [PATCH 31/64] Fix behavior of inlined NDirect methods with MulticoreJit (#55185) * Disable loading of methods from r2r images in MulticoreJit thread, if they have NDirect methods inlined in them NDirect methods can be inlined in other methods during aot compilation. If such method is loaded in mcj thread, it results in NDirect method being loaded. Additionally, there's no way to control inlining during aot from runtime side, because r2r ni.dll might already exist. In order to fix this, runtime aborts loading if method has NDirect methods inlined in it and this all happens in mcj thread. * Forbid inlining of pinvoke methods with SuppressGCTransitionAttribute in MulticoreJit thread --- src/coreclr/debug/daccess/nidump.cpp | 5 +++-- src/coreclr/debug/daccess/nidump.h | 4 ++-- src/coreclr/vm/ceeload.cpp | 6 +++--- src/coreclr/vm/ceeload.h | 6 +++--- src/coreclr/vm/ceeload.inl | 8 ++++---- src/coreclr/vm/jitinterface.cpp | 30 ++++++++++++++++++++++++---- src/coreclr/vm/jitinterface.h | 4 ++-- src/coreclr/vm/prestub.cpp | 6 ++++++ src/coreclr/vm/readytoruninfo.cpp | 7 ++++++- 9 files changed, 55 insertions(+), 21 deletions(-) diff --git a/src/coreclr/debug/daccess/nidump.cpp b/src/coreclr/debug/daccess/nidump.cpp index e421e15aadd00b..06f02a3d0da95e 100644 --- a/src/coreclr/debug/daccess/nidump.cpp +++ b/src/coreclr/debug/daccess/nidump.cpp @@ -1623,7 +1623,8 @@ NativeImageDumper::PrintManifestTokenName(mdToken token, BOOL NativeImageDumper::HandleFixupForHistogram(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, - SIZE_T *fixupCell) + SIZE_T *fixupCell, + BOOL mayUsePrecompiledNDirectMethods) { COUNT_T nImportSections; PTR_CORCOMPILE_IMPORT_SECTION pImportSections = m_decoder.GetNativeImportSections(&nImportSections); @@ -3577,7 +3578,7 @@ size_t NativeImageDumper::TranslateSymbol(IXCLRDisassemblySupport *dis, return 0; } -BOOL NativeImageDumper::HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell) +BOOL NativeImageDumper::HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell, BOOL mayUsePrecompiledNDirectMethods) { PTR_SIZE_T fixupPtr(TO_TADDR(fixupCell)); m_display->StartElement( "Fixup" ); diff --git a/src/coreclr/debug/daccess/nidump.h b/src/coreclr/debug/daccess/nidump.h index a6e9461a475ae6..f39b4db15a4377 100644 --- a/src/coreclr/debug/daccess/nidump.h +++ b/src/coreclr/debug/daccess/nidump.h @@ -283,10 +283,10 @@ class NativeImageDumper IMetaDataAssemblyImport *m_manifestAssemblyImport; //helper for ComputeMethodFixupHistogram - BOOL HandleFixupForHistogram(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell); + BOOL HandleFixupForHistogram(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell, BOOL mayUsePrecompiledNDirectMethods = TRUE); //helper for DumpMethodFixups - BOOL HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell); + BOOL HandleFixupForMethodDump(PTR_CORCOMPILE_IMPORT_SECTION pSection, SIZE_T fixupIndex, SIZE_T *fixupCell, BOOL mayUsePrecompiledNDirectMethods = TRUE); // Dependencies diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index c5a9d98ac6e4e2..e0944f0a8dd10e 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -10262,7 +10262,7 @@ PTR_BYTE Module::GetNativeDebugInfo(MethodDesc * pMD) //----------------------------------------------------------------------------- -BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION* pSection, SIZE_T fixupIndex, SIZE_T* fixupCell) +BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION* pSection, SIZE_T fixupIndex, SIZE_T* fixupCell, BOOL mayUsePrecompiledNDirectMethods) { CONTRACTL { @@ -10280,7 +10280,7 @@ BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION* pSection, SIZE_T fixupI { PTR_DWORD pSignatures = dac_cast(GetNativeOrReadyToRunImage()->GetRvaData(pSection->Signatures)); - if (!LoadDynamicInfoEntry(this, pSignatures[fixupIndex], fixupCell)) + if (!LoadDynamicInfoEntry(this, pSignatures[fixupIndex], fixupCell, mayUsePrecompiledNDirectMethods)) return FALSE; _ASSERTE(*fixupCell != NULL); @@ -10291,7 +10291,7 @@ BOOL Module::FixupNativeEntry(CORCOMPILE_IMPORT_SECTION* pSection, SIZE_T fixupI if (CORCOMPILE_IS_FIXUP_TAGGED(fixup, pSection)) { // Fixup has not been fixed up yet - if (!LoadDynamicInfoEntry(this, (RVA)CORCOMPILE_UNTAG_TOKEN(fixup), fixupCell)) + if (!LoadDynamicInfoEntry(this, (RVA)CORCOMPILE_UNTAG_TOKEN(fixup), fixupCell, mayUsePrecompiledNDirectMethods)) return FALSE; _ASSERTE(!CORCOMPILE_IS_FIXUP_TAGGED(*fixupCell, pSection)); diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index 81116102682c62..963ee161605540 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -2679,17 +2679,17 @@ class Module IMDInternalImport *GetNativeAssemblyImport(BOOL loadAllowed = TRUE); IMDInternalImport *GetNativeAssemblyImportIfLoaded(); - BOOL FixupNativeEntry(CORCOMPILE_IMPORT_SECTION * pSection, SIZE_T fixupIndex, SIZE_T *fixup); + BOOL FixupNativeEntry(CORCOMPILE_IMPORT_SECTION * pSection, SIZE_T fixupIndex, SIZE_T *fixup, BOOL mayUsePrecompiledNDirectMethods = TRUE); //this split exists to support new CLR Dump functionality in DAC. The //template removes any indirections. - BOOL FixupDelayList(TADDR pFixupList); + BOOL FixupDelayList(TADDR pFixupList, BOOL mayUsePrecompiledNDirectMethods = TRUE); template BOOL FixupDelayListAux(TADDR pFixupList, Ptr pThis, FixupNativeEntryCallback pfnCB, PTR_CORCOMPILE_IMPORT_SECTION pImportSections, COUNT_T nImportSections, - PEDecoder * pNativeImage); + PEDecoder * pNativeImage, BOOL mayUsePrecompiledNDirectMethods = TRUE); void RunEagerFixups(); void RunEagerFixupsUnlocked(); diff --git a/src/coreclr/vm/ceeload.inl b/src/coreclr/vm/ceeload.inl index d6dbe8e7b40ba7..f71511cbb9ac3d 100644 --- a/src/coreclr/vm/ceeload.inl +++ b/src/coreclr/vm/ceeload.inl @@ -463,21 +463,21 @@ FORCEINLINE PTR_DomainLocalModule Module::GetDomainLocalModule() #include "nibblestream.h" -FORCEINLINE BOOL Module::FixupDelayList(TADDR pFixupList) +FORCEINLINE BOOL Module::FixupDelayList(TADDR pFixupList, BOOL mayUsePrecompiledNDirectMethods) { WRAPPER_NO_CONTRACT; COUNT_T nImportSections; PTR_CORCOMPILE_IMPORT_SECTION pImportSections = GetImportSections(&nImportSections); - return FixupDelayListAux(pFixupList, this, &Module::FixupNativeEntry, pImportSections, nImportSections, GetNativeOrReadyToRunImage()); + return FixupDelayListAux(pFixupList, this, &Module::FixupNativeEntry, pImportSections, nImportSections, GetNativeOrReadyToRunImage(), mayUsePrecompiledNDirectMethods); } template BOOL Module::FixupDelayListAux(TADDR pFixupList, Ptr pThis, FixupNativeEntryCallback pfnCB, PTR_CORCOMPILE_IMPORT_SECTION pImportSections, COUNT_T nImportSections, - PEDecoder * pNativeImage) + PEDecoder * pNativeImage, BOOL mayUsePrecompiledNDirectMethods) { CONTRACTL { @@ -567,7 +567,7 @@ BOOL Module::FixupDelayListAux(TADDR pFixupList, { CONSISTENCY_CHECK(fixupIndex * sizeof(TADDR) < cbData); - if (!(pThis->*pfnCB)(pImportSection, fixupIndex, dac_cast(pData + fixupIndex * sizeof(TADDR)))) + if (!(pThis->*pfnCB)(pImportSection, fixupIndex, dac_cast(pData + fixupIndex * sizeof(TADDR)), mayUsePrecompiledNDirectMethods)) return FALSE; int delta = reader.ReadEncodedU32(); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 51c87fa8d678e3..692c35eb6dae7e 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -10162,6 +10162,20 @@ bool CEEInfo::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, CORINFO_SI #endif } + PrepareCodeConfig *config = GetThread()->GetCurrentPrepareCodeConfig(); + if (config != nullptr && config->IsForMulticoreJit()) + { + bool suppressGCTransition = false; + CorInfoCallConvExtension unmanagedCallConv = getUnmanagedCallConv(method, callSiteSig, &suppressGCTransition); + + if (suppressGCTransition) + { + // MultiCoreJit thread can't inline PInvoke with SuppressGCTransitionAttribute, + // because it can't be resolved in mcj thread + result = TRUE; + } + } + EE_TO_JIT_TRANSITION(); return result; @@ -13777,7 +13791,8 @@ bool IsInstructionSetSupported(CORJIT_FLAGS jitFlags, ReadyToRunInstructionSet r BOOL LoadDynamicInfoEntry(Module *currentModule, RVA fixupRva, - SIZE_T *entry) + SIZE_T *entry, + BOOL mayUsePrecompiledNDirectMethods) { STANDARD_VM_CONTRACT; @@ -14005,10 +14020,17 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, case ENCODE_PINVOKE_TARGET: { - MethodDesc *pMethod = ZapSig::DecodeMethod(currentModule, pInfoModule, pBlob); + if (mayUsePrecompiledNDirectMethods) + { + MethodDesc *pMethod = ZapSig::DecodeMethod(currentModule, pInfoModule, pBlob); - _ASSERTE(pMethod->IsNDirect()); - result = (size_t)(LPVOID)NDirectMethodDesc::ResolveAndSetNDirectTarget((NDirectMethodDesc*)pMethod); + _ASSERTE(pMethod->IsNDirect()); + result = (size_t)(LPVOID)NDirectMethodDesc::ResolveAndSetNDirectTarget((NDirectMethodDesc*)pMethod); + } + else + { + return FALSE; + } } break; diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index feb9ed94f7e1f3..c231cc865ccaea 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -89,7 +89,8 @@ void getMethodInfoILMethodHeaderHelper( BOOL LoadDynamicInfoEntry(Module *currentModule, RVA fixupRva, - SIZE_T *entry); + SIZE_T *entry, + BOOL mayUsePrecompiledNDirectMethods = TRUE); // // The legacy x86 monitor helpers do not need a state argument @@ -1163,4 +1164,3 @@ FCDECL1(INT64, GetCompiledMethodCount, CLR_BOOL currentThread); FCDECL1(INT64, GetCompilationTimeInTicks, CLR_BOOL currentThread); #endif // JITINTERFACE_H - diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index 20f5cbfaf72799..75f78f55d62e36 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -426,6 +426,12 @@ PCODE MethodDesc::PrepareILBasedCode(PrepareCodeConfig* pConfig) #endif } + if (pConfig->IsForMulticoreJit() && pCode == NULL && pConfig->ReadyToRunRejectedPrecompiledCode()) + { + // Was unable to load code from r2r image in mcj thread, don't try to jit it, this method will be loaded later + return NULL; + } + if (pCode == NULL) { LOG((LF_CLASSLOADER, LL_INFO1000000, diff --git a/src/coreclr/vm/readytoruninfo.cpp b/src/coreclr/vm/readytoruninfo.cpp index cf2803dec9375b..0253d59e09c22f 100644 --- a/src/coreclr/vm/readytoruninfo.cpp +++ b/src/coreclr/vm/readytoruninfo.cpp @@ -978,7 +978,12 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, PrepareCodeConfig* pConfig if (fFixups) { - if (!m_pModule->FixupDelayList(dac_cast(GetImage()->GetBase()) + offset)) + BOOL mayUsePrecompiledNDirectMethods = TRUE; +#ifndef CROSSGEN_COMPILE + mayUsePrecompiledNDirectMethods = !pConfig->IsForMulticoreJit(); +#endif // CROSSGEN_COMPILE + + if (!m_pModule->FixupDelayList(dac_cast(GetImage()->GetBase()) + offset, mayUsePrecompiledNDirectMethods)) { #ifndef CROSSGEN_COMPILE pConfig->SetReadyToRunRejectedPrecompiledCode(); From bb7e7f9251ce1306f83266306300eefeb0a1dc44 Mon Sep 17 00:00:00 2001 From: John Call Date: Mon, 2 Aug 2021 09:29:53 -0700 Subject: [PATCH 32/64] Add equality override for KeyValuePairComparer (#56634) --- .../Collections/Generic/SortedDictionary.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/SortedDictionary.cs b/src/libraries/System.Collections/src/System/Collections/Generic/SortedDictionary.cs index 35da349f532979..c28fa0123728c8 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/SortedDictionary.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/SortedDictionary.cs @@ -947,6 +947,21 @@ public override int Compare(KeyValuePair x, KeyValuePair Date: Tue, 3 Aug 2021 00:36:11 +0800 Subject: [PATCH 33/64] Minor cleanups for System.Runtime.Numerics (#53984) * Replace union with BitConverter * Replace CombineHash with HashCode * Replace CbitHighZero with LeadingZeroCount * Remove another LeadingZeros * More cleanup in BigInteger * Cleanup complex * Apply suggestions from code review Co-authored-by: Tanner Gooding * Convert body-less for to while * Use HashCode.AddBytes Co-authored-by: Tanner Gooding --- .../src/System/Numerics/BigInteger.cs | 62 ++++++------- .../Numerics/BigIntegerCalculator.DivRem.cs | 36 +------- .../Numerics/BigIntegerCalculator.GcdInv.cs | 2 +- .../src/System/Numerics/Complex.cs | 12 +-- .../src/System/Numerics/NumericsHelpers.cs | 89 +++---------------- 5 files changed, 50 insertions(+), 151 deletions(-) diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs index ffee155326a5f1..fbb8ab78b3a630 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Runtime.InteropServices; namespace System.Numerics { @@ -263,7 +264,7 @@ public BigInteger(ReadOnlySpan value, bool isUnsigned = false, bool isBigE bool isNegative; if (byteCount > 0) { - byte mostSignificantByte = isBigEndian ? value[0] : value[byteCount - 1]; + byte mostSignificantByte = isBigEndian ? value[0] : value[^1]; isNegative = (mostSignificantByte & 0x80) != 0 && !isUnsigned; if (mostSignificantByte == 0) @@ -639,12 +640,12 @@ public bool IsPowerOfTwo AssertValid(); if (_bits == null) - return (_sign & (_sign - 1)) == 0 && _sign != 0; + return BitOperations.IsPow2(_sign); if (_sign != 1) return false; int iu = _bits.Length - 1; - if ((_bits[iu] & (_bits[iu] - 1)) != 0) + if (!BitOperations.IsPow2(_bits[iu])) return false; while (--iu >= 0) { @@ -818,12 +819,12 @@ public static double Log(BigInteger value, double baseValue) if (value._bits == null) return Math.Log(value._sign, baseValue); - ulong h = value._bits[value._bits.Length - 1]; - ulong m = value._bits.Length > 1 ? value._bits[value._bits.Length - 2] : 0; - ulong l = value._bits.Length > 2 ? value._bits[value._bits.Length - 3] : 0; + ulong h = value._bits[^1]; + ulong m = value._bits.Length > 1 ? value._bits[^2] : 0; + ulong l = value._bits.Length > 2 ? value._bits[^3] : 0; // Measure the exact bit count - int c = NumericsHelpers.CbitHighZero((uint)h); + int c = BitOperations.LeadingZeroCount((uint)h); long b = (long)value._bits.Length * 32 - c; // Extract most significant bits @@ -989,19 +990,17 @@ public override int GetHashCode() if (_bits == null) return _sign; - int hash = _sign; - for (int iv = _bits.Length; --iv >= 0;) - hash = NumericsHelpers.CombineHash(hash, unchecked((int)_bits[iv])); - return hash; + + HashCode hash = default; + hash.Add(_sign); + hash.AddBytes(MemoryMarshal.AsBytes(_bits.AsSpan())); + return hash.ToHashCode(); } public override bool Equals([NotNullWhen(true)] object? obj) { AssertValid(); - - if (!(obj is BigInteger)) - return false; - return Equals((BigInteger)obj); + return obj is BigInteger other && Equals(other); } public bool Equals(long other) @@ -1124,9 +1123,9 @@ public int CompareTo(object? obj) { if (obj == null) return 1; - if (!(obj is BigInteger)) + if (obj is not BigInteger bigInt) throw new ArgumentException(SR.Argument_MustBeBigInt, nameof(obj)); - return CompareTo((BigInteger)obj); + return CompareTo(bigInt); } /// @@ -1294,13 +1293,13 @@ private enum GetBytesMode { AllocateArray, Count, Span } // because a bits array of all zeros would represent 0, and this case // would be encoded as _bits = null and _sign = 0. Debug.Assert(bits.Length > 0); - Debug.Assert(bits[bits.Length - 1] != 0); + Debug.Assert(bits[^1] != 0); while (bits[nonZeroDwordIndex] == 0U) { nonZeroDwordIndex++; } - highDword = ~bits[bits.Length - 1]; + highDword = ~bits[^1]; if (bits.Length - 1 == nonZeroDwordIndex) { // This will not overflow because highDword is less than or equal to uint.MaxValue - 1. @@ -1312,7 +1311,7 @@ private enum GetBytesMode { AllocateArray, Count, Span } { Debug.Assert(sign == 1); highByte = 0x00; - highDword = bits[bits.Length - 1]; + highDword = bits[^1]; } byte msb; @@ -1470,15 +1469,18 @@ private ReadOnlySpan ToUInt32Span(Span scratch) } // Find highest significant byte and ensure high bit is 0 if positive, 1 if negative - int msb; - for (msb = dwords.Length - 1; msb > 0 && dwords[msb] == highDWord; msb--); + int msb = dwords.Length - 1; + while (msb > 0 && dwords[msb] == highDWord) + { + msb--; + } bool needExtraByte = (dwords[msb] & 0x80000000) != (highDWord & 0x80000000); int length = msb + 1 + (needExtraByte ? 1 : 0); bool copyDwordsToScratch = true; if (length <= scratch.Length) { - scratch = scratch.Slice(0, length); + scratch = scratch[..length]; copyDwordsToScratch = !dwordsIsScratch; } else @@ -1488,7 +1490,7 @@ private ReadOnlySpan ToUInt32Span(Span scratch) if (copyDwordsToScratch) { - dwords.Slice(0, msb + 1).CopyTo(scratch); + dwords[..(msb + 1)].CopyTo(scratch); } if (needExtraByte) @@ -1818,11 +1820,11 @@ public static explicit operator double(BigInteger value) return double.NegativeInfinity; } - ulong h = bits[length - 1]; - ulong m = length > 1 ? bits[length - 2] : 0; - ulong l = length > 2 ? bits[length - 3] : 0; + ulong h = bits[^1]; + ulong m = length > 1 ? bits[^2] : 0; + ulong l = length > 2 ? bits[^3] : 0; - int z = NumericsHelpers.CbitHighZero((uint)h); + int z = BitOperations.LeadingZeroCount((uint)h); int exp = (length - 2) * 32 - z; ulong man = (h << 32 + z) | (m << z) | (l >> 32 - z); @@ -2416,7 +2418,7 @@ public long GetBitLength() else { bitsArrayLength = bits.Length; - highValue = bits[bitsArrayLength - 1]; + highValue = bits[^1]; } long bitLength = bitsArrayLength * 32L - BitOperations.LeadingZeroCount(highValue); @@ -2493,7 +2495,7 @@ private void AssertValid() // Wasted space: _bits[0] could have been packed into _sign Debug.Assert(_bits.Length > 1 || _bits[0] >= kuMaskHighBit); // Wasted space: leading zeros could have been truncated - Debug.Assert(_bits[_bits.Length - 1] != 0); + Debug.Assert(_bits[^1] != 0); } else { diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs index bb75e77a228d01..de1001d7f4f38f 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs @@ -173,7 +173,7 @@ private static unsafe void Divide(uint* left, int leftLength, uint divLo = rightLength > 1 ? right[rightLength - 2] : 0; // We measure the leading zeros of the divisor - int shift = LeadingZeros(divHi); + int shift = BitOperations.LeadingZeroCount(divHi); int backShift = 32 - shift; // And, we make sure the most significant bit is set @@ -316,39 +316,5 @@ private static bool DivideGuessTooBig(ulong q, ulong valHi, uint valLo, return false; } - - private static int LeadingZeros(uint value) - { - if (value == 0) - return 32; - - int count = 0; - if ((value & 0xFFFF0000) == 0) - { - count += 16; - value = value << 16; - } - if ((value & 0xFF000000) == 0) - { - count += 8; - value = value << 8; - } - if ((value & 0xF0000000) == 0) - { - count += 4; - value = value << 4; - } - if ((value & 0xC0000000) == 0) - { - count += 2; - value = value << 2; - } - if ((value & 0x80000000) == 0) - { - count += 1; - } - - return count; - } } } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.GcdInv.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.GcdInv.cs index d984912ec62467..9368891c0428e2 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.GcdInv.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.GcdInv.cs @@ -238,7 +238,7 @@ private static void ExtractDigits(ref BitsBuffer xBuffer, } // Use all the bits but one, see [hac] 14.58 (ii) - int z = LeadingZeros((uint)xh); + int z = BitOperations.LeadingZeroCount((uint)xh); x = ((xh << 32 + z) | (xm << z) | (xl >> 32 - z)) >> 1; y = ((yh << 32 + z) | (ym << z) | (yl >> 32 - z)) >> 1; diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs index 9325be0d806c27..8ec356e6dc2153 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs @@ -370,8 +370,7 @@ public static Complex Reciprocal(Complex value) public override bool Equals([NotNullWhen(true)] object? obj) { - if (!(obj is Complex)) return false; - return Equals((Complex)obj); + return obj is Complex other && Equals(other); } public bool Equals(Complex value) @@ -379,14 +378,7 @@ public bool Equals(Complex value) return m_real.Equals(value.m_real) && m_imaginary.Equals(value.m_imaginary); } - public override int GetHashCode() - { - int n1 = 99999997; - int realHash = m_real.GetHashCode() % n1; - int imaginaryHash = m_imaginary.GetHashCode(); - int finalHash = realHash ^ imaginaryHash; - return finalHash; - } + public override int GetHashCode() => HashCode.Combine(m_real, m_imaginary); public override string ToString() => $"({m_real}, {m_imaginary})"; diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/NumericsHelpers.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/NumericsHelpers.cs index e89bc4acd13e8f..0926f69e2ba685 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/NumericsHelpers.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/NumericsHelpers.cs @@ -2,32 +2,20 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Runtime.InteropServices; namespace System.Numerics { - [StructLayout(LayoutKind.Explicit)] - internal struct DoubleUlong - { - [FieldOffset(0)] - public double dbl; - [FieldOffset(0)] - public ulong uu; - } - internal static class NumericsHelpers { private const int kcbitUint = 32; public static void GetDoubleParts(double dbl, out int sign, out int exp, out ulong man, out bool fFinite) { - DoubleUlong du; - du.uu = 0; - du.dbl = dbl; + ulong bits = BitConverter.DoubleToUInt64Bits(dbl); - sign = 1 - ((int)(du.uu >> 62) & 2); - man = du.uu & 0x000FFFFFFFFFFFFF; - exp = (int)(du.uu >> 52) & 0x7FF; + sign = 1 - ((int)(bits >> 62) & 2); + man = bits & 0x000FFFFFFFFFFFFF; + exp = (int)(bits >> 52) & 0x7FF; if (exp == 0) { // Denormalized number. @@ -51,15 +39,14 @@ public static void GetDoubleParts(double dbl, out int sign, out int exp, out ulo public static double GetDoubleFromParts(int sign, int exp, ulong man) { - DoubleUlong du; - du.dbl = 0; + ulong bits; if (man == 0) - du.uu = 0; + bits = 0; else { // Normalize so that 0x0010 0000 0000 0000 is the highest bit set. - int cbitShift = CbitHighZero(man) - 11; + int cbitShift = BitOperations.LeadingZeroCount(man) - 11; if (cbitShift < 0) man >>= -cbitShift; else @@ -74,7 +61,7 @@ public static double GetDoubleFromParts(int sign, int exp, ulong man) if (exp >= 0x7FF) { // Infinity. - du.uu = 0x7FF0000000000000; + bits = 0x7FF0000000000000; } else if (exp <= 0) { @@ -83,25 +70,25 @@ public static double GetDoubleFromParts(int sign, int exp, ulong man) if (exp < -52) { // Underflow to zero. - du.uu = 0; + bits = 0; } else { - du.uu = man >> -exp; - Debug.Assert(du.uu != 0); + bits = man >> -exp; + Debug.Assert(bits != 0); } } else { // Mask off the implicit high bit. - du.uu = (man & 0x000FFFFFFFFFFFFF) | ((ulong)exp << 52); + bits = (man & 0x000FFFFFFFFFFFFF) | ((ulong)exp << 52); } } if (sign < 0) - du.uu |= 0x8000000000000000; + bits |= 0x8000000000000000; - return du.dbl; + return BitConverter.UInt64BitsToDouble(bits); } // Do an in-place two's complement. "Dangerous" because it causes @@ -139,53 +126,5 @@ public static uint Abs(int a) return ((uint)a ^ mask) - mask; } } - - public static uint CombineHash(uint u1, uint u2) - { - return ((u1 << 7) | (u1 >> 25)) ^ u2; - } - - public static int CombineHash(int n1, int n2) - { - return unchecked((int)CombineHash((uint)n1, (uint)n2)); - } - - public static int CbitHighZero(uint u) - { - if (u == 0) - return 32; - - int cbit = 0; - if ((u & 0xFFFF0000) == 0) - { - cbit += 16; - u <<= 16; - } - if ((u & 0xFF000000) == 0) - { - cbit += 8; - u <<= 8; - } - if ((u & 0xF0000000) == 0) - { - cbit += 4; - u <<= 4; - } - if ((u & 0xC0000000) == 0) - { - cbit += 2; - u <<= 2; - } - if ((u & 0x80000000) == 0) - cbit += 1; - return cbit; - } - - public static int CbitHighZero(ulong uu) - { - if ((uu & 0xFFFFFFFF00000000) == 0) - return 32 + CbitHighZero((uint)uu); - return CbitHighZero((uint)(uu >> 32)); - } } } From 3dc99e900b46eff4900ca46a63ba7da963271d10 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 2 Aug 2021 09:53:48 -0700 Subject: [PATCH 34/64] Build C++/CLI tests as .NET Core C++/CLI (#56502) * Build IJW assemblies against LKG SDK ref pack. * Allow building against the live ref assemblies by passing `-cmakeargs -DCPP_CLI_LIVE_REF_ASSEMBLIES=1` to the test build script. * Add test instructions * Error handling * Add support for the stdcall-mangled _CorDllMain entrypoint on x86 since MSVC uses it if it exists. * Write out ref-pack path. --- .../coreclr/windows-test-instructions.md | 16 ++++++++++ src/coreclr/vm/ceeload.cpp | 6 +++- .../CopyConstructorMarshaler.cs | 4 +-- .../CopyConstructorMarshaler.csproj | 1 - .../FixupCallsHostWhenLoaded.cs | 5 ++-- .../FixupCallsHostWhenLoaded.csproj | 1 - src/tests/Interop/IJW/IJW.cmake | 30 ++++++++++++++++++- src/tests/Interop/IJW/IjwHelper.cs | 21 ------------- .../LoadIjwFromModuleHandle.cs | 7 ++--- .../ManagedCallingNative.cs | 14 +-------- .../ManagedCallingNative.csproj | 1 - .../NativeCallingManaged.cs | 14 +-------- .../NativeCallingManaged.csproj | 1 - .../IJW/NativeVarargs/IjwNativeVarargs.cpp | 3 +- .../IJW/NativeVarargs/NativeVarargsTest.cs | 2 +- .../NativeVarargs/NativeVarargsTest.csproj | 1 - .../IJW/getRefPackFolderFromArtifacts.ps1 | 21 +++++++++++++ .../Interop/IJW/getRefPackFolderFromSdk.ps1 | 28 +++++++++++++++++ .../Interop/IJW/ijwhostmock/CMakeLists.txt | 8 ++--- .../ijwhostmock/{mscoree.cpp => ijwhost.cpp} | 3 -- src/tests/build.cmd | 5 ++-- 21 files changed, 117 insertions(+), 75 deletions(-) delete mode 100644 src/tests/Interop/IJW/IjwHelper.cs create mode 100644 src/tests/Interop/IJW/getRefPackFolderFromArtifacts.ps1 create mode 100644 src/tests/Interop/IJW/getRefPackFolderFromSdk.ps1 rename src/tests/Interop/IJW/ijwhostmock/{mscoree.cpp => ijwhost.cpp} (79%) diff --git a/docs/workflow/testing/coreclr/windows-test-instructions.md b/docs/workflow/testing/coreclr/windows-test-instructions.md index 3819907618b4b9..dccf41f9b86bc7 100644 --- a/docs/workflow/testing/coreclr/windows-test-instructions.md +++ b/docs/workflow/testing/coreclr/windows-test-instructions.md @@ -15,6 +15,22 @@ By default, the test build uses Release as the libraries configuration. To use a src\tests\build.cmd /p:LibrariesConfiguration=Debug ``` +## Building Native Test Components + +Sometimes you want to only build the native test components instead of the managed and native components. To build the native test components only, pass the `skipmanaged` and `skipgeneratelayout` parameters to the build script as follows: + +``` +src\tests\build.cmd skipmanaged skipgeneratelayout +``` + +## Building C++/CLI native test components against the live ref assemblies + +By default, the C++/CLI native test components build against the ref pack from the SDK specified in the `global.json` file in the root of the repository. To build these components against the ref assemblies produced in the build, pass the `-cmakeargs -DCPP_CLI_LIVE_REF_ASSEMBLIES=1` parameters to the test build. For example: + +``` +src\tests\build.cmd skipmanaged -cmakeargs -DCPP_CLI_LIVE_REF_ASSEMBLIES=1 +``` + ## Building Precompiled Tests ``` diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index e0944f0a8dd10e..8540e907ffb455 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -5996,7 +5996,11 @@ static HMODULE GetIJWHostForModule(Module* module) if ((importNameTable[thunkIndex].u1.Ordinal & (1LL << (sizeof(importNameTable[thunkIndex].u1.Ordinal) * CHAR_BIT - 1))) == 0) { IMAGE_IMPORT_BY_NAME* nameImport = (IMAGE_IMPORT_BY_NAME*)(baseAddress + importNameTable[thunkIndex].u1.AddressOfData); - if (strcmp("_CorDllMain", nameImport->Name) == 0) + if (strcmp("_CorDllMain", nameImport->Name) == 0 +#ifdef TARGET_X86 + || strcmp("__CorDllMain@12", nameImport->Name) == 0 // The MSVC compiler can and will bind to the stdcall-decorated name of _CorDllMain if it exists, even if the _CorDllMain symbol also exists. +#endif + ) { HMODULE ijwHost; diff --git a/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.cs b/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.cs index 7c04e2890f0972..4b3008aa72dd02 100644 --- a/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.cs +++ b/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.cs @@ -20,7 +20,7 @@ static int Main(string[] args) try { - Assembly ijwNativeDll = IjwHelper.LoadIjwAssembly("IjwCopyConstructorMarshaler"); + Assembly ijwNativeDll = Assembly.Load("IjwCopyConstructorMarshaler"); Type testType = ijwNativeDll.GetType("TestClass"); object testInstance = Activator.CreateInstance(testType); MethodInfo testMethod = testType.GetMethod("PInvokeNumCopies"); @@ -33,7 +33,7 @@ static int Main(string[] args) // Reverse PInvoke will copy 3 times. Two are from the same paths as the PInvoke, // and the third is from the reverse P/Invoke call. Assert.AreEqual(3, (int)testMethod.Invoke(testInstance, null)); - + testMethod = testType.GetMethod("PInvokeNumCopiesDerivedType"); // PInvoke will copy twice. Once from argument to parameter, and once from the managed to native parameter. diff --git a/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.csproj b/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.csproj index 47e6c3d8060e2c..1cebb6f0730140 100644 --- a/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.csproj +++ b/src/tests/Interop/IJW/CopyConstructorMarshaler/CopyConstructorMarshaler.csproj @@ -14,7 +14,6 @@ - diff --git a/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.cs b/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.cs index 9997f1d6857fc2..5007ec3c80f0a4 100644 --- a/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.cs +++ b/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.cs @@ -21,8 +21,7 @@ static int Main(string[] args) try { - // Load a fake mscoree.dll to avoid starting desktop - IntPtr ijwHost = NativeLibrary.Load(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "mscoree.dll")); + IntPtr ijwHost = NativeLibrary.Load(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ijwhost.dll")); WasModuleVTableQueriedDelegate wasModuleVTableQueried = Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(ijwHost, "WasModuleVTableQueried")); @@ -30,7 +29,7 @@ static int Main(string[] args) Assembly.Load("IjwNativeDll"); IntPtr ijwModuleHandle = GetModuleHandle("IjwNativeDll.dll"); - + Assert.AreNotEqual(IntPtr.Zero, ijwModuleHandle); Assert.IsTrue(wasModuleVTableQueried(ijwModuleHandle)); } diff --git a/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.csproj b/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.csproj index 4343f56386fa4a..d6cec7a1845e1e 100644 --- a/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.csproj +++ b/src/tests/Interop/IJW/FixupCallsHostWhenLoaded/FixupCallsHostWhenLoaded.csproj @@ -14,7 +14,6 @@ - diff --git a/src/tests/Interop/IJW/IJW.cmake b/src/tests/Interop/IJW/IJW.cmake index b41a83794d99b1..1ba007427185c2 100644 --- a/src/tests/Interop/IJW/IJW.cmake +++ b/src/tests/Interop/IJW/IJW.cmake @@ -3,7 +3,7 @@ if (CLR_CMAKE_HOST_WIN32) add_compile_options(/wd4365) # IJW - add_compile_options(/clr) + add_compile_options(/clr:netcore) # IJW requires the CRT as a dll, not linked in set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded$<$,$>:Debug>DLL) @@ -32,4 +32,32 @@ if (CLR_CMAKE_HOST_WIN32) string(REPLACE "/GR-" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") endif() + set(CLR_SDK_REF_PACK "") + set(CLR_SDK_REF_PACK_DISCOVERY_ERROR "") + set(CLR_SDK_REF_PACK_DISCOVERY_RESULT 0) + + if (CPP_CLI_LIVE_REF_ASSEMBLIES) + message("Using live-built ref assemblies for C++/CLI runtime tests.") + execute_process( + COMMAND powershell -ExecutionPolicy ByPass -NoProfile "${CMAKE_CURRENT_LIST_DIR}/getRefPackFolderFromArtifacts.ps1" + OUTPUT_VARIABLE CLR_SDK_REF_PACK + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE CLR_SDK_REF_PACK_DISCOVERY_ERROR + RESULT_VARIABLE CLR_SDK_REF_PACK_DISCOVERY_RESULT) + else() + execute_process( + COMMAND powershell -ExecutionPolicy ByPass -NoProfile "${CMAKE_CURRENT_LIST_DIR}/getRefPackFolderFromSdk.ps1" + OUTPUT_VARIABLE CLR_SDK_REF_PACK + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE CLR_SDK_REF_PACK_DISCOVERY_ERROR + RESULT_VARIABLE CLR_SDK_REF_PACK_DISCOVERY_RESULT) + endif() + + if (NOT CLR_SDK_REF_PACK_DISCOVERY_RESULT EQUAL 0) + message(FATAL_ERROR "Unable to find reference assemblies: ${CLR_SDK_REF_PACK_DISCOVERY_ERROR}") + endif() + + add_compile_options(/AI${CLR_SDK_REF_PACK}) + + list(APPEND LINK_LIBRARIES_ADDITIONAL ijwhost) endif() diff --git a/src/tests/Interop/IJW/IjwHelper.cs b/src/tests/Interop/IJW/IjwHelper.cs deleted file mode 100644 index 007229b8a18805..00000000000000 --- a/src/tests/Interop/IJW/IjwHelper.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.IO; -using System.Reflection; -using System.Runtime.InteropServices; -using TestLibrary; - -class IjwHelper -{ - private const string ijwHostName = "mscoree.dll"; - - public static Assembly LoadIjwAssembly(string name) - { - // Load our mock ijwhost before we load the IJW assembly. - NativeLibrary.Load(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), ijwHostName)); - - return Assembly.Load(name); - } -} diff --git a/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.cs b/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.cs index 6dca0e8853e8d0..cdcacd6b3eb2a0 100644 --- a/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.cs +++ b/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.cs @@ -26,9 +26,6 @@ unsafe static int Main(string[] args) { HostPolicyMock.Initialize(Environment.CurrentDirectory, null); - // Load our fake mscoree to prevent .NET Framework from loading. - NativeLibrary.Load(Path.Combine(Environment.CurrentDirectory, "mscoree.dll")); - Console.WriteLine("Verify that we can load an IJW assembly from native code."); string ijwModulePath = Path.Combine(Environment.CurrentDirectory, "IjwNativeCallingManagedDll.dll"); IntPtr ijwNativeHandle = NativeLibrary.Load(ijwModulePath); @@ -42,7 +39,7 @@ unsafe static int Main(string[] args) { InMemoryAssemblyLoader.LoadInMemoryAssembly(ijwNativeHandle, (IntPtr)path); } - + NativeEntryPointDelegate nativeEntryPoint = Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(ijwNativeHandle, "NativeEntryPoint")); Assert.AreEqual(100, nativeEntryPoint()); @@ -63,7 +60,7 @@ unsafe static int Main(string[] args) changeReturnedValueMethod.Invoke(null, new object[] { newValue }); Assert.AreEqual(newValue, (int)getReturnValueMethod.Invoke(null, null)); - + // Native images are only loaded into memory once. As a result, the stubs in the vtfixup table // will always point to JIT stubs that exist in the first ALC that the module was loaded into. // As a result, if an IJW module is loaded into two different ALCs, or if the module is diff --git a/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.cs b/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.cs index 6fbd95199e0ff8..19910a66d973a0 100644 --- a/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.cs +++ b/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.cs @@ -20,7 +20,7 @@ static int Main(string[] args) } bool success = true; - Assembly ijwNativeDll = IjwHelper.LoadIjwAssembly("IjwNativeDll"); + Assembly ijwNativeDll = Assembly.Load("IjwNativeDll"); TestFramework.BeginTestCase("Call native method returning int"); Type testType = ijwNativeDll.GetType("TestClass"); @@ -45,19 +45,7 @@ static int Main(string[] args) catch { } TestFramework.EndTestCase(); - TestFramework.BeginTestCase("Ensure .NET Framework was not loaded"); - IntPtr clrHandle = GetModuleHandle("mscoreei.dll"); - if (clrHandle != IntPtr.Zero) - { - TestFramework.LogError("IJW", ".NET Framework loaded by IJw module load"); - success = false; - } - TestFramework.EndTestCase(); - return success ? 100 : 99; } - - [DllImport("kernel32.dll")] - static extern IntPtr GetModuleHandle(string lpModuleName); } } diff --git a/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.csproj b/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.csproj index f9af5043b8faf7..858100113ee548 100644 --- a/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.csproj +++ b/src/tests/Interop/IJW/ManagedCallingNative/ManagedCallingNative.csproj @@ -14,7 +14,6 @@ - diff --git a/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.cs b/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.cs index adf1ac4b4d7690..95516edb90ef02 100644 --- a/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.cs +++ b/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.cs @@ -20,7 +20,7 @@ static int Main(string[] args) } bool success = true; - Assembly ijwNativeDll = IjwHelper.LoadIjwAssembly("IjwNativeCallingManagedDll"); + Assembly ijwNativeDll = Assembly.Load("IjwNativeCallingManagedDll"); TestFramework.BeginTestCase("Call native method returning int"); Type testType = ijwNativeDll.GetType("TestClass"); @@ -34,19 +34,7 @@ static int Main(string[] args) } TestFramework.EndTestCase(); - TestFramework.BeginTestCase("Ensure .NET Framework was not loaded"); - IntPtr clrHandle = GetModuleHandle("mscoreei.dll"); - if (clrHandle != IntPtr.Zero) - { - TestFramework.LogError("IJW", ".NET Framework loaded by IJw module load"); - success = false; - } - TestFramework.EndTestCase(); - return success ? 100 : 99; } - - [DllImport("kernel32.dll")] - static extern IntPtr GetModuleHandle(string lpModuleName); } } diff --git a/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.csproj b/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.csproj index e2699c214d49ae..9ea4b4cde8a492 100644 --- a/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.csproj +++ b/src/tests/Interop/IJW/NativeCallingManaged/NativeCallingManaged.csproj @@ -14,7 +14,6 @@ - diff --git a/src/tests/Interop/IJW/NativeVarargs/IjwNativeVarargs.cpp b/src/tests/Interop/IJW/NativeVarargs/IjwNativeVarargs.cpp index 23b382365b1807..a2b9cc92ce8585 100644 --- a/src/tests/Interop/IJW/NativeVarargs/IjwNativeVarargs.cpp +++ b/src/tests/Interop/IJW/NativeVarargs/IjwNativeVarargs.cpp @@ -8,7 +8,8 @@ #include #include #include -#using +#using +#using using namespace System::Collections::Generic; public enum class TestCases diff --git a/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.cs b/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.cs index abc8374353b6b2..ffbf04eda1d309 100644 --- a/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.cs +++ b/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.cs @@ -26,7 +26,7 @@ static int Main(string[] args) try { - Assembly ijwNativeDll = IjwHelper.LoadIjwAssembly("IjwNativeVarargs"); + Assembly ijwNativeDll = Assembly.Load("IjwNativeVarargs"); Type testType = ijwNativeDll.GetType("TestClass"); object testInstance = Activator.CreateInstance(testType); MethodInfo testMethod = testType.GetMethod("RunTests"); diff --git a/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.csproj b/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.csproj index 157d90264bc024..b8d593f7ba87cb 100644 --- a/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.csproj +++ b/src/tests/Interop/IJW/NativeVarargs/NativeVarargsTest.csproj @@ -16,7 +16,6 @@ - diff --git a/src/tests/Interop/IJW/getRefPackFolderFromArtifacts.ps1 b/src/tests/Interop/IJW/getRefPackFolderFromArtifacts.ps1 new file mode 100644 index 00000000000000..aaf5e93661ae3a --- /dev/null +++ b/src/tests/Interop/IJW/getRefPackFolderFromArtifacts.ps1 @@ -0,0 +1,21 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +$interopFolder = Split-Path $PSScriptRoot -Parent +$testsFolder = Split-Path $interopFolder -Parent +$srcFolder = Split-Path $testsFolder -Parent +$repoRoot = Split-Path $srcFolder -Parent + +$versionPropsFile = "$repoRoot/eng/Versions.props" + +$majorVersion = Select-Xml -Path $versionPropsFile -XPath "/Project/PropertyGroup/MajorVersion" | %{$_.Node.InnerText} +$minorVersion = Select-Xml -Path $versionPropsFile -XPath "/Project/PropertyGroup/MinorVersion" | %{$_.Node.InnerText} + +$refPackPath = "$repoRoot/artifacts/bin/ref/net$majorVersion.$minorVersion" + +if (-not (Test-Path $refPackPath)) +{ + Write-Error "Reference assemblies not found in the artifacts folder at '$refPackPath'. Did you build the libs.ref subset? Did the repo layout change?" + return 1 +} + +Write-Output $refPackPath diff --git a/src/tests/Interop/IJW/getRefPackFolderFromSdk.ps1 b/src/tests/Interop/IJW/getRefPackFolderFromSdk.ps1 new file mode 100644 index 00000000000000..bb2404d27a6265 --- /dev/null +++ b/src/tests/Interop/IJW/getRefPackFolderFromSdk.ps1 @@ -0,0 +1,28 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +$interopFolder = Split-Path $PSScriptRoot -Parent +$testsFolder = Split-Path $interopFolder -Parent +$srcFolder = Split-Path $testsFolder -Parent +$repoRoot = Split-Path $srcFolder -Parent + + +. "$repoRoot/eng/common/tools.ps1" + +$dotnetRoot = InitializeDotNetCli $true $false + +$dotnetSdkVersion = $GlobalJson.tools.dotnet + +$sdkBundledVersionsFile = "$dotnetRoot/sdk/$dotnetSdkVersion/Microsoft.NETCoreSdk.BundledVersions.props" + +$refPackVersion = Select-Xml -Path $sdkBundledVersionsFile -XPath "/Project/PropertyGroup/BundledNETCoreAppPackageVersion" | %{$_.Node.InnerText} +$refPackTfmVersion = Select-Xml -Path $sdkBundledVersionsFile -XPath "/Project/PropertyGroup/BundledNETCoreAppTargetFrameworkVersion" | %{$_.Node.InnerText} + +$refPackPath = "$dotnetRoot/packs/Microsoft.NETCore.App.Ref/$refPackVersion/ref/net$refPackTfmVersion" + +if (-not (Test-Path $refPackPath)) +{ + Write-Error "Reference assemblies not found in the SDK folder. Did the SDK layout change? Did the SDK change how it describes the bundled runtime version?" + return 1 +} + +Write-Output $refPackPath diff --git a/src/tests/Interop/IJW/ijwhostmock/CMakeLists.txt b/src/tests/Interop/IJW/ijwhostmock/CMakeLists.txt index df4b1934195729..b6bbd047ab37f0 100644 --- a/src/tests/Interop/IJW/ijwhostmock/CMakeLists.txt +++ b/src/tests/Interop/IJW/ijwhostmock/CMakeLists.txt @@ -1,10 +1,10 @@ project (mscoree) include_directories( ${INC_PLATFORM_DIR} ) -set(SOURCES mscoree.cpp) +set(SOURCES ijwhost.cpp) # add the shared library -add_library (mscoree SHARED ${SOURCES}) -target_link_libraries(mscoree ${LINK_LIBRARIES_ADDITIONAL}) +add_library (ijwhost SHARED ${SOURCES}) +target_link_libraries(ijwhost ${LINK_LIBRARIES_ADDITIONAL}) # add the install targets -install (TARGETS mscoree DESTINATION bin) +install (TARGETS ijwhost DESTINATION bin) diff --git a/src/tests/Interop/IJW/ijwhostmock/mscoree.cpp b/src/tests/Interop/IJW/ijwhostmock/ijwhost.cpp similarity index 79% rename from src/tests/Interop/IJW/ijwhostmock/mscoree.cpp rename to src/tests/Interop/IJW/ijwhostmock/ijwhost.cpp index 8c466d3996f427..abc554b81b9f89 100644 --- a/src/tests/Interop/IJW/ijwhostmock/mscoree.cpp +++ b/src/tests/Interop/IJW/ijwhostmock/ijwhost.cpp @@ -8,9 +8,6 @@ std::set g_modulesQueried = {}; #if defined HOST_X86 -// We need to use a double-underscore here because the VC linker drops the first underscore -// to help people who are exporting cdecl functions to easily export the right thing. -#pragma comment(linker, "/export:__CorDllMain=__CorDllMain@12") #pragma comment(linker, "/export:GetTokenForVTableEntry=_GetTokenForVTableEntry@8") #endif diff --git a/src/tests/build.cmd b/src/tests/build.cmd index 453bc09efcbb24..aac5ffd6fb1646 100644 --- a/src/tests/build.cmd +++ b/src/tests/build.cmd @@ -56,6 +56,7 @@ set __CopyNativeProjectsAfterCombinedTestBuild=true set __SkipGenerateLayout=0 set __GenerateLayoutOnly=0 set __Ninja=1 +set __CMakeArgs= @REM CMD has a nasty habit of eating "=" on the argument list, so passing: @REM -priority=1 @@ -97,7 +98,7 @@ if /i "%1" == "skipgeneratelayout" (set __SkipGenerateLayout=1&set processedA if /i "%1" == "copynativeonly" (set __CopyNativeTestBinaries=1&set __SkipNative=1&set __CopyNativeProjectsAfterCombinedTestBuild=false&set __SkipGenerateLayout=1&set __SkipTestWrappers=1&set __SkipCrossgenFramework=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "generatelayoutonly" (set __SkipManaged=1&set __SkipNative=1&set __CopyNativeProjectsAfterCombinedTestBuild=false&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "buildtestwrappersonly" (set __SkipNative=1&set __SkipManaged=1&set __BuildTestWrappersOnly=1&set __SkipGenerateLayout=1&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) - +if /i "%1" == "-cmakeargs" (set __CMakeArgs="%2=%3" %__CMakeArgs%&set "processedArgs=!processedArgs! %1 %2=%3"&shift&shift&goto Arg_Loop) if /i "%1" == "-msbuild" (set __Ninja=0&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) if /i "%1" == "buildagainstpackages" (echo error: Remove /BuildAgainstPackages switch&&exit /b1) if /i "%1" == "crossgen2" (set __DoCrossgen2=1&set __TestBuildMode=crossgen2&set processedArgs=!processedArgs! %1&shift&goto Arg_Loop) @@ -226,7 +227,7 @@ if %__Ninja% EQU 1 ( ) else ( set __ExtraCmakeArgs="-DCMAKE_SYSTEM_VERSION=10.0" ) -call "%__RepoRootDir%\eng\native\gen-buildsys.cmd" "%__ProjectFilesDir%" "%__NativeTestIntermediatesDir%" %__VSVersion% %__BuildArch% !__ExtraCmakeArgs! +call "%__RepoRootDir%\eng\native\gen-buildsys.cmd" "%__ProjectFilesDir%" "%__NativeTestIntermediatesDir%" %__VSVersion% %__BuildArch% !__ExtraCmakeArgs! !__CMakeArgs! if not !errorlevel! == 0 ( echo %__ErrMsgPrefix%%__MsgPrefix%Error: failed to generate native component build project! From f0d1a8b390305095e8e562ef4780377b832077ce Mon Sep 17 00:00:00 2001 From: iinuwa Date: Mon, 2 Aug 2021 12:17:23 -0500 Subject: [PATCH 35/64] Fix indentation on Interop directory tree example (#56718) --- docs/coding-guidelines/interop-guidelines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/coding-guidelines/interop-guidelines.md b/docs/coding-guidelines/interop-guidelines.md index 00c05415425cfd..997aa1fd3772a8 100644 --- a/docs/coding-guidelines/interop-guidelines.md +++ b/docs/coding-guidelines/interop-guidelines.md @@ -55,7 +55,7 @@ internal static partial class Interop \Windows \mincore ... interop files - \Unix + \Unix \libc ... interop files \Linux From 077db00337f9f4819c2951e9713bd17c5ceb187d Mon Sep 17 00:00:00 2001 From: Manish Godse <61718172+mangod9@users.noreply.github.com> Date: Mon, 2 Aug 2021 10:17:47 -0700 Subject: [PATCH 36/64] removing excludes since 47096 is fixed. (#56727) --- src/tests/issues.targets | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 854204fd744fc9..747903cb427adf 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -719,16 +719,6 @@ - - - - https://github.com/dotnet/runtime/issues/47096 - - - https://github.com/dotnet/runtime/issues/47096 - - - From 200d03e289cb914a61f4df888e3f9ba945659b3c Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Mon, 2 Aug 2021 19:22:16 +0200 Subject: [PATCH 37/64] see if GetArrayDataReference_NullInput_ThrowsNullRef passes on tvOS now, fixes #36885 (#56724) --- .../System.Memory/tests/MemoryMarshal/GetArrayDataReference.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Memory/tests/MemoryMarshal/GetArrayDataReference.cs b/src/libraries/System.Memory/tests/MemoryMarshal/GetArrayDataReference.cs index c5ed1414d6a99f..ea9ab626213630 100644 --- a/src/libraries/System.Memory/tests/MemoryMarshal/GetArrayDataReference.cs +++ b/src/libraries/System.Memory/tests/MemoryMarshal/GetArrayDataReference.cs @@ -11,7 +11,6 @@ namespace System.SpanTests public static partial class MemoryMarshalTests { [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36885", TestPlatforms.tvOS)] public static void GetArrayDataReference_NullInput_ThrowsNullRef() { Assert.Throws(() => MemoryMarshal.GetArrayDataReference((object[])null)); From 31e038f7f6905531e2db95b11d4aa19e6dd9b428 Mon Sep 17 00:00:00 2001 From: Brian Sullivan Date: Mon, 2 Aug 2021 10:40:25 -0700 Subject: [PATCH 38/64] Fixes 55107 (#56259) * Fixes 55107 Add support for the very rare case of a constant byref to Compiler::optAssertionPropGlobal_RelOp Added test case * Changed casts as suggested by Jakob --- src/coreclr/jit/assertionprop.cpp | 9 +++++ .../JitBlue/Runtime_55107/Runtime_55107.cs | 40 +++++++++++++++++++ .../Runtime_55107/Runtime_55107.csproj | 22 ++++++++++ 3 files changed, 71 insertions(+) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.csproj diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 410c57264c02bf..917aa9420349e7 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -3394,6 +3394,10 @@ GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, Gen assert(vnStore->ConstantValue(vnCns) == 0); printf("null\n"); } + else if (op1->TypeGet() == TYP_BYREF) + { + printf("%d (byref)\n", static_cast(vnStore->ConstantValue(vnCns))); + } else { printf("??unknown\n"); @@ -3449,6 +3453,11 @@ GenTree* Compiler::optAssertionPropGlobal_RelOp(ASSERT_VALARG_TP assertions, Gen noway_assert(vnStore->ConstantValue(vnCns) == 0); op1->AsIntCon()->gtIconVal = 0; } + else if (op1->TypeGet() == TYP_BYREF) + { + op1->ChangeOperConst(GT_CNS_INT); + op1->AsIntCon()->gtIconVal = static_cast(vnStore->ConstantValue(vnCns)); + } else { noway_assert(!"unknown type in Global_RelOp"); diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.cs b/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.cs new file mode 100644 index 00000000000000..366bd506c1bac4 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.cs @@ -0,0 +1,40 @@ + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; + +namespace Runtime_55107 +{ + class Program + { + class G + { + } + + static int Main(string[] args) + { + G g = new G(); + + ref G iprnull = ref Unsafe.NullRef(); + ref G ipr1 = ref g; + + if(Unsafe.AreSame(ref ipr1, ref iprnull)) + { + // Failure case 1 + return -101; + } + else if(Unsafe.AreSame(ref ipr1, ref Unsafe.NullRef())) + { + // Failure case 2 + return -102; + } + else + { + // Successful exit + return 100; + } + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.csproj new file mode 100644 index 00000000000000..dad19c468a03ae --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_55107/Runtime_55107.csproj @@ -0,0 +1,22 @@ + + + Exe + + + + True + + + + + + + + + From f35b474fd587ea670bf09cdbef46e83a161ce586 Mon Sep 17 00:00:00 2001 From: Drew Scoggins Date: Mon, 2 Aug 2021 10:54:09 -0700 Subject: [PATCH 39/64] Add new msbuild prop for wasm runtime config path (#56650) --- eng/testing/performance/blazor_perf.proj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/eng/testing/performance/blazor_perf.proj b/eng/testing/performance/blazor_perf.proj index 1c3e46304dfa67..0c62c3a2ba62ec 100644 --- a/eng/testing/performance/blazor_perf.proj +++ b/eng/testing/performance/blazor_perf.proj @@ -37,13 +37,13 @@ $(WorkItemDirectory) - cd $(BlazorMinDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true" --msbuild-static AdditionalMonoLinkerOptions="%24(AdditionalMonoLinkerOptions) --dump-dependencies" + cd $(BlazorMinDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true;/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions="%24(AdditionalMonoLinkerOptions) --dump-dependencies" $(Python) test.py sod --scenario-name "%(Identity)" $(WorkItemDirectory) - cd $(BlazorMinAOTDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true" --msbuild-static AdditionalMonoLinkerOptions="%24(AdditionalMonoLinkerOptions) --dump-dependencies" + cd $(BlazorMinAOTDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true;/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions="%24(AdditionalMonoLinkerOptions) --dump-dependencies" $(Python) test.py sod --scenario-name "%(Identity)" @@ -54,7 +54,7 @@ $(WorkItemDirectory) - cd $(BlazorAOTDirectory);$(Python) pre.py publish --msbuild %27/p:_TrimmerDumpDependencies=true%27 --msbuild-static AdditionalMonoLinkerOptions=%27"%24(AdditionalMonoLinkerOptions) --dump-dependencies"%27 --binlog %27./traces/blazor_publish.binlog%27 + cd $(BlazorAOTDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true;/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions=%27"%24(AdditionalMonoLinkerOptions) --dump-dependencies"%27 --binlog %27./traces/blazor_publish.binlog%27 $(Python) test.py sod --scenario-name "%(Identity)" $(Python) post.py @@ -68,7 +68,7 @@ $(WorkItemDirectory) - cd $(BlazorPizzaAOTDirectory);$(Python) pre.py publish -f $(PerflabTargetFrameworks) --msbuild "/p:_TrimmerDumpDependencies=true" --msbuild-static AdditionalMonoLinkerOptions=%27"%24(AdditionalMonoLinkerOptions) --dump-dependencies"%27 --binlog %27./traces/blazor_publish.binlog%27 + cd $(BlazorPizzaAOTDirectory);$(Python) pre.py publish -f $(PerflabTargetFrameworks) --msbuild "/p:_TrimmerDumpDependencies=true;/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions=%27"%24(AdditionalMonoLinkerOptions) --dump-dependencies"%27 --binlog %27./traces/blazor_publish.binlog%27 $(Python) test.py sod --scenario-name "%(Identity)" --dirs $(PizzaAppPubLocation) $(Python) post.py 1:00 From d01dae43e1a30d340d994ffb4ed34ae28d3c5664 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Mon, 2 Aug 2021 11:20:23 -0700 Subject: [PATCH 40/64] JIT: don't allow negative edge weights (#56651) Due to rounding errors or inconsistencies we may end up with unexpected ratios of profile counts. Fix one place where that was leading to a negative edge weight. Fixes #56647. --- src/coreclr/jit/fgprofile.cpp | 2 ++ src/coreclr/jit/optimizer.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp index 31d7c208ebaf01..d5667a2b1c90c2 100644 --- a/src/coreclr/jit/fgprofile.cpp +++ b/src/coreclr/jit/fgprofile.cpp @@ -3000,6 +3000,8 @@ bool flowList::setEdgeWeightMaxChecked(BasicBlock::weight_t newWeight, void flowList::setEdgeWeights(BasicBlock::weight_t theMinWeight, BasicBlock::weight_t theMaxWeight, BasicBlock* bDst) { assert(theMinWeight <= theMaxWeight); + assert(theMinWeight >= 0.0f); + assert(theMaxWeight >= 0.0f); JITDUMP("Setting edge weights for " FMT_BB " -> " FMT_BB " to [" FMT_WT " .. " FMT_WT "]\n", getBlock()->bbNum, bDst->bbNum, theMinWeight, theMaxWeight); diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 26e2e15f375718..3a5cfaa7f5b5bf 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -4467,7 +4467,7 @@ bool Compiler::optInvertWhileLoop(BasicBlock* block) // Note "next" is the loop top block, not bTest's bbNext, // we'll call this latter block "after". // - BasicBlock::weight_t const testToNextLikelihood = weightNext / weightTest; + BasicBlock::weight_t const testToNextLikelihood = min(1.0f, weightNext / weightTest); BasicBlock::weight_t const testToAfterLikelihood = 1.0f - testToNextLikelihood; // Adjust edges out of bTest (which now has weight weightNext) From 7bcc2b413d288c67341401640239fe5211a397a7 Mon Sep 17 00:00:00 2001 From: Viktor Hofer Date: Mon, 2 Aug 2021 20:36:53 +0200 Subject: [PATCH 41/64] React to Verify* task PackageTesting change (#56694) * React to Verify* task PackageTesting change Depends on https://github.com/dotnet/arcade/pull/7692 Removing the dependency on the Packaging assembly in favor of the PackageTesting assembly which now contains the VerifyClosure and VerifyTypes tasks that are required for package testing. Also removing some obsolete properties and files. --- eng/Version.Details.xml | 2 +- eng/Versions.props | 2 +- .../pkg/test/build/packageTest.targets | 12 ++++----- .../netcore50/settings.targets | 5 ---- .../netcoreapp2.2/settings.targets | 8 ------ .../pkg/test/project.csproj.template | 2 -- src/libraries/pkg/test/testPackages.proj | 25 +++++++------------ 7 files changed, 17 insertions(+), 39 deletions(-) delete mode 100644 src/libraries/pkg/test/frameworkSettings/netcore50/settings.targets delete mode 100644 src/libraries/pkg/test/packageSettings/Microsoft.NETCore.Platforms/netcoreapp2.2/settings.targets diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 57e52dc79db2be..b1f8ce8b27f247 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -198,7 +198,7 @@ https://github.com/dotnet/xharness ccb49ae05b6d98b29871a1779408d4579e16d6e5 - + https://github.com/dotnet/arcade c6a28c81f96d196338b3ea520bc1e6dc7c440ee2 diff --git a/eng/Versions.props b/eng/Versions.props index b03ef6f33987fb..2a4f7a6a74987b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -65,7 +65,7 @@ 6.0.0-beta.21373.11 6.0.0-beta.21373.11 6.0.0-beta.21373.11 - 6.0.0-beta.21373.11 + 6.0.0-beta.21402.1 6.0.0-preview.1.102 diff --git a/src/libraries/pkg/test/build/packageTest.targets b/src/libraries/pkg/test/build/packageTest.targets index 8bffafc8e918d2..022944a2e0e024 100644 --- a/src/libraries/pkg/test/build/packageTest.targets +++ b/src/libraries/pkg/test/build/packageTest.targets @@ -1,16 +1,17 @@ - - <_targetFrameworkIdentifier>$(TargetFrameworkIdentifier.Substring(1).ToLower()) - - + <_targetFrameworkIdentifier Condition="'$(TargetFrameworkIdentifier)' != ''">$(TargetFrameworkIdentifier.Substring(1).ToLower()) true true - + + + + + @@ -28,7 +29,6 @@ - diff --git a/src/libraries/pkg/test/frameworkSettings/netcore50/settings.targets b/src/libraries/pkg/test/frameworkSettings/netcore50/settings.targets deleted file mode 100644 index b54cf42617011d..00000000000000 --- a/src/libraries/pkg/test/frameworkSettings/netcore50/settings.targets +++ /dev/null @@ -1,5 +0,0 @@ - - - 10.0.0 - - \ No newline at end of file diff --git a/src/libraries/pkg/test/packageSettings/Microsoft.NETCore.Platforms/netcoreapp2.2/settings.targets b/src/libraries/pkg/test/packageSettings/Microsoft.NETCore.Platforms/netcoreapp2.2/settings.targets deleted file mode 100644 index 46711d09936571..00000000000000 --- a/src/libraries/pkg/test/packageSettings/Microsoft.NETCore.Platforms/netcoreapp2.2/settings.targets +++ /dev/null @@ -1,8 +0,0 @@ - - - - $(NoWarn);NU1605 - - \ No newline at end of file diff --git a/src/libraries/pkg/test/project.csproj.template b/src/libraries/pkg/test/project.csproj.template index b2c4858b1e1f47..e0baba921e330e 100644 --- a/src/libraries/pkg/test/project.csproj.template +++ b/src/libraries/pkg/test/project.csproj.template @@ -14,8 +14,6 @@ {MicrosoftNetCoreAppFrameworkName} {MicrosoftNetCoreAppRefPackDir} - - false $(NetCoreAppCurrentVersion) diff --git a/src/libraries/pkg/test/testPackages.proj b/src/libraries/pkg/test/testPackages.proj index e4080b6116eb20..544ebe1b25f332 100644 --- a/src/libraries/pkg/test/testPackages.proj +++ b/src/libraries/pkg/test/testPackages.proj @@ -1,13 +1,7 @@ - - - - @@ -38,11 +32,6 @@ - - - - - @@ -59,9 +48,6 @@ build\Directory.Build.props; build\Directory.Build.targets" DestinationFolder="$(TestDir)" /> - @@ -77,7 +63,14 @@ - + + + + + + @@ -98,7 +91,7 @@ <_supportedPackageByTargetFrameworkToRemove Include="@(_supportedPackageByTargetFramework)" Exclude="@(TargetFrameworksToInclude)" Condition="'@(TargetFrameworksToInclude)' != ''" /> - <_filteredSupportedPackageByTargetFramework Include="@(_supportedPackageByTargetFramework)" Exclude="@(TargetFrameworksToExclude);@(_supportedPackageByTargetFrameworkToRemove)" /> + <_filteredSupportedPackageByTargetFramework Include="@(_supportedPackageByTargetFramework)" Exclude="@(_supportedPackageByTargetFrameworkToRemove)" /> From f44037126872f2157ed20847e1012df08f0357f4 Mon Sep 17 00:00:00 2001 From: Viktor Hofer Date: Mon, 2 Aug 2021 20:53:45 +0200 Subject: [PATCH 42/64] Convert AspNetCore transport pkgproj to Pack task (#56674) * Convert AspNetCore transport pkgproj to Pack task Converting the Microsoft.AspNetCore.Internal.Transport package to a proj file which uses the NuGet Pack task. Also moving some more packaging related targets into packaging.targets. * Update Microsoft.AspNetCore.Internal.Transport.proj --- eng/packaging.targets | 65 +++++++++++++++++++ src/libraries/Directory.Build.targets | 60 ----------------- ...soft.AspNetCore.Internal.Transport.pkgproj | 18 ----- ...crosoft.AspNetCore.Internal.Transport.proj | 31 +++++++-- 4 files changed, 92 insertions(+), 82 deletions(-) delete mode 100644 src/libraries/Microsoft.AspNetCore.Internal.Transport/pkg/Microsoft.AspNetCore.Internal.Transport.pkgproj diff --git a/eng/packaging.targets b/eng/packaging.targets index d6344a0b666d79..8bf2b09abf81c9 100644 --- a/eng/packaging.targets +++ b/eng/packaging.targets @@ -8,8 +8,25 @@ true $(MSBuildThisFileDirectory)useSharedDesignerContext.txt $([MSBuild]::Subtract($(MajorVersion), 1)).0.0 + IncludeAnalyzersInPackage;$(BeforePack) + $(BuildProjectReferences) + false + + + + + + + + + + + + + <_TargetPathsToSymbols Include="@(_AnalyzerFile)" TargetPath="/%(_AnalyzerFile.PackagePath)" Condition="%(_AnalyzerFile.IsSymbol)" /> + + + + + + <_analyzerPath>analyzers/dotnet + <_analyzerPath Condition="'$(AnalyzerLanguage)' != ''">$(_analyzerPath)/$(AnalyzerLanguage) + + + <_AnalyzerPackFile Include="@(_BuildOutputInPackage)" IsSymbol="false" /> + <_AnalyzerPackFile Include="@(_TargetPathsToSymbols)" IsSymbol="true" /> + <_AnalyzerPackFile PackagePath="$(_analyzerPath)/%(TargetPath)" /> + + + diff --git a/src/libraries/Directory.Build.targets b/src/libraries/Directory.Build.targets index 2e90117f462b4c..2e0e5676c2aada 100644 --- a/src/libraries/Directory.Build.targets +++ b/src/libraries/Directory.Build.targets @@ -272,65 +272,5 @@ - - - <_intellisenseRootFolder>$(BuildOutputTargetFolder) - <_intellisenseRootFolder Condition="'$(_intellisenseRootFolder)' == ''">lib - - - - - - - - IncludeAnalyzersInPackage;$(BeforePack) - $(BuildProjectReferences) - false - - - - - - - - - - - - - - - - - <_TargetPathsToSymbols Include="@(_AnalyzerFile)" TargetPath="/%(_AnalyzerFile.PackagePath)" Condition="%(_AnalyzerFile.IsSymbol)" /> - - - - - - <_analyzerPath>analyzers/dotnet - <_analyzerPath Condition="'$(AnalyzerLanguage)' != ''">$(_analyzerPath)/$(AnalyzerLanguage) - - - <_AnalyzerPackFile Include="@(_BuildOutputInPackage)" IsSymbol="false" /> - <_AnalyzerPackFile Include="@(_TargetPathsToSymbols)" IsSymbol="true" /> - <_AnalyzerPackFile PackagePath="$(_analyzerPath)/%(TargetPath)" /> - - - - diff --git a/src/libraries/Microsoft.AspNetCore.Internal.Transport/pkg/Microsoft.AspNetCore.Internal.Transport.pkgproj b/src/libraries/Microsoft.AspNetCore.Internal.Transport/pkg/Microsoft.AspNetCore.Internal.Transport.pkgproj deleted file mode 100644 index 23046099e10ada..00000000000000 --- a/src/libraries/Microsoft.AspNetCore.Internal.Transport/pkg/Microsoft.AspNetCore.Internal.Transport.pkgproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - true - true - false - false - Internal transport package to provide aspnetcore with the assemblies that make up the Microsoft.ASPNetCore.App shared framework. - - - <_analyzers Include="$(ASPNETCoreAppPackageRootPath)\analyzers\**\*.*" /> - - <_libDocs Include="$(ASPNETCoreAppPackageRuntimePath)\*.xml" /> - - - - - diff --git a/src/libraries/Microsoft.AspNetCore.Internal.Transport/src/Microsoft.AspNetCore.Internal.Transport.proj b/src/libraries/Microsoft.AspNetCore.Internal.Transport/src/Microsoft.AspNetCore.Internal.Transport.proj index 8d90792dd6ffe1..8f8f7feae0fbb3 100644 --- a/src/libraries/Microsoft.AspNetCore.Internal.Transport/src/Microsoft.AspNetCore.Internal.Transport.proj +++ b/src/libraries/Microsoft.AspNetCore.Internal.Transport/src/Microsoft.AspNetCore.Internal.Transport.proj @@ -1,6 +1,29 @@ - - + - netstandard2.0 + $(NetCoreAppCurrent) + true + false + + true + Internal transport package to provide aspnetcore with the assemblies that make up the Microsoft.ASPNetCore.App shared framework. + + $(NoWarn);NU5131 - \ No newline at end of file + + + <_analyzer Include="$(ASPNETCoreAppPackageRootPath)\analyzers\**\*.*" /> + <_libDoc Include="$(ASPNETCoreAppPackageRuntimePath)\*.xml" /> + + + + + + From faa05598c1981d74b9dc37504da8472400b3aeba Mon Sep 17 00:00:00 2001 From: David Fowler Date: Mon, 2 Aug 2021 11:57:24 -0700 Subject: [PATCH 43/64] Dump the environment variable prefix in ToString (#56685) * Dump the environment variable prefix in ToString - This allows tools that dump the providers (like GetDebugView) to see a little more data about the configured providers when debugging. --- .../src/EnvironmentVariablesConfigurationProvider.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs index 294956a5e737ee..5ea29116ca2d9b 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs @@ -38,6 +38,13 @@ public EnvironmentVariablesConfigurationProvider(string prefix) => public override void Load() => Load(Environment.GetEnvironmentVariables()); + /// + /// Generates a string representing this provider name and relevant details. + /// + /// The configuration name. + public override string ToString() + => $"{GetType().Name} Prefix: '{_prefix}'"; + internal void Load(IDictionary envVariables) { var data = new Dictionary(StringComparer.OrdinalIgnoreCase); From 4e05e94635b89e8a4cf8be098fc47ffbf6933c31 Mon Sep 17 00:00:00 2001 From: Maoni Stephens Date: Mon, 2 Aug 2021 11:58:09 -0700 Subject: [PATCH 44/64] counting the LOH pad objects in the free object space (#56665) --- src/coreclr/gc/gc.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 9d285b64a38f8d..51af19280eee52 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -15047,6 +15047,7 @@ BOOL gc_heap::a_fit_free_list_uoh_p (size_t size, if (loh_pad) { make_unused_array (free_list, loh_pad); + generation_free_obj_space (gen) += loh_pad; limit -= loh_pad; free_list += loh_pad; free_list_size -= loh_pad; @@ -15185,6 +15186,7 @@ BOOL gc_heap::a_fit_segment_end_p (int gen_number, if (gen_number == loh_generation) { make_unused_array (allocated, loh_pad); + generation_free_obj_space (generation_of (gen_number)) += loh_pad; allocated += loh_pad; limit -= loh_pad; } From f83a9d9689433ce522b91e74a9631c83847e3b64 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Mon, 2 Aug 2021 23:06:47 +0300 Subject: [PATCH 45/64] Match xplat event source conditions (#56435) --- src/coreclr/clr.featuredefines.props | 2 +- src/coreclr/vm/ecall.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/coreclr/clr.featuredefines.props b/src/coreclr/clr.featuredefines.props index 60e38832295192..511db52edc1020 100644 --- a/src/coreclr/clr.featuredefines.props +++ b/src/coreclr/clr.featuredefines.props @@ -14,7 +14,7 @@ - true + true true true diff --git a/src/coreclr/vm/ecall.cpp b/src/coreclr/vm/ecall.cpp index c6d1b6d2f1eddd..3dd1c44aa26498 100644 --- a/src/coreclr/vm/ecall.cpp +++ b/src/coreclr/vm/ecall.cpp @@ -659,6 +659,13 @@ LPVOID ECall::GetQCallImpl(MethodDesc * pMD) if (id == 0) { id = ECall::GetIDForMethod(pMD); + +#ifdef _DEBUG + CONSISTENCY_CHECK_MSGF(id != 0, + ("%s::%s is not registered in ecall.cpp", + pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName)); +#endif + _ASSERTE(id != 0); // Cache the id From 643ab28503fb4e65c59456eafdbc87d9822d8c06 Mon Sep 17 00:00:00 2001 From: Mateo Torres-Ruiz Date: Mon, 2 Aug 2021 14:14:38 -0700 Subject: [PATCH 46/64] Disable failing arm64 win10 Graphics.FromHdc tests (#56732) * Disable arm64-win10 tests preventing clean build * Use ActiveIssue with conditional --- src/libraries/System.Drawing.Common/tests/GraphicsTests.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libraries/System.Drawing.Common/tests/GraphicsTests.cs b/src/libraries/System.Drawing.Common/tests/GraphicsTests.cs index ba8246641c6e2b..8c0f280b863613 100644 --- a/src/libraries/System.Drawing.Common/tests/GraphicsTests.cs +++ b/src/libraries/System.Drawing.Common/tests/GraphicsTests.cs @@ -98,6 +98,7 @@ public static IEnumerable FromHdc_TestData() } [ActiveIssue("https://github.com/dotnet/runtime/issues/22221", TestPlatforms.AnyUnix)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51097", typeof(PlatformDetection), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsWindows10OrLater))] [ConditionalTheory(Helpers.IsDrawingSupported)] [MemberData(nameof(FromHdc_TestData))] public void FromHdc_ValidHdc_ReturnsExpected(IntPtr hdc) @@ -110,6 +111,7 @@ public void FromHdc_ValidHdc_ReturnsExpected(IntPtr hdc) } [ActiveIssue("https://github.com/dotnet/runtime/issues/22221", TestPlatforms.AnyUnix)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51097", typeof(PlatformDetection), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsWindows10OrLater))] [ConditionalTheory(Helpers.IsDrawingSupported)] [MemberData(nameof(FromHdc_TestData))] public void FromHdc_ValidHdcWithContext_ReturnsExpected(IntPtr hdc) @@ -122,6 +124,7 @@ public void FromHdc_ValidHdcWithContext_ReturnsExpected(IntPtr hdc) } [ActiveIssue("https://github.com/dotnet/runtime/issues/22221", TestPlatforms.AnyUnix)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51097", typeof(PlatformDetection), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsWindows10OrLater))] [ConditionalTheory(Helpers.IsDrawingSupported)] [MemberData(nameof(FromHdc_TestData))] public void FromHdcInternal_GetDC_ReturnsExpected(IntPtr hdc) @@ -258,6 +261,7 @@ public static IEnumerable Hwnd_TestData() } [ActiveIssue("https://github.com/dotnet/runtime/issues/22221", TestPlatforms.AnyUnix)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51097", typeof(PlatformDetection), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsWindows10OrLater))] [ConditionalTheory(Helpers.IsDrawingSupported)] [MemberData(nameof(Hwnd_TestData))] public void FromHwnd_ValidHwnd_ReturnsExpected(IntPtr hWnd) @@ -270,6 +274,7 @@ public void FromHwnd_ValidHwnd_ReturnsExpected(IntPtr hWnd) } [ActiveIssue("https://github.com/dotnet/runtime/issues/22221", TestPlatforms.AnyUnix)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51097", typeof(PlatformDetection), nameof(PlatformDetection.IsArm64Process), nameof(PlatformDetection.IsWindows10OrLater))] [ConditionalTheory(Helpers.IsDrawingSupported)] [MemberData(nameof(Hwnd_TestData))] public void FromHwndInternal_ValidHwnd_ReturnsExpected(IntPtr hWnd) From 5a55a0aaf362af87e505e85e9f346dba927909df Mon Sep 17 00:00:00 2001 From: Mitchell Hwang <16830051+mdh1418@users.noreply.github.com> Date: Mon, 2 Aug 2021 17:28:50 -0400 Subject: [PATCH 47/64] [libraries] Reenable System.Diagnostics.DiagnosticSorce.Switches.Tests on mobile (#56737) Co-authored-by: Mitchell Hwang --- .../tests/TestWithConfigSwitches/ActivityTests.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/ActivityTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/ActivityTests.cs index 5890e43abd37b0..cb848a9c1cb408 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/ActivityTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/TestWithConfigSwitches/ActivityTests.cs @@ -6,8 +6,6 @@ namespace System.Diagnostics.Tests { - [ActiveIssue("https://github.com/dotnet/runtime/issues/37073", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/51376", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public class ActivityTests : IDisposable { [Fact] From f74c14fd62ae9c30ef6a375846c88c0dfa15feb0 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Mon, 2 Aug 2021 16:39:24 -0700 Subject: [PATCH 48/64] Make sure ServerGCHeapDetails is up to date (#56056) --- src/coreclr/debug/daccess/request.cpp | 31 +++--- src/coreclr/debug/daccess/request_common.h | 107 ++++++++++++++++++--- src/coreclr/debug/daccess/request_svr.cpp | 83 +++++++++++----- src/coreclr/gc/gc.cpp | 26 ++++- src/coreclr/gc/gc_typefields.h | 32 ++++++ src/coreclr/gc/gcinterface.dac.h | 28 +++--- src/coreclr/gc/gcinterface.dacvars.def | 3 +- src/coreclr/gc/gcpriv.h | 26 ----- 8 files changed, 248 insertions(+), 88 deletions(-) create mode 100644 src/coreclr/gc/gc_typefields.h diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 968664489d8909..4e729c8733964b 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -2772,19 +2772,24 @@ ClrDataAccess::GetGCHeapDetails(CLRDATA_ADDRESS heap, struct DacpGcHeapDetails * HRESULT ClrDataAccess::GetGCHeapStaticData(struct DacpGcHeapDetails *detailsData) { + // Make sure ClrDataAccess::ServerGCHeapDetails() is updated as well. if (detailsData == NULL) + { return E_INVALIDARG; + } SOSDacEnter(); + detailsData->heapAddr = NULL; + detailsData->lowest_address = PTR_CDADDR(g_lowest_address); detailsData->highest_address = PTR_CDADDR(g_highest_address); - detailsData->card_table = PTR_CDADDR(g_card_table); - detailsData->heapAddr = NULL; + detailsData->current_c_gc_state = (CLRDATA_ADDRESS)*g_gcDacGlobals->current_c_gc_state; + detailsData->alloc_allocated = (CLRDATA_ADDRESS)*g_gcDacGlobals->alloc_allocated; detailsData->ephemeral_heap_segment = (CLRDATA_ADDRESS)*g_gcDacGlobals->ephemeral_heap_segment; + detailsData->card_table = PTR_CDADDR(g_card_table); detailsData->mark_array = (CLRDATA_ADDRESS)*g_gcDacGlobals->mark_array; - detailsData->current_c_gc_state = (CLRDATA_ADDRESS)*g_gcDacGlobals->current_c_gc_state; detailsData->next_sweep_obj = (CLRDATA_ADDRESS)*g_gcDacGlobals->next_sweep_obj; if (g_gcDacGlobals->saved_sweep_ephemeral_seg != nullptr) { @@ -2801,13 +2806,12 @@ ClrDataAccess::GetGCHeapStaticData(struct DacpGcHeapDetails *detailsData) detailsData->background_saved_lowest_address = (CLRDATA_ADDRESS)*g_gcDacGlobals->background_saved_lowest_address; detailsData->background_saved_highest_address = (CLRDATA_ADDRESS)*g_gcDacGlobals->background_saved_highest_address; - for (unsigned int i=0; i < *g_gcDacGlobals->max_gen + 2; i++) + // get bounds for the different generations + for (unsigned int i=0; i < DAC_NUMBERGENERATIONS; i++) { DPTR(dac_generation) generation = GenerationTableIndex(g_gcDacGlobals->generation_table, i); detailsData->generation_table[i].start_segment = (CLRDATA_ADDRESS) dac_cast(generation->start_segment); - detailsData->generation_table[i].allocation_start = (CLRDATA_ADDRESS) generation->allocation_start; - DPTR(gc_alloc_context) alloc_context = dac_cast(generation) + offsetof(dac_generation, allocation_context); detailsData->generation_table[i].allocContextPtr = (CLRDATA_ADDRESS)alloc_context->alloc_ptr; detailsData->generation_table[i].allocContextLimit = (CLRDATA_ADDRESS)alloc_context->alloc_limit; @@ -2817,7 +2821,7 @@ ClrDataAccess::GetGCHeapStaticData(struct DacpGcHeapDetails *detailsData) { DPTR(dac_finalize_queue) fq = Dereference(g_gcDacGlobals->finalize_queue); DPTR(uint8_t*) fillPointersTable = dac_cast(fq) + offsetof(dac_finalize_queue, m_FillPointers); - for (unsigned int i = 0; i<(*g_gcDacGlobals->max_gen + 2 + dac_finalize_queue::ExtraSegCount); i++) + for (unsigned int i = 0; i < DAC_NUMBERGENERATIONS + 3; i++) { detailsData->finalization_fill_pointers[i] = (CLRDATA_ADDRESS)*TableIndex(fillPointersTable, i, sizeof(uint8_t*)); } @@ -4699,13 +4703,13 @@ HRESULT ClrDataAccess::GetGenerationTableSvr(CLRDATA_ADDRESS heapAddr, unsigned } else { - DPTR(dac_gc_heap) pHeap = __DPtr(TO_TADDR(heapAddr)); + TADDR heapAddress = TO_TADDR(heapAddr); - if (pHeap.IsValid()) + if (heapAddress != 0) { for (unsigned int i = 0; i < numGenerationTableEntries; ++i) { - DPTR(dac_generation) generation = ServerGenerationTableIndex(pHeap, i); + DPTR(dac_generation) generation = ServerGenerationTableIndex(heapAddress, i); pGenerationData[i].start_segment = (CLRDATA_ADDRESS)dac_cast(generation->start_segment); pGenerationData[i].allocation_start = (CLRDATA_ADDRESS)(ULONG_PTR)generation->allocation_start; DPTR(gc_alloc_context) alloc_context = dac_cast(generation) + offsetof(dac_generation, allocation_context); @@ -4749,10 +4753,11 @@ HRESULT ClrDataAccess::GetFinalizationFillPointersSvr(CLRDATA_ADDRESS heapAddr, } else { - DPTR(dac_gc_heap) pHeap = __DPtr(TO_TADDR(heapAddr)); - - if (pHeap.IsValid()) + TADDR heapAddress = TO_TADDR(heapAddr); + if (heapAddress != 0) { + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; DPTR(dac_finalize_queue) fq = pHeap->finalize_queue; DPTR(uint8_t*) pFillPointerArray= dac_cast(fq) + offsetof(dac_finalize_queue, m_FillPointers); for (unsigned int i = 0; i < numFillPointers; ++i) diff --git a/src/coreclr/debug/daccess/request_common.h b/src/coreclr/debug/daccess/request_common.h index d5f60df957c8bc..1b86b463802048 100644 --- a/src/coreclr/debug/daccess/request_common.h +++ b/src/coreclr/debug/daccess/request_common.h @@ -26,6 +26,16 @@ DPTR(T) Dereference(DPTR(T*) ptr) return __DPtr(ptr_base); } +// Indexes into the global heap table, returning a TADDR to the requested +// heap instance. +inline TADDR +HeapTableIndex(DPTR(opaque_gc_heap**) heaps, size_t index) +{ + DPTR(opaque_gc_heap*) heap_table = Dereference(heaps); + DPTR(opaque_gc_heap*) ptr = TableIndex(heap_table, index, sizeof(void*)); + return Dereference(ptr).GetAddr(); +} + // Indexes into a given generation table, returning a DPTR to the // requested element (the element at the given index) of the table. inline DPTR(dac_generation) @@ -34,24 +44,99 @@ GenerationTableIndex(DPTR(dac_generation) base, size_t index) return TableIndex(base, index, g_gcDacGlobals->generation_size); } +// Starting .NET 6, it is possible for the gc_heap object to have different layouts +// for coreclr.dll and clrgc.dll. Instead of using assuming dac_gc_heap and gc_heap +// have identical layout, we have the gc exported an array of field offsets instead. +// These offsets could be -1, indicating the field does not exist in the current +// gc_heap being used. + +// field_offset = g_gcDacGlobals->gc_heap_field_offsets +// p_field_offset = field_offset[field_index] +// p_field = heap + p_field_offset +// field_index++ +#define LOAD_BASE(field_name, field_type) \ + DPTR(int) p_##field_name##_offset = TableIndex(field_offsets, field_index, sizeof(int)); \ + int field_name##_offset = *p_##field_name##_offset; \ + DPTR(field_type) p_##field_name = heap + field_name##_offset; \ + field_index++; + +// if (field_offset != -1) +// result.field = *p_field +#define LOAD(field_name, field_type) \ + LOAD_BASE(field_name, field_type) \ + if (field_name##_offset != -1) \ + { \ + field_type field_name = *p_##field_name; \ + result.field_name = field_name; \ + } + +// if (field_offset != -1) +// result.field = DPTR(field_type)field_name +#define LOAD_DPTR(field_name, field_type) \ + LOAD_BASE(field_name, field_type*) \ + if (field_name##_offset != -1) \ + { \ + field_type* field_name = *p_##field_name; \ + result.field_name = DPTR(field_type)((TADDR)field_name); \ + } + +// if (field_offset != -1) +// for i from 0 to array_length - 1 +// result.field[i] = *p_field +// p_field = p_field + 1 +#define LOAD_ARRAY(field_name, field_type, array_length) \ + LOAD_BASE(field_name, field_type) \ + if (field_name##_offset != -1) \ + { \ + for (int i = 0; i < array_length; i++) \ + { \ + result.field_name[i] = *p_##field_name; \ + p_##field_name = p_##field_name + 1; \ + } \ + } + // Indexes into a heap's generation table, given the heap instance // and the desired index. Returns a DPTR to the requested element. inline DPTR(dac_generation) -ServerGenerationTableIndex(DPTR(dac_gc_heap) heap, size_t index) +ServerGenerationTableIndex(TADDR heap, size_t index) { - TADDR base_addr = dac_cast(heap) + offsetof(dac_gc_heap, generation_table); - DPTR(dac_generation) base = __DPtr(base_addr); - return TableIndex(base, index, g_gcDacGlobals->generation_size); + DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets; + int field_index = GENERATION_TABLE_FIELD_INDEX; + LOAD_BASE (generation_table, dac_generation); + assert (generation_table_offset != -1); + return TableIndex(p_generation_table, index, g_gcDacGlobals->generation_size); } -// Indexes into the global heap table, returning a DPTR to the requested -// heap instance. -inline DPTR(dac_gc_heap) -HeapTableIndex(DPTR(dac_gc_heap**) heaps, size_t index) +// Load an instance of dac_gc_heap for the heap pointed by heap. +// Fields that does not exist in the current gc_heap instance is zero initialized. +// Return the dac_gc_heap object. +inline dac_gc_heap +LoadGcHeapData(TADDR heap) { - DPTR(dac_gc_heap*) heap_table = Dereference(heaps); - DPTR(dac_gc_heap*) ptr = TableIndex(heap_table, index, sizeof(dac_gc_heap*)); - return Dereference(ptr); + dac_gc_heap result; + memset(&result, 0, sizeof(dac_gc_heap)); + + DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets; + int field_index = 0; + +#define ALL_FIELDS +#define DEFINE_FIELD(field_name, field_type) LOAD(field_name, field_type) +#define DEFINE_DPTR_FIELD(field_name, field_type) LOAD_DPTR(field_name, field_type) +#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) LOAD_ARRAY(field_name, field_type, array_length); + +#include "../../gc/gc_typefields.h" + +#undef DEFINE_ARRAY_FIELD +#undef DEFINE_DPTR_FIELD +#undef DEFINE_FIELD +#undef ALL_FIELDS + + return result; } +#undef LOAD_ARRAY +#undef LOAD_DPTR +#undef LOAD +#undef LOAD_BASE + #endif // _REQUEST_COMMON_H_ diff --git a/src/coreclr/debug/daccess/request_svr.cpp b/src/coreclr/debug/daccess/request_svr.cpp index 558ac0c33471b3..691171f3af91cb 100644 --- a/src/coreclr/debug/daccess/request_svr.cpp +++ b/src/coreclr/debug/daccess/request_svr.cpp @@ -64,7 +64,7 @@ HRESULT GetServerHeaps(CLRDATA_ADDRESS pGCHeaps[], ICorDebugDataTarget * pTarget // heap addresses. for (int i = 0; i < GCHeapCount(); i++) { - pGCHeaps[i] = (CLRDATA_ADDRESS)HeapTableIndex(g_gcDacGlobals->g_heaps, i).GetAddr(); + pGCHeaps[i] = (CLRDATA_ADDRESS)HeapTableIndex(g_gcDacGlobals->g_heaps, i); } return S_OK; @@ -86,7 +86,7 @@ HRESULT ClrDataAccess::GetServerAllocData(unsigned int count, struct DacpGenerat for (unsigned int n=0; n < heaps; n++) { - DPTR(dac_gc_heap) pHeap = HeapTableIndex(g_gcDacGlobals->g_heaps, n); + TADDR pHeap = HeapTableIndex(g_gcDacGlobals->g_heaps, n); for (int i=0;i(TO_TADDR(heapAddr)); - int i; + TADDR heapAddress = TO_TADDR(heapAddr); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; //get global information first detailsData->heapAddr = heapAddr; detailsData->lowest_address = PTR_CDADDR(g_lowest_address); detailsData->highest_address = PTR_CDADDR(g_highest_address); - detailsData->card_table = PTR_CDADDR(g_card_table); + detailsData->current_c_gc_state = (CLRDATA_ADDRESS)*g_gcDacGlobals->current_c_gc_state; // now get information specific to this heap (server mode gives us several heaps; we're getting // information about only one of them. detailsData->alloc_allocated = (CLRDATA_ADDRESS)pHeap->alloc_allocated; detailsData->ephemeral_heap_segment = (CLRDATA_ADDRESS)dac_cast(pHeap->ephemeral_heap_segment); + detailsData->card_table = (CLRDATA_ADDRESS)pHeap->card_table; + detailsData->mark_array = (CLRDATA_ADDRESS)pHeap->mark_array; + detailsData->next_sweep_obj = (CLRDATA_ADDRESS)pHeap->next_sweep_obj; + if (pHeap->saved_sweep_ephemeral_seg.IsValid()) + { + detailsData->saved_sweep_ephemeral_seg = (CLRDATA_ADDRESS)dac_cast(pHeap->saved_sweep_ephemeral_seg); + detailsData->saved_sweep_ephemeral_start = (CLRDATA_ADDRESS)*pHeap->saved_sweep_ephemeral_start; + } + else + { + // with regions, we don't have these variables anymore + // use special value -1 in saved_sweep_ephemeral_seg to signal the region case + detailsData->saved_sweep_ephemeral_seg = (CLRDATA_ADDRESS)-1; + detailsData->saved_sweep_ephemeral_start = 0; + } + detailsData->background_saved_lowest_address = (CLRDATA_ADDRESS)pHeap->background_saved_lowest_address; + detailsData->background_saved_highest_address = (CLRDATA_ADDRESS)pHeap->background_saved_highest_address; // get bounds for the different generations - for (i=0; igeneration_table[i].start_segment = (CLRDATA_ADDRESS)dac_cast(generation->start_segment); detailsData->generation_table[i].allocation_start = (CLRDATA_ADDRESS)(ULONG_PTR)generation->allocation_start; DPTR(gc_alloc_context) alloc_context = dac_cast(generation) + offsetof(dac_generation, allocation_context); @@ -134,10 +158,13 @@ HRESULT ClrDataAccess::ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr, DacpGcHeapD } DPTR(dac_finalize_queue) fq = pHeap->finalize_queue; - DPTR(uint8_t*) pFillPointerArray= dac_cast(fq) + offsetof(dac_finalize_queue, m_FillPointers); - for(i=0; i<(NUMBERGENERATIONS+dac_finalize_queue::ExtraSegCount); i++) + if (fq.IsValid()) { - detailsData->finalization_fill_pointers[i] = (CLRDATA_ADDRESS) pFillPointerArray[i]; + DPTR(uint8_t*) fillPointersTable = dac_cast(fq) + offsetof(dac_finalize_queue, m_FillPointers); + for (unsigned int i = 0; i < DAC_NUMBERGENERATIONS + 3; i++) + { + detailsData->finalization_fill_pointers[i] = (CLRDATA_ADDRESS)*TableIndex(fillPointersTable, i, sizeof(uint8_t*)); + } } return S_OK; @@ -146,7 +173,9 @@ HRESULT ClrDataAccess::ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr, DacpGcHeapD HRESULT ClrDataAccess::ServerOomData(CLRDATA_ADDRESS addr, DacpOomData *oomData) { - DPTR(dac_gc_heap) pHeap = __DPtr(TO_TADDR(addr)); + TADDR heapAddress = TO_TADDR(addr); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; oom_history pOOMInfo = pHeap->oom_info; oomData->reason = pOOMInfo.reason; @@ -193,7 +222,9 @@ HRESULT ClrDataAccess::ServerGCHeapAnalyzeData(CLRDATA_ADDRESS heapAddr, DacpGcH return E_INVALIDARG; } - DPTR(dac_gc_heap) pHeap = __DPtr(TO_TADDR(heapAddr)); + TADDR heapAddress = TO_TADDR(heapAddr); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; analyzeData->heapAddr = heapAddr; analyzeData->internal_root_array = (CLRDATA_ADDRESS)pHeap->internal_root_array; @@ -221,7 +252,9 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) for (int i = 0; i < heaps; i++) { - DPTR(dac_gc_heap) pHeap = HeapTableIndex(g_gcDacGlobals->g_heaps, i); + TADDR heapAddress = HeapTableIndex(g_gcDacGlobals->g_heaps, i); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; size_t gen_table_size = g_gcDacGlobals->generation_size * (*g_gcDacGlobals->max_gen + 2); DacEnumMemoryRegion(dac_cast(pHeap), sizeof(dac_gc_heap)); @@ -235,7 +268,7 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) // this is the convention in the GC so it is repeated here for (ULONG i = *g_gcDacGlobals->max_gen; i <= *g_gcDacGlobals->max_gen +1; i++) { - DPTR(dac_heap_segment) seg = ServerGenerationTableIndex(pHeap, i)->start_segment; + DPTR(dac_heap_segment) seg = ServerGenerationTableIndex(heapAddress, i)->start_segment; while (seg) { DacEnumMemoryRegion(PTR_HOST_TO_TADDR(seg), sizeof(dac_heap_segment)); @@ -270,18 +303,20 @@ HRESULT DacHeapWalker::InitHeapDataSvr(HeapData *&pHeaps, size_t &pCount) for (int i = 0; i < heaps; ++i) { // Basic heap info. - DPTR(dac_gc_heap) heap = HeapTableIndex(g_gcDacGlobals->g_heaps, i); - dac_generation gen0 = *ServerGenerationTableIndex(heap, 0); - dac_generation gen1 = *ServerGenerationTableIndex(heap, 1); - dac_generation gen2 = *ServerGenerationTableIndex(heap, 2); - dac_generation loh = *ServerGenerationTableIndex(heap, 3); - dac_generation poh = *ServerGenerationTableIndex(heap, 4); + TADDR heapAddress = HeapTableIndex(g_gcDacGlobals->g_heaps, i); + dac_gc_heap heap = LoadGcHeapData(heapAddress); + dac_gc_heap* pHeap = &heap; + dac_generation gen0 = *ServerGenerationTableIndex(heapAddress, 0); + dac_generation gen1 = *ServerGenerationTableIndex(heapAddress, 1); + dac_generation gen2 = *ServerGenerationTableIndex(heapAddress, 2); + dac_generation loh = *ServerGenerationTableIndex(heapAddress, 3); + dac_generation poh = *ServerGenerationTableIndex(heapAddress, 4); pHeaps[i].YoungestGenPtr = (CORDB_ADDRESS)gen0.allocation_context.alloc_ptr; pHeaps[i].YoungestGenLimit = (CORDB_ADDRESS)gen0.allocation_context.alloc_limit; pHeaps[i].Gen0Start = (CORDB_ADDRESS)gen0.allocation_start; - pHeaps[i].Gen0End = (CORDB_ADDRESS)heap->alloc_allocated; + pHeaps[i].Gen0End = (CORDB_ADDRESS)pHeap->alloc_allocated; pHeaps[i].Gen1Start = (CORDB_ADDRESS)gen1.allocation_start; // Segments @@ -300,9 +335,9 @@ HRESULT DacHeapWalker::InitHeapDataSvr(HeapData *&pHeaps, size_t &pCount) for (; seg && (j < count); ++j) { pHeaps[i].Segments[j].Start = (CORDB_ADDRESS)seg->mem; - if (seg.GetAddr() == heap->ephemeral_heap_segment.GetAddr()) + if (seg.GetAddr() == pHeap->ephemeral_heap_segment.GetAddr()) { - pHeaps[i].Segments[j].End = (CORDB_ADDRESS)heap->alloc_allocated; + pHeaps[i].Segments[j].End = (CORDB_ADDRESS)pHeap->alloc_allocated; pHeaps[i].EphemeralSegment = j; pHeaps[i].Segments[j].Generation = 1; } diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 51af19280eee52..9c8acf346ff424 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -45569,6 +45569,27 @@ bool GCHeap::IsConcurrentGCEnabled() void PopulateDacVars(GcDacVars *gcDacVars) { #ifndef DACCESS_COMPILE + +#ifdef MULTIPLE_HEAPS + static int gc_heap_field_offsets[] = { + +#define DEFINE_FIELD(field_name, field_type) offsetof(gc_heap, field_name), +#define DEFINE_DPTR_FIELD(field_name, field_type) offsetof(gc_heap, field_name), +#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) offsetof(gc_heap, field_name), +#define DEFINE_MISSING_FIELD -1, + +#include "gc_typefields.h" + +#undef DEFINE_MISSING_FIELD +#undef DEFINE_ARRAY_FIELD +#undef DEFINE_DPTR_FIELD +#undef DEFINE_FIELD + + offsetof(gc_heap, generation_table) + }; + static_assert(sizeof(gc_heap_field_offsets) == (GENERATION_TABLE_FIELD_INDEX + 1) * sizeof(int), "GENERATION_TABLE_INDEX mismatch"); +#endif //MULTIPLE_HEAPS + assert(gcDacVars != nullptr); *gcDacVars = {}; // Note: these version numbers are not actually checked by SOS, so if you change @@ -45582,10 +45603,10 @@ void PopulateDacVars(GcDacVars *gcDacVars) gcDacVars->generation_size = sizeof(generation); gcDacVars->total_generation_count = total_generation_count; gcDacVars->max_gen = &g_max_generation; + gcDacVars->current_c_gc_state = const_cast(&gc_heap::current_c_gc_state); #ifndef MULTIPLE_HEAPS gcDacVars->mark_array = &gc_heap::mark_array; gcDacVars->ephemeral_heap_segment = reinterpret_cast(&gc_heap::ephemeral_heap_segment); - gcDacVars->current_c_gc_state = const_cast(&gc_heap::current_c_gc_state); #ifdef USE_REGIONS gcDacVars->saved_sweep_ephemeral_seg = 0; gcDacVars->saved_sweep_ephemeral_start = 0; @@ -45614,7 +45635,8 @@ void PopulateDacVars(GcDacVars *gcDacVars) #endif // HEAP_ANALYZE #else gcDacVars->n_heaps = &gc_heap::n_heaps; - gcDacVars->g_heaps = reinterpret_cast(&gc_heap::g_heaps); + gcDacVars->g_heaps = reinterpret_cast(&gc_heap::g_heaps); + gcDacVars->gc_heap_field_offsets = reinterpret_cast(&gc_heap_field_offsets); #endif // MULTIPLE_HEAPS #else UNREFERENCED_PARAMETER(gcDacVars); diff --git a/src/coreclr/gc/gc_typefields.h b/src/coreclr/gc/gc_typefields.h new file mode 100644 index 00000000000000..f690a6cddc8ead --- /dev/null +++ b/src/coreclr/gc/gc_typefields.h @@ -0,0 +1,32 @@ +DEFINE_FIELD (alloc_allocated, uint8_t*) +DEFINE_DPTR_FIELD (ephemeral_heap_segment, dac_heap_segment) +DEFINE_DPTR_FIELD (finalize_queue, dac_finalize_queue) +DEFINE_FIELD (oom_info, oom_history) +DEFINE_ARRAY_FIELD (interesting_data_per_heap, size_t, NUM_GC_DATA_POINTS) +DEFINE_ARRAY_FIELD (compact_reasons_per_heap, size_t, MAX_COMPACT_REASONS_COUNT) +DEFINE_ARRAY_FIELD (expand_mechanisms_per_heap, size_t, MAX_EXPAND_MECHANISMS_COUNT) +DEFINE_ARRAY_FIELD (interesting_mechanism_bits_per_heap,size_t, MAX_GC_MECHANISM_BITS_COUNT) +DEFINE_FIELD (internal_root_array, uint8_t*) +DEFINE_FIELD (internal_root_array_index, size_t) +DEFINE_FIELD (heap_analyze_success, BOOL) +DEFINE_FIELD (card_table, uint32_t*) +#if defined(ALL_FIELDS) || defined(BACKGROUND_GC) +DEFINE_FIELD (mark_array, uint32_t*) +DEFINE_FIELD (next_sweep_obj, uint8_t*) +DEFINE_FIELD (background_saved_lowest_address, uint8_t*) +DEFINE_FIELD (background_saved_highest_address, uint8_t*) +#if defined(ALL_FIELDS) || !defined(USE_REGIONS) +DEFINE_DPTR_FIELD (saved_sweep_ephemeral_seg, dac_heap_segment) +DEFINE_FIELD (saved_sweep_ephemeral_start, uint8_t*) +#else +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +#endif +#else +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +DEFINE_MISSING_FIELD +#endif diff --git a/src/coreclr/gc/gcinterface.dac.h b/src/coreclr/gc/gcinterface.dac.h index 348279b5b69110..3a4697a96da2bd 100644 --- a/src/coreclr/gc/gcinterface.dac.h +++ b/src/coreclr/gc/gcinterface.dac.h @@ -136,17 +136,17 @@ struct oom_history // GC heap (of which there are multiple, with server GC). class dac_gc_heap { public: - uint8_t* alloc_allocated; - DPTR(dac_heap_segment) ephemeral_heap_segment; - DPTR(dac_finalize_queue) finalize_queue; - oom_history oom_info; - size_t interesting_data_per_heap[NUM_GC_DATA_POINTS]; - size_t compact_reasons_per_heap[MAX_COMPACT_REASONS_COUNT]; - size_t expand_mechanisms_per_heap[MAX_EXPAND_MECHANISMS_COUNT]; - size_t interesting_mechanism_bits_per_heap[MAX_GC_MECHANISM_BITS_COUNT]; - uint8_t* internal_root_array; - size_t internal_root_array_index; - BOOL heap_analyze_success; +#define ALL_FIELDS +#define DEFINE_FIELD(field_name, field_type) field_type field_name; +#define DEFINE_DPTR_FIELD(field_name, field_type) DPTR(field_type) field_name; +#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) field_type field_name[array_length]; + +#include "gc_typefields.h" + +#undef DEFINE_ARRAY_FIELD +#undef DEFINE_DPTR_FIELD +#undef DEFINE_FIELD +#undef ALL_FIELDS // The generation table must always be last, because the size of this array // (stored inline in the gc_heap class) can vary. @@ -162,6 +162,12 @@ class dac_gc_heap { dac_generation generation_table[1]; }; +#define GENERATION_TABLE_FIELD_INDEX 18 + +struct opaque_gc_heap +{ + uint8_t unused; +}; // The DAC links against six symbols that build as part of the VM DACCESS_COMPILE // build. These symbols are considered to be GC-private functions, but the DAC needs diff --git a/src/coreclr/gc/gcinterface.dacvars.def b/src/coreclr/gc/gcinterface.dacvars.def index b572e6cb3764bf..2f27df72e1cbc0 100644 --- a/src/coreclr/gc/gcinterface.dacvars.def +++ b/src/coreclr/gc/gcinterface.dacvars.def @@ -53,13 +53,14 @@ GC_DAC_PTR_VAR (uint8_t*, internal_root_array) GC_DAC_VAR (size_t, internal_root_array_index) GC_DAC_VAR (BOOL, heap_analyze_success) GC_DAC_VAR (int, n_heaps) -GC_DAC_PTR_VAR (dac_gc_heap*, g_heaps) +GC_DAC_PTR_VAR (opaque_gc_heap*, g_heaps) GC_DAC_VAR (int32_t, gc_structures_invalid_cnt) GC_DAC_ARRAY_VAR (size_t, interesting_data_per_heap) GC_DAC_ARRAY_VAR (size_t, compact_reasons_per_heap) GC_DAC_ARRAY_VAR (size_t, expand_mechanisms_per_heap) GC_DAC_ARRAY_VAR (size_t, interesting_mechanism_bits_per_heap) GC_DAC_VAR (dac_handle_table_map, handle_table_map) +GC_DAC_ARRAY_VAR (int, gc_heap_field_offsets) #undef GC_DAC_VAR #undef GC_DAC_ARRAY_VAR diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 36a1e8326aff72..bbc7e055f2661a 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -3426,9 +3426,6 @@ class gc_heap GCEvent bgc_start_event; #endif //BACKGROUND_GC - // The variables in this block are known to the DAC and must come first - // in the gc_heap class. - // Keeps track of the highest address allocated by Alloc PER_HEAP uint8_t* alloc_allocated; @@ -3468,12 +3465,9 @@ class gc_heap PER_HEAP BOOL heap_analyze_success; - // The generation table. Must always be last. PER_HEAP generation generation_table [total_generation_count]; - // End DAC zone - #ifdef USE_REGIONS #ifdef STRESS_REGIONS // TODO: could consider dynamically grow this. @@ -4941,26 +4935,6 @@ class gc_heap void update_collection_counts (); }; // class gc_heap -#define ASSERT_OFFSETS_MATCH(field) \ - static_assert(offsetof(dac_gc_heap, field) == offsetof(gc_heap, field), #field " offset mismatch") - -#ifndef USE_REGIONS -#ifdef MULTIPLE_HEAPS -ASSERT_OFFSETS_MATCH(alloc_allocated); -ASSERT_OFFSETS_MATCH(ephemeral_heap_segment); -ASSERT_OFFSETS_MATCH(finalize_queue); -ASSERT_OFFSETS_MATCH(oom_info); -ASSERT_OFFSETS_MATCH(interesting_data_per_heap); -ASSERT_OFFSETS_MATCH(compact_reasons_per_heap); -ASSERT_OFFSETS_MATCH(expand_mechanisms_per_heap); -ASSERT_OFFSETS_MATCH(interesting_mechanism_bits_per_heap); -ASSERT_OFFSETS_MATCH(internal_root_array); -ASSERT_OFFSETS_MATCH(internal_root_array_index); -ASSERT_OFFSETS_MATCH(heap_analyze_success); -ASSERT_OFFSETS_MATCH(generation_table); -#endif // MULTIPLE_HEAPS -#endif //USE_REGIONS - #ifdef FEATURE_PREMORTEM_FINALIZATION class CFinalize { From 43db0fe1d44c13653fb9d125fe0aa03b35548398 Mon Sep 17 00:00:00 2001 From: Santiago Fernandez Madero Date: Mon, 2 Aug 2021 17:42:37 -0700 Subject: [PATCH 49/64] Set `DisableImplicitNamespaceImports_Dotnet=true` to workaround sdk issue (#56744) * Set `DisableImplicitNamespaceImports_Dotnet=true` to workaround sdk issue * Disable just the imports declaration rather than the functionality --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 2e8a20b3a0eb83..556b399aa3dc05 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -287,7 +287,7 @@ false - true + true From 70eec277f4c27b4e8d3cd4219d368e6fcd2cd835 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 2 Aug 2021 18:08:45 -0700 Subject: [PATCH 50/64] Use ComWrappers in some Marshal unit-tests and update platform metadata (#56595) * Remove the SupportedOSPlatform attribute from the ComWrappers API. * Test the Marshal.QueryInterface, Marshal.AddRef, and Marshal.Release using ComWrappers. --- .../Runtime/InteropServices/ComWrappers.cs | 1 + .../ComWrappers.PlatformNotSupported.cs | 1 + .../Runtime/InteropServices/ComWrappers.cs | 6 +- .../ref/System.Runtime.InteropServices.cs | 7 +- .../src/MatchingRefApiCompatBaseline.txt | 2 +- ...ystem.Runtime.InteropServices.Tests.csproj | 1 + .../InteropServices/Marshal/AddRefTests.cs | 6 +- .../Marshal/Common/COMWrappersImpl.cs | 43 ++++++++++ .../Marshal/QueryInterfaceTests.Windows.cs | 34 +++++++- .../Marshal/QueryInterfaceTests.cs | 78 +++---------------- .../InteropServices/Marshal/ReleaseTests.cs | 6 +- src/libraries/shims/ApiCompat.proj | 2 +- .../ApiCompatBaseline.PreviousNetCoreApp.txt | 15 ++-- 13 files changed, 118 insertions(+), 84 deletions(-) create mode 100644 src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/COMWrappersImpl.cs diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs index 8538e63c068801..a6351198a2c595 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs @@ -300,6 +300,7 @@ public static void RegisterForTrackerSupport(ComWrappers instance) /// * P/Invokes with COM-related types /// * COM activation /// + [SupportedOSPlatform("windows")] public static void RegisterForMarshalling(ComWrappers instance) { if (instance == null) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.PlatformNotSupported.cs index 2cfac1e1919e90..f2701035b93ab5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.PlatformNotSupported.cs @@ -41,6 +41,7 @@ public static void RegisterForTrackerSupport(ComWrappers instance) throw new PlatformNotSupportedException(); } + [SupportedOSPlatform("windows")] public static void RegisterForMarshalling(ComWrappers instance) { throw new PlatformNotSupportedException(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs index 72019f3d833cc4..ff16e14d4e39d5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs @@ -69,7 +69,11 @@ public enum CreateObjectFlags /// /// Class for managing wrappers of COM IUnknown types. /// - [SupportedOSPlatform("windows")] + [UnsupportedOSPlatform("android")] + [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("maccatalyst")] + [UnsupportedOSPlatform("tvos")] [CLSCompliant(false)] public abstract partial class ComWrappers { diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs index e6c03d03d24181..feb8ae7135abb5 100644 --- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs +++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs @@ -1125,7 +1125,11 @@ public enum CreateObjectFlags Aggregation = 4, Unwrap = 8, } - [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] + [System.Runtime.Versioning.UnsupportedOSPlatform("browser")] + [System.Runtime.Versioning.UnsupportedOSPlatform("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatform("maccatalyst")] + [System.Runtime.Versioning.UnsupportedOSPlatform("tvos")] [System.CLSCompliantAttribute(false)] public abstract class ComWrappers { @@ -1147,6 +1151,7 @@ public struct ComInterfaceDispatch public object GetOrRegisterObjectForComInstance(System.IntPtr externalComObject, CreateObjectFlags flags, object wrapper, System.IntPtr inner) { throw null; } protected abstract void ReleaseObjects(System.Collections.IEnumerable objects); public static void RegisterForTrackerSupport(ComWrappers instance) { } + [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public static void RegisterForMarshalling(ComWrappers instance) { } protected static void GetIUnknownImpl(out System.IntPtr fpQueryInterface, out System.IntPtr fpAddRef, out System.IntPtr fpRelease) { throw null; } } diff --git a/src/libraries/System.Runtime.InteropServices/src/MatchingRefApiCompatBaseline.txt b/src/libraries/System.Runtime.InteropServices/src/MatchingRefApiCompatBaseline.txt index 8a50ec864714be..dd2e06b69c3c29 100644 --- a/src/libraries/System.Runtime.InteropServices/src/MatchingRefApiCompatBaseline.txt +++ b/src/libraries/System.Runtime.InteropServices/src/MatchingRefApiCompatBaseline.txt @@ -1,5 +1,6 @@ Compat issues with assembly System.Runtime.InteropServices: TypesMustExist : Type 'System.Runtime.InteropServices.AssemblyRegistrationFlags' does not exist in the reference but it does exist in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Runtime.InteropServices.ComWrappers' changed from '[UnsupportedOSPlatformAttribute("android")]' in the implementation to '[UnsupportedOSPlatformAttribute("android")]' in the reference. TypesMustExist : Type 'System.Runtime.InteropServices.ExporterEventKind' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Runtime.InteropServices.IDispatchImplAttribute' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Runtime.InteropServices.IDispatchImplType' does not exist in the reference but it does exist in the implementation. @@ -7,5 +8,4 @@ TypesMustExist : Type 'System.Runtime.InteropServices.RegistrationClassContext' TypesMustExist : Type 'System.Runtime.InteropServices.RegistrationConnectionType' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Runtime.InteropServices.SetWin32ContextInIDispatchAttribute' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public void System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute..ctor()' does not exist in the reference but it does exist in the implementation. -CannotRemoveAttribute : Attribute 'System.CLSCompliantAttribute' exists on 'System.Runtime.InteropServices.ComTypes.IDataObject' in the implementation but not the reference. Total Issues: 9 diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.Tests.csproj index f0ffe70d47c314..5235b8023a63dd 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.Tests.csproj @@ -137,6 +137,7 @@ + diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/AddRefTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/AddRefTests.cs index c8cd89168b3526..ec5ae351bc79c0 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/AddRefTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/AddRefTests.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.Runtime.InteropServices.Tests.Common; using Xunit; namespace System.Runtime.InteropServices.Tests @@ -8,10 +9,11 @@ namespace System.Runtime.InteropServices.Tests public class AddRefTests { [Fact] - [PlatformSpecific(TestPlatforms.Windows)] + [SkipOnMono("ComWrappers are not supported on Mono")] public void AddRef_ValidPointer_Success() { - IntPtr iUnknown = Marshal.GetIUnknownForObject(new object()); + var cw = new ComWrappersImpl(); + IntPtr iUnknown = cw.GetOrCreateComInterfaceForObject(new object(), CreateComInterfaceFlags.None); try { Assert.Equal(2, Marshal.AddRef(iUnknown)); diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/COMWrappersImpl.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/COMWrappersImpl.cs new file mode 100644 index 00000000000000..f6b7180c299e3b --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/COMWrappersImpl.cs @@ -0,0 +1,43 @@ +// 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; +using System.Runtime.CompilerServices; +using Xunit; + +namespace System.Runtime.InteropServices.Tests.Common +{ + public class ComWrappersImpl : ComWrappers + { + // Doesn't represent a real interface. The value is only used to support a call to QueryInterface for testing. + public const string IID_TestQueryInterface = "1F906666-B388-4729-B78C-826BC5FD4245"; + + protected unsafe override ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count) + { + Assert.Equal(CreateComInterfaceFlags.None, flags); + + IntPtr fpQueryInterface = default; + IntPtr fpAddRef = default; + IntPtr fpRelease = default; + ComWrappers.GetIUnknownImpl(out fpQueryInterface, out fpAddRef, out fpRelease); + + var vtblRaw = (IntPtr*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(ComWrappersImpl), IntPtr.Size * 3); + vtblRaw[0] = fpQueryInterface; + vtblRaw[1] = fpAddRef; + vtblRaw[2] = fpRelease; + + var entryRaw = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(ComWrappersImpl), sizeof(ComInterfaceEntry)); + entryRaw->IID = new Guid(IID_TestQueryInterface); + entryRaw->Vtable = (IntPtr)vtblRaw; + + count = 1; + return entryRaw; + } + + protected override object CreateObject(IntPtr externalComObject, CreateObjectFlags flag) + => throw new NotImplementedException(); + + protected override void ReleaseObjects(IEnumerable objects) + => throw new NotImplementedException(); + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.Windows.cs index 30657253cc8248..74ffdaad3b2dbd 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.Windows.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.Windows.cs @@ -9,6 +9,7 @@ namespace System.Runtime.InteropServices.Tests { public partial class QueryInterfaceTests { + public const string IID_IDISPATCH = "00020400-0000-0000-C000-000000000046"; public const string IID_IINSPECTABLE = "AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90"; public static IEnumerable QueryInterface_ValidComObjectInterface_TestData() @@ -45,7 +46,25 @@ public static IEnumerable QueryInterface_ValidComObjectInterface_TestD [MemberData(nameof(QueryInterface_ValidComObjectInterface_TestData))] public void QueryInterface_ValidComObjectInterface_Success(object o, string iidString) { - QueryInterface_ValidInterface_Success(o, iidString); + IntPtr ptr = Marshal.GetIUnknownForObject(o); + try + { + Guid guid = new Guid(iidString); + Assert.Equal(0, Marshal.QueryInterface(ptr, ref guid, out IntPtr ppv)); + Assert.NotEqual(IntPtr.Zero, ppv); + try + { + Assert.Equal(new Guid(iidString), guid); + } + finally + { + Marshal.Release(ppv); + } + } + finally + { + Marshal.Release(ptr); + } } public static IEnumerable QueryInterface_NoSuchComObjectInterface_TestData() @@ -83,7 +102,18 @@ public static IEnumerable QueryInterface_NoSuchComObjectInterface_Test [MemberData(nameof(QueryInterface_NoSuchComObjectInterface_TestData))] public void QueryInterface_NoSuchComObjectInterface_Success(object o, string iidString) { - QueryInterface_NoSuchInterface_Success(o, iidString); + IntPtr ptr = Marshal.GetIUnknownForObject(o); + try + { + Guid iid = new Guid(iidString); + Assert.Equal(E_NOINTERFACE, Marshal.QueryInterface(ptr, ref iid, out IntPtr ppv)); + Assert.Equal(IntPtr.Zero, ppv); + Assert.Equal(new Guid(iidString), iid); + } + finally + { + Marshal.Release(ptr); + } } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.cs index fbb7ca8c0fa6bd..a52f710abf5760 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.cs @@ -12,71 +12,28 @@ public partial class QueryInterfaceTests { public const int E_NOINTERFACE = unchecked((int)0x80004002); public const string IID_IUNKNOWN = "00000000-0000-0000-C000-000000000046"; - public const string IID_IDISPATCH = "00020400-0000-0000-C000-000000000046"; public static IEnumerable QueryInterface_ValidInterface_TestData() { yield return new object[] { new object(), IID_IUNKNOWN }; - yield return new object[] { new object(), IID_IDISPATCH }; - - yield return new object[] { 10, IID_IUNKNOWN }; - if (!PlatformDetection.IsNetCore) - { - yield return new object[] { 10, IID_IDISPATCH }; - } - - yield return new object[] { "string", IID_IUNKNOWN }; - if (!PlatformDetection.IsNetCore) - { - yield return new object[] { "string", IID_IDISPATCH }; - } - - yield return new object[] { new NonGenericClass(), IID_IUNKNOWN }; - if (!PlatformDetection.IsNetCore) - { - yield return new object[] { new NonGenericClass(), IID_IDISPATCH }; - } - yield return new object[] { new GenericClass(), IID_IUNKNOWN }; - - yield return new object[] { new NonGenericStruct(), IID_IUNKNOWN }; - if (!PlatformDetection.IsNetCore) - { - yield return new object[] { new NonGenericStruct(), IID_IDISPATCH }; - } - yield return new object[] { new GenericStruct(), IID_IUNKNOWN }; - - yield return new object[] { Int32Enum.Value1, IID_IUNKNOWN }; - if (!PlatformDetection.IsNetCore) - { - yield return new object[] { Int32Enum.Value1, IID_IDISPATCH }; - } - - yield return new object[] { new int[] { 10 }, IID_IUNKNOWN }; - yield return new object[] { new int[][] { new int[] { 10 } }, IID_IUNKNOWN }; - yield return new object[] { new int[,] { { 10 } }, IID_IUNKNOWN }; - - MethodInfo method = typeof(GetObjectForIUnknownTests).GetMethod(nameof(NonGenericMethod), BindingFlags.NonPublic | BindingFlags.Static); - Delegate d = method.CreateDelegate(typeof(NonGenericDelegate)); - yield return new object[] { d, IID_IUNKNOWN }; - yield return new object[] { d, IID_IDISPATCH }; - - yield return new object[] { new KeyValuePair("key", 10), IID_IUNKNOWN }; + yield return new object[] { new object(), ComWrappersImpl.IID_TestQueryInterface }; } [Theory] [MemberData(nameof(QueryInterface_ValidInterface_TestData))] - [PlatformSpecific(TestPlatforms.Windows)] - public void QueryInterface_ValidInterface_Success(object o, string guid) + [SkipOnMono("ComWrappers are not supported on Mono")] + public void QueryInterface_ValidInterface_Success(object o, string iidString) { - IntPtr ptr = Marshal.GetIUnknownForObject(o); + var cw = new ComWrappersImpl(); + IntPtr ptr = cw.GetOrCreateComInterfaceForObject(o, CreateComInterfaceFlags.None); try { - Guid iidString = new Guid(guid); - Assert.Equal(0, Marshal.QueryInterface(ptr, ref iidString, out IntPtr ppv)); + Guid guid = new Guid(iidString); + Assert.Equal(0, Marshal.QueryInterface(ptr, ref guid, out IntPtr ppv)); Assert.NotEqual(IntPtr.Zero, ppv); try { - Assert.Equal(new Guid(guid), iidString); + Assert.Equal(new Guid(iidString), guid); } finally { @@ -93,23 +50,15 @@ public static IEnumerable QueryInterface_NoSuchInterface_TestData() { yield return new object[] { new object(), Guid.Empty.ToString() }; yield return new object[] { new object(), "927971f5-0939-11d1-8be1-00c04fd8d503" }; - - yield return new object[] { new int[] { 10 }, IID_IDISPATCH }; - yield return new object[] { new int[][] { new int[] { 10 } }, IID_IDISPATCH }; - yield return new object[] { new int[,] { { 10 } }, IID_IDISPATCH }; - - yield return new object[] { new GenericClass(), IID_IDISPATCH }; - yield return new object[] { new Dictionary(), IID_IDISPATCH }; - yield return new object[] { new GenericStruct(), IID_IDISPATCH }; - yield return new object[] { new KeyValuePair(), IID_IDISPATCH }; } [Theory] [MemberData(nameof(QueryInterface_NoSuchInterface_TestData))] - [PlatformSpecific(TestPlatforms.Windows)] + [SkipOnMono("ComWrappers are not supported on Mono")] public void QueryInterface_NoSuchInterface_Success(object o, string iidString) { - IntPtr ptr = Marshal.GetIUnknownForObject(o); + var cw = new ComWrappersImpl(); + IntPtr ptr = cw.GetOrCreateComInterfaceForObject(o, CreateComInterfaceFlags.None); try { Guid iid = new Guid(iidString); @@ -129,10 +78,5 @@ public void QueryInterface_ZeroPointer_ThrowsArgumentNullException() Guid iid = Guid.Empty; AssertExtensions.Throws("pUnk", () => Marshal.QueryInterface(IntPtr.Zero, ref iid, out IntPtr ppv)); } - - private static void NonGenericMethod(int i) { } - public delegate void NonGenericDelegate(int i); - - public enum Int32Enum : int { Value1, Value2 } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseTests.cs index 211270c6995785..3ef69cfc0920fc 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseTests.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.Runtime.InteropServices.Tests.Common; using Xunit; namespace System.Runtime.InteropServices.Tests @@ -8,10 +9,11 @@ namespace System.Runtime.InteropServices.Tests public class ReleaseTests { [Fact] - [PlatformSpecific(TestPlatforms.Windows)] + [SkipOnMono("ComWrappers are not supported on Mono")] public void Release_ValidPointer_Success() { - IntPtr iUnknown = Marshal.GetIUnknownForObject(new object()); + var cw = new ComWrappersImpl(); + IntPtr iUnknown = cw.GetOrCreateComInterfaceForObject(new object(), CreateComInterfaceFlags.None); try { Marshal.AddRef(iUnknown); diff --git a/src/libraries/shims/ApiCompat.proj b/src/libraries/shims/ApiCompat.proj index 9885f574fc6d80..4ade3e1c90441e 100644 --- a/src/libraries/shims/ApiCompat.proj +++ b/src/libraries/shims/ApiCompat.proj @@ -107,7 +107,7 @@ - + diff --git a/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt b/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt index 54945167821c83..69f17447741d89 100644 --- a/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt +++ b/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt @@ -89,6 +89,8 @@ CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Ru CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.Marshal.AddRef(System.IntPtr)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.Marshal.QueryInterface(System.IntPtr, System.Guid, System.IntPtr)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.Marshal.Release(System.IntPtr)' in the contract but not the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesCcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesGcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.CryptoConfig' in the contract but not the implementation. Compat issues with assembly System: CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerAttribute' on 'System.ComponentModel.IComponent' changed from '[DesignerAttribute("System.ComponentModel.Design.ComponentDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]' in the contract to '[DesignerAttribute("System.ComponentModel.Design.ComponentDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]' in the implementation. @@ -164,13 +166,14 @@ CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Ru CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Runtime.Versioning.SupportedOSPlatformAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=true, Inherited=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=true, Inherited=false)]' in the implementation. CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=true, Inherited=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Enum | AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Module | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=true, Inherited=false)]' in the implementation. Compat issues with assembly System.Runtime.InteropServices: +CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.ComWrappers' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.Marshal.AddRef(System.IntPtr)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.Marshal.QueryInterface(System.IntPtr, System.Guid, System.IntPtr)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' exists on 'System.Runtime.InteropServices.Marshal.Release(System.IntPtr)' in the contract but not the implementation. Compat issues with assembly System.Security.Cryptography.Algorithms: +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesCcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesGcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Security.Cryptography.CryptoConfig' in the contract but not the implementation. -Compat issues with assembly System.Threading.Tasks.Extensions: -CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Runtime.CompilerServices.AsyncMethodBuilderAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Struct, Inherited=false, AllowMultiple=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Struct, Inherited=false, AllowMultiple=false)]' in the implementation. Compat issues with assembly System.Text.Json: CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute' exists on parameter 'returnType' on member 'System.Text.Json.JsonSerializer.Deserialize(System.ReadOnlySpan, System.Type, System.Text.Json.JsonSerializerOptions)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute' exists on parameter 'returnType' on member 'System.Text.Json.JsonSerializer.Deserialize(System.String, System.Type, System.Text.Json.JsonSerializerOptions)' in the contract but not the implementation. @@ -180,9 +183,7 @@ CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAc CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute' exists on parameter 'inputType' on member 'System.Text.Json.JsonSerializer.Serialize(System.Text.Json.Utf8JsonWriter, System.Object, System.Type, System.Text.Json.JsonSerializerOptions)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute' exists on parameter 'inputType' on member 'System.Text.Json.JsonSerializer.SerializeAsync(System.IO.Stream, System.Object, System.Type, System.Text.Json.JsonSerializerOptions, System.Threading.CancellationToken)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute' exists on parameter 'inputType' on member 'System.Text.Json.JsonSerializer.SerializeToUtf8Bytes(System.Object, System.Type, System.Text.Json.JsonSerializerOptions)' in the contract but not the implementation. -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesCcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesGcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesCcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Security.Cryptography.AesGcm' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("browser")]' in the implementation. CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Text.Json.Serialization.JsonConverterAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Property | AttributeTargets.Struct, AllowMultiple=false)]' in the implementation. -Total Issues: 171 +Compat issues with assembly System.Threading.Tasks.Extensions: +CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Runtime.CompilerServices.AsyncMethodBuilderAttribute' changed from '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Struct, Inherited=false, AllowMultiple=false)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Struct, Inherited=false, AllowMultiple=false)]' in the implementation. +Total Issues: 172 From 814fb1be3423c95861bc414a1d6aabd0a52a3873 Mon Sep 17 00:00:00 2001 From: Sychev Vadim Date: Tue, 3 Aug 2021 06:30:14 +0300 Subject: [PATCH 51/64] Add DictionaryKeyPolicy support for EnumConverter [#47765] (#54429) * Add DictionaryKeyPolicy support for EnumConverter [#47765] * Moved DictionaryKeyPolicy parsing code to WriteWithQuotes [#47765] * Refactored the bugfix in accordance to the comments (#47765) * Made few minor corrections (#47765) --- .../Converters/Value/EnumConverter.cs | 77 ++++++++++++--- .../CollectionTests.Dictionary.KeyPolicy.cs | 95 +++++++++++++++++++ 2 files changed, 158 insertions(+), 14 deletions(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs index 64e891b5b0f1f1..b4e666bc96b8a5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverter.cs @@ -25,6 +25,8 @@ internal sealed class EnumConverter : JsonConverter private readonly ConcurrentDictionary _nameCache; + private ConcurrentDictionary? _dictionaryKeyPolicyCache; + // This is used to prevent flooding the cache due to exponential bitwise combinations of flags. // Since multiple threads can add to the cache, a few more values might be added. private const int NameCacheSizeSoftLimit = 64; @@ -325,35 +327,82 @@ internal override void WriteWithQuotes(Utf8JsonWriter writer, T value, JsonSeria ulong key = ConvertToUInt64(value); - if (_nameCache.TryGetValue(key, out JsonEncodedText formatted)) + // Try to obtain values from caches + if (options.DictionaryKeyPolicy != null) + { + Debug.Assert(!state.Current.IgnoreDictionaryKeyPolicy); + + if (_dictionaryKeyPolicyCache != null && _dictionaryKeyPolicyCache.TryGetValue(key, out JsonEncodedText formatted)) + { + writer.WritePropertyName(formatted); + return; + } + } + else if (_nameCache.TryGetValue(key, out JsonEncodedText formatted)) { writer.WritePropertyName(formatted); return; } + + // if there are not cached values string original = value.ToString(); if (IsValidIdentifier(original)) { - // We are dealing with a combination of flag constants since - // all constant values were cached during warm-up. - JavaScriptEncoder? encoder = options.Encoder; - - if (_nameCache.Count < NameCacheSizeSoftLimit) + if (options.DictionaryKeyPolicy != null) { - formatted = JsonEncodedText.Encode(original, encoder); + original = options.DictionaryKeyPolicy.ConvertName(original); - writer.WritePropertyName(formatted); + if (original == null) + { + ThrowHelper.ThrowInvalidOperationException_NamingPolicyReturnNull(options.DictionaryKeyPolicy); + } + + _dictionaryKeyPolicyCache ??= new ConcurrentDictionary(); + + if (_dictionaryKeyPolicyCache.Count < NameCacheSizeSoftLimit) + { + JavaScriptEncoder? encoder = options.Encoder; + + JsonEncodedText formatted = JsonEncodedText.Encode(original, encoder); + + writer.WritePropertyName(formatted); + + _dictionaryKeyPolicyCache.TryAdd(key, formatted); + } + else + { + // We also do not create a JsonEncodedText instance here because passing the string + // directly to the writer is cheaper than creating one and not caching it for reuse. + writer.WritePropertyName(original); + } - _nameCache.TryAdd(key, formatted); + return; } else { - // We also do not create a JsonEncodedText instance here because passing the string - // directly to the writer is cheaper than creating one and not caching it for reuse. - writer.WritePropertyName(original); - } + // We might be dealing with a combination of flag constants since all constant values were + // likely cached during warm - up(assuming the number of constants <= NameCacheSizeSoftLimit). - return; + JavaScriptEncoder? encoder = options.Encoder; + + if (_nameCache.Count < NameCacheSizeSoftLimit) + { + JsonEncodedText formatted = JsonEncodedText.Encode(original, encoder); + + writer.WritePropertyName(formatted); + + _nameCache.TryAdd(key, formatted); + } + else + { + // We also do not create a JsonEncodedText instance here because passing the string + // directly to the writer is cheaper than creating one and not caching it for reuse. + writer.WritePropertyName(original); + } + + return; + } } switch (s_enumTypeCode) diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.KeyPolicy.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.KeyPolicy.cs index 1a90f20a2744ca..bb00474f510fa7 100644 --- a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.KeyPolicy.cs +++ b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.KeyPolicy.cs @@ -188,6 +188,101 @@ public async Task CustomNameSerialize() Assert.Equal(JsonCustomKey, json); } + public enum ETestEnum + { + TestValue1 = 1, + TestValue2 = 2, + } + + [Fact] + public static void EnumSerialization_DictionaryPolicy_Honored_CamelCase() + { + var options = new JsonSerializerOptions + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, + }; + + Dictionary dict = new Dictionary { [ETestEnum.TestValue1] = ETestEnum.TestValue1 }; + string value = JsonSerializer.Serialize(dict, options); + Assert.Equal("{\"testValue1\":1}", value); + + dict = new Dictionary { [ETestEnum.TestValue2] = ETestEnum.TestValue2 }; + value = JsonSerializer.Serialize(dict, options); + Assert.Equal("{\"testValue2\":2}", value); + + dict = new Dictionary { [ETestEnum.TestValue1] = ETestEnum.TestValue1, [ETestEnum.TestValue2] = ETestEnum.TestValue2 }; + value = JsonSerializer.Serialize(dict, options); + Assert.Equal("{\"testValue1\":1,\"testValue2\":2}", value); + } + + [Fact] + public static void EnumSerializationAsDictKey_NoDictionaryKeyPolicy() + { + Dictionary dict = new Dictionary { [ETestEnum.TestValue1] = ETestEnum.TestValue1 }; + string value = JsonSerializer.Serialize(dict); + Assert.Equal("{\"TestValue1\":1}", value); + + dict = new Dictionary { [ETestEnum.TestValue2] = ETestEnum.TestValue2 }; + value = JsonSerializer.Serialize(dict); + Assert.Equal("{\"TestValue2\":2}", value); + + dict = new Dictionary { [ETestEnum.TestValue1] = ETestEnum.TestValue1, [ETestEnum.TestValue2] = ETestEnum.TestValue2 }; + value = JsonSerializer.Serialize(dict); + Assert.Equal("{\"TestValue1\":1,\"TestValue2\":2}", value); + } + + public class ClassWithEnumProperties + { + public ETestEnum TestEnumProperty1 { get; } = ETestEnum.TestValue2; + public DayOfWeek TestEnumProperty2 { get; } = DayOfWeek.Monday; + } + + [Fact] + public static void EnumSerialization_DictionaryPolicy_NotApplied_WhenEnumsAreSerialized() + { + var options = new JsonSerializerOptions + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, + }; + + string value = JsonSerializer.Serialize(DayOfWeek.Friday, options); + + Assert.Equal("5", value); + + value = JsonSerializer.Serialize(ETestEnum.TestValue2, options); + + Assert.Equal("2", value); + + + value = JsonSerializer.Serialize(new ClassWithEnumProperties(), options); + + Assert.Equal("{\"TestEnumProperty1\":2,\"TestEnumProperty2\":1}", value); + + value = JsonSerializer.Serialize(new List { DayOfWeek.Sunday, DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday, DayOfWeek.Saturday}, options); + + Assert.Equal("[0,1,2,3,4,5,6]", value); + } + + public class CustomJsonNamingPolicy : JsonNamingPolicy + { + public override string ConvertName(string name) => null; + } + + [Fact] + public static void EnumSerialization_DictionaryPolicy_ThrowsException_WhenNamingPolicyReturnsNull() + { + var options = new JsonSerializerOptions + { + DictionaryKeyPolicy = new CustomJsonNamingPolicy(), + }; + + Dictionary dict = new Dictionary { [ETestEnum.TestValue1] = ETestEnum.TestValue1 }; + + InvalidOperationException ex = Assert.Throws(() => JsonSerializer.Serialize(dict, options)); + + Assert.Contains(typeof(CustomJsonNamingPolicy).ToString(), ex.Message); + } + [Fact] public async Task NullNamePolicy() { From f21aca10e4906b7763c6bf0841a59bcbaaf91439 Mon Sep 17 00:00:00 2001 From: Juan Hoyos Date: Mon, 2 Aug 2021 22:25:32 -0700 Subject: [PATCH 52/64] Fix race in crossdac publishing with PGO (#56762) --- eng/pipelines/coreclr/templates/build-job.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/pipelines/coreclr/templates/build-job.yml b/eng/pipelines/coreclr/templates/build-job.yml index 699983fa0c38c6..e94d630ba2e957 100644 --- a/eng/pipelines/coreclr/templates/build-job.yml +++ b/eng/pipelines/coreclr/templates/build-job.yml @@ -269,7 +269,7 @@ jobs: artifactName: $(buildProductArtifactName) displayName: 'product build' - - ${{ if and(in(parameters.osGroup, 'windows', 'Linux'), ne(parameters.archType, 'x86'), ne(parameters.compilerName, 'gcc'), ne(parameters.testGroup, 'clrTools')) }}: + - ${{ if and(in(parameters.osGroup, 'windows', 'Linux'), ne(parameters.archType, 'x86'), ne(parameters.compilerName, 'gcc'), ne(parameters.testGroup, 'clrTools'), eq(parameters.pgoType, '')) }}: - template: /eng/pipelines/coreclr/templates/crossdac-build.yml parameters: archType: ${{ parameters.archType }} From a0ff4e1a4390813a2c93684f88b96a0082811729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Tue, 3 Aug 2021 14:34:45 +0900 Subject: [PATCH 53/64] Simplify JIT shutdown logic in crossgen2 (#56687) There was unanswered comment about thread safety in https://github.com/dotnet/runtime/pull/56187/files#r675461236 so I just decided to fix it myself. While on it, I simplified shutdown to use `AppDomain.ProcessExit`. I'm not sure `AppDomain.UnhandledException` is needed but the original code had this in a `finally`. The better fix would be to allow JIT to be initialized right before we start a compilation and shut down after, but that would require no process wide state in the JIT. As it stands now, JIT is once-per-process-global. --- .../tools/Common/JitInterface/CorInfoImpl.cs | 33 +++++++------------ .../ReadyToRunCodegenCompilationBuilder.cs | 6 ---- src/coreclr/tools/aot/crossgen2/Program.cs | 18 ++-------- 3 files changed, 13 insertions(+), 44 deletions(-) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index ff268b787e440d..d5dc33be71cf71 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -79,32 +79,26 @@ private static class JitPointerAccessor [DllImport(JitLibrary)] private extern static IntPtr getJit(); - public static IntPtr Get() - { - if (s_jit != IntPtr.Zero) - { - return s_jit; - } - - lock(typeof(JitPointerAccessor)) - { - s_jit = getJit(); - return s_jit; - } - } - [DllImport(JitSupportLibrary)] private extern static CorJitResult JitProcessShutdownWork(IntPtr jit); - public static void ShutdownJit() + static JitPointerAccessor() { + s_jit = getJit(); + if (s_jit != IntPtr.Zero) { - JitProcessShutdownWork(s_jit); + AppDomain.CurrentDomain.ProcessExit += (_, _) => JitProcessShutdownWork(s_jit); + AppDomain.CurrentDomain.UnhandledException += (_, _) => JitProcessShutdownWork(s_jit); } } - private static IntPtr s_jit; + public static IntPtr Get() + { + return s_jit; + } + + private static readonly IntPtr s_jit; } [DllImport(JitLibrary)] @@ -159,11 +153,6 @@ public static void Startup() jitStartup(GetJitHost(JitConfigProvider.Instance.UnmanagedInstance)); } - public static void ShutdownJit() - { - JitPointerAccessor.ShutdownJit(); - } - public CorInfoImpl() { _jit = JitPointerAccessor.Get(); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs index 4b5d4a7ca31684..c1207a4b5b2f00 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs @@ -65,12 +65,6 @@ public ReadyToRunCodegenCompilationBuilder( ((ReadyToRunCompilerContext)context).SetCompilationGroup(group); } - // Shutdown the Jit if it has been loaded. This must only be called once per process - public static void ShutdownJit() - { - CorInfoImpl.ShutdownJit(); - } - public override CompilationBuilder UseBackendOptions(IEnumerable options) { var builder = new ArrayBuilder>(); diff --git a/src/coreclr/tools/aot/crossgen2/Program.cs b/src/coreclr/tools/aot/crossgen2/Program.cs index d5418516e1cd16..afae84f57f6fac 100644 --- a/src/coreclr/tools/aot/crossgen2/Program.cs +++ b/src/coreclr/tools/aot/crossgen2/Program.cs @@ -989,14 +989,7 @@ private static int Main(string[] args) #if DEBUG try { - try - { - return new Program().Run(args); - } - finally - { - ReadyToRunCodegenCompilationBuilder.ShutdownJit(); - } + return new Program().Run(args); } catch (CodeGenerationFailedException ex) when (DumpReproArguments(ex)) { @@ -1005,14 +998,7 @@ private static int Main(string[] args) #else try { - try - { - return new Program().Run(args); - } - finally - { - ReadyToRunCodegenCompilationBuilder.ShutdownJit(); - } + return new Program().Run(args); } catch (Exception e) { From 5b4fbd4230f02e24047aec55034343094aeb420a Mon Sep 17 00:00:00 2001 From: Santiago Fernandez Madero Date: Mon, 2 Aug 2021 23:33:41 -0700 Subject: [PATCH 54/64] Fix build error when building some packages (#56767) * Fix build error when building some packages * Actually move declaration to Directory.Build.targets as they should be used in other scenarios --- eng/packaging.targets | 16 ---------------- src/libraries/Directory.Build.targets | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/eng/packaging.targets b/eng/packaging.targets index 8bf2b09abf81c9..6af2a73afc12dd 100644 --- a/eng/packaging.targets +++ b/eng/packaging.targets @@ -9,24 +9,8 @@ $(MSBuildThisFileDirectory)useSharedDesignerContext.txt $([MSBuild]::Subtract($(MajorVersion), 1)).0.0 IncludeAnalyzersInPackage;$(BeforePack) - $(BuildProjectReferences) - false - - - - - + + + From 7f931b13e3320c1a0531f0a997f143e7609f4e64 Mon Sep 17 00:00:00 2001 From: Viktor Hofer Date: Tue, 3 Aug 2021 10:46:24 +0200 Subject: [PATCH 55/64] Move Windows Compat pack to NuGet pack task (#56686) * Move Windows Compat pack to NuGet pack task This is a straight port from pkgproj to csproj and also enables building the compat pack together with its dependencies. As usual, if the compat pack alone should be built (i.e. for inner loop tests), the `--no-dependencies` flag should be used, i.e. `dotnet build --no-dependencies` or `dotnet pack --no-build`. * Fix traversal builds and don't overbuild packages * Update libraries-packages.proj --- ...ensions.HostFactoryResolver.Sources.csproj | 2 - .../src/Microsoft.NETCore.Platforms.csproj | 2 - .../Microsoft.Windows.Compatibility.csproj | 70 +++++++++++++ src/libraries/libraries-packages.proj | 8 +- .../Microsoft.Windows.Compatibility.pkgproj | 98 ------------------- .../Microsoft.Windows.Compatibility.proj | 10 -- src/libraries/pkg/baseline/packageIndex.json | 19 ---- .../runtime.native.System.IO.Ports.proj | 2 +- src/libraries/src.proj | 6 ++ 9 files changed, 81 insertions(+), 136 deletions(-) create mode 100644 src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj delete mode 100644 src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.pkgproj delete mode 100644 src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.proj diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj index dff90383f96cbf..31cd86025ee019 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj @@ -3,8 +3,6 @@ package infra globs for .cs files. --> netstandard2.0 - - true false true diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index 299a8b2ceb7342..9aad9681e31f98 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -6,8 +6,6 @@ $(MSBuildProjectName) true Microsoft.NETCore.Platforms.BuildTasks - - true false true diff --git a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj new file mode 100644 index 00000000000000..86afb922f869e5 --- /dev/null +++ b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj @@ -0,0 +1,70 @@ + + + + $(NetCoreAppCurrent);netcoreapp3.1;netstandard2.1;netstandard2.0 + true + + false + + $(NoWarn);NU5128 + This Windows Compatibility Pack provides access to APIs that were previously available only for .NET Framework. It can be used from both .NET Core as well as .NET Standard. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/libraries-packages.proj b/src/libraries/libraries-packages.proj index f67803e79972bc..0bc55ebbffd53b 100644 --- a/src/libraries/libraries-packages.proj +++ b/src/libraries/libraries-packages.proj @@ -2,13 +2,13 @@ + - + + + Exclude="$(MSBuildThisFileDirectory)*\src\**\*.shproj" /> diff --git a/src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.pkgproj b/src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.pkgproj deleted file mode 100644 index c1a3f16e19ec1c..00000000000000 --- a/src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.pkgproj +++ /dev/null @@ -1,98 +0,0 @@ - - - - - false - This Windows Compatibility Pack provides access to APIs that were previously available only for .NET Framework. It can be used from both .NET Core as well as .NET Standard. - - - - $(PackageVersion) - - - $(PackageVersion) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.proj b/src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.proj deleted file mode 100644 index 17a7f16890297a..00000000000000 --- a/src/libraries/pkg/Microsoft.Windows.Compatibility/Microsoft.Windows.Compatibility.proj +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/libraries/pkg/baseline/packageIndex.json b/src/libraries/pkg/baseline/packageIndex.json index 6c24d93bbb4860..09f1be0796e397 100644 --- a/src/libraries/pkg/baseline/packageIndex.json +++ b/src/libraries/pkg/baseline/packageIndex.json @@ -1439,25 +1439,6 @@ "6.0.0.0": "6.0.0" } }, - "Microsoft.Windows.Compatibility": { - "StableVersions": [ - "2.0.0", - "2.0.1", - "2.1.0", - "2.1.1", - "3.0.0", - "3.0.1", - "5.0.0" - ], - "InboxOn": {} - }, - "Microsoft.Windows.Compatibility.Shims": { - "StableVersions": [ - "2.0.0", - "2.0.1" - ], - "InboxOn": {} - }, "Microsoft.XmlSerializer.Generator": { "StableVersions": [ "1.0.0", diff --git a/src/libraries/pkg/runtime.native.System.IO.Ports/runtime.native.System.IO.Ports.proj b/src/libraries/pkg/runtime.native.System.IO.Ports/runtime.native.System.IO.Ports.proj index a1ec1ea4bd1c98..4cccee8eede3c0 100644 --- a/src/libraries/pkg/runtime.native.System.IO.Ports/runtime.native.System.IO.Ports.proj +++ b/src/libraries/pkg/runtime.native.System.IO.Ports/runtime.native.System.IO.Ports.proj @@ -1,7 +1,7 @@ - + diff --git a/src/libraries/src.proj b/src/libraries/src.proj index 5862082f7e3ef9..0faa26075e2d7d 100644 --- a/src/libraries/src.proj +++ b/src/libraries/src.proj @@ -7,6 +7,12 @@ <_allSrc Include="$(MSBuildThisFileDirectory)*\src\*.csproj" Exclude="@(ProjectExclusions)" /> + + <_allSrc Update="$(MSBuildThisFileDirectory)Microsoft.Windows.Compatibility\src\Microsoft.Windows.Compatibility.csproj" + AdditionalProperties="BuildProjectReferences=false" /> + + <_allSrc Remove="$(MSBuildThisFileDirectory)Microsoft.Windows.Compatibility\src\Microsoft.Windows.Compatibility.csproj" + Condition="'$(BuildAllConfigurations)' != 'true'" /> + + sample + "); + + var serializer = new XmlSerializer(typeof(TestClass)); + TestClass obj = (TestClass)serializer.Deserialize(stringReader); + + var result = obj.TestData == "sample" ? 42 : 1; + + Console.WriteLine("Done!"); + await Task.Delay(5000); + + return result; + } + + [XmlType("TestClass", AnonymousType = true, Namespace = "")] + public class TestClass + { + public TestClass() + { + } + + [XmlElement("TestData")] + public string TestData { get; set; } + } +} diff --git a/src/tests/FunctionalTests/iOS/Simulator/XmlSerializer_Deserialize/iOS.Simulator.XmlSerializer_Deserialize.Test.csproj b/src/tests/FunctionalTests/iOS/Simulator/XmlSerializer_Deserialize/iOS.Simulator.XmlSerializer_Deserialize.Test.csproj new file mode 100644 index 00000000000000..e56efb092cec72 --- /dev/null +++ b/src/tests/FunctionalTests/iOS/Simulator/XmlSerializer_Deserialize/iOS.Simulator.XmlSerializer_Deserialize.Test.csproj @@ -0,0 +1,19 @@ + + + + Exe + false + true + true + $(NetCoreAppCurrent) + iOSSimulator + iOS.Simulator.XmlSerializer_Deserialize.Test.dll + false + 42 + true + + + + + + From 28ce2cc5e487f504c8fc91515c41a5fb0e86552c Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Tue, 3 Aug 2021 14:43:14 +0200 Subject: [PATCH 57/64] Fix stack overflow handling issue in GC stress (#56733) This change fixes a problem when in GC stress mode 3, GC started to run on the thread that hit stack overflow due to the GCX_PREEMP in DebuggerRCThread::DoFavor that is called from the EEPolicy::HandleFatalStackOverflow. It was causing failures in the CI. The issue is GC stress specific, the GCX_PREEMP would not start running GC on the current thread in regular cases. The fix is to inhibit GC stress in the HandleFatalStackOverflow. --- src/coreclr/vm/eepolicy.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index 1c250c7d40a091..9f1f9624941a57 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -616,6 +616,10 @@ void DECLSPEC_NORETURN EEPolicy::HandleFatalStackOverflow(EXCEPTION_POINTERS *pE WRAPPER_NO_CONTRACT; + // Disable GC stress triggering GC at this point, we don't want the GC to start running + // on this thread when we have only a very limited space left on the stack + GCStressPolicy::InhibitHolder iholder; + STRESS_LOG0(LF_EH, LL_INFO100, "In EEPolicy::HandleFatalStackOverflow\n"); FrameWithCookie fef; From 9be8c6249e5276caf42141a1539495c267ff7bf2 Mon Sep 17 00:00:00 2001 From: Thays Grazia Date: Tue, 3 Aug 2021 10:58:00 -0300 Subject: [PATCH 58/64] [wasm][debugger] Inspect static class (#56740) * Trying to fix 45104 * Implementing getting property and checking failures. * Fix android compilation --- src/mono/mono/component/debugger-agent.c | 129 +++++++++--------- src/mono/mono/component/debugger-protocol.h | 3 +- src/mono/mono/metadata/object-internals.h | 2 +- .../debugger/BrowserDebugProxy/DebugStore.cs | 10 +- .../MemberReferenceResolver.cs | 60 +++++++- .../BrowserDebugProxy/MonoSDBHelper.cs | 73 +++++++++- .../EvaluateOnCallFrameTests.cs | 35 +++++ .../debugger-test/debugger-evaluate-test.cs | 7 + 8 files changed, 247 insertions(+), 72 deletions(-) diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index fbe89da9bda495..d5c8a3484f18e4 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -7617,67 +7617,67 @@ assembly_commands (int command, guint8 *p, guint8 *end, Buffer *buf) g_free (name); break; } - case CMD_ASSEMBLY_GET_METADATA_BLOB: { - MonoImage* image = ass->image; - if (ass->dynamic) { - return ERR_NOT_IMPLEMENTED; - } - buffer_add_byte_array (buf, (guint8*)image->raw_data, image->raw_data_len); - break; - } - case CMD_ASSEMBLY_GET_IS_DYNAMIC: { - buffer_add_byte (buf, ass->dynamic); - break; - } - case CMD_ASSEMBLY_GET_PDB_BLOB: { - MonoImage* image = ass->image; - MonoDebugHandle* handle = mono_debug_get_handle (image); - if (!handle) { - return ERR_INVALID_ARGUMENT; - } - MonoPPDBFile* ppdb = handle->ppdb; - if (ppdb) { - image = mono_ppdb_get_image (ppdb); - buffer_add_byte_array (buf, (guint8*)image->raw_data, image->raw_data_len); - } else { - buffer_add_byte_array (buf, NULL, 0); - } - break; - } - case CMD_ASSEMBLY_GET_TYPE_FROM_TOKEN: { - if (ass->dynamic) { - return ERR_NOT_IMPLEMENTED; - } - guint32 token = decode_int (p, &p, end); - ERROR_DECL (error); - error_init (error); - MonoClass* mono_class = mono_class_get_checked (ass->image, token, error); - if (!is_ok (error)) { - add_error_string (buf, mono_error_get_message (error)); - mono_error_cleanup (error); - return ERR_INVALID_ARGUMENT; - } - buffer_add_typeid (buf, domain, mono_class); - mono_error_cleanup (error); - break; - } - case CMD_ASSEMBLY_GET_METHOD_FROM_TOKEN: { - if (ass->dynamic) { - return ERR_NOT_IMPLEMENTED; - } - guint32 token = decode_int (p, &p, end); - ERROR_DECL (error); - error_init (error); - MonoMethod* mono_method = mono_get_method_checked (ass->image, token, NULL, NULL, error); - if (!is_ok (error)) { - add_error_string (buf, mono_error_get_message (error)); - mono_error_cleanup (error); - return ERR_INVALID_ARGUMENT; - } - buffer_add_methodid (buf, domain, mono_method); - mono_error_cleanup (error); - break; - } + case CMD_ASSEMBLY_GET_METADATA_BLOB: { + MonoImage* image = ass->image; + if (ass->dynamic) { + return ERR_NOT_IMPLEMENTED; + } + buffer_add_byte_array (buf, (guint8*)image->raw_data, image->raw_data_len); + break; + } + case CMD_ASSEMBLY_GET_IS_DYNAMIC: { + buffer_add_byte (buf, ass->dynamic); + break; + } + case CMD_ASSEMBLY_GET_PDB_BLOB: { + MonoImage* image = ass->image; + MonoDebugHandle* handle = mono_debug_get_handle (image); + if (!handle) { + return ERR_INVALID_ARGUMENT; + } + MonoPPDBFile* ppdb = handle->ppdb; + if (ppdb) { + image = mono_ppdb_get_image (ppdb); + buffer_add_byte_array (buf, (guint8*)image->raw_data, image->raw_data_len); + } else { + buffer_add_byte_array (buf, NULL, 0); + } + break; + } + case CMD_ASSEMBLY_GET_TYPE_FROM_TOKEN: { + if (ass->dynamic) { + return ERR_NOT_IMPLEMENTED; + } + guint32 token = decode_int (p, &p, end); + ERROR_DECL (error); + error_init (error); + MonoClass* mono_class = mono_class_get_checked (ass->image, token, error); + if (!is_ok (error)) { + add_error_string (buf, mono_error_get_message (error)); + mono_error_cleanup (error); + return ERR_INVALID_ARGUMENT; + } + buffer_add_typeid (buf, domain, mono_class); + mono_error_cleanup (error); + break; + } + case CMD_ASSEMBLY_GET_METHOD_FROM_TOKEN: { + if (ass->dynamic) { + return ERR_NOT_IMPLEMENTED; + } + guint32 token = decode_int (p, &p, end); + ERROR_DECL (error); + error_init (error); + MonoMethod* mono_method = mono_get_method_checked (ass->image, token, NULL, NULL, error); + if (!is_ok (error)) { + add_error_string (buf, mono_error_get_message (error)); + mono_error_cleanup (error); + return ERR_INVALID_ARGUMENT; + } + buffer_add_methodid (buf, domain, mono_method); + mono_error_cleanup (error); + break; + } case CMD_ASSEMBLY_HAS_DEBUG_INFO: { buffer_add_byte (buf, !ass->dynamic && mono_debug_image_has_debug_info (ass->image)); break; @@ -8377,6 +8377,13 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint } break; } + case MDBGPROT_CMD_TYPE_INITIALIZE: { + MonoVTable *vtable = mono_class_vtable_checked (klass, error); + goto_if_nok (error, loader_error); + mono_runtime_class_init_full (vtable, error); + goto_if_nok (error, loader_error); + break; + } default: err = ERR_NOT_IMPLEMENTED; goto exit; diff --git a/src/mono/mono/component/debugger-protocol.h b/src/mono/mono/component/debugger-protocol.h index 292b723cc351b1..6bce7c5ff2ec1e 100644 --- a/src/mono/mono/component/debugger-protocol.h +++ b/src/mono/mono/component/debugger-protocol.h @@ -201,7 +201,8 @@ typedef enum { MDBGPROT_CMD_TYPE_CREATE_INSTANCE = 19, MDBGPROT_CMD_TYPE_GET_VALUE_SIZE = 20, MDBGPROT_CMD_TYPE_GET_VALUES_ICORDBG = 21, - MDBGPROT_CMD_TYPE_GET_PARENTS = 22 + MDBGPROT_CMD_TYPE_GET_PARENTS = 22, + MDBGPROT_CMD_TYPE_INITIALIZE = 23 } MdbgProtCmdType; typedef enum { diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index d87ab17fdab75c..9702920b3c26eb 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -1599,7 +1599,7 @@ mono_class_try_get_vtable (MonoClass *klass); gboolean mono_runtime_run_module_cctor (MonoImage *image, MonoError *error); -gboolean +MONO_COMPONENT_API gboolean mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error); void diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index c1e8ce60bda6c2..c398ca8a2c1208 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -453,14 +453,16 @@ public VarInfo[] GetLiveVarsAt(int offset) internal class TypeInfo { - private AssemblyInfo assembly; + internal AssemblyInfo assembly; private TypeDefinition type; private List methods; + public int Token { get; } - public TypeInfo(AssemblyInfo assembly, TypeDefinition type) + public TypeInfo(AssemblyInfo assembly, TypeDefinitionHandle typeHandle, TypeDefinition type) { this.assembly = assembly; var metadataReader = assembly.asmMetadataReader; + Token = MetadataTokens.GetToken(metadataReader, typeHandle); this.type = type; methods = new List(); Name = metadataReader.GetString(type.Name); @@ -594,7 +596,7 @@ SourceFile FindSource(DocumentHandle doc, int rowid, string documentName) { var typeDefinition = asmMetadataReader.GetTypeDefinition(type); - var typeInfo = new TypeInfo(this, typeDefinition); + var typeInfo = new TypeInfo(this, type, typeDefinition); typesByName[typeInfo.FullName] = typeInfo; if (pdbMetadataReader != null) { @@ -876,7 +878,7 @@ public object ToScriptSource(int executionContextId, object executionContextAuxD internal class DebugStore { - private List assemblies = new List(); + internal List assemblies = new List(); private readonly HttpClient client; private readonly ILogger logger; diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs index 3e791f2f3e057d..e08904a99b6eb8 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs @@ -75,6 +75,57 @@ public async Task GetValueFromObject(JToken objRet, CancellationToken t } return null; } + + public async Task TryToRunOnLoadedClasses(string varName, CancellationToken token) + { + string classNameToFind = ""; + string[] parts = varName.Split("."); + var typeId = -1; + foreach (string part in parts) + { + if (classNameToFind.Length > 0) + classNameToFind += "."; + classNameToFind += part.Trim(); + if (typeId != -1) + { + var fields = await proxy.SdbHelper.GetTypeFields(sessionId, typeId, token); + foreach (var field in fields) + { + if (field.Name == part.Trim()) + { + var isInitialized = await proxy.SdbHelper.TypeIsInitialized(sessionId, typeId, token); + if (isInitialized == 0) + { + isInitialized = await proxy.SdbHelper.TypeInitialize(sessionId, typeId, token); + } + var valueRet = await proxy.SdbHelper.GetFieldValue(sessionId, typeId, field.Id, token); + return await GetValueFromObject(valueRet, token); + } + } + var methodId = await proxy.SdbHelper.GetPropertyMethodIdByName(sessionId, typeId, part.Trim(), token); + if (methodId != -1) + { + var commandParamsObj = new MemoryStream(); + var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); + commandParamsObjWriter.Write(0); //param count + var retMethod = await proxy.SdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token); + return await GetValueFromObject(retMethod, token); + } + } + var store = await proxy.LoadStore(sessionId, token); + foreach (var asm in store.assemblies) + { + var type = asm.GetTypeByName(classNameToFind); + if (type != null) + { + var assemblyId = await proxy.SdbHelper.GetAssemblyId(sessionId, type.assembly.Name, token); + typeId = await proxy.SdbHelper.GetTypeIdFromToken(sessionId, assemblyId, type.Token, token); + } + } + } + return null; + } + // Checks Locals, followed by `this` public async Task Resolve(string varName, CancellationToken token) { @@ -140,7 +191,8 @@ public async Task Resolve(string varName, CancellationToken token) } else { - return null; + rootObject = await TryToRunOnLoadedClasses(varName, token); + return rootObject; } } } @@ -177,8 +229,8 @@ public async Task Resolve(InvocationExpressionSyntax method, Dictionary var typeName = await proxy.SdbHelper.GetTypeName(sessionId, typeId[0], token); throw new Exception($"Method '{methodName}' not found in type '{typeName}'"); } - var command_params_obj = new MemoryStream(); - var commandParamsObjWriter = new MonoBinaryWriter(command_params_obj); + var commandParamsObj = new MemoryStream(); + var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj); commandParamsObjWriter.WriteObj(objectId, proxy.SdbHelper); if (method.ArgumentList != null) { @@ -197,7 +249,7 @@ public async Task Resolve(InvocationExpressionSyntax method, Dictionary return null; } } - var retMethod = await proxy.SdbHelper.InvokeMethod(sessionId, command_params_obj.ToArray(), methodId, "methodRet", token); + var retMethod = await proxy.SdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token); return await GetValueFromObject(retMethod, token); } } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index 77b3695ff7d309..2cb784123bcf88 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -240,7 +240,8 @@ internal enum CmdType { CreateInstance = 19, GetValueSize = 20, GetValuesICorDbg = 21, - GetParents = 22 + GetParents = 22, + Initialize = 23, } internal enum CmdArray { @@ -929,6 +930,41 @@ public async Task ClearSingleStep(SessionId sessionId, int req_id, Cancell return false; } + public async Task GetFieldValue(SessionId sessionId, int typeId, int fieldId, CancellationToken token) + { + var ret = new List(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(typeId); + commandParamsWriter.Write(1); + commandParamsWriter.Write(fieldId); + + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetValues, commandParams, token); + return await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, "", false, -1, token); + } + + public async Task TypeIsInitialized(SessionId sessionId, int typeId, CancellationToken token) + { + var ret = new List(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(typeId); + + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.IsInitialized, commandParams, token); + return retDebuggerCmdReader.ReadInt32(); + } + + public async Task TypeInitialize(SessionId sessionId, int typeId, CancellationToken token) + { + var ret = new List(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(typeId); + + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.Initialize, commandParams, token); + return retDebuggerCmdReader.ReadInt32(); + } + public async Task> GetTypeFields(SessionId sessionId, int type_id, CancellationToken token) { var ret = new List(); @@ -1128,6 +1164,17 @@ public async Task GetClassNameFromObject(SessionId sessionId, int object return await GetTypeName(sessionId, type_id[0], token); } + public async Task GetTypeIdFromToken(SessionId sessionId, int assemblyId, int typeToken, CancellationToken token) + { + var ret = new List(); + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write((int)assemblyId); + commandParamsWriter.Write((int)typeToken); + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdAssembly.GetTypeFromToken, commandParams, token); + return retDebuggerCmdReader.ReadInt32(); + } + public async Task GetMethodIdByName(SessionId sessionId, int type_id, string method_name, CancellationToken token) { var ret = new List(); @@ -1191,6 +1238,30 @@ public async Task InvokeMethod(SessionId sessionId, byte[] valueTypeBuf retDebuggerCmdReader.ReadByte(); //number of objects returned. return await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, varName, false, -1, token); } + + public async Task GetPropertyMethodIdByName(SessionId sessionId, int typeId, string propertyName, CancellationToken token) + { + var commandParams = new MemoryStream(); + var commandParamsWriter = new MonoBinaryWriter(commandParams); + commandParamsWriter.Write(typeId); + + var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetProperties, commandParams, token); + var nProperties = retDebuggerCmdReader.ReadInt32(); + for (int i = 0 ; i < nProperties; i++) + { + retDebuggerCmdReader.ReadInt32(); //propertyId + string propertyNameStr = retDebuggerCmdReader.ReadString(); + var getMethodId = retDebuggerCmdReader.ReadInt32(); + retDebuggerCmdReader.ReadInt32(); //setmethod + var attrs = retDebuggerCmdReader.ReadInt32(); //attrs + if (propertyNameStr == propertyName) + { + return getMethodId; + } + } + return -1; + } + public async Task CreateJArrayForProperties(SessionId sessionId, int typeId, byte[] object_buffer, JArray attributes, bool isAutoExpandable, string objectId, bool isOwn, CancellationToken token) { JArray ret = new JArray(); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs index a28080c4c70f7c..91f369b71be821 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs @@ -585,6 +585,41 @@ await EvaluateOnCallFrameAndCheck(id, props = await GetObjectOnFrame(frame, "this"); CheckNumber(props, "a", 11); }); + + [Fact] + public async Task EvaluateStaticClass() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateMethodTestsClass/TestEvaluate", "run", 9, "run", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateMethodTestsClass:EvaluateMethods'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + + var frame = pause_location["callFrames"][0]; + + await EvaluateOnCallFrameAndCheck(id, + ("DebuggerTests.EvaluateStaticClass.StaticField1", TNumber(10))); + await EvaluateOnCallFrameAndCheck(id, + ("DebuggerTests.EvaluateStaticClass.StaticProperty1", TString("StaticProperty1"))); + await EvaluateOnCallFrameAndCheck(id, + ("DebuggerTests.EvaluateStaticClass.StaticPropertyWithError", TString("System.Exception: not implemented"))); + }); + + [Fact] + public async Task EvaluateStaticClassInvalidField() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateMethodTestsClass/TestEvaluate", "run", 9, "run", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateMethodTestsClass:EvaluateMethods'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + + var frame = pause_location["callFrames"][0]; + + var (_, res) = await EvaluateOnCallFrame(id, "DebuggerTests.EvaluateStaticClass.StaticProperty2", expect_ok: false); + AssertEqual("Failed to resolve member access for DebuggerTests.EvaluateStaticClass.StaticProperty2", res.Error["result"]?["description"]?.Value(), "wrong error message"); + + (_, res) = await EvaluateOnCallFrame(id, "DebuggerTests.InvalidEvaluateStaticClass.StaticProperty2", expect_ok: false); + AssertEqual("Failed to resolve member access for DebuggerTests.InvalidEvaluateStaticClass.StaticProperty2", res.Error["result"]?["description"]?.Value(), "wrong error message"); + }); } } diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs index 1583ce1fd6f86d..01bdda2868ddde 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs @@ -406,4 +406,11 @@ public static void EvaluateMethods() } + public static class EvaluateStaticClass + { + public static int StaticField1 = 10; + public static string StaticProperty1 => "StaticProperty1"; + public static string StaticPropertyWithError => throw new Exception("not implemented"); + } + } From 7abe597cffd1e4d8859cc2eb216279eed818a7f5 Mon Sep 17 00:00:00 2001 From: Steve Harter Date: Tue, 3 Aug 2021 09:17:57 -0500 Subject: [PATCH 59/64] Update doc and generic parameter name for JsonValue.GetValue (#56639) --- .../System.Text.Json/ref/System.Text.Json.cs | 2 +- .../src/System/Text/Json/Nodes/JsonNode.cs | 16 ++++++++++++---- .../src/System/Text/Json/Nodes/JsonValue.cs | 9 +++++++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index 99a987c5792917..757d8d63d51338 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -595,7 +595,7 @@ internal JsonNode() { } public System.Text.Json.Nodes.JsonObject AsObject() { throw null; } public System.Text.Json.Nodes.JsonValue AsValue() { throw null; } public string GetPath() { throw null; } - public virtual TValue GetValue() { throw null; } + public virtual T GetValue() { throw null; } public static explicit operator bool (System.Text.Json.Nodes.JsonNode value) { throw null; } public static explicit operator byte (System.Text.Json.Nodes.JsonNode value) { throw null; } public static explicit operator char (System.Text.Json.Nodes.JsonNode value) { throw null; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.cs index 6de74aef8ec3b6..71ccc3f4b24b32 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; namespace System.Text.Json.Nodes { @@ -165,14 +164,23 @@ public JsonNode Root /// /// Gets the value for the current . /// + /// + /// {T} can be the type or base type of the underlying value. + /// If the underlying value is a then {T} can also be the type of any primitive + /// value supported by current . + /// Specifying the type for {T} will always succeed and return the underlying value as .
+ /// The underlying value of a after deserialization is an instance of , + /// otherwise it's the value specified when the was created. + ///
+ /// /// - /// The current cannot be represented as a {TValue}. + /// The current cannot be represented as a {T}. /// /// /// The current is not a or - /// is not compatible with {TValue}. + /// is not compatible with {T}. /// - public virtual TValue GetValue() => + public virtual T GetValue() => throw new InvalidOperationException(SR.Format(SR.NodeWrongType, nameof(JsonValue))); /// diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValue.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValue.cs index 1d0eb05631c47b..87b6953f46765b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValue.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonValue.cs @@ -99,6 +99,15 @@ internal override void GetPath(List path, JsonNode? child) /// /// Tries to obtain the current JSON value and returns a value that indicates whether the operation succeeded. /// + /// + /// {T} can be the type or base type of the underlying value. + /// If the underlying value is a then {T} can also be the type of any primitive + /// value supported by current . + /// Specifying the type for {T} will always succeed and return the underlying value as .
+ /// The underlying value of a after deserialization is an instance of , + /// otherwise it's the value specified when the was created. + ///
+ /// /// The type of value to obtain. /// When this method returns, contains the parsed value. /// if the value can be successfully obtained; otherwise, . From b8a9eabb16da3461a2715c70f84b9bc733c98bf0 Mon Sep 17 00:00:00 2001 From: Chris Ross Date: Tue, 3 Aug 2021 07:48:59 -0700 Subject: [PATCH 60/64] Update windows-requirements.md (#56476) --- docs/workflow/requirements/windows-requirements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/workflow/requirements/windows-requirements.md b/docs/workflow/requirements/windows-requirements.md index 4430e47d7853cb..ee874e85abde58 100644 --- a/docs/workflow/requirements/windows-requirements.md +++ b/docs/workflow/requirements/windows-requirements.md @@ -32,7 +32,7 @@ Visual Studio 2019 installation process: - For Arm32, check the box for **MSVC v142 - VS 2019 C++ ARM build tools (Latest)** (v14.23 or newer), - For Arm64, check the box for **MSVC v142 - VS 2019 C++ ARM64 build tools (Latest)** (v14.23 or newer). - To build the tests, you will need some additional components: - - **Windows 10 SDK (10.0.18362)** or newer. This component is installed by default as a part of **Desktop Development with C++** workload. + - **Windows 10 SDK (10.0.19041)** or newer. This component is installed by default as a part of **Desktop Development with C++** workload. - **C++/CLI support for v142 build tools (Latest)** (v14.23 or newer). A `.vsconfig` file is included in the root of the dotnet/runtime repository that includes all components needed to build the dotnet/runtime repository. You can [import `.vsconfig` in your Visual Studio installer](https://docs.microsoft.com/en-us/visualstudio/install/import-export-installation-configurations?view=vs-2019#import-a-configuration) to install all necessary components. From 0ea6d0c8e45646cc2e359c32aae970ec4baa2c5b Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 3 Aug 2021 11:24:52 -0400 Subject: [PATCH 61/64] [mono] Remove gdb xdebug and binary writer support, it hasn't worked in a while. (#56759) * [mono] Remove gdb xdebug support, it hasn't worked in a while. * [mono] Remove binary writer code, it haven't been used or worked in a while. * Remove MONO_DEBUG=gdb option. --- src/mono/mono/mini/CMakeLists.txt | 1 - src/mono/mono/mini/aot-compiler.c | 2 +- src/mono/mono/mini/driver.c | 3 - src/mono/mono/mini/image-writer.c | 1711 +---------------------------- src/mono/mono/mini/image-writer.h | 34 +- src/mono/mono/mini/mini-runtime.c | 18 +- src/mono/mono/mini/mini-runtime.h | 5 - src/mono/mono/mini/mini.c | 40 +- src/mono/mono/mini/mini.h | 7 - src/mono/mono/mini/xdebug.c | 398 ------- 10 files changed, 16 insertions(+), 2203 deletions(-) delete mode 100644 src/mono/mono/mini/xdebug.c diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt index b07e58569160c2..3e9ca497336abf 100644 --- a/src/mono/mono/mini/CMakeLists.txt +++ b/src/mono/mono/mini/CMakeLists.txt @@ -144,7 +144,6 @@ set(mini_common_sources dwarfwriter.c mini-gc.h mini-gc.c - xdebug.c mini-llvm.h mini-llvm-cpp.h llvm-jit.h diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index ba1c7ea043c7e2..369016e11892d6 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -14299,7 +14299,7 @@ emit_aot_image (MonoAotCompile *acfg) return 1; } if (acfg->fp) - acfg->w = mono_img_writer_create (acfg->fp, FALSE); + acfg->w = mono_img_writer_create (acfg->fp); /* Compute symbols for methods */ for (i = 0; i < acfg->nmethods; ++i) { diff --git a/src/mono/mono/mini/driver.c b/src/mono/mono/mini/driver.c index f2792e4e6a4e41..3e7a07c17c674a 100644 --- a/src/mono/mono/mini/driver.c +++ b/src/mono/mono/mini/driver.c @@ -216,9 +216,6 @@ parse_debug_options (const char* p) } else if (!strncmp (p, "mdb-optimizations", 17)) { opt->mdb_optimizations = TRUE; p += 17; - } else if (!strncmp (p, "gdb", 3)) { - opt->gdb = TRUE; - p += 3; } else if (!strncmp (p, "ignore", 6)) { opt->enabled = FALSE; p += 6; diff --git a/src/mono/mono/mini/image-writer.c b/src/mono/mono/mini/image-writer.c index 97d1a042c0fd82..cc81ac7b070dcd 100644 --- a/src/mono/mono/mini/image-writer.c +++ b/src/mono/mono/mini/image-writer.c @@ -22,33 +22,13 @@ #include #include #include -#ifndef HOST_WIN32 -#include -#else -#include -#include -#endif - #include #include -#include /* for PAGESIZE */ -#ifndef PAGESIZE -#define PAGESIZE 4096 -#endif #include "image-writer.h" -#ifndef HOST_WIN32 -#include -#include -#endif - #include "mini.h" -#define TV_DECLARE(name) gint64 name -#define TV_GETTIME(tv) tv = mono_100ns_ticks () -#define TV_ELAPSED(start,end) (((end) - (start)) / 10) - /* * The used assembler dialect * TARGET_ASM_APPLE == apple assembler on OSX @@ -122,14 +102,6 @@ #define ROUND_DOWN(VALUE,SIZE) ((VALUE) & ~((SIZE) - 1)) -#ifdef USE_BIN_WRITER - -typedef struct _BinSymbol BinSymbol; -typedef struct _BinReloc BinReloc; -typedef struct _BinSection BinSection; - -#endif - /* emit mode */ enum { EMIT_NONE, @@ -141,24 +113,12 @@ enum { struct _MonoImageWriter { MonoMemPool *mempool; char *outfile; - gboolean use_bin_writer; const char *current_section; int current_subsection; const char *section_stack [16]; int subsection_stack [16]; int stack_pos; FILE *fp; - /* Bin writer */ -#ifdef USE_BIN_WRITER - BinSymbol *symbols; - BinSection *sections; - BinSection *cur_section; - BinReloc *relocations; - GHashTable *labels; - int num_relocs; - guint8 *out_buf; - int out_buf_size, out_buf_pos; -#endif /* Asm writer */ char *tmpfname; int mode; /* emit mode */ @@ -175,1482 +135,6 @@ ilog2(int value) return count; } -#ifdef USE_BIN_WRITER - -typedef struct _BinLabel BinLabel; -struct _BinLabel { - char *name; - BinSection *section; - int offset; -}; - -struct _BinReloc { - BinReloc *next; - char *val1; - char *val2; - BinSection *val2_section; - int val2_offset; - int offset; - BinSection *section; - int section_offset; - int reloc_type; -}; - -struct _BinSymbol { - BinSymbol *next; - char *name; - BinSection *section; - int offset; - gboolean is_function; - gboolean is_global; - char *end_label; -}; - -struct _BinSection { - BinSection *next; - BinSection *parent; - char *name; - int subsection; - guint8 *data; - int data_len; - int cur_offset; - int file_offset; - int virt_offset; - int shidx; - guint64 addr; - gboolean has_addr; -}; - -static void -bin_writer_emit_start (MonoImageWriter *acfg) -{ - acfg->labels = g_hash_table_new (g_str_hash, g_str_equal); -} - -static void -bin_writer_emit_section_change (MonoImageWriter *acfg, const char *section_name, int subsection_index) -{ - BinSection *section; - - if (acfg->cur_section && acfg->cur_section->subsection == subsection_index - && strcmp (acfg->cur_section->name, section_name) == 0) - return; - for (section = acfg->sections; section; section = section->next) { - if (section->subsection == subsection_index && strcmp (section->name, section_name) == 0) { - acfg->cur_section = section; - return; - } - } - if (!section) { - section = g_new0 (BinSection, 1); - section->name = g_strdup (section_name); - section->subsection = subsection_index; - section->next = acfg->sections; - acfg->sections = section; - acfg->cur_section = section; - } -} - -static void -bin_writer_set_section_addr (MonoImageWriter *acfg, guint64 addr) -{ - acfg->cur_section->addr = addr; - acfg->cur_section->has_addr = TRUE; -} - -static void -bin_writer_emit_symbol_inner (MonoImageWriter *acfg, const char *name, const char *end_label, gboolean is_global, gboolean func) -{ - BinSymbol *symbol = g_new0 (BinSymbol, 1); - symbol->name = g_strdup (name); - if (end_label) - symbol->end_label = g_strdup (end_label); - symbol->is_function = func; - symbol->is_global = is_global; - symbol->section = acfg->cur_section; - /* FIXME: we align after this call... */ - symbol->offset = symbol->section->cur_offset; - symbol->next = acfg->symbols; - acfg->symbols = symbol; -} - -static void -bin_writer_emit_global (MonoImageWriter *acfg, const char *name, gboolean func) -{ - bin_writer_emit_symbol_inner (acfg, name, NULL, TRUE, func); -} - -static void -bin_writer_emit_local_symbol (MonoImageWriter *acfg, const char *name, const char *end_label, gboolean func) -{ - bin_writer_emit_symbol_inner (acfg, name, end_label, FALSE, func); -} - -static void -bin_writer_emit_label (MonoImageWriter *acfg, const char *name) -{ - BinLabel *label = g_new0 (BinLabel, 1); - label->name = g_strdup (name); - label->section = acfg->cur_section; - label->offset = acfg->cur_section->cur_offset; - g_hash_table_insert (acfg->labels, label->name, label); -} - -static void -bin_writer_emit_ensure_buffer (BinSection *section, int size) -{ - int new_offset = section->cur_offset + size; - if (new_offset >= section->data_len) { - int new_size = section->data_len? section->data_len * 2: 256; - guint8 *data; - while (new_size <= new_offset) - new_size *= 2; - data = (guint8 *)g_malloc0 (new_size); - memcpy (data, section->data, section->data_len); - g_free (section->data); - section->data = data; - section->data_len = new_size; - } -} - -static void -bin_writer_emit_bytes (MonoImageWriter *acfg, const guint8* buf, int size) -{ - bin_writer_emit_ensure_buffer (acfg->cur_section, size); - memcpy (acfg->cur_section->data + acfg->cur_section->cur_offset, buf, size); - acfg->cur_section->cur_offset += size; -} - -static void -bin_writer_emit_string (MonoImageWriter *acfg, const char *value) -{ - int size = strlen (value) + 1; - bin_writer_emit_bytes (acfg, (const guint8*)value, size); -} - -static void -bin_writer_emit_line (MonoImageWriter *acfg) -{ - /* Nothing to do in binary writer */ -} - -static void -bin_writer_emit_alignment (MonoImageWriter *acfg, int size) -{ - int offset = acfg->cur_section->cur_offset; - int add; - offset += (size - 1); - offset &= ~(size - 1); - add = offset - acfg->cur_section->cur_offset; - if (add) { - bin_writer_emit_ensure_buffer (acfg->cur_section, add); - acfg->cur_section->cur_offset += add; - } -} - -static void -bin_writer_emit_pointer_unaligned (MonoImageWriter *acfg, const char *target) -{ - BinReloc *reloc; - - if (!target) { - acfg->cur_section->cur_offset += sizeof (gpointer); - return; - } - - reloc = g_new0 (BinReloc, 1); - reloc->val1 = g_strdup (target); - reloc->section = acfg->cur_section; - reloc->section_offset = acfg->cur_section->cur_offset; - reloc->next = acfg->relocations; - acfg->relocations = reloc; - if (strcmp (reloc->section->name, ".data") == 0) { - acfg->num_relocs++; - //g_print ("reloc: %s at %d\n", target, acfg->cur_section->cur_offset); - } - acfg->cur_section->cur_offset += sizeof (gpointer); -} - -static void -bin_writer_emit_pointer (MonoImageWriter *acfg, const char *target) -{ - bin_writer_emit_alignment (acfg, sizeof (gpointer)); - bin_writer_emit_pointer_unaligned (acfg, target); -} - -static void -bin_writer_emit_int16 (MonoImageWriter *acfg, int value) -{ - guint8 *data; - bin_writer_emit_ensure_buffer (acfg->cur_section, 2); - data = acfg->cur_section->data + acfg->cur_section->cur_offset; - acfg->cur_section->cur_offset += 2; - /* FIXME: little endian */ - data [0] = value; - data [1] = value >> 8; -} - -static void -bin_writer_emit_int32 (MonoImageWriter *acfg, int value) -{ - guint8 *data; - bin_writer_emit_ensure_buffer (acfg->cur_section, 4); - data = acfg->cur_section->data + acfg->cur_section->cur_offset; - acfg->cur_section->cur_offset += 4; - /* FIXME: little endian */ - data [0] = value; - data [1] = value >> 8; - data [2] = value >> 16; - data [3] = value >> 24; -} - -static BinReloc* -create_reloc (MonoImageWriter *acfg, const char *end, const char* start, int offset) -{ - BinReloc *reloc; - reloc = (BinReloc *)mono_mempool_alloc0 (acfg->mempool, sizeof (BinReloc)); - reloc->val1 = mono_mempool_strdup (acfg->mempool, end); - if (start) - { - if (strcmp (start, ".") == 0) { - reloc->val2_section = acfg->cur_section; - reloc->val2_offset = acfg->cur_section->cur_offset; - } else { - reloc->val2 = mono_mempool_strdup (acfg->mempool, start); - } - } - reloc->offset = offset; - reloc->section = acfg->cur_section; - reloc->section_offset = acfg->cur_section->cur_offset; - reloc->next = acfg->relocations; - acfg->relocations = reloc; - return reloc; -} - -static void -bin_writer_emit_symbol (MonoImageWriter *acfg, const char *symbol) -{ - create_reloc (acfg, symbol, NULL, 0); - acfg->cur_section->cur_offset += 4; -} - -static void -bin_writer_emit_symbol_diff (MonoImageWriter *acfg, const char *end, const char* start, int offset) -{ - create_reloc (acfg, end, start, offset); - acfg->cur_section->cur_offset += 4; - /*if (strcmp (reloc->section->name, ".data") == 0) { - acfg->num_relocs++; - g_print ("reloc: %s - %s + %d at %d\n", end, start, offset, acfg->cur_section->cur_offset - 4); - }*/ -} - -/* - * Emit a relocation entry of type RELOC_TYPE against symbol SYMBOL at the current PC. - * Do not advance PC. - */ -static G_GNUC_UNUSED void -bin_writer_emit_reloc (MonoImageWriter *acfg, int reloc_type, const char *symbol, int addend) -{ - BinReloc *reloc = create_reloc (acfg, symbol, ".", addend); - reloc->reloc_type = reloc_type; -} - -static void -bin_writer_emit_zero_bytes (MonoImageWriter *acfg, int num) -{ - bin_writer_emit_ensure_buffer (acfg->cur_section, num); - acfg->cur_section->cur_offset += num; -} - -static void -bin_writer_fwrite (MonoImageWriter *acfg, void *val, size_t size, size_t nmemb) -{ - if (acfg->fp) - fwrite (val, size, nmemb, acfg->fp); - else { - g_assert (acfg->out_buf_pos + (size * nmemb) <= acfg->out_buf_size); - memcpy (acfg->out_buf + acfg->out_buf_pos, val, size * nmemb); - acfg->out_buf_pos += (size * nmemb); - } -} - -static void -bin_writer_fseek (MonoImageWriter *acfg, int offset) -{ - if (acfg->fp) - fseek (acfg->fp, offset, SEEK_SET); - else - acfg->out_buf_pos = offset; -} - -#ifdef USE_MACH_WRITER - -/* - * This is a minimal implementation designed to support xdebug on 32 bit osx - * FIXME: 64 bit support - */ - -#include - -static gsize -get_label_addr (MonoImageWriter *acfg, const char *name) -{ - int offset; - BinLabel *lab; - BinSection *section; - gsize value; - - lab = g_hash_table_lookup (acfg->labels, name); - if (!lab) - g_error ("Undefined label: '%s'.\n", name); - section = lab->section; - offset = lab->offset; - if (section->parent) { - value = section->parent->virt_offset + section->cur_offset + offset; - } else { - value = section->virt_offset + offset; - } - return value; -} - - -static void -resolve_reloc (MonoImageWriter *acfg, BinReloc *reloc, guint8 **out_data, gsize *out_vaddr, gsize *out_start_val, gsize *out_end_val) -{ - guint8 *data; - gssize end_val, start_val; - gsize vaddr; - - end_val = get_label_addr (acfg, reloc->val1); - if (reloc->val2) { - start_val = get_label_addr (acfg, reloc->val2); - } else if (reloc->val2_section) { - start_val = reloc->val2_offset; - if (reloc->val2_section->parent) - start_val += reloc->val2_section->parent->virt_offset + reloc->val2_section->cur_offset; - else - start_val += reloc->val2_section->virt_offset; - } else { - start_val = 0; - } - end_val = end_val - start_val + reloc->offset; - if (reloc->section->parent) { - data = reloc->section->parent->data; - data += reloc->section->cur_offset; - data += reloc->section_offset; - vaddr = reloc->section->parent->virt_offset; - vaddr += reloc->section->cur_offset; - vaddr += reloc->section_offset; - } else { - data = reloc->section->data; - data += reloc->section_offset; - vaddr = reloc->section->virt_offset; - vaddr += reloc->section_offset; - } - - *out_start_val = start_val; - *out_end_val = end_val; - *out_data = data; - *out_vaddr = vaddr; -} - -static void -resolve_relocations (MonoImageWriter *acfg) -{ - BinReloc *reloc; - guint8 *data; - gsize end_val, start_val; - gsize vaddr; - - /* Only resolve static relocations */ - for (reloc = acfg->relocations; reloc; reloc = reloc->next) { - resolve_reloc (acfg, reloc, &data, &vaddr, &start_val, &end_val); - data [0] = end_val; - data [1] = end_val >> 8; - data [2] = end_val >> 16; - data [3] = end_val >> 24; - } -} - -static int -bin_writer_emit_writeout (MonoImageWriter *acfg) -{ - BinSection *s; - int sindex, file_size, nsections, file_offset, vmaddr; - struct mach_header header; - struct segment_command segment; - struct section *sections; - - /* Assing vm addresses to sections */ - nsections = 0; - vmaddr = 0; - for (s = acfg->sections; s; s = s->next) { - s->virt_offset = vmaddr; - vmaddr += s->cur_offset; - nsections ++; - } - - resolve_relocations (acfg); - - file_offset = 0; - - memset (&header, 0, sizeof (header)); - header.magic = MH_MAGIC; - header.cputype = CPU_TYPE_X86; - header.cpusubtype = CPU_SUBTYPE_X86_ALL; - header.filetype = MH_OBJECT; - header.ncmds = 0; - header.sizeofcmds = 0; - header.flags = 0; - - file_offset += sizeof (header); - - memset (&segment, 0, sizeof (segment)); - segment.cmd = LC_SEGMENT; - segment.cmdsize = sizeof (segment); - segment.maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE; - segment.initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE; - - file_offset += sizeof (segment); - file_offset += nsections * sizeof (struct section); - - sections = g_new0 (struct section, nsections); - sindex = 0; - for (s = acfg->sections; s; s = s->next) { - s->file_offset = file_offset; - - /* .debug_line -> __debug_line */ - sprintf (sections [sindex].sectname, "__%s", s->name + 1); - sprintf (sections [sindex].segname, "%s", "__DWARF"); - sections [sindex].addr = s->virt_offset; - sections [sindex].size = s->cur_offset; - sections [sindex].offset = s->file_offset; - - file_offset += s->cur_offset; - - segment.nsects ++; - segment.cmdsize += sizeof (struct section); - - sindex ++; - } - - header.ncmds ++; - header.sizeofcmds += segment.cmdsize; - - /* Emit data */ - file_size = file_offset; - - if (!acfg->fp) { - acfg->out_buf_size = file_size; - acfg->out_buf = g_malloc (acfg->out_buf_size); - } - - bin_writer_fwrite (acfg, &header, sizeof (header), 1); - bin_writer_fwrite (acfg, &segment, sizeof (segment), 1); - bin_writer_fwrite (acfg, sections, sizeof (struct section), nsections); - for (s = acfg->sections; s; s = s->next) { - if (!acfg->fp) - g_assert (acfg->out_buf_pos == s->file_offset); - bin_writer_fwrite (acfg, s->data, s->cur_offset, 1); - } - - if (acfg->fp) - fclose (acfg->fp); - - return 0; -} - -#endif - -#ifdef USE_ELF_WRITER - -enum { - SECT_NULL, - SECT_HASH, - SECT_DYNSYM, - SECT_DYNSTR, - SECT_REL_DYN, - SECT_RELA_DYN, - SECT_TEXT, - SECT_RODATA, - SECT_DYNAMIC, - SECT_GOT_PLT, - SECT_DATA, - SECT_BSS, - SECT_DEBUG_FRAME, - SECT_DEBUG_INFO, - SECT_DEBUG_ABBREV, - SECT_DEBUG_LINE, - SECT_DEBUG_LOC, - SECT_SHSTRTAB, - SECT_SYMTAB, - SECT_STRTAB, - SECT_NUM -}; - -#if TARGET_SIZEOF_VOID_P == 4 - -typedef Elf32_Ehdr ElfHeader; -typedef Elf32_Shdr ElfSectHeader; -typedef Elf32_Phdr ElfProgHeader; -typedef Elf32_Sym ElfSymbol; -typedef Elf32_Rel ElfReloc; -typedef Elf32_Rela ElfRelocA; -typedef Elf32_Dyn ElfDynamic; - -#else - -typedef Elf64_Ehdr ElfHeader; -typedef Elf64_Shdr ElfSectHeader; -typedef Elf64_Phdr ElfProgHeader; -typedef Elf64_Sym ElfSymbol; -typedef Elf64_Rel ElfReloc; -typedef Elf64_Rela ElfRelocA; -typedef Elf64_Dyn ElfDynamic; - -#endif - -typedef struct { - const char *name; - int type; - int esize; - int flags; - int align; -} SectInfo; - -static SectInfo section_info [] = { - {"", 0, 0, 0, 0}, - {".hash", SHT_HASH, 4, 2, TARGET_SIZEOF_VOID_P}, - {".dynsym", SHT_DYNSYM, sizeof (ElfSymbol), 2, TARGET_SIZEOF_VOID_P}, - {".dynstr", SHT_STRTAB, 0, 2, 1}, - {".rel.dyn", SHT_REL, sizeof (ElfReloc), 2, TARGET_SIZEOF_VOID_P}, - {".rela.dyn", SHT_RELA, sizeof (ElfRelocA), 2, TARGET_SIZEOF_VOID_P}, - {".text", SHT_PROGBITS, 0, 6, 4096}, - {".rodata", SHT_PROGBITS, 0, SHF_ALLOC, 4096}, - {".dynamic", SHT_DYNAMIC, sizeof (ElfDynamic), 3, TARGET_SIZEOF_VOID_P}, - {".got.plt", SHT_PROGBITS, TARGET_SIZEOF_VOID_P, 3, TARGET_SIZEOF_VOID_P}, - {".data", SHT_PROGBITS, 0, 3, 8}, - {".bss", SHT_NOBITS, 0, 3, 8}, - {".debug_frame", SHT_PROGBITS, 0, 0, 8}, - {".debug_info", SHT_PROGBITS, 0, 0, 1}, - {".debug_abbrev", SHT_PROGBITS, 0, 0, 1}, - {".debug_line", SHT_PROGBITS, 0, 0, 1}, - {".debug_loc", SHT_PROGBITS, 0, 0, 1}, - {".shstrtab", SHT_STRTAB, 0, 0, 1}, - {".symtab", SHT_SYMTAB, sizeof (ElfSymbol), 0, TARGET_SIZEOF_VOID_P}, - {".strtab", SHT_STRTAB, 0, 0, 1} -}; - -typedef struct { - GString *data; - GHashTable *hash; -} ElfStrTable; - -static int -str_table_add (ElfStrTable *table, const char* value) -{ - int idx; - if (!table->data) { - table->data = g_string_new_len ("", 1); - table->hash = g_hash_table_new (g_str_hash, g_str_equal); - } - idx = GPOINTER_TO_UINT (g_hash_table_lookup (table->hash, value)); - if (idx) - return idx; - idx = table->data->len; - g_string_append (table->data, value); - g_string_append_c (table->data, 0); - g_hash_table_insert (table->hash, (void*)value, GUINT_TO_POINTER (idx)); - return idx; -} - -static void -append_subsection (MonoImageWriter *acfg, ElfSectHeader *sheaders, BinSection *sect, BinSection *add) -{ - int offset = sect->cur_offset; - /*offset += (sheaders [sect->shidx].sh_addralign - 1); - offset &= ~(sheaders [sect->shidx].sh_addralign - 1);*/ - /* - * FIXME: we shouldn't align subsections at all, but if we don't then the - * stuff inside the subsections which is aligned won't get aligned. - */ - if (strcmp (sect->name, ".debug_line") != 0) { - offset += (8 - 1); - offset &= ~(8 - 1); - } - bin_writer_emit_ensure_buffer (sect, offset); - //g_print ("section %s aligned to %d from %d\n", sect->name, offset, sect->cur_offset); - sect->cur_offset = offset; - - bin_writer_emit_ensure_buffer (sect, add->cur_offset); - memcpy (sect->data + sect->cur_offset, add->data, add->cur_offset); - add->parent = sect; - sect->cur_offset += add->cur_offset; - add->cur_offset = offset; /* it becomes the offset in the parent section */ - //g_print ("subsection %d of %s added at offset %d (align: %d)\n", add->subsection, sect->name, add->cur_offset, (int)sheaders [sect->shidx].sh_addralign); - add->data = NULL; - add->data_len = 0; -} - -/* merge the subsections */ -static int -collect_sections (MonoImageWriter *acfg, ElfSectHeader *sheaders, BinSection **out, int num) -{ - int i, j, maxs, num_sections; - BinSection *sect; - - num_sections = 0; - maxs = 0; - for (sect = acfg->sections; sect; sect = sect->next) { - if (sect->subsection == 0) { - out [num_sections++] = sect; - g_assert (num_sections < num); - } - maxs = MAX (maxs, sect->subsection); - } - for (i = 0; i < num_sections; i++) { - for (j = 1; j <= maxs; ++j) { - for (sect = acfg->sections; sect; sect = sect->next) { - if (sect->subsection == j && strcmp (out [i]->name, sect->name) == 0) { - append_subsection (acfg, sheaders, out [i], sect); - } - } - } - } - return num_sections; -} - -static unsigned long -elf_hash (const unsigned char *name) -{ - unsigned long h = 0, g; - while (*name) { - h = (h << 4) + *name++; - if ((g = h & 0xf0000000)) - h ^= g >> 24; - h &= ~g; - } - return h; -} - -#define NUM_BUCKETS 17 - -static int* -build_hash (MonoImageWriter *acfg, int num_sections, ElfStrTable *dynstr) -{ - int *data; - int num_symbols = 1 + num_sections + 3; - BinSymbol *symbol; - - for (symbol = acfg->symbols; symbol; symbol = symbol->next) { - if (!symbol->is_global) - continue; - num_symbols++; - str_table_add (dynstr, symbol->name); - /*g_print ("adding sym: %s\n", symbol->name);*/ - } - str_table_add (dynstr, "__bss_start"); - str_table_add (dynstr, "_edata"); - str_table_add (dynstr, "_end"); - - data = g_new0 (int, num_symbols + 2 + NUM_BUCKETS); - data [0] = NUM_BUCKETS; - data [1] = num_symbols; - - return data; -} - -static gsize -get_label_addr (MonoImageWriter *acfg, const char *name) -{ - int offset; - BinLabel *lab; - BinSection *section; - gsize value; - - lab = (BinLabel *)g_hash_table_lookup (acfg->labels, name); - if (!lab) - g_error ("Undefined label: '%s'.\n", name); - section = lab->section; - offset = lab->offset; - if (section->parent) { - value = section->parent->virt_offset + section->cur_offset + offset; - } else { - value = section->virt_offset + offset; - } - return value; -} - -static ElfSymbol* -collect_syms (MonoImageWriter *acfg, int *hash, ElfStrTable *strtab, ElfSectHeader *sheaders, int *num_syms) -{ - ElfSymbol *symbols; - BinSymbol *symbol; - BinSection *section; - int i; - int *bucket; - int *chain; - unsigned long hashc; - - if (hash) - symbols = g_new0 (ElfSymbol, hash [1]); - else { - i = 0; - for (symbol = acfg->symbols; symbol; symbol = symbol->next) - i ++; - - symbols = g_new0 (ElfSymbol, i + SECT_NUM + 10); /* FIXME */ - } - - /* the first symbol is undef, all zeroes */ - i = 1; - if (sheaders) { - int j; - for (j = 1; j < SECT_NUM; ++j) { - symbols [i].st_info = ELF32_ST_INFO (STB_LOCAL, STT_SECTION); - symbols [i].st_shndx = j; - symbols [i].st_value = sheaders [j].sh_addr; - ++i; - } - } else { - for (section = acfg->sections; section; section = section->next) { - if (section->parent) - continue; - symbols [i].st_info = ELF32_ST_INFO (STB_LOCAL, STT_SECTION); - if (strcmp (section->name, ".text") == 0) { - symbols [i].st_shndx = SECT_TEXT; - section->shidx = SECT_TEXT; - section->file_offset = 4096; - symbols [i].st_value = section->virt_offset; - } else if (strcmp (section->name, ".rodata") == 0) { - symbols [i].st_shndx = SECT_RODATA; - section->shidx = SECT_RODATA; - section->file_offset = 4096; - symbols [i].st_value = section->virt_offset; - } else if (strcmp (section->name, ".data") == 0) { - symbols [i].st_shndx = SECT_DATA; - section->shidx = SECT_DATA; - section->file_offset = 4096 + 28; /* FIXME */ - symbols [i].st_value = section->virt_offset; - } else if (strcmp (section->name, ".bss") == 0) { - symbols [i].st_shndx = SECT_BSS; - section->shidx = SECT_BSS; - section->file_offset = 4096 + 28 + 8; /* FIXME */ - symbols [i].st_value = section->virt_offset; - } - ++i; - } - } - for (symbol = acfg->symbols; symbol; symbol = symbol->next) { - int offset; - BinLabel *lab; - if (!symbol->is_global && hash) - continue; - symbols [i].st_info = ELF32_ST_INFO (symbol->is_global ? STB_GLOBAL : STB_LOCAL, symbol->is_function? STT_FUNC : STT_OBJECT); - symbols [i].st_name = str_table_add (strtab, symbol->name); - /*g_print ("sym name %s tabled to %d\n", symbol->name, symbols [i].st_name);*/ - section = symbol->section; - symbols [i].st_shndx = section->parent? section->parent->shidx: section->shidx; - lab = (BinLabel *)g_hash_table_lookup (acfg->labels, symbol->name); - offset = lab->offset; - if (section->parent) { - symbols [i].st_value = section->parent->virt_offset + section->cur_offset + offset; - } else { - symbols [i].st_value = section->virt_offset + offset; - } - - if (symbol->end_label) { - BinLabel *elab = (BinLabel *)g_hash_table_lookup (acfg->labels, symbol->end_label); - g_assert (elab); - symbols [i].st_size = elab->offset - lab->offset; - } - ++i; - } - /* add special symbols */ - symbols [i].st_name = str_table_add (strtab, "__bss_start"); - symbols [i].st_shndx = 0xfff1; - symbols [i].st_info = ELF32_ST_INFO (STB_GLOBAL, 0); - ++i; - symbols [i].st_name = str_table_add (strtab, "_edata"); - symbols [i].st_shndx = 0xfff1; - symbols [i].st_info = ELF32_ST_INFO (STB_GLOBAL, 0); - ++i; - symbols [i].st_name = str_table_add (strtab, "_end"); - symbols [i].st_shndx = 0xfff1; - symbols [i].st_info = ELF32_ST_INFO (STB_GLOBAL, 0); - ++i; - - if (num_syms) - *num_syms = i; - - /* add to hash table */ - if (hash) { - bucket = hash + 2; - chain = hash + 2 + hash [0]; - for (i = 0; i < hash [1]; ++i) { - int slot; - /*g_print ("checking %d '%s' (sym %d)\n", symbols [i].st_name, strtab->data->str + symbols [i].st_name, i);*/ - if (!symbols [i].st_name) - continue; - hashc = elf_hash ((guint8*)strtab->data->str + symbols [i].st_name); - slot = hashc % hash [0]; - /*g_print ("hashing '%s' at slot %d (sym %d)\n", strtab->data->str + symbols [i].st_name, slot, i);*/ - if (bucket [slot]) { - chain [i] = bucket [slot]; - bucket [slot] = i; - } else { - bucket [slot] = i; - } - } - } - return symbols; -} - -static void -reloc_symbols (MonoImageWriter *acfg, ElfSymbol *symbols, ElfSectHeader *sheaders, ElfStrTable *strtab, gboolean dynamic) -{ - BinSection *section; - BinSymbol *symbol; - int i; - - i = 1; - if (dynamic) { - for (section = acfg->sections; section; section = section->next) { - if (section->parent) - continue; - symbols [i].st_value = sheaders [section->shidx].sh_addr; - ++i; - } - } else { - for (i = 1; i < SECT_NUM; ++i) { - symbols [i].st_value = sheaders [i].sh_addr; - } - } - for (symbol = acfg->symbols; symbol; symbol = symbol->next) { - int offset; - BinLabel *lab; - if (dynamic && !symbol->is_global) - continue; - section = symbol->section; - lab = (BinLabel *)g_hash_table_lookup (acfg->labels, symbol->name); - offset = lab->offset; - if (section->parent) { - symbols [i].st_value = sheaders [section->parent->shidx].sh_addr + section->cur_offset + offset; - } else { - symbols [i].st_value = sheaders [section->shidx].sh_addr + offset; - } - ++i; - } - /* __bss_start */ - symbols [i].st_value = sheaders [SECT_BSS].sh_addr; - ++i; - /* _edata */ - symbols [i].st_value = sheaders [SECT_DATA].sh_addr + sheaders [SECT_DATA].sh_size; - ++i; - /* _end */ - symbols [i].st_value = sheaders [SECT_BSS].sh_addr + sheaders [SECT_BSS].sh_size; - ++i; -} - -static void -resolve_reloc (MonoImageWriter *acfg, BinReloc *reloc, guint8 **out_data, gsize *out_vaddr, gsize *out_start_val, gsize *out_end_val) -{ - guint8 *data; - gssize end_val, start_val; - gsize vaddr; - - end_val = get_label_addr (acfg, reloc->val1); - if (reloc->val2) { - start_val = get_label_addr (acfg, reloc->val2); - } else if (reloc->val2_section) { - start_val = reloc->val2_offset; - if (reloc->val2_section->parent) - start_val += reloc->val2_section->parent->virt_offset + reloc->val2_section->cur_offset; - else - start_val += reloc->val2_section->virt_offset; - } else { - start_val = 0; - } - end_val = end_val - start_val + reloc->offset; - if (reloc->section->parent) { - data = reloc->section->parent->data; - data += reloc->section->cur_offset; - data += reloc->section_offset; - vaddr = reloc->section->parent->virt_offset; - vaddr += reloc->section->cur_offset; - vaddr += reloc->section_offset; - } else { - data = reloc->section->data; - data += reloc->section_offset; - vaddr = reloc->section->virt_offset; - vaddr += reloc->section_offset; - } - - *out_start_val = start_val; - *out_end_val = end_val; - *out_data = data; - *out_vaddr = vaddr; -} - -#ifdef USE_ELF_RELA - -static ElfRelocA* -resolve_relocations (MonoImageWriter *acfg) -{ - BinReloc *reloc; - guint8 *data; - gsize end_val, start_val; - ElfRelocA *rr; - int i; - gsize vaddr; - - rr = g_new0 (ElfRelocA, acfg->num_relocs); - i = 0; - - for (reloc = acfg->relocations; reloc; reloc = reloc->next) { - resolve_reloc (acfg, reloc, &data, &vaddr, &start_val, &end_val); - /* FIXME: little endian */ - data [0] = end_val; - data [1] = end_val >> 8; - data [2] = end_val >> 16; - data [3] = end_val >> 24; - // FIXME: - if (start_val == 0 && reloc->val1 [0] != '.') { - rr [i].r_offset = vaddr; - rr [i].r_info = R_X86_64_RELATIVE; - rr [i].r_addend = end_val; - ++i; - g_assert (i <= acfg->num_relocs); - } - } - return rr; -} - -#else /* USE_ELF_RELA */ - -static void -do_reloc (MonoImageWriter *acfg, BinReloc *reloc, guint8 *data, gssize addr) -{ -#ifdef TARGET_ARM - /* - * We use the official ARM relocation types, but implement only the stuff actually - * needed by the code we generate. - */ - switch (reloc->reloc_type) { - case R_ARM_CALL: - case R_ARM_JUMP24: { - guint32 *code = (guint32*)(gpointer)data; - guint32 ins = *code; - int diff = addr; - - if (reloc->reloc_type == R_ARM_CALL) - /* bl */ - g_assert (data [3] == 0xeb); - else - /* b */ - g_assert (data [3] == 0xea); - if (diff >= 0 && diff <= 33554431) { - diff >>= 2; - ins = (ins & 0xff000000) | diff; - *code = ins; - } else if (diff <= 0 && diff >= -33554432) { - diff >>= 2; - ins = (ins & 0xff000000) | (diff & ~0xff000000); - *code = ins; - } else { - g_assert_not_reached (); - } - break; - } - case R_ARM_ALU_PC_G0_NC: { - /* Generated by emit_plt () */ - guint8 *code = data; - guint32 val = addr; - - g_assert (val <= 0xffffff); - if (val & 0xff0000) - ARM_ADD_REG_IMM (code, ARMREG_IP, ARMREG_PC, (val & 0xFF0000) >> 16, 16); - else - ARM_ADD_REG_IMM (code, ARMREG_IP, ARMREG_PC, 0, 0); - ARM_ADD_REG_IMM (code, ARMREG_IP, ARMREG_IP, (val & 0xFF00) >> 8, 24); - ARM_LDR_IMM (code, ARMREG_PC, ARMREG_IP, val & 0xFF); - break; - } - default: - g_assert_not_reached (); - } -#else - g_assert_not_reached (); -#endif -} - -static ElfReloc* -resolve_relocations (MonoImageWriter *acfg) -{ - BinReloc *reloc; - guint8 *data; - gsize end_val, start_val; - ElfReloc *rr; - int i; - gsize vaddr; - - rr = g_new0 (ElfReloc, acfg->num_relocs); - i = 0; - - for (reloc = acfg->relocations; reloc; reloc = reloc->next) { - resolve_reloc (acfg, reloc, &data, &vaddr, &start_val, &end_val); - /* FIXME: little endian */ - if (reloc->reloc_type) { - /* Must be static */ - g_assert (start_val > 0); - do_reloc (acfg, reloc, data, end_val); - } else { - data [0] = end_val; - data [1] = end_val >> 8; - data [2] = end_val >> 16; - data [3] = end_val >> 24; - } - // FIXME: - if (start_val == 0 && reloc->val1 [0] != '.') { - rr [i].r_offset = vaddr; - rr [i].r_info = R_386_RELATIVE; - ++i; - g_assert (i <= acfg->num_relocs); - } - } - return rr; -} - -#endif /* USE_ELF_RELA */ - -static int normal_sections [] = { SECT_DATA, SECT_DEBUG_FRAME, SECT_DEBUG_INFO, SECT_DEBUG_ABBREV, SECT_DEBUG_LINE, SECT_DEBUG_LOC }; - -static int -bin_writer_emit_writeout (MonoImageWriter *acfg) -{ - ElfHeader header; - ElfProgHeader progh [4]; - ElfSectHeader secth [SECT_NUM]; -#ifdef USE_ELF_RELA - ElfRelocA *relocs; -#else - ElfReloc *relocs; -#endif - ElfStrTable str_table = {NULL, NULL}; - ElfStrTable sh_str_table = {NULL, NULL}; - ElfStrTable dyn_str_table = {NULL, NULL}; - BinSection* all_sections [32]; - BinSection* sections [SECT_NUM]; - ElfSymbol *dynsym; - ElfSymbol *symtab; - ElfDynamic dynamic [14]; - int *hash; - int i, num_sections, file_offset, virt_offset, size; - int num_local_syms; - - /* Section headers */ - memset (§h, 0, sizeof (secth)); - memset (&dynamic, 0, sizeof (dynamic)); - memset (&header, 0, sizeof (header)); - - for (i = 1; i < SECT_NUM; ++i) { - secth [i].sh_name = str_table_add (&sh_str_table, section_info [i].name); - secth [i].sh_type = section_info [i].type; - secth [i].sh_addralign = section_info [i].align; - secth [i].sh_flags = section_info [i].flags; - secth [i].sh_entsize = section_info [i].esize; - } - secth [SECT_DYNSYM].sh_info = TARGET_SIZEOF_VOID_P == 4 ? 4 : 2; - secth [SECT_SYMTAB].sh_info = TARGET_SIZEOF_VOID_P == 4 ? 20 : 17; - secth [SECT_HASH].sh_link = SECT_DYNSYM; - secth [SECT_DYNSYM].sh_link = SECT_DYNSTR; - secth [SECT_REL_DYN].sh_link = SECT_DYNSYM; - secth [SECT_RELA_DYN].sh_link = SECT_DYNSYM; - secth [SECT_DYNAMIC].sh_link = SECT_DYNSTR; - secth [SECT_SYMTAB].sh_link = SECT_STRTAB; - - num_sections = collect_sections (acfg, secth, all_sections, 16); - hash = build_hash (acfg, num_sections, &dyn_str_table); -#if 0 - g_print ("num_sections: %d\n", num_sections); - g_print ("dynsym: %d, dynstr size: %d\n", hash [1], (int)dyn_str_table.data->len); - for (i = 0; i < num_sections; ++i) { - g_print ("section %s, size: %d, %x\n", all_sections [i]->name, all_sections [i]->cur_offset, all_sections [i]->cur_offset); - } -#endif - /* Associate the bin sections with the ELF sections */ - memset (sections, 0, sizeof (sections)); - for (i = 0; i < num_sections; ++i) { - BinSection *sect = all_sections [i]; - int j; - - for (j = 0; j < SECT_NUM; ++j) { - if (strcmp (sect->name, section_info [j].name) == 0) { - sect->shidx = j; - break; - } - } - - sections [all_sections [i]->shidx] = sect; - } - - /* at this point we know where in the file the first segment sections go */ - dynsym = collect_syms (acfg, hash, &dyn_str_table, NULL, NULL); - num_local_syms = hash [1]; - symtab = collect_syms (acfg, NULL, &str_table, secth, &num_local_syms); - - file_offset = virt_offset = sizeof (header) + sizeof (progh); - secth [SECT_HASH].sh_addr = secth [SECT_HASH].sh_offset = file_offset; - size = sizeof (int) * (2 + hash [0] + hash [1]); - virt_offset = (file_offset += size); - secth [SECT_HASH].sh_size = size; - secth [SECT_DYNSYM].sh_addr = secth [SECT_DYNSYM].sh_offset = file_offset; - size = sizeof (ElfSymbol) * hash [1]; - virt_offset = (file_offset += size); - secth [SECT_DYNSYM].sh_size = size; - secth [SECT_DYNSTR].sh_addr = secth [SECT_DYNSTR].sh_offset = file_offset; - size = dyn_str_table.data->len; - virt_offset = (file_offset += size); - secth [SECT_DYNSTR].sh_size = size; - file_offset += 4-1; - file_offset &= ~(4-1); - secth [SECT_REL_DYN].sh_addr = secth [SECT_REL_DYN].sh_offset = file_offset; -#ifndef USE_ELF_RELA - size = sizeof (ElfReloc) * acfg->num_relocs; -#else - size = 0; -#endif - virt_offset = (file_offset += size); - secth [SECT_REL_DYN].sh_size = size; - secth [SECT_RELA_DYN].sh_addr = secth [SECT_RELA_DYN].sh_offset = file_offset; -#ifdef USE_ELF_RELA - size = sizeof (ElfRelocA) * acfg->num_relocs; -#else - size = 0; -#endif - virt_offset = (file_offset += size); - secth [SECT_RELA_DYN].sh_size = size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_TEXT].sh_addralign); - virt_offset = file_offset; - secth [SECT_TEXT].sh_addr = secth [SECT_TEXT].sh_offset = file_offset; - if (sections [SECT_TEXT]) { - if (sections [SECT_TEXT]->has_addr) { - secth [SECT_TEXT].sh_addr = sections [SECT_TEXT]->addr; - secth [SECT_TEXT].sh_flags &= ~SHF_ALLOC; - } - size = sections [SECT_TEXT]->cur_offset; - secth [SECT_TEXT].sh_size = size; - file_offset += size; - } - - file_offset = ALIGN_TO (file_offset, secth [SECT_RODATA].sh_addralign); - virt_offset = file_offset; - secth [SECT_RODATA].sh_addr = virt_offset; - secth [SECT_RODATA].sh_offset = file_offset; - if (sections [SECT_RODATA]) { - size = sections [SECT_RODATA]->cur_offset; - secth [SECT_RODATA].sh_size = size; - file_offset += size; - virt_offset += size; - } - - file_offset = ALIGN_TO (file_offset, secth [SECT_DYNAMIC].sh_addralign); - virt_offset = file_offset; - - /* .dynamic, .got.plt, .data, .bss here */ - /* Have to increase the virt offset since these go to a separate segment */ - virt_offset += PAGESIZE; - secth [SECT_DYNAMIC].sh_addr = virt_offset; - secth [SECT_DYNAMIC].sh_offset = file_offset; - size = sizeof (dynamic); - secth [SECT_DYNAMIC].sh_size = size; - file_offset += size; - virt_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_GOT_PLT].sh_addralign); - virt_offset = ALIGN_TO (virt_offset, secth [SECT_GOT_PLT].sh_addralign); - secth [SECT_GOT_PLT].sh_addr = virt_offset; - secth [SECT_GOT_PLT].sh_offset = file_offset; - size = 3 * TARGET_SIZEOF_VOID_P; - secth [SECT_GOT_PLT].sh_size = size; - file_offset += size; - virt_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_DATA].sh_addralign); - virt_offset = ALIGN_TO (virt_offset, secth [SECT_DATA].sh_addralign); - secth [SECT_DATA].sh_addr = virt_offset; - secth [SECT_DATA].sh_offset = file_offset; - if (sections [SECT_DATA]) { - size = sections [SECT_DATA]->cur_offset; - secth [SECT_DATA].sh_size = size; - file_offset += size; - virt_offset += size; - } - - file_offset = ALIGN_TO (file_offset, secth [SECT_BSS].sh_addralign); - virt_offset = ALIGN_TO (virt_offset, secth [SECT_BSS].sh_addralign); - secth [SECT_BSS].sh_addr = virt_offset; - secth [SECT_BSS].sh_offset = file_offset; - if (sections [SECT_BSS]) { - size = sections [SECT_BSS]->cur_offset; - secth [SECT_BSS].sh_size = size; - } - - /* virtual doesn't matter anymore */ - file_offset = ALIGN_TO (file_offset, secth [SECT_DEBUG_FRAME].sh_addralign); - secth [SECT_DEBUG_FRAME].sh_offset = file_offset; - if (sections [SECT_DEBUG_FRAME]) - size = sections [SECT_DEBUG_FRAME]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_FRAME].sh_size = size; - file_offset += size; - - secth [SECT_DEBUG_INFO].sh_offset = file_offset; - if (sections [SECT_DEBUG_INFO]) - size = sections [SECT_DEBUG_INFO]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_INFO].sh_size = size; - file_offset += size; - - secth [SECT_DEBUG_ABBREV].sh_offset = file_offset; - if (sections [SECT_DEBUG_ABBREV]) - size = sections [SECT_DEBUG_ABBREV]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_ABBREV].sh_size = size; - file_offset += size; - - secth [SECT_DEBUG_LINE].sh_offset = file_offset; - if (sections [SECT_DEBUG_LINE]) - size = sections [SECT_DEBUG_LINE]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_LINE].sh_size = size; - file_offset += size; - - secth [SECT_DEBUG_LOC].sh_offset = file_offset; - if (sections [SECT_DEBUG_LOC]) - size = sections [SECT_DEBUG_LOC]->cur_offset; - else - size = 0; - secth [SECT_DEBUG_LOC].sh_size = size; - file_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_SHSTRTAB].sh_addralign); - secth [SECT_SHSTRTAB].sh_offset = file_offset; - size = sh_str_table.data->len; - secth [SECT_SHSTRTAB].sh_size = size; - file_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_SYMTAB].sh_addralign); - secth [SECT_SYMTAB].sh_offset = file_offset; - size = sizeof (ElfSymbol) * num_local_syms; - secth [SECT_SYMTAB].sh_size = size; - file_offset += size; - - file_offset = ALIGN_TO (file_offset, secth [SECT_STRTAB].sh_addralign); - secth [SECT_STRTAB].sh_offset = file_offset; - size = str_table.data->len; - secth [SECT_STRTAB].sh_size = size; - file_offset += size; - - for (i = 1; i < SECT_NUM; ++i) { - if (section_info [i].esize != 0) - g_assert (secth [i].sh_size % section_info [i].esize == 0); - } - - file_offset += 4-1; - file_offset &= ~(4-1); - - header.e_ident [EI_MAG0] = ELFMAG0; - header.e_ident [EI_MAG1] = ELFMAG1; - header.e_ident [EI_MAG2] = ELFMAG2; - header.e_ident [EI_MAG3] = ELFMAG3; - header.e_ident [EI_CLASS] = TARGET_SIZEOF_VOID_P == 4 ? ELFCLASS32 : ELFCLASS64; - header.e_ident [EI_DATA] = ELFDATA2LSB; - header.e_ident [EI_VERSION] = EV_CURRENT; - header.e_ident [EI_OSABI] = ELFOSABI_NONE; - header.e_ident [EI_ABIVERSION] = 0; - for (i = EI_PAD; i < EI_NIDENT; ++i) - header.e_ident [i] = 0; - - header.e_type = ET_DYN; -#if defined(TARGET_X86) - header.e_machine = EM_386; -#elif defined(TARGET_AMD64) - header.e_machine = EM_X86_64; -#elif defined(TARGET_ARM) - header.e_machine = EM_ARM; -#else - g_assert_not_reached (); -#endif - header.e_version = 1; - - header.e_phoff = sizeof (header); - header.e_ehsize = sizeof (header); - header.e_phentsize = sizeof (ElfProgHeader); - header.e_phnum = 4; - header.e_entry = secth [SECT_TEXT].sh_addr; - header.e_shstrndx = SECT_SHSTRTAB; - header.e_shentsize = sizeof (ElfSectHeader); - header.e_shnum = SECT_NUM; - header.e_shoff = file_offset; - - /* dynamic data */ - i = 0; - dynamic [i].d_tag = DT_HASH; - dynamic [i].d_un.d_val = secth [SECT_HASH].sh_offset; - ++i; - dynamic [i].d_tag = DT_STRTAB; - dynamic [i].d_un.d_val = secth [SECT_DYNSTR].sh_offset; - ++i; - dynamic [i].d_tag = DT_SYMTAB; - dynamic [i].d_un.d_val = secth [SECT_DYNSYM].sh_offset; - ++i; - dynamic [i].d_tag = DT_STRSZ; - dynamic [i].d_un.d_val = dyn_str_table.data->len; - ++i; - dynamic [i].d_tag = DT_SYMENT; - dynamic [i].d_un.d_val = sizeof (ElfSymbol); - ++i; -#ifdef USE_ELF_RELA - dynamic [i].d_tag = DT_RELA; - dynamic [i].d_un.d_val = secth [SECT_RELA_DYN].sh_offset; - ++i; - dynamic [i].d_tag = DT_RELASZ; - dynamic [i].d_un.d_val = secth [SECT_RELA_DYN].sh_size; - ++i; - dynamic [i].d_tag = DT_RELAENT; - dynamic [i].d_un.d_val = sizeof (ElfRelocA); - ++i; -#else - dynamic [i].d_tag = DT_REL; - dynamic [i].d_un.d_val = secth [SECT_REL_DYN].sh_offset; - ++i; - dynamic [i].d_tag = DT_RELSZ; - dynamic [i].d_un.d_val = secth [SECT_REL_DYN].sh_size; - ++i; - dynamic [i].d_tag = DT_RELENT; - dynamic [i].d_un.d_val = sizeof (ElfReloc); - ++i; -#endif - dynamic [i].d_tag = DT_RELCOUNT; - dynamic [i].d_un.d_val = acfg->num_relocs; - ++i; - - /* Program header */ - memset (&progh, 0, sizeof (progh)); - progh [0].p_type = PT_LOAD; - progh [0].p_filesz = progh [0].p_memsz = secth [SECT_DYNAMIC].sh_offset; - progh [0].p_align = 4096; - progh [0].p_flags = 5; - - progh [1].p_type = PT_LOAD; - progh [1].p_offset = secth [SECT_DYNAMIC].sh_offset; - progh [1].p_vaddr = progh [1].p_paddr = secth [SECT_DYNAMIC].sh_addr; - progh [1].p_filesz = secth [SECT_BSS].sh_offset - secth [SECT_DYNAMIC].sh_offset; - progh [1].p_memsz = secth [SECT_BSS].sh_addr + secth [SECT_BSS].sh_size - secth [SECT_DYNAMIC].sh_addr; - progh [1].p_align = 4096; - progh [1].p_flags = 6; - - progh [2].p_type = PT_DYNAMIC; - progh [2].p_offset = secth [SECT_DYNAMIC].sh_offset; - progh [2].p_vaddr = progh [2].p_paddr = secth [SECT_DYNAMIC].sh_addr; - progh [2].p_filesz = progh [2].p_memsz = secth [SECT_DYNAMIC].sh_size; - progh [2].p_align = TARGET_SIZEOF_VOID_P; - progh [2].p_flags = 6; - - progh [3].p_type = PT_GNU_STACK; - progh [3].p_offset = secth [SECT_DYNAMIC].sh_offset; - progh [3].p_vaddr = progh [3].p_paddr = secth [SECT_DYNAMIC].sh_addr; - progh [3].p_filesz = progh [3].p_memsz = secth [SECT_DYNAMIC].sh_size; - progh [3].p_align = TARGET_SIZEOF_VOID_P; - progh [3].p_flags = 6; - - /* Compute the addresses of the bin sections, so relocation can be done */ - for (i = 0; i < SECT_NUM; ++i) { - if (sections [i]) { - sections [i]->file_offset = secth [i].sh_offset; - sections [i]->virt_offset = secth [i].sh_addr; - } - } - - reloc_symbols (acfg, dynsym, secth, &dyn_str_table, TRUE); - reloc_symbols (acfg, symtab, secth, &str_table, FALSE); - relocs = resolve_relocations (acfg); - - if (!acfg->fp) { - acfg->out_buf_size = file_offset + sizeof (secth); - acfg->out_buf = (guint8 *)g_malloc (acfg->out_buf_size); - } - - bin_writer_fwrite (acfg, &header, sizeof (header), 1); - bin_writer_fwrite (acfg, &progh, sizeof (progh), 1); - bin_writer_fwrite (acfg, hash, sizeof (int) * (hash [0] + hash [1] + 2), 1); - bin_writer_fwrite (acfg, dynsym, sizeof (ElfSymbol) * hash [1], 1); - bin_writer_fwrite (acfg, dyn_str_table.data->str, dyn_str_table.data->len, 1); - /* .rel.dyn */ - bin_writer_fseek (acfg, secth [SECT_REL_DYN].sh_offset); - bin_writer_fwrite (acfg, relocs, sizeof (ElfReloc), acfg->num_relocs); - - /* .rela.dyn */ - bin_writer_fseek (acfg, secth [SECT_RELA_DYN].sh_offset); - bin_writer_fwrite (acfg, relocs, secth [SECT_RELA_DYN].sh_size, 1); - - /* .text */ - if (sections [SECT_TEXT]) { - bin_writer_fseek (acfg, secth [SECT_TEXT].sh_offset); - bin_writer_fwrite (acfg, sections [SECT_TEXT]->data, sections [SECT_TEXT]->cur_offset, 1); - } - /* .rodata */ - if (sections [SECT_RODATA]) { - bin_writer_fseek (acfg, secth [SECT_RODATA].sh_offset); - bin_writer_fwrite (acfg, sections [SECT_RODATA]->data, sections [SECT_RODATA]->cur_offset, 1); - } - /* .dynamic */ - bin_writer_fseek (acfg, secth [SECT_DYNAMIC].sh_offset); - bin_writer_fwrite (acfg, dynamic, sizeof (dynamic), 1); - - /* .got.plt */ - size = secth [SECT_DYNAMIC].sh_addr; - bin_writer_fseek (acfg, secth [SECT_GOT_PLT].sh_offset); - bin_writer_fwrite (acfg, &size, sizeof (size), 1); - - /* normal sections */ - for (i = 0; i < sizeof (normal_sections) / sizeof (normal_sections [0]); ++i) { - int sect = normal_sections [i]; - - if (sections [sect]) { - bin_writer_fseek (acfg, secth [sect].sh_offset); - bin_writer_fwrite (acfg, sections [sect]->data, sections [sect]->cur_offset, 1); - } - } - - bin_writer_fseek (acfg, secth [SECT_SHSTRTAB].sh_offset); - bin_writer_fwrite (acfg, sh_str_table.data->str, sh_str_table.data->len, 1); - bin_writer_fseek (acfg, secth [SECT_SYMTAB].sh_offset); - bin_writer_fwrite (acfg, symtab, sizeof (ElfSymbol) * num_local_syms, 1); - bin_writer_fseek (acfg, secth [SECT_STRTAB].sh_offset); - bin_writer_fwrite (acfg, str_table.data->str, str_table.data->len, 1); - /*g_print ("file_offset %d vs %d\n", file_offset, ftell (file));*/ - /*g_assert (file_offset >= ftell (file));*/ - bin_writer_fseek (acfg, file_offset); - bin_writer_fwrite (acfg, §h, sizeof (secth), 1); - - if (acfg->fp) - fclose (acfg->fp); - - return 0; -} - -#endif /* USE_ELF_WRITER */ - -#endif /* USE_BIN_WRITER */ - /* ASM WRITER */ static void @@ -1852,7 +336,6 @@ asm_writer_emit_alignment (MonoImageWriter *acfg, int size) #endif } -#ifndef USE_BIN_WRITER static void asm_writer_emit_alignment_fill (MonoImageWriter *acfg, int size, int fill) { @@ -1863,7 +346,6 @@ asm_writer_emit_alignment_fill (MonoImageWriter *acfg, int size, int fill) asm_writer_emit_alignment (acfg, size); #endif } -#endif static void asm_writer_emit_pointer_unaligned (MonoImageWriter *acfg, const char *target) @@ -2019,27 +501,13 @@ asm_writer_emit_zero_bytes (MonoImageWriter *acfg, int num) void mono_img_writer_emit_start (MonoImageWriter *acfg) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_start (acfg); - else - asm_writer_emit_start (acfg); -#else asm_writer_emit_start (acfg); -#endif } void mono_img_writer_emit_section_change (MonoImageWriter *acfg, const char *section_name, int subsection_index) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_section_change (acfg, section_name, subsection_index); - else - asm_writer_emit_section_change (acfg, section_name, subsection_index); -#else asm_writer_emit_section_change (acfg, section_name, subsection_index); -#endif acfg->current_section = section_name; acfg->current_subsection = subsection_index; @@ -2067,229 +535,109 @@ mono_img_writer_emit_pop_section (MonoImageWriter *acfg) void mono_img_writer_set_section_addr (MonoImageWriter *acfg, guint64 addr) { -#ifdef USE_BIN_WRITER - if (!acfg->use_bin_writer) - NOT_IMPLEMENTED; - else - bin_writer_set_section_addr (acfg, addr); -#else NOT_IMPLEMENTED; -#endif } void mono_img_writer_emit_global (MonoImageWriter *acfg, const char *name, gboolean func) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_global (acfg, name, func); - else - asm_writer_emit_global (acfg, name, func); -#else asm_writer_emit_global (acfg, name, func); -#endif } void mono_img_writer_emit_local_symbol (MonoImageWriter *acfg, const char *name, const char *end_label, gboolean func) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_local_symbol (acfg, name, end_label, func); - else - asm_writer_emit_local_symbol (acfg, name, end_label, func); -#else asm_writer_emit_local_symbol (acfg, name, end_label, func); -#endif } void mono_img_writer_emit_symbol_size (MonoImageWriter *acfg, const char *name, const char *end_label) { - if (!acfg->use_bin_writer) - asm_writer_emit_symbol_size (acfg, name, end_label); + asm_writer_emit_symbol_size (acfg, name, end_label); } void mono_img_writer_emit_label (MonoImageWriter *acfg, const char *name) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_label (acfg, name); - else - asm_writer_emit_label (acfg, name); -#else asm_writer_emit_label (acfg, name); -#endif } void mono_img_writer_emit_bytes (MonoImageWriter *acfg, const guint8* buf, int size) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_bytes (acfg, buf, size); - else - asm_writer_emit_bytes (acfg, buf, size); -#else asm_writer_emit_bytes (acfg, buf, size); -#endif } void mono_img_writer_emit_string (MonoImageWriter *acfg, const char *value) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_string (acfg, value); - else - asm_writer_emit_string (acfg, value); -#else asm_writer_emit_string (acfg, value); -#endif } void mono_img_writer_emit_line (MonoImageWriter *acfg) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_line (acfg); - else - asm_writer_emit_line (acfg); -#else - asm_writer_emit_line (acfg); -#endif + asm_writer_emit_line (acfg); } void mono_img_writer_emit_alignment (MonoImageWriter *acfg, int size) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_alignment (acfg, size); - else - asm_writer_emit_alignment (acfg, size); -#else asm_writer_emit_alignment (acfg, size); -#endif } void mono_img_writer_emit_alignment_fill (MonoImageWriter *acfg, int size, int fill) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_alignment (acfg, size); - else - asm_writer_emit_alignment (acfg, size); -#else asm_writer_emit_alignment_fill (acfg, size, fill); -#endif } void mono_img_writer_emit_pointer_unaligned (MonoImageWriter *acfg, const char *target) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_pointer_unaligned (acfg, target); - else - asm_writer_emit_pointer_unaligned (acfg, target); -#else asm_writer_emit_pointer_unaligned (acfg, target); -#endif } void mono_img_writer_emit_pointer (MonoImageWriter *acfg, const char *target) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_pointer (acfg, target); - else - asm_writer_emit_pointer (acfg, target); -#else asm_writer_emit_pointer (acfg, target); -#endif } void mono_img_writer_emit_int16 (MonoImageWriter *acfg, int value) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_int16 (acfg, value); - else - asm_writer_emit_int16 (acfg, value); -#else asm_writer_emit_int16 (acfg, value); -#endif } void mono_img_writer_emit_int32 (MonoImageWriter *acfg, int value) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_int32 (acfg, value); - else - asm_writer_emit_int32 (acfg, value); -#else asm_writer_emit_int32 (acfg, value); -#endif } void mono_img_writer_emit_symbol (MonoImageWriter *acfg, const char *symbol) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_symbol (acfg, symbol); - else - asm_writer_emit_symbol (acfg, symbol); -#else asm_writer_emit_symbol (acfg, symbol); -#endif } void mono_img_writer_emit_symbol_diff (MonoImageWriter *acfg, const char *end, const char* start, int offset) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_symbol_diff (acfg, end, start, offset); - else - asm_writer_emit_symbol_diff (acfg, end, start, offset); -#else asm_writer_emit_symbol_diff (acfg, end, start, offset); -#endif } void mono_img_writer_emit_zero_bytes (MonoImageWriter *acfg, int num) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_zero_bytes (acfg, num); - else - asm_writer_emit_zero_bytes (acfg, num); -#else asm_writer_emit_zero_bytes (acfg, num); -#endif } int mono_img_writer_emit_writeout (MonoImageWriter *acfg) { -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - return bin_writer_emit_writeout (acfg); - else - return asm_writer_emit_writeout (acfg); -#else - return asm_writer_emit_writeout (acfg); -#endif + return asm_writer_emit_writeout (acfg); } void @@ -2305,15 +653,7 @@ mono_img_writer_emit_byte (MonoImageWriter *acfg, guint8 val) void mono_img_writer_emit_reloc (MonoImageWriter *acfg, int reloc_type, const char *symbol, int addend) { - /* This is only supported by the bin writer */ -#ifdef USE_BIN_WRITER - if (acfg->use_bin_writer) - bin_writer_emit_reloc (acfg, reloc_type, symbol, addend); - else - g_assert_not_reached (); -#else - g_assert_not_reached (); -#endif + g_assert_not_reached (); } /* @@ -2325,8 +665,7 @@ mono_img_writer_emit_reloc (MonoImageWriter *acfg, int reloc_type, const char *s void mono_img_writer_emit_unset_mode (MonoImageWriter *acfg) { - if (!acfg->use_bin_writer) - asm_writer_emit_unset_mode (acfg); + asm_writer_emit_unset_mode (acfg); } /* @@ -2338,55 +677,23 @@ mono_img_writer_emit_unset_mode (MonoImageWriter *acfg) guint8* mono_img_writer_get_output (MonoImageWriter *acfg, guint32 *size) { -#ifdef USE_BIN_WRITER - guint8 *buf; - - g_assert (acfg->use_bin_writer); - - buf = acfg->out_buf; - *size = acfg->out_buf_size; - acfg->out_buf = NULL; - return buf; -#else g_assert_not_reached (); return NULL; -#endif -} - -/* - * Return whenever the binary writer is supported on this platform. - */ -gboolean -mono_bin_writer_supported (void) -{ -#ifdef USE_BIN_WRITER - return TRUE; -#else - return FALSE; -#endif } /* * mono_img_writer_create: * - * Create an image writer writing to FP. If USE_BIN_WRITER is TRUE, FP can be NULL, - * in this case the image writer will write to a memory buffer obtainable by calling - * mono_img_writer_get_output (). + * Create an image writer writing to FP. */ MonoImageWriter* -mono_img_writer_create (FILE *fp, gboolean use_bin_writer) +mono_img_writer_create (FILE *fp) { MonoImageWriter *w = g_new0 (MonoImageWriter, 1); - -#ifndef USE_BIN_WRITER - g_assert (!use_bin_writer); -#endif - if (!use_bin_writer) - g_assert (fp); + g_assert (fp); w->fp = fp; - w->use_bin_writer = use_bin_writer; w->mempool = mono_mempool_new (); return w; @@ -2404,7 +711,7 @@ gboolean mono_img_writer_subsections_supported (MonoImageWriter *acfg) { #ifdef TARGET_ASM_APPLE - return acfg->use_bin_writer; + return FALSE; #else return TRUE; #endif diff --git a/src/mono/mono/mini/image-writer.h b/src/mono/mono/mini/image-writer.h index 309ec37c059a77..c6d855fa1b4103 100644 --- a/src/mono/mono/mini/image-writer.h +++ b/src/mono/mono/mini/image-writer.h @@ -22,39 +22,7 @@ typedef struct _MonoImageWriter MonoImageWriter; -#if defined(TARGET_AMD64) && !defined(HOST_WIN32) && !defined(__APPLE__) -#define USE_ELF_WRITER 1 -#define USE_ELF_RELA 1 -#endif - -#if defined(TARGET_X86) && !defined(HOST_WIN32) && !defined(__APPLE__) -#define USE_ELF_WRITER 1 -#endif - -#if defined(TARGET_ARM) && !defined(TARGET_MACH) && !defined(HOST_WIN32) -//#define USE_ELF_WRITER 1 -#endif - -#if defined(__mips__) -#define USE_ELF_WRITER 1 -#endif - -#if defined(TARGET_X86) && defined(__APPLE__) -//#define USE_MACH_WRITER -#endif - -#if defined(USE_ELF_WRITER) || defined(USE_MACH_WRITER) -#define USE_BIN_WRITER 1 -#endif - -/* Relocation types */ -#define R_ARM_CALL 28 -#define R_ARM_JUMP24 29 -#define R_ARM_ALU_PC_G0_NC 59 - -gboolean mono_bin_writer_supported (void); - -MonoImageWriter* mono_img_writer_create (FILE *fp, gboolean use_bin_writer); +MonoImageWriter* mono_img_writer_create (FILE *fp); void mono_img_writer_destroy (MonoImageWriter *w); diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 36400c7e9fdbbe..bea43f236a65c8 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -523,7 +523,6 @@ mono_tramp_info_register_internal (MonoTrampInfo *info, MonoMemoryManager *mem_m copy->uw_info_len = info->uw_info_len; } - mono_save_trampoline_xdebug_info (info); mono_lldb_save_trampoline_info (info); #ifdef MONO_ARCH_HAVE_UNWIND_TABLE @@ -3934,7 +3933,7 @@ mini_parse_debug_option (const char *option) else if (!strcmp (option, "dyn-runtime-invoke")) mini_debug_options.dyn_runtime_invoke = TRUE; else if (!strcmp (option, "gdb")) - mini_debug_options.gdb = TRUE; + fprintf (stderr, "MONO_DEBUG=gdb is deprecated."); else if (!strcmp (option, "lldb")) mini_debug_options.lldb = TRUE; else if (!strcmp (option, "llvm-disable-inlining")) @@ -4431,21 +4430,6 @@ mini_init (const char *filename, const char *runtime_version) mono_dont_free_domains = TRUE; } -#ifdef XDEBUG_ENABLED - char *mono_xdebug = g_getenv ("MONO_XDEBUG"); - if (mono_xdebug) { - mono_xdebug_init (mono_xdebug); - g_free (mono_xdebug); - /* So methods for multiple domains don't have the same address */ - mono_dont_free_domains = TRUE; - mono_using_xdebug = TRUE; - } else if (mini_debug_options.gdb) { - mono_xdebug_init ((char*)"gdb"); - mono_dont_free_domains = TRUE; - mono_using_xdebug = TRUE; - } -#endif - #ifdef ENABLE_LLVM if (mono_use_llvm) mono_llvm_init (!mono_compile_aot); diff --git a/src/mono/mono/mini/mini-runtime.h b/src/mono/mono/mini/mini-runtime.h index 2e349a35ed0317..562d98eb5357d6 100644 --- a/src/mono/mono/mini/mini-runtime.h +++ b/src/mono/mono/mini/mini-runtime.h @@ -245,7 +245,6 @@ typedef struct MonoDebugOptions { gboolean suspend_on_exception; gboolean suspend_on_unhandled; gboolean dyn_runtime_invoke; - gboolean gdb; gboolean lldb; /* @@ -571,10 +570,6 @@ MONO_API char *mono_pmip (void *ip); MONO_API int mono_ee_api_version (void); gboolean mono_debug_count (void); -#ifdef __linux__ -#define XDEBUG_ENABLED 1 -#endif - #ifdef __linux__ /* maybe enable also for other systems? */ #define ENABLE_JIT_MAP 1 diff --git a/src/mono/mono/mini/mini.c b/src/mono/mono/mini/mini.c index 28ce38aa7b6b7f..f3cfa3895e67a5 100644 --- a/src/mono/mono/mini/mini.c +++ b/src/mono/mono/mini/mini.c @@ -83,7 +83,6 @@ int mono_inject_async_exc_pos; MonoMethodDesc *mono_break_at_bb_method; int mono_break_at_bb_bb_num; gboolean mono_do_x86_stack_align = TRUE; -gboolean mono_using_xdebug; /* Counters */ static guint32 discarded_code; @@ -2046,19 +2045,9 @@ mono_codegen (MonoCompile *cfg) MonoBasicBlock *bb; int max_epilog_size; guint8 *code; - MonoMemoryManager *code_mem_manager; + MonoMemoryManager *code_mem_manager = cfg->mem_manager; guint unwindlen = 0; - if (mono_using_xdebug) - /* - * Recent gdb versions have trouble processing symbol files containing - * overlapping address ranges, so allocate all code from the code manager - * of the root domain. (#666152). - */ - code_mem_manager = get_default_mem_manager (); - else - code_mem_manager = cfg->mem_manager; - for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { cfg->spill_count = 0; /* we reuse dfn here */ @@ -2133,11 +2122,7 @@ mono_codegen (MonoCompile *cfg) g_hash_table_insert (jit_mm->dynamic_code_hash, cfg->method, cfg->dynamic_info); jit_mm_unlock (jit_mm); - if (mono_using_xdebug) - /* See the comment for cfg->code_domain */ - code = (guint8 *)mono_mem_manager_code_reserve (code_mem_manager, cfg->code_size + cfg->thunk_area + unwindlen); - else - code = (guint8 *)mono_code_manager_reserve (cfg->dynamic_info->code_mp, cfg->code_size + cfg->thunk_area + unwindlen); + code = (guint8 *)mono_code_manager_reserve (cfg->dynamic_info->code_mp, cfg->code_size + cfg->thunk_area + unwindlen); } else { code = (guint8 *)mono_mem_manager_code_reserve (code_mem_manager, cfg->code_size + cfg->thunk_area + unwindlen); } @@ -2220,10 +2205,7 @@ mono_codegen (MonoCompile *cfg) } if (cfg->method->dynamic) { - if (mono_using_xdebug) - mono_mem_manager_code_commit (code_mem_manager, cfg->native_code, cfg->code_size, cfg->code_len); - else - mono_code_manager_commit (cfg->dynamic_info->code_mp, cfg->native_code, cfg->code_size, cfg->code_len); + mono_code_manager_commit (cfg->dynamic_info->code_mp, cfg->native_code, cfg->code_size, cfg->code_len); } else { mono_mem_manager_code_commit (code_mem_manager, cfg->native_code, cfg->code_size, cfg->code_len); } @@ -3381,18 +3363,6 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts cfg->disable_out_of_line_bblocks = TRUE; } - if (mono_using_xdebug) { - /* - * Make each variable use its own register/stack slot and extend - * their liveness to cover the whole method, making them displayable - * in gdb even after they are dead. - */ - cfg->disable_reuse_registers = TRUE; - cfg->disable_reuse_stack_slots = TRUE; - cfg->extend_live_ranges = TRUE; - cfg->compute_precise_live_ranges = TRUE; - } - mini_gc_init_cfg (cfg); if (method->wrapper_type == MONO_WRAPPER_OTHER) { @@ -3932,10 +3902,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, JitFlags flags, int parts MONO_TIME_TRACK (mono_jit_stats.jit_gc_create_gc_map, mini_gc_create_gc_map (cfg)); MONO_TIME_TRACK (mono_jit_stats.jit_save_seq_point_info, mono_save_seq_point_info (cfg, cfg->jit_info)); - if (!cfg->compile_aot) { - mono_save_xdebug_info (cfg); + if (!cfg->compile_aot) mono_lldb_save_method_info (cfg); - } if (cfg->verbose_level >= 2) { char *id = mono_method_full_name (cfg->method, TRUE); diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index e454d89ef41b81..5001ee38ddd091 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -365,7 +365,6 @@ extern int mono_inject_async_exc_pos; extern MonoMethodDesc *mono_break_at_bb_method; extern int mono_break_at_bb_bb_num; extern gboolean mono_do_x86_stack_align; -extern gboolean mono_using_xdebug; extern int mini_verbose; extern int valgrind_register; @@ -2206,12 +2205,6 @@ void mono_liveness_handle_exception_clauses (MonoCompile *cfg); gpointer mono_realloc_native_code (MonoCompile *cfg); -void mono_xdebug_init (const char *xdebug_opts); -void mono_save_xdebug_info (MonoCompile *cfg); -void mono_save_trampoline_xdebug_info (MonoTrampInfo *info); -/* This is an exported function */ -void mono_xdebug_flush (void); - void mono_register_opcode_emulation (int opcode, const char* name, MonoMethodSignature *sig, gpointer func, gboolean no_throw); void mono_draw_graph (MonoCompile *cfg, MonoGraphOptions draw_options); void mono_add_ins_to_end (MonoBasicBlock *bb, MonoInst *inst); diff --git a/src/mono/mono/mini/xdebug.c b/src/mono/mono/mini/xdebug.c deleted file mode 100644 index 868acaafacb011..00000000000000 --- a/src/mono/mono/mini/xdebug.c +++ /dev/null @@ -1,398 +0,0 @@ -/** - * \file - * Support for emitting gdb debug info for JITted code. - * - * Author: - * Zoltan Varga (vargaz@gmail.com) - * - * (C) 2010 Novell, Inc. - */ - -/* - * This works as follows: - * - the runtime writes out an xdb.s file containing DWARF debug info. - * - the user calls a gdb macro - * - the macro compiles and loads this shared library using add-symbol-file. - * - * This is based on the xdebug functionality in the Kaffe Java VM. - * - * We emit assembly code instead of using the ELF writer, so we can emit debug info - * incrementally as each method is JITted, and the debugger doesn't have to call - * into the runtime to emit the shared library, which would cause all kinds of - * complications, like threading issues, and the fact that the ELF writer's - * emit_writeout () function cannot be called more than once. - * GDB 7.0 and later has a JIT interface. - */ - -#include "config.h" -#include -#include "mini.h" -#include "mini-runtime.h" - -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_STDINT_H -#include -#endif -#include -#include -#include -#ifndef HOST_WIN32 -#include -#else -#include -#include -#endif - -#include -#include - -#include "image-writer.h" - -#if !defined(DISABLE_AOT) && !defined(DISABLE_JIT) && USE_BIN_WRITER - -#include "dwarfwriter.h" - -#include "mono/utils/mono-compiler.h" - -#define USE_GDB_JIT_INTERFACE - -/* The recommended gdb macro is: */ -/* - define xdb - shell rm -f xdb.so && as --64 -o xdb.o xdb.s && ld -shared -o xdb.so xdb.o - add-symbol-file xdb.so 0 - end -*/ - -/* - * GDB JIT interface definitions. - * - * http://sources.redhat.com/gdb/onlinedocs/gdb_30.html - */ -typedef enum -{ - JIT_NOACTION = 0, - JIT_REGISTER_FN, - JIT_UNREGISTER_FN -} jit_actions_t; - -struct jit_code_entry; -typedef struct jit_code_entry jit_code_entry; - -struct jit_code_entry -{ - jit_code_entry *next_entry; - jit_code_entry *prev_entry; - const char *symfile_addr; - /* - * The gdb code in gdb/jit.c which reads this structure ignores alignment - * requirements, so use two 32 bit fields. - */ - guint32 symfile_size1, symfile_size2; -}; - -typedef struct jit_descriptor -{ - guint32 version; - /* This type should be jit_actions_t, but we use guint32 - to be explicit about the bitwidth. */ - guint32 action_flag; - jit_code_entry *relevant_entry; - jit_code_entry *first_entry; -} jit_descriptor; - -G_BEGIN_DECLS - -/* GDB puts a breakpoint in this function. */ -void MONO_NEVER_INLINE __jit_debug_register_code(void); - -#if defined(ENABLE_LLVM) && !defined(MONO_CROSS_COMPILE) - -/* LLVM already defines these */ - -extern jit_descriptor __jit_debug_descriptor; - -#else - -/* gcc seems to inline/eliminate calls to noinline functions, thus the asm () */ -void MONO_NEVER_INLINE __jit_debug_register_code(void) { -#if defined(__GNUC__) - asm (""); -#endif -} - -/* Make sure to specify the version statically, because the - debugger may check the version before we can set it. */ -jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; - -#endif - -G_END_DECLS - -static MonoImageWriter *xdebug_w; -static MonoDwarfWriter *xdebug_writer; -static FILE *xdebug_fp, *il_file; -static gboolean use_gdb_interface, save_symfiles; -static int il_file_line_index; -static GHashTable *xdebug_syms; - -void -mono_xdebug_init (const char *options) -{ - MonoImageWriter *w; - char **args, **ptr; - - args = g_strsplit (options, ",", -1); - for (ptr = args; ptr && *ptr; ptr ++) { - char *arg = *ptr; - - if (!strcmp (arg, "gdb")) - use_gdb_interface = TRUE; - if (!strcmp (arg, "save-symfiles")) - save_symfiles = TRUE; - } - - /* This file will contain the IL code for methods which don't have debug info */ - il_file = fopen ("xdb.il", "w"); - if (il_file == NULL) { - use_gdb_interface = FALSE; - g_warning ("** Unable to create xdb.il. Managed symbol names won't be available."); - return; - } - - if (use_gdb_interface) - return; - - unlink ("xdb.s"); - xdebug_fp = fopen ("xdb.s", "w"); - - w = mono_img_writer_create (xdebug_fp, FALSE); - - mono_img_writer_emit_start (w); - - xdebug_writer = mono_dwarf_writer_create (w, il_file, 0, TRUE); - - /* Emit something so the file has a text segment */ - mono_img_writer_emit_section_change (w, ".text", 0); - mono_img_writer_emit_string (w, ""); - - mono_dwarf_writer_emit_base_info (xdebug_writer, "JITted code", mono_unwind_get_cie_program ()); -} - -static void -xdebug_begin_emit (MonoImageWriter **out_w, MonoDwarfWriter **out_dw) -{ - MonoImageWriter *w; - MonoDwarfWriter *dw; - - w = mono_img_writer_create (NULL, TRUE); - - mono_img_writer_emit_start (w); - - /* This file will contain the IL code for methods which don't have debug info */ - if (!il_file) - il_file = fopen ("xdb.il", "w"); - - dw = mono_dwarf_writer_create (w, il_file, il_file_line_index, TRUE); - - mono_dwarf_writer_emit_base_info (dw, "JITted code", mono_unwind_get_cie_program ()); - - *out_w = w; - *out_dw = dw; -} - -static void -xdebug_end_emit (MonoImageWriter *w, MonoDwarfWriter *dw, MonoMethod *method) -{ - guint8 *img; - guint32 img_size; - jit_code_entry *entry; - guint64 *psize; - - il_file_line_index = mono_dwarf_writer_get_il_file_line_index (dw); - mono_dwarf_writer_close (dw); - - mono_img_writer_emit_writeout (w); - - img = mono_img_writer_get_output (w, &img_size); - - mono_img_writer_destroy (w); - - if (FALSE) { - /* Save the symbol files to help debugging */ - FILE *fp; - char *file_name; - static int file_counter; - - file_counter ++; - file_name = g_strdup_printf ("xdb-%d.o", file_counter); - printf ("%s %p %d\n", file_name, img, img_size); - - fp = fopen (file_name, "w"); - fwrite (img, img_size, 1, fp); - fclose (fp); - g_free (file_name); - } - - /* Register the image with GDB */ - - entry = g_malloc0 (sizeof (jit_code_entry)); - - entry->symfile_addr = (const char*)img; - psize = (guint64*)&entry->symfile_size1; - *psize = img_size; - - entry->next_entry = __jit_debug_descriptor.first_entry; - if (__jit_debug_descriptor.first_entry) - __jit_debug_descriptor.first_entry->prev_entry = entry; - __jit_debug_descriptor.first_entry = entry; - - __jit_debug_descriptor.relevant_entry = entry; - __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; - - __jit_debug_register_code (); -} - -/* - * mono_xdebug_flush: - * - * This could be called from inside gdb to flush the debugging information not yet - * registered with gdb. - */ -void -mono_xdebug_flush (void) -{ - if (xdebug_w) - xdebug_end_emit (xdebug_w, xdebug_writer, NULL); - - xdebug_begin_emit (&xdebug_w, &xdebug_writer); -} - -static int xdebug_method_count; - -/* - * mono_save_xdebug_info: - * - * Emit debugging info for METHOD into an assembly file which can be assembled - * and loaded into gdb to provide debugging info for JITted code. - * LOCKING: Acquires the loader lock. - */ -void -mono_save_xdebug_info (MonoCompile *cfg) -{ - MonoDebugMethodJitInfo *dmji; - - if (use_gdb_interface) { - mono_loader_lock (); - - if (!xdebug_syms) - xdebug_syms = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - - /* - * gdb is not designed to handle 1000s of symbol files (one per method). So we - * group them into groups of 100. - */ - if ((xdebug_method_count % 100) == 0) - mono_xdebug_flush (); - - xdebug_method_count ++; - - dmji = mono_debug_find_method (jinfo_get_method (cfg->jit_info), mono_domain_get ()); - mono_dwarf_writer_emit_method (xdebug_writer, cfg, jinfo_get_method (cfg->jit_info), NULL, NULL, NULL, - (guint8*)cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, dmji); - mono_debug_free_method_jit_info (dmji); - -#if 0 - /* - * Emit a symbol for the code by emitting it at the beginning of the text - * segment, and setting the text segment to have an absolute address. - * This symbol can be used to set breakpoints in gdb. - * FIXME: This doesn't work when multiple methods are emitted into the same file. - */ - sym = get_debug_sym (cfg->jit_info->method, "", xdebug_syms); - mono_img_writer_emit_section_change (w, ".text", 0); - if (!xdebug_text_addr) { - xdebug_text_addr = cfg->jit_info->code_start; - mono_img_writer_set_section_addr (w, (gssize)xdebug_text_addr); - } - mono_img_writer_emit_global_with_size (w, sym, cfg->jit_info->code_size, TRUE); - mono_img_writer_emit_label (w, sym); - mono_img_writer_emit_bytes (w, cfg->jit_info->code_start, cfg->jit_info->code_size); - g_free (sym); -#endif - - mono_loader_unlock (); - } else { - if (!xdebug_writer) - return; - - mono_loader_lock (); - dmji = mono_debug_find_method (jinfo_get_method (cfg->jit_info), mono_domain_get ()); - mono_dwarf_writer_emit_method (xdebug_writer, cfg, jinfo_get_method (cfg->jit_info), NULL, NULL, NULL, - (guint8*)cfg->jit_info->code_start, cfg->jit_info->code_size, cfg->args, cfg->locals, cfg->unwind_ops, dmji); - mono_debug_free_method_jit_info (dmji); - fflush (xdebug_fp); - mono_loader_unlock (); - } - -} - -/* - * mono_save_trampoline_xdebug_info: - * - * Same as mono_save_xdebug_info, but for trampolines. - * LOCKING: Acquires the loader lock. - */ -void -mono_save_trampoline_xdebug_info (MonoTrampInfo *info) -{ - const char *info_name = info->name; - if (info_name == NULL) - info_name = ""; - - if (use_gdb_interface) { - MonoImageWriter *w; - MonoDwarfWriter *dw; - - /* This can be called before the loader lock is initialized */ - mono_loader_lock_if_inited (); - - xdebug_begin_emit (&w, &dw); - - mono_dwarf_writer_emit_trampoline (dw, info_name, NULL, NULL, info->code, info->code_size, info->unwind_ops); - - xdebug_end_emit (w, dw, NULL); - - mono_loader_unlock_if_inited (); - } else { - if (!xdebug_writer) - return; - - mono_loader_lock_if_inited (); - mono_dwarf_writer_emit_trampoline (xdebug_writer, info_name, NULL, NULL, info->code, info->code_size, info->unwind_ops); - fflush (xdebug_fp); - mono_loader_unlock_if_inited (); - } -} - -#else /* !defined(DISABLE_AOT) && !defined(DISABLE_JIT) */ - -void -mono_xdebug_init (const char *options) -{ -} - -void -mono_save_xdebug_info (MonoCompile *cfg) -{ -} - -void -mono_save_trampoline_xdebug_info (MonoTrampInfo *info) -{ -} - -#endif From 394e24f7045d0e1921bd352bda9027e343cc6b7c Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Tue, 3 Aug 2021 09:06:47 -0700 Subject: [PATCH 62/64] Ensure MetadataEnumResult is sufficiently updated by MetaDataImport::Enum (#56756) `MetadataEnumResult` has a fixed inline buffer for returning small results and a pointer to allow it to return larger ones. The indexer for this checks the pointer and if non-null assumes that's the current set of values. But if a `MetadataEnumResult` is re-used within a loop, values written to it by `MetaDataImport::Enum` may bleed from one loop iteration to the next if the iterations first get a large result and then a small one. One case where this could happen was in libraries PGO tests, where PGO data encouraged the jit to inline `MemberInfoCache.PopulateProperties(Filter,...)` into `MemberInfoCache.PopulateProperties(Filter)`. Note this also is a conseqeunce of skipping zero init locals; without that the struct would have been zeroed each loop iteration. Fixes #56655. --- src/coreclr/vm/managedmdimport.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/vm/managedmdimport.cpp b/src/coreclr/vm/managedmdimport.cpp index 6bea537f1c8e1e..ec2aef0cc03987 100644 --- a/src/coreclr/vm/managedmdimport.cpp +++ b/src/coreclr/vm/managedmdimport.cpp @@ -163,6 +163,7 @@ static int * EnsureResultSize(MetadataEnumResult * pResult, ULONG length) else { ZeroMemory(pResult->smallResult, sizeof(pResult->smallResult)); + pResult->largeResult = NULL; p = pResult->smallResult; } From f9cbd72baba7f76f32b355fbc3da735f5d8bacfb Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Tue, 3 Aug 2021 09:30:43 -0700 Subject: [PATCH 63/64] Mark new test as incompatible with GC Mark4781_1GcStressIncompatible (#56739) This test relies on triggering GC at an exact point. Closes #56704. --- .../JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.csproj index f3e1cbd44b4041..7052da0bcb87ed 100644 --- a/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.csproj +++ b/src/tests/JIT/Regression/JitBlue/Runtime_4781/Runtime_4781_1.csproj @@ -5,6 +5,7 @@ None True + true From 71f9191846292b61a93de54a18bdcac389d90988 Mon Sep 17 00:00:00 2001 From: Thays Grazia Date: Tue, 3 Aug 2021 13:56:08 -0300 Subject: [PATCH 64/64] [wasm][debugger] Create test Inherited Properties (#56754) * Created test case do close 47658. * Moving test to file that @radical suggested. --- .../DebuggerTestSuite/GetPropertiesTests.cs | 26 ++++++++++++++++++ .../tests/debugger-test/debugger-test2.cs | 27 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs index 3215ef1184d89c..6b4dcd65900be9 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs @@ -335,6 +335,32 @@ await CheckExpectedProperties( AssertEqual(expected_names.Length, filtered_props.Count(), $"expected number of properties"); } + [Fact] + public async Task GetObjectValueWithInheritance() + { + var pause_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] TestChild:TestWatchWithInheritance'); }, 1);", + "dotnet://debugger-test.dll/debugger-test2.cs", 83, 4, + "TestWatchWithInheritance"); + var frame_id = pause_location["callFrames"][0]["callFrameId"].Value(); + var frame_locals = await GetProperties(frame_id); + var test_props = await GetObjectOnLocals(frame_locals, "test"); + await CheckProps(test_props, new + { + j = TNumber(20), + i = TNumber(50), + k = TNumber(30), + GetJ = TGetter("GetJ"), + GetI = TGetter("GetI"), + GetK = TGetter("GetK") + }, "test_props"); + await EvaluateOnCallFrameAndCheck(frame_id, + ($"test.GetJ", TNumber(20)), + ($"test.GetI", TNumber(50)), + ($"test.GetK", TNumber(30)) + ); + } + private async Task CheckExpectedProperties(string[] expected_names, Func get_actual_prop, Dictionary all_props) { foreach (var exp_name in expected_names) diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test2.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-test2.cs index b9d97c8e23484b..d360819356479d 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test2.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test2.cs @@ -56,3 +56,30 @@ public static void BreakOnDebuggerBreakCommand() Debugger.Break(); } } + +public class TestParent2 +{ + public int k = 30; + public int GetK => k; +} + +public class TestParent : TestParent2 +{ + public int j = 20; + public int GetJ => j; +} + +public class TestChild : TestParent +{ + public int i = 50; + public int GetI => i; + public TestChild() + { + Console.WriteLine("Hi"); + } + public static void TestWatchWithInheritance() + { + TestChild test = new TestChild(); + Debugger.Break(); + } +}