diff options
author | Levi Broderick <levib@microsoft.com> | 2019-04-10 22:56:33 -0700 |
---|---|---|
committer | Levi Broderick <levib@microsoft.com> | 2019-04-10 22:56:33 -0700 |
commit | eda0c04f28b9d0ecf3d29fc2c860eac1606d9e6d (patch) | |
tree | 0cadf7e159302d9fc6e193420f17f2e4f707dc98 | |
parent | bae40fa2c2d8f9acb9b8148b7d6a6b91ace55058 (diff) | |
parent | 232ba42911f8266a96f73a77bc1e18f431d96862 (diff) | |
download | coreclr-eda0c04f28b9d0ecf3d29fc2c860eac1606d9e6d.tar.gz coreclr-eda0c04f28b9d0ecf3d29fc2c860eac1606d9e6d.tar.bz2 coreclr-eda0c04f28b9d0ecf3d29fc2c860eac1606d9e6d.zip |
Merge remote-tracking branch 'origin/master' into utf8_validation_apis_3
114 files changed, 3320 insertions, 2068 deletions
diff --git a/Documentation/building/windows-instructions.md b/Documentation/building/windows-instructions.md index afb216fccb..bb24140829 100644 --- a/Documentation/building/windows-instructions.md +++ b/Documentation/building/windows-instructions.md @@ -50,7 +50,7 @@ Visual Studio Express is not supported. ## CMake -The CoreCLR repo build has been validated using CMake 3.9.3. +The CoreCLR repo build has been validated using CMake 3.9.3. When using Visual Studio 2019 at least version 3.14.1 is required. - Install [CMake](http://www.cmake.org/download) for Windows. - Add its location (e.g. C:\Program Files (x86)\CMake\bin) to the PATH environment variable. @@ -60,7 +60,7 @@ The CoreCLR repo build has been validated using CMake 3.9.3. ## Python -Python is used in the build system. We are currently using python 2.7.9, although +Python is used in the build system. We are currently using Python 2.7.9, although any recent (2.4+) version of Python should work, including Python 3. - Install [Python](https://www.python.org/downloads/) for Windows. - Add its location (e.g. C:\Python*\) to the PATH environment variable. diff --git a/Documentation/project-docs/profiling-api-status.md b/Documentation/project-docs/profiling-api-status.md index 1cd9c7eb55..98d486cd12 100644 --- a/Documentation/project-docs/profiling-api-status.md +++ b/Documentation/project-docs/profiling-api-status.md @@ -18,6 +18,10 @@ The implementation of this API was making some questionable assumptions about Wi ReJIT feature is only available on x86/x64 for now. +### Profiler Attach/Detach + +We only support launch at the moment, see https://github.com/dotnet/coreclr/issues/16796 + ### Any issues we missed? -Please let us know and we will get it addressed. Thanks!
\ No newline at end of file +Please let us know and we will get it addressed. Thanks! diff --git a/ILAsmVersion.txt b/ILAsmVersion.txt index a1f2eb6926..5c9f405bdd 100644 --- a/ILAsmVersion.txt +++ b/ILAsmVersion.txt @@ -1 +1 @@ -3.0.0-preview5-27609-71 +3.0.0-preview5-27610-71 diff --git a/dependencies.props b/dependencies.props index 324ac8b040..8286509813 100644 --- a/dependencies.props +++ b/dependencies.props @@ -26,13 +26,13 @@ <!-- Source of truth for dependency tooling: the commit hash of the dotnet/versions master branch as of the last auto-upgrade. --> <PropertyGroup> - <CoreClrCurrentRef>5928d719ef5382c7436f460326c1a92ced0af1cd</CoreClrCurrentRef> + <CoreClrCurrentRef>5b279e7174e71e3a94d48562f049f21ff3a0d33a</CoreClrCurrentRef> <BuildToolsCurrentRef>66f3bb05de8ac6063fbedff5816ef25cc6ecfa11</BuildToolsCurrentRef> </PropertyGroup> <!-- Tests/infrastructure dependency versions. --> <PropertyGroup> - <MicrosoftNETCoreRuntimeCoreCLRPackageVersion>3.0.0-preview5-27609-71</MicrosoftNETCoreRuntimeCoreCLRPackageVersion> + <MicrosoftNETCoreRuntimeCoreCLRPackageVersion>3.0.0-preview5-27610-71</MicrosoftNETCoreRuntimeCoreCLRPackageVersion> <XunitPackageVersion>2.4.1</XunitPackageVersion> <XunitPerformanceApiPackageVersion>1.0.0-beta-build0015</XunitPerformanceApiPackageVersion> <MicrosoftDiagnosticsTracingTraceEventPackageVersion>2.0.36</MicrosoftDiagnosticsTracingTraceEventPackageVersion> diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index e123af5458..1ca9752957 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -19,9 +19,9 @@ <Uri>https://github.com/dotnet/corefx</Uri> <Sha>87fdc75beacc76e02c8e572ae3b0613b418200eb</Sha> </Dependency> - <Dependency Name="Microsoft.NETCore.App" Version="3.0.0-preview5-27608-16"> + <Dependency Name="Microsoft.NETCore.App" Version="3.0.0-preview5-27609-17"> <Uri>https://github.com/dotnet/core-setup</Uri> - <Sha>59c193bd93deafba5926cb827872b80338aca7c0</Sha> + <Sha>9e195d41f604e38fb227eaed017c9292c884149c</Sha> </Dependency> <Dependency Name="optimization.IBC.CoreCLR" Version="99.99.99-master-20190313.3"> <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-optimization</Uri> diff --git a/eng/Versions.props b/eng/Versions.props index 65cb6bb303..098b045fd5 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -11,7 +11,7 @@ <MicrosoftNetFrameworkReferenceAssembliesVersion>1.0.0-alpha-004</MicrosoftNetFrameworkReferenceAssembliesVersion> <MicrosoftPrivateCoreFxNETCoreAppVersion>4.6.0-preview5.19208.1</MicrosoftPrivateCoreFxNETCoreAppVersion> <MicrosoftNETCorePlatformsVersion>3.0.0-preview5.19208.1</MicrosoftNETCorePlatformsVersion> - <MicrosoftNETCoreAppVersion>3.0.0-preview5-27608-16</MicrosoftNETCoreAppVersion> + <MicrosoftNETCoreAppVersion>3.0.0-preview5-27609-17</MicrosoftNETCoreAppVersion> <optimizationIBCCoreCLRVersion>99.99.99-master-20190313.3</optimizationIBCCoreCLRVersion> <optimizationPGOCoreCLRVersion>99.99.99-master-20190313.3</optimizationPGOCoreCLRVersion> </PropertyGroup> diff --git a/src/System.Private.CoreLib/ILLinkTrim.xml b/src/System.Private.CoreLib/ILLinkTrim.xml index 5820e2be13..b621468b61 100644 --- a/src/System.Private.CoreLib/ILLinkTrim.xml +++ b/src/System.Private.CoreLib/ILLinkTrim.xml @@ -15,6 +15,7 @@ <property name="ParentForDebugger" /> <property name="StateFlagsForDebugger" /> <method name="GetDelegateContinuationsForDebugger" /> + <method name="SetNotificationForWaitCompletion" /> </type> <type fullname="System.Threading.ThreadPool"> <method name="GetQueuedWorkItemsForDebugger" /> @@ -36,6 +37,7 @@ </type> <type fullname="System.Runtime.CompilerServices.AsyncTaskMethodBuilder*"> <property name="ObjectIdForDebugger" /> + <method name="SetNotificationForWaitCompletion" /> </type> <type fullname="System.Threading.Tasks.Task"> <!-- Methods is used by VS Tasks Window. --> diff --git a/src/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/System.Private.CoreLib/System.Private.CoreLib.csproj index 96b9584874..23392972ac 100644 --- a/src/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -175,7 +175,7 @@ <Compile Include="$(BclSourcesRoot)\System\Object.CoreCLR.cs" /> <Compile Include="$(BclSourcesRoot)\System\OleAutBinder.cs" Condition="'$(FeatureClassicCominterop)' == 'true'" /> <Compile Include="$(BclSourcesRoot)\System\Reflection\Assembly.CoreCLR.cs" /> - <Compile Include="$(BclSourcesRoot)\System\Reflection\AssemblyName.cs" /> + <Compile Include="$(BclSourcesRoot)\System\Reflection\AssemblyName.CoreCLR.cs" /> <Compile Include="$(BclSourcesRoot)\System\Reflection\Associates.cs" /> <Compile Include="$(BclSourcesRoot)\System\Reflection\ConstructorInfo.CoreCLR.cs" /> <Compile Include="$(BclSourcesRoot)\System\Reflection\CustomAttribute.cs" /> @@ -276,9 +276,6 @@ <Compile Include="shared\Interop\Windows\Kernel32\Interop.HandleTypes.cs" /> <Compile Include="shared\Interop\Windows\Kernel32\Interop.GetStdHandle.cs" /> <Compile Include="shared\Interop\Windows\Kernel32\Interop.LocalAlloc.cs" /> - <Compile Include="shared\Interop\Windows\Kernel32\Interop.QueryUnbiasedInterruptTime.cs" /> - <Compile Include="shared\Interop\Windows\Kernel32\Interop.VerifyVersionExW.cs" /> - <Compile Include="shared\Interop\Windows\Kernel32\Interop.VerSetConditionMask.cs" /> <Compile Include="shared\Interop\Windows\Ole32\Interop.CoTaskMemAlloc.cs" /> <Compile Include="shared\Interop\Windows\OleAut32\Interop.SysAllocStringByteLen.cs" /> </ItemGroup> diff --git a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems index 9dfd24a9ef..02656f57ad 100644 --- a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems +++ b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems @@ -422,6 +422,7 @@ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyKeyFileAttribute.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyKeyNameAttribute.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyMetadataAttribute.cs" /> + <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyName.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyNameFlags.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyNameFormatter.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\AssemblyProductAttribute.cs" /> @@ -913,7 +914,7 @@ </ItemGroup> <ItemGroup> <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\ActivityTracker.cs" /> - <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\BaseCounter.cs" /> + <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\DiagnosticCounter.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\CounterGroup.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\CounterPayload.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Tracing\EventActivityOptions.cs" /> @@ -1037,6 +1038,7 @@ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.OutputDebugString.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.QueryPerformanceCounter.cs" Condition="'$(FeaturePortableThreadPool)' == 'true'" /> <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.QueryPerformanceFrequency.cs" Condition="'$(FeaturePortableThreadPool)' == 'true'" /> + <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.QueryUnbiasedInterruptTime.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.ReadFile_SafeHandle_IntPtr.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.ReadFile_SafeHandle_NativeOverlapped.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.ResolveLocaleName.cs" /> @@ -1089,6 +1091,7 @@ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshal.Windows.cs" Condition="'$(TargetsCoreRT)' != 'true'" /> <Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.Windows.cs" /> <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Thread.Windows.cs" /> + <Compile Include="$(MSBuildThisFileDirectory)System\Threading\TimerQueue.Windows.cs" /> </ItemGroup> <ItemGroup Condition="'$(FeatureAsyncCausalityTracer)' != 'true'"> <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\AsyncCausalityTracer.Noop.cs" /> @@ -1120,6 +1123,8 @@ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.LoadLibraryEx.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.MUI.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.TimeZone.Registry.cs" /> + <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.VerifyVersionExW.cs" /> + <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.VerSetConditionMask.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\NtDll\NtQueryInformationFile.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.Constants.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.LoadString.cs" /> diff --git a/src/System.Private.CoreLib/shared/System/Activator.RuntimeType.cs b/src/System.Private.CoreLib/shared/System/Activator.RuntimeType.cs index f328b9c251..270aa6ad65 100644 --- a/src/System.Private.CoreLib/shared/System/Activator.RuntimeType.cs +++ b/src/System.Private.CoreLib/shared/System/Activator.RuntimeType.cs @@ -4,6 +4,7 @@ using System.Reflection; using System.Globalization; +using System.Runtime.Loader; using System.Runtime.Remoting; using System.Threading; @@ -126,7 +127,7 @@ namespace System { // Classic managed type assembly = RuntimeAssembly.InternalLoadAssemblyName( - assemblyName, ref stackMark); + assemblyName, ref stackMark, AssemblyLoadContext.CurrentContextualReflectionContext); } } diff --git a/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs b/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs index 5c5fd994ed..59e109a043 100644 --- a/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs +++ b/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs @@ -301,12 +301,12 @@ namespace System.Buffers const double HighPressureThreshold = .90; // Percent of GC memory pressure threshold we consider "high" const double MediumPressureThreshold = .70; // Percent of GC memory pressure threshold we consider "medium" - GC.GetMemoryInfo(out uint threshold, out _, out uint lastLoad, out _, out _); - if (lastLoad >= threshold * HighPressureThreshold) + GCMemoryInfo memoryInfo = GC.GetGCMemoryInfo(); + if (memoryInfo.MemoryLoadBytes >= memoryInfo.HighMemoryLoadThresholdBytes * HighPressureThreshold) { return MemoryPressure.High; } - else if (lastLoad >= threshold * MediumPressureThreshold) + else if (memoryInfo.MemoryLoadBytes >= memoryInfo.HighMemoryLoadThresholdBytes * MediumPressureThreshold) { return MemoryPressure.Medium; } diff --git a/src/System.Private.CoreLib/shared/System/Delegate.cs b/src/System.Private.CoreLib/shared/System/Delegate.cs index 1e8b8c967a..0c60ba5c40 100644 --- a/src/System.Private.CoreLib/shared/System/Delegate.cs +++ b/src/System.Private.CoreLib/shared/System/Delegate.cs @@ -11,10 +11,6 @@ namespace System { public abstract partial class Delegate : ICloneable, ISerializable { - private Delegate() - { - } - public virtual object Clone() => MemberwiseClone(); public static Delegate? Combine(Delegate? a, Delegate? b) @@ -37,8 +33,6 @@ namespace System return d; } - protected virtual Delegate CombineImpl(Delegate? d) => throw new MulticastNotSupportedException(SR.Multicast_Combine); - // V2 api: Creates open or closed delegates to static or instance methods - relaxed signature checking allowed. public static Delegate CreateDelegate(Type type, object? firstArgument, MethodInfo method) => CreateDelegate(type, firstArgument, method, throwOnBindFailure: true)!; @@ -53,19 +47,23 @@ namespace System public static Delegate CreateDelegate(Type type, Type target, string method) => CreateDelegate(type, target, method, ignoreCase: false, throwOnBindFailure: true)!; public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase) => CreateDelegate(type, target, method, ignoreCase, throwOnBindFailure: true)!; +#if !CORERT + protected virtual Delegate CombineImpl(Delegate? d) => throw new MulticastNotSupportedException(SR.Multicast_Combine); + + protected virtual Delegate? RemoveImpl(Delegate d) => d.Equals(this) ? null : this; + + public virtual Delegate[] GetInvocationList() => new Delegate[] { this }; + public object? DynamicInvoke(params object?[]? args) { return DynamicInvokeImpl(args); } - - public virtual Delegate[] GetInvocationList() => new Delegate[] { this }; +#endif public virtual void GetObjectData(SerializationInfo info, StreamingContext context) => throw new PlatformNotSupportedException(); public MethodInfo Method => GetMethodImpl(); - protected virtual Delegate? RemoveImpl(Delegate d) => d.Equals(this) ? null : this; - public static Delegate? Remove(Delegate? source, Delegate? value) { if (source == null) diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterGroup.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterGroup.cs index 010cbd508f..0382556f3b 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterGroup.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterGroup.cs @@ -20,22 +20,22 @@ namespace System.Diagnostics.Tracing internal class CounterGroup { private readonly EventSource _eventSource; - private readonly List<BaseCounter> _counters; + private readonly List<DiagnosticCounter> _counters; internal CounterGroup(EventSource eventSource) { _eventSource = eventSource; - _counters = new List<BaseCounter>(); + _counters = new List<DiagnosticCounter>(); RegisterCommandCallback(); } - internal void Add(BaseCounter eventCounter) + internal void Add(DiagnosticCounter eventCounter) { lock (this) // Lock the CounterGroup _counters.Add(eventCounter); } - internal void Remove(BaseCounter eventCounter) + internal void Remove(DiagnosticCounter eventCounter) { lock (this) // Lock the CounterGroup _counters.Remove(eventCounter); diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterPayload.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterPayload.cs index ae4a1a7280..1be7d5494a 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterPayload.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterPayload.cs @@ -17,52 +17,6 @@ namespace Microsoft.Diagnostics.Tracing namespace System.Diagnostics.Tracing #endif { - // TODO: This should be removed as we make the new payloads public - [EventData] - internal class EventCounterPayload : IEnumerable<KeyValuePair<string, object>> - { - public string Name { get; set; } - - public float Mean { get; set; } - - public float StandardDeviation { get; set; } - - public int Count { get; set; } - - public float Min { get; set; } - - public float Max { get; set; } - - public float IntervalSec { get; internal set; } - - #region Implementation of the IEnumerable interface - - public IEnumerator<KeyValuePair<string, object>> GetEnumerator() - { - return ForEnumeration.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return ForEnumeration.GetEnumerator(); - } - - private IEnumerable<KeyValuePair<string, object>> ForEnumeration - { - get - { - yield return new KeyValuePair<string, object>("Name", Name); - yield return new KeyValuePair<string, object>("Mean", Mean); - yield return new KeyValuePair<string, object>("StandardDeviation", StandardDeviation); - yield return new KeyValuePair<string, object>("Count", Count); - yield return new KeyValuePair<string, object>("Min", Min); - yield return new KeyValuePair<string, object>("Max", Max); - } - } - - #endregion // Implementation of the IEnumerable interface - } - [EventData] internal class CounterPayload : IEnumerable<KeyValuePair<string, object>> { @@ -70,19 +24,19 @@ namespace System.Diagnostics.Tracing public string DisplayName { get; set; } - public float Mean { get; set; } + public double Mean { get; set; } - public float StandardDeviation { get; set; } + public double StandardDeviation { get; set; } public int Count { get; set; } - public float Min { get; set; } + public double Min { get; set; } - public float Max { get; set; } + public double Max { get; set; } public float IntervalSec { get; internal set; } - public string MetaData { get; set; } + public string Metadata { get; set; } #region Implementation of the IEnumerable interface @@ -110,7 +64,7 @@ namespace System.Diagnostics.Tracing yield return new KeyValuePair<string, object>("IntervalSec", IntervalSec); yield return new KeyValuePair<string, object>("Series", $"Interval={IntervalSec}"); yield return new KeyValuePair<string, object>("CounterType", "Mean"); - yield return new KeyValuePair<string, object>("MetaData", MetaData); + yield return new KeyValuePair<string, object>("Metadata", Metadata); } } @@ -126,11 +80,11 @@ namespace System.Diagnostics.Tracing public string DisplayRateTimeScale { get; set; } - public float Increment { get; set; } + public double Increment { get; set; } public float IntervalSec { get; internal set; } - public string MetaData { get; set; } + public string Metadata { get; set; } #region Implementation of the IEnumerable interface @@ -155,7 +109,7 @@ namespace System.Diagnostics.Tracing yield return new KeyValuePair<string, object>("IntervalSec", IntervalSec); yield return new KeyValuePair<string, object>("Series", $"Interval={IntervalSec}"); yield return new KeyValuePair<string, object>("CounterType", "Sum"); - yield return new KeyValuePair<string, object>("MetaData", MetaData); + yield return new KeyValuePair<string, object>("Metadata", Metadata); } } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/BaseCounter.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/DiagnosticCounter.cs index 447852e84a..ea4cb92612 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/BaseCounter.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/DiagnosticCounter.cs @@ -19,10 +19,10 @@ namespace System.Diagnostics.Tracing #endif { /// <summary> - /// BaseCounter is an abstract class that serves as the parent class for various Counter* classes, + /// DiagnosticCounter is an abstract class that serves as the parent class for various Counter* classes, /// namely EventCounter, PollingCounter, IncrementingEventCounter, and IncrementingPollingCounter. /// </summary> - public abstract class BaseCounter : IDisposable + public abstract class DiagnosticCounter : IDisposable { /// <summary> /// All Counters live as long as the EventSource that they are attached to unless they are @@ -30,23 +30,22 @@ namespace System.Diagnostics.Tracing /// </summary> /// <param name="name">The name.</param> /// <param name="eventSource">The event source.</param> - public BaseCounter(string name, EventSource eventSource) + public DiagnosticCounter(string name, EventSource eventSource) { if (name == null) { - throw new ArgumentNullException(nameof(_name)); + throw new ArgumentNullException(nameof(Name)); } if (eventSource == null) { - throw new ArgumentNullException(nameof(eventSource)); + throw new ArgumentNullException(nameof(EventSource)); } _group = CounterGroup.GetCounterGroup(eventSource); _group.Add(this); - _eventSource = eventSource; - _name = name; - _metaData = new Dictionary<string, string>(); + Name = name; + EventSource = eventSource; } /// <summary> @@ -67,38 +66,45 @@ namespace System.Diagnostics.Tracing /// <summary> /// Adds a key-value metadata to the EventCounter that will be included as a part of the payload /// </summary> - internal void AddMetaData(string key, string value) + public void AddMetadata(string key, string value) { lock (MyLock) { - _metaData.Add(key, value); + _metadata = _metadata ?? new Dictionary<string, string>(); + _metadata.Add(key, value); } } - internal string DisplayName { get; set; } + public string DisplayName { get; set; } - #region private implementation + public string Name { get; } + + public EventSource EventSource { get; } - internal readonly string _name; + #region private implementation private CounterGroup _group; - private Dictionary<string, string> _metaData; - internal EventSource _eventSource; + private Dictionary<string, string> _metadata; internal abstract void WritePayload(float intervalSec); // arbitrarily we use name as the lock object. - internal object MyLock { get { return _name; } } + internal object MyLock { get { return Name; } } internal void ReportOutOfBandMessage(string message) { - _eventSource.ReportOutOfBandMessage(message, true); + EventSource.ReportOutOfBandMessage(message, true); } - internal string GetMetaDataString() + internal string GetMetadataString() { + if (_metadata == null) + { + return ""; + } + StringBuilder sb = new StringBuilder(""); - foreach(KeyValuePair<string, string> kvPair in _metaData) + foreach(KeyValuePair<string, string> kvPair in _metadata) { sb.Append($"{kvPair.Key}:{kvPair.Value},"); } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventCounter.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventCounter.cs index 85fc40a08c..a9fc0895c9 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventCounter.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventCounter.cs @@ -26,7 +26,7 @@ namespace System.Diagnostics.Tracing /// See https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestEventCounter.cs /// which shows tests, which are also useful in seeing actual use. /// </summary> - public partial class EventCounter : BaseCounter + public partial class EventCounter : DiagnosticCounter { /// <summary> /// Initializes a new instance of the <see cref="EventCounter"/> class. @@ -37,8 +37,8 @@ namespace System.Diagnostics.Tracing /// <param name="eventSource">The event source.</param> public EventCounter(string name, EventSource eventSource) : base(name, eventSource) { - _min = float.PositiveInfinity; - _max = float.NegativeInfinity; + _min = double.PositiveInfinity; + _max = double.NegativeInfinity; InitializeBuffer(); } @@ -50,21 +50,26 @@ namespace System.Diagnostics.Tracing /// <param name="value">The value.</param> public void WriteMetric(float value) { + Enqueue((double)value); + } + + public void WriteMetric(double value) + { Enqueue(value); } - public override string ToString() => $"EventCounter '{_name}' Count {_count} Mean {(((double)_sum) / _count).ToString("n3")}"; + public override string ToString() => $"EventCounter '{Name}' Count {_count} Mean {(_sum / _count).ToString("n3")}"; #region Statistics Calculation // Statistics private int _count; - private float _sum; - private float _sumSquared; - private float _min; - private float _max; + private double _sum; + private double _sumSquared; + private double _min; + private double _max; - internal void OnMetricWritten(float value) + internal void OnMetricWritten(double value) { Debug.Assert(Monitor.IsEntered(MyLock)); _sum += value; @@ -83,14 +88,13 @@ namespace System.Diagnostics.Tracing lock (MyLock) { Flush(); - EventCounterPayload payload = new EventCounterPayload(); - payload.Name = _name; + CounterPayload payload = new CounterPayload(); payload.Count = _count; payload.IntervalSec = intervalSec; if (0 < _count) { payload.Mean = _sum / _count; - payload.StandardDeviation = (float)Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count); + payload.StandardDeviation = Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count); } else { @@ -99,8 +103,12 @@ namespace System.Diagnostics.Tracing } payload.Min = _min; payload.Max = _max; + + payload.Metadata = GetMetadataString(); + payload.DisplayName = DisplayName; + payload.Name = Name; ResetStatistics(); - _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new EventCounterPayloadType(payload)); + EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new CounterPayloadType(payload)); } } private void ResetStatistics() @@ -109,35 +117,35 @@ namespace System.Diagnostics.Tracing _count = 0; _sum = 0; _sumSquared = 0; - _min = float.PositiveInfinity; - _max = float.NegativeInfinity; + _min = double.PositiveInfinity; + _max = double.NegativeInfinity; } #endregion // Statistics Calculation // Values buffering private const int BufferedSize = 10; - private const float UnusedBufferSlotValue = float.NegativeInfinity; + private const double UnusedBufferSlotValue = double.NegativeInfinity; private const int UnsetIndex = -1; - private volatile float[] _bufferedValues; + private volatile double[] _bufferedValues; private volatile int _bufferedValuesIndex; private void InitializeBuffer() { - _bufferedValues = new float[BufferedSize]; + _bufferedValues = new double[BufferedSize]; for (int i = 0; i < _bufferedValues.Length; i++) { _bufferedValues[i] = UnusedBufferSlotValue; } } - protected void Enqueue(float value) + private void Enqueue(double value) { // It is possible that two threads read the same bufferedValuesIndex, but only one will be able to write the slot, so that is okay. int i = _bufferedValuesIndex; while (true) { - float result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue); + double result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue); i++; if (_bufferedValues.Length <= i) { @@ -178,10 +186,10 @@ namespace System.Diagnostics.Tracing /// This is the payload that is sent in the with EventSource.Write /// </summary> [EventData] - class EventCounterPayloadType + class CounterPayloadType { - public EventCounterPayloadType(EventCounterPayload payload) { Payload = payload; } - public EventCounterPayload Payload { get; set; } + public CounterPayloadType(CounterPayload payload) { Payload = payload; } + public CounterPayload Payload { get; set; } } } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSourceException.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSourceException.cs index 2e821ac10d..f5f9ba13b1 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSourceException.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSourceException.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. #nullable enable +using System; using System.Runtime.Serialization; #if ES_BUILD_STANDALONE diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingEventCounter.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingEventCounter.cs index 569c9a0113..40581051cc 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingEventCounter.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingEventCounter.cs @@ -23,7 +23,7 @@ namespace System.Diagnostics.Tracing /// It does not calculate statistics like mean, standard deviation, etc. because it only accumulates /// the counter value. /// </summary> - internal partial class IncrementingEventCounter : BaseCounter + public partial class IncrementingEventCounter : DiagnosticCounter { /// <summary> /// Initializes a new instance of the <see cref="IncrementingEventCounter"/> class. @@ -41,7 +41,7 @@ namespace System.Diagnostics.Tracing /// be logged on the next timer interval. /// </summary> /// <param name="increment">The value to increment by.</param> - public void Increment(float increment = 1) + public void Increment(double increment = 1) { lock(MyLock) { @@ -49,25 +49,25 @@ namespace System.Diagnostics.Tracing } } - internal TimeSpan DisplayRateTimeScale { get; set; } - private float _increment; - private float _prevIncrement; + public TimeSpan DisplayRateTimeScale { get; set; } + private double _increment; + private double _prevIncrement; - public override string ToString() => $"IncrementingEventCounter '{_name}' Increment {_increment}"; + public override string ToString() => $"IncrementingEventCounter '{Name}' Increment {_increment}"; internal override void WritePayload(float intervalSec) { lock (MyLock) // Lock the counter { IncrementingCounterPayload payload = new IncrementingCounterPayload(); - payload.Name = _name; + payload.Name = Name; payload.IntervalSec = intervalSec; payload.DisplayName = DisplayName ?? ""; payload.DisplayRateTimeScale = (DisplayRateTimeScale == TimeSpan.Zero) ? "" : DisplayRateTimeScale.ToString("c"); - payload.MetaData = GetMetaDataString(); + payload.Metadata = GetMetadataString(); payload.Increment = _increment - _prevIncrement; _prevIncrement = _increment; - _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingEventCounterPayloadType(payload)); + EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingEventCounterPayloadType(payload)); } } } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingPollingCounter.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingPollingCounter.cs index 8bad728a18..1b8ee7553e 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingPollingCounter.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingPollingCounter.cs @@ -25,7 +25,7 @@ namespace System.Diagnostics.Tracing /// Unlike IncrementingEventCounter, this takes in a polling callback that it can call to update /// its own metric periodically. /// </summary> - internal partial class IncrementingPollingCounter : BaseCounter + public partial class IncrementingPollingCounter : DiagnosticCounter { /// <summary> /// Initializes a new instance of the <see cref="IncrementingPollingCounter"/> class. @@ -34,20 +34,20 @@ namespace System.Diagnostics.Tracing /// </summary> /// <param name="name">The name.</param> /// <param name="eventSource">The event source.</param> - public IncrementingPollingCounter(string name, EventSource eventSource, Func<float> getCountFunction) : base(name, eventSource) + public IncrementingPollingCounter(string name, EventSource eventSource, Func<double> totalValueProvider) : base(name, eventSource) { - _getCountFunction = getCountFunction; + _totalValueProvider = totalValueProvider; } - public override string ToString() => $"IncrementingPollingCounter '{_name}' Increment {_increment}"; + public override string ToString() => $"IncrementingPollingCounter '{Name}' Increment {_increment}"; - internal TimeSpan DisplayRateTimeScale { get; set; } - private float _increment; - private float _prevIncrement; - private Func<float> _getCountFunction; + public TimeSpan DisplayRateTimeScale { get; set; } + private double _increment; + private double _prevIncrement; + private Func<double> _totalValueProvider; /// <summary> - /// Calls "_getCountFunction" to enqueue the counter value to the queue. + /// Calls "_totalValueProvider" to enqueue the counter value to the queue. /// </summary> private void UpdateMetric() { @@ -55,12 +55,12 @@ namespace System.Diagnostics.Tracing { lock(MyLock) { - _increment = _getCountFunction(); + _increment = _totalValueProvider(); } } catch (Exception ex) { - ReportOutOfBandMessage($"ERROR: Exception during EventCounter {_name} getMetricFunction callback: " + ex.Message); + ReportOutOfBandMessage($"ERROR: Exception during EventCounter {Name} getMetricFunction callback: " + ex.Message); } } @@ -70,14 +70,14 @@ namespace System.Diagnostics.Tracing lock (MyLock) // Lock the counter { IncrementingCounterPayload payload = new IncrementingCounterPayload(); - payload.Name = _name; + payload.Name = Name; payload.DisplayName = DisplayName ?? ""; payload.DisplayRateTimeScale = (DisplayRateTimeScale == TimeSpan.Zero) ? "" : DisplayRateTimeScale.ToString("c"); payload.IntervalSec = intervalSec; - payload.MetaData = GetMetaDataString(); + payload.Metadata = GetMetadataString(); payload.Increment = _increment - _prevIncrement; _prevIncrement = _increment; - _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingPollingCounterPayloadType(payload)); + EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingPollingCounterPayloadType(payload)); } } } diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/PollingCounter.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/PollingCounter.cs index 695b357f45..e0577181fa 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/PollingCounter.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/PollingCounter.cs @@ -23,7 +23,7 @@ namespace System.Diagnostics.Tracing /// function to collect metrics on its own rather than the user having to call WriteMetric() /// every time. /// </summary> - internal partial class PollingCounter : BaseCounter + public partial class PollingCounter : DiagnosticCounter { /// <summary> /// Initializes a new instance of the <see cref="PollingCounter"/> class. @@ -32,41 +32,42 @@ namespace System.Diagnostics.Tracing /// </summary> /// <param name="name">The name.</param> /// <param name="eventSource">The event source.</param> - public PollingCounter(string name, EventSource eventSource, Func<float> getMetricFunction) : base(name, eventSource) + public PollingCounter(string name, EventSource eventSource, Func<double> metricProvider) : base(name, eventSource) { - _getMetricFunction = getMetricFunction; + _metricProvider = metricProvider; } - public override string ToString() => $"PollingCounter '{_name}' Count {1} Mean {_lastVal.ToString("n3")}"; + public override string ToString() => $"PollingCounter '{Name}' Count {1} Mean {_lastVal.ToString("n3")}"; - private Func<float> _getMetricFunction; - private float _lastVal; + private Func<double> _metricProvider; + private double _lastVal; internal override void WritePayload(float intervalSec) { lock (MyLock) { - float value = 0; + double value = 0; try { - value = _getMetricFunction(); + value = _metricProvider(); } catch (Exception ex) { - ReportOutOfBandMessage($"ERROR: Exception during EventCounter {_name} getMetricFunction callback: " + ex.Message); + ReportOutOfBandMessage($"ERROR: Exception during EventCounter {Name} metricProvider callback: " + ex.Message); } CounterPayload payload = new CounterPayload(); - payload.Name = _name; + payload.Name = Name; payload.DisplayName = DisplayName ?? ""; payload.Count = 1; // NOTE: These dumb-looking statistics is intentional payload.IntervalSec = intervalSec; payload.Mean = value; payload.Max = value; payload.Min = value; + payload.Metadata = GetMetadataString(); payload.StandardDeviation = 0; _lastVal = value; - _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new PollingPayloadType(payload)); + EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new PollingPayloadType(payload)); } } } diff --git a/src/System.Private.CoreLib/shared/System/Environment.Win32.cs b/src/System.Private.CoreLib/shared/System/Environment.Win32.cs index f7b87ff786..90e1ca92a6 100644 --- a/src/System.Private.CoreLib/shared/System/Environment.Win32.cs +++ b/src/System.Private.CoreLib/shared/System/Environment.Win32.cs @@ -14,6 +14,8 @@ namespace System { public static partial class Environment { + internal static bool IsWindows8OrAbove => WindowsVersion.IsWindows8OrAbove; + private static string GetEnvironmentVariableFromRegistry(string variable, bool fromMachine) { Debug.Assert(variable != null); @@ -418,5 +420,35 @@ namespace System } } #endif + + // Seperate type so a .cctor is not created for Enviroment which then would be triggered during startup + private static class WindowsVersion + { + // Cache the value in readonly static that can be optimized out by the JIT + internal readonly static bool IsWindows8OrAbove = GetIsWindows8OrAbove(); + + private static bool GetIsWindows8OrAbove() + { + ulong conditionMask = Interop.Kernel32.VerSetConditionMask(0, Interop.Kernel32.VER_MAJORVERSION, Interop.Kernel32.VER_GREATER_EQUAL); + conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_MINORVERSION, Interop.Kernel32.VER_GREATER_EQUAL); + conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_SERVICEPACKMAJOR, Interop.Kernel32.VER_GREATER_EQUAL); + conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_SERVICEPACKMINOR, Interop.Kernel32.VER_GREATER_EQUAL); + + // Windows 8 version is 6.2 + Interop.Kernel32.OSVERSIONINFOEX version = default; + unsafe + { + version.dwOSVersionInfoSize = sizeof(Interop.Kernel32.OSVERSIONINFOEX); + } + version.dwMajorVersion = 6; + version.dwMinorVersion = 2; + version.wServicePackMajor = 0; + version.wServicePackMinor = 0; + + return Interop.Kernel32.VerifyVersionInfoW(ref version, + Interop.Kernel32.VER_MAJORVERSION | Interop.Kernel32.VER_MINORVERSION | Interop.Kernel32.VER_SERVICEPACKMAJOR | Interop.Kernel32.VER_SERVICEPACKMINOR, + conditionMask); + } + } } } diff --git a/src/System.Private.CoreLib/shared/System/Environment.WinRT.cs b/src/System.Private.CoreLib/shared/System/Environment.WinRT.cs index a8e3dbced8..27e0fc2431 100644 --- a/src/System.Private.CoreLib/shared/System/Environment.WinRT.cs +++ b/src/System.Private.CoreLib/shared/System/Environment.WinRT.cs @@ -13,6 +13,8 @@ namespace System public static string UserDomainName => "Windows Domain"; + internal static readonly bool IsWindows8OrAbove = true; + private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOption option) { WinRTInteropCallbacks callbacks = WinRTInterop.UnsafeCallbacks; diff --git a/src/System.Private.CoreLib/shared/System/Range.cs b/src/System.Private.CoreLib/shared/System/Range.cs index 0098dea17f..fc5ec52423 100644 --- a/src/System.Private.CoreLib/shared/System/Range.cs +++ b/src/System.Private.CoreLib/shared/System/Range.cs @@ -95,15 +95,15 @@ namespace System /// <summary>Create a Range object starting from first element to the end.</summary> public static Range All => new Range(Index.Start, Index.End); - /// <summary>Destruct the range object according to a collection length and return the start offset from the beginning and the length of this range.</summary> - /// <param name="length">The length of the collection that the range will be used with. length has to be a positive value</param> + /// <summary>Calculate the start offset and length of range object using a collection length.</summary> + /// <param name="length">The length of the collection that the range will be used with. length has to be a positive value.</param> /// <remarks> /// For performance reason, we don't validate the input length parameter against negative values. /// It is expected Range will be used with collections which always have non negative length/count. /// We validate the range is inside the length scope though. /// </remarks> [MethodImpl(MethodImplOptions.AggressiveInlining)] - public OffsetAndLength GetOffsetAndLength(int length) + public (int Offset, int Length) GetOffsetAndLength(int length) { int start; Index startIndex = Start; @@ -124,25 +124,7 @@ namespace System ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length); } - return new OffsetAndLength(start, end - start); - } - - public readonly struct OffsetAndLength - { - public int Offset { get; } - public int Length { get; } - - public OffsetAndLength(int offset, int length) - { - Offset = offset; - Length = length; - } - - public void Deconstruct(out int offset, out int length) - { - offset = Offset; - length = Length; - } + return (start, end - start); } } } diff --git a/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyName.cs index e804799035..89a6217d7c 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs +++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyName.cs @@ -4,14 +4,13 @@ using System.Configuration.Assemblies; using System.IO; -using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Text; using CultureInfo = System.Globalization.CultureInfo; namespace System.Reflection { - public sealed class AssemblyName : ICloneable, IDeserializationCallback, ISerializable + public sealed partial class AssemblyName : ICloneable, IDeserializationCallback, ISerializable { // If you modify any of these fields, you must also update the // AssemblyBaseObject structure in object.h @@ -38,18 +37,6 @@ namespace System.Reflection _flags = AssemblyNameFlags.None; } - public AssemblyName(string assemblyName) - { - if (assemblyName == null) - throw new ArgumentNullException(nameof(assemblyName)); - if ((assemblyName.Length == 0) || - (assemblyName[0] == '\0')) - throw new ArgumentException(SR.Format_StringZeroLength); - - _name = assemblyName; - nInit(); - } - // Set and get the name of the assembly. If this is a weak Name // then it optionally contains a site. For strong assembly names, // the name partitions up the strong name's namespace @@ -144,19 +131,20 @@ namespace System.Reflection // Make a copy of this assembly name. public object Clone() { - AssemblyName name = new AssemblyName(); - name.Init(_name, - _publicKey, - _publicKeyToken, - _version, - _cultureInfo, - _hashAlgorithm, - _versionCompatibility, - _codeBase, - _flags, - _strongNameKeyPair); - name._hashForControl = _hashForControl; - name._hashAlgorithmForControl = _hashAlgorithmForControl; + var name = new AssemblyName + { + _name = _name, + _publicKey = (byte[])_publicKey?.Clone(), + _publicKeyToken = (byte[])_publicKeyToken?.Clone(), + _cultureInfo = _cultureInfo, + _version = (Version)_version?.Clone(), + _flags = _flags, + _codeBase = _codeBase, + _hashAlgorithm = _hashAlgorithm, + _versionCompatibility = _versionCompatibility, + _hashForControl = _hashForControl, + _hashAlgorithmForControl = _hashAlgorithmForControl + }; return name; } @@ -170,16 +158,9 @@ namespace System.Reflection if (assemblyFile == null) throw new ArgumentNullException(nameof(assemblyFile)); - // Assembly.GetNameInternal() will not demand path discovery - // permission, so do that first. - string fullPath = Path.GetFullPath(assemblyFile); - return nGetFileInformation(fullPath); + return GetFileInformationCore(assemblyFile); } - // The public key that is used to verify an assemblies - // inclusion into the namespace. If the public key associated - // with the namespace cannot verify the assembly the assembly - // will fail to load. public byte[] GetPublicKey() { return _publicKey; @@ -200,7 +181,7 @@ namespace System.Reflection public byte[] GetPublicKeyToken() { if (_publicKeyToken == null) - _publicKeyToken = nGetPublicKeyToken(); + _publicKeyToken = ComputePublicKeyToken(); return _publicKeyToken; } @@ -251,7 +232,7 @@ namespace System.Reflection if (this.Name == null) return string.Empty; // Do not call GetPublicKeyToken() here - that latches the result into AssemblyName which isn't a side effect we want. - byte[] pkt = _publicKeyToken ?? nGetPublicKeyToken(); + byte[] pkt = _publicKeyToken ?? ComputePublicKeyToken(); return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, Flags, ContentType); } } @@ -296,103 +277,6 @@ namespace System.Reflection return refName.Equals(defName, StringComparison.OrdinalIgnoreCase); } - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern void nInit(out RuntimeAssembly assembly, bool raiseResolveEvent); - - internal void nInit() - { - RuntimeAssembly dummy = null; - nInit(out dummy, false); - } - - internal void SetProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm) - { - ProcessorArchitecture = CalculateProcArchIndex(pek, ifm, _flags); - } - - internal static ProcessorArchitecture CalculateProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm, AssemblyNameFlags flags) - { - if (((uint)flags & 0xF0) == 0x70) - return ProcessorArchitecture.None; - - if ((pek & System.Reflection.PortableExecutableKinds.PE32Plus) == System.Reflection.PortableExecutableKinds.PE32Plus) - { - switch (ifm) - { - case System.Reflection.ImageFileMachine.IA64: - return ProcessorArchitecture.IA64; - case System.Reflection.ImageFileMachine.AMD64: - return ProcessorArchitecture.Amd64; - case System.Reflection.ImageFileMachine.I386: - if ((pek & System.Reflection.PortableExecutableKinds.ILOnly) == System.Reflection.PortableExecutableKinds.ILOnly) - return ProcessorArchitecture.MSIL; - break; - } - } - else - { - if (ifm == System.Reflection.ImageFileMachine.I386) - { - if ((pek & System.Reflection.PortableExecutableKinds.Required32Bit) == System.Reflection.PortableExecutableKinds.Required32Bit) - return ProcessorArchitecture.X86; - - if ((pek & System.Reflection.PortableExecutableKinds.ILOnly) == System.Reflection.PortableExecutableKinds.ILOnly) - return ProcessorArchitecture.MSIL; - - return ProcessorArchitecture.X86; - } - if (ifm == System.Reflection.ImageFileMachine.ARM) - { - return ProcessorArchitecture.Arm; - } - } - return ProcessorArchitecture.None; - } - - internal void Init(string name, - byte[] publicKey, - byte[] publicKeyToken, - Version version, - CultureInfo cultureInfo, - AssemblyHashAlgorithm hashAlgorithm, - AssemblyVersionCompatibility versionCompatibility, - string codeBase, - AssemblyNameFlags flags, - StrongNameKeyPair keyPair) // Null if ref, matching Assembly if def - { - _name = name; - - if (publicKey != null) - { - _publicKey = new byte[publicKey.Length]; - Array.Copy(publicKey, 0, _publicKey, 0, publicKey.Length); - } - - if (publicKeyToken != null) - { - _publicKeyToken = new byte[publicKeyToken.Length]; - Array.Copy(publicKeyToken, 0, _publicKeyToken, 0, publicKeyToken.Length); - } - - if (version != null) - _version = (Version)version.Clone(); - - _cultureInfo = cultureInfo; - _hashAlgorithm = hashAlgorithm; - _versionCompatibility = versionCompatibility; - _codeBase = codeBase; - _flags = flags; - _strongNameKeyPair = keyPair; - } - - // This call opens and closes the file, but does not add the - // assembly to the domain. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern AssemblyName nGetFileInformation(string s); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern byte[] nGetPublicKeyToken(); - internal static string EscapeCodeBase(string codebase) { if (codebase == null) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeHelpers.cs index 8dea0ae1d4..6925d97b9b 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeHelpers.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -23,29 +23,29 @@ namespace System.Runtime.CompilerServices ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - Range.OffsetAndLength offLen = range.GetOffsetAndLength(array.Length); + (int offset, int length) = range.GetOffsetAndLength(array.Length); if (default(T) != null || typeof(T[]) == array.GetType()) { // We know the type of the array to be exactly T[]. - if (offLen.Length == 0) + if (length == 0) { return Array.Empty<T>(); } - var dest = new T[offLen.Length]; + var dest = new T[length]; Buffer.Memmove( ref Unsafe.As<byte, T>(ref dest.GetRawSzArrayData()), - ref Unsafe.Add(ref Unsafe.As<byte, T>(ref array.GetRawSzArrayData()), offLen.Offset), - (uint)offLen.Length); + ref Unsafe.Add(ref Unsafe.As<byte, T>(ref array.GetRawSzArrayData()), offset), + (uint)length); return dest; } else { // The array is actually a U[] where U:T. - T[] dest = (T[])Array.CreateInstance(array.GetType().GetElementType(), offLen.Length); - Array.Copy(array, offLen.Offset, dest, 0, offLen.Length); + T[] dest = (T[])Array.CreateInstance(array.GetType().GetElementType(), length); + Array.Copy(array, offset, dest, 0, length); return dest; } } @@ -56,7 +56,7 @@ namespace System.Runtime.CompilerServices { throw new ArgumentNullException(nameof(type), SR.ArgumentNull_Type); } - + if (!type.IsRuntimeImplemented()) { throw new SerializationException(SR.Format(SR.Serialization_InvalidType, type.ToString())); diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs index 903d2cd941..e0ab5c28bf 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs @@ -105,13 +105,13 @@ namespace System.Runtime.Intrinsics { if (typeof(T) == typeof(float)) { - Vector256<float> result = Avx.Compare(this.AsSingle(), other.AsSingle(), FloatComparisonMode.EqualOrderedNonSignaling); + Vector256<float> result = Avx.Compare(this.AsSingle(), other.AsSingle(), FloatComparisonMode.OrderedEqualNonSignaling); return Avx.MoveMask(result) == 0b1111_1111; // We have one bit per element } if (typeof(T) == typeof(double)) { - Vector256<double> result = Avx.Compare(this.AsDouble(), other.AsDouble(), FloatComparisonMode.EqualOrderedNonSignaling); + Vector256<double> result = Avx.Compare(this.AsDouble(), other.AsDouble(), FloatComparisonMode.OrderedEqualNonSignaling); return Avx.MoveMask(result) == 0b1111; // We have one bit per element } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs index 6a7ca3c52a..4ed32660ce 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs @@ -674,64 +674,131 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// __m256i _mm256_cvtepi8_epi16 (__m128i a) - /// VPMOVSXBW ymm, xmm/m128 + /// VPMOVSXBW ymm, xmm /// </summary> public static Vector256<short> ConvertToVector256Int16(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m256i _mm256_cvtepu8_epi16 (__m128i a) - /// VPMOVZXBW ymm, xmm/m128 + /// VPMOVZXBW ymm, xmm /// </summary> public static Vector256<ushort> ConvertToVector256UInt16(Vector128<byte> value) { throw new PlatformNotSupportedException(); } + public static Vector256<short> ConvertToVector256Int16(Vector128<byte> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m256i _mm256_cvtepi8_epi32 (__m128i a) - /// VPMOVSXBD ymm, xmm/m128 + /// VPMOVSXBD ymm, xmm /// </summary> public static Vector256<int> ConvertToVector256Int32(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); } /// <summary> - /// __m256i _mm256_cvtepi16_epi32 (__m128i a) - /// VPMOVSXWD ymm, xmm/m128 - /// </summary> - public static Vector256<int> ConvertToVector256Int32(Vector128<short> value) { throw new PlatformNotSupportedException(); } - /// <summary> /// __m256i _mm256_cvtepu8_epi32 (__m128i a) - /// VPMOVZXBD ymm, xmm/m128 + /// VPMOVZXBD ymm, xmm /// </summary> public static Vector256<uint> ConvertToVector256UInt32(Vector128<byte> value) { throw new PlatformNotSupportedException(); } + public static Vector256<int> ConvertToVector256Int32(Vector128<byte> value) { throw new PlatformNotSupportedException(); } + /// <summary> + /// __m256i _mm256_cvtepi16_epi32 (__m128i a) + /// VPMOVSXWD ymm, xmm + /// </summary> + public static Vector256<int> ConvertToVector256Int32(Vector128<short> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m256i _mm256_cvtepu16_epi32 (__m128i a) - /// VPMOVZXWD ymm, xmm/m128 + /// VPMOVZXWD ymm, xmm /// </summary> public static Vector256<uint> ConvertToVector256UInt32(Vector128<ushort> value) { throw new PlatformNotSupportedException(); } + public static Vector256<int> ConvertToVector256Int32(Vector128<ushort> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m256i _mm256_cvtepi8_epi64 (__m128i a) - /// VPMOVSXBQ ymm, xmm/m128 + /// VPMOVSXBQ ymm, xmm /// </summary> public static Vector256<long> ConvertToVector256Int64(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); } /// <summary> + /// __m256i _mm256_cvtepu8_epi64 (__m128i a) + /// VPMOVZXBQ ymm, xmm + /// </summary> + public static Vector256<ulong> ConvertToVector256UInt64(Vector128<byte> value) { throw new PlatformNotSupportedException(); } + public static Vector256<long> ConvertToVector256Int64(Vector128<byte> value) { throw new PlatformNotSupportedException(); } + /// <summary> /// __m256i _mm256_cvtepi16_epi64 (__m128i a) - /// VPMOVSXWQ ymm, xmm/m128 + /// VPMOVSXWQ ymm, xmm /// </summary> public static Vector256<long> ConvertToVector256Int64(Vector128<short> value) { throw new PlatformNotSupportedException(); } /// <summary> + /// __m256i _mm256_cvtepu16_epi64 (__m128i a) + /// VPMOVZXWQ ymm, xmm + /// </summary> + public static Vector256<ulong> ConvertToVector256UInt64(Vector128<ushort> value) { throw new PlatformNotSupportedException(); } + public static Vector256<long> ConvertToVector256Int64(Vector128<ushort> value) { throw new PlatformNotSupportedException(); } + /// <summary> /// __m256i _mm256_cvtepi32_epi64 (__m128i a) - /// VPMOVSXDQ ymm, xmm/m128 + /// VPMOVSXDQ ymm, xmm /// </summary> public static Vector256<long> ConvertToVector256Int64(Vector128<int> value) { throw new PlatformNotSupportedException(); } /// <summary> - /// __m256i _mm256_cvtepu8_epi64 (__m128i a) - /// VPMOVZXBQ ymm, xmm/m128 + /// __m256i _mm256_cvtepu32_epi64 (__m128i a) + /// VPMOVZXDQ ymm, xmm /// </summary> - public static Vector256<ulong> ConvertToVector256UInt64(Vector128<byte> value) { throw new PlatformNotSupportedException(); } + public static Vector256<ulong> ConvertToVector256UInt64(Vector128<uint> value) { throw new PlatformNotSupportedException(); } + public static Vector256<long> ConvertToVector256Int64(Vector128<uint> value) { throw new PlatformNotSupportedException(); } + /// <summary> - /// __m256i _mm256_cvtepu16_epi64 (__m128i a) - /// VPMOVZXWQ ymm, xmm/m128 + /// VPMOVSXBW ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. /// </summary> - public static Vector256<ulong> ConvertToVector256UInt64(Vector128<ushort> value) { throw new PlatformNotSupportedException(); } + public static unsafe Vector256<short> ConvertToVector256Int16(sbyte* address) { throw new PlatformNotSupportedException(); } /// <summary> - /// __m256i _mm256_cvtepu32_epi64 (__m128i a) - /// VPMOVZXDQ ymm, xmm/m128 + /// VPMOVZXBW ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. /// </summary> - public static Vector256<ulong> ConvertToVector256UInt64(Vector128<uint> value) { throw new PlatformNotSupportedException(); } + public static unsafe Vector256<short> ConvertToVector256Int16(byte* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// VPMOVSXBD ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<int> ConvertToVector256Int32(sbyte* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// VPMOVZXBD ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<int> ConvertToVector256Int32(byte* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// VPMOVSXWD ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<int> ConvertToVector256Int32(short* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// VPMOVZXWD ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<int> ConvertToVector256Int32(ushort* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// VPMOVSXBQ ymm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<long> ConvertToVector256Int64(sbyte* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// VPMOVZXBQ ymm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<long> ConvertToVector256Int64(byte* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// VPMOVSXWQ ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<long> ConvertToVector256Int64(short* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// VPMOVZXWQ ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<long> ConvertToVector256Int64(ushort* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// VPMOVSXDQ ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<long> ConvertToVector256Int64(int* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// VPMOVZXDQ ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<long> ConvertToVector256Int64(uint* address) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs index 33b101b962..e2eb364b25 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs @@ -674,64 +674,131 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// __m256i _mm256_cvtepi8_epi16 (__m128i a) - /// VPMOVSXBW ymm, xmm/m128 + /// VPMOVSXBW ymm, xmm /// </summary> public static Vector256<short> ConvertToVector256Int16(Vector128<sbyte> value) => ConvertToVector256Int16(value); /// <summary> /// __m256i _mm256_cvtepu8_epi16 (__m128i a) - /// VPMOVZXBW ymm, xmm/m128 + /// VPMOVZXBW ymm, xmm /// </summary> public static Vector256<ushort> ConvertToVector256UInt16(Vector128<byte> value) => ConvertToVector256UInt16(value); + public static Vector256<short> ConvertToVector256Int16(Vector128<byte> value) => ConvertToVector256Int16(value); /// <summary> /// __m256i _mm256_cvtepi8_epi32 (__m128i a) - /// VPMOVSXBD ymm, xmm/m128 + /// VPMOVSXBD ymm, xmm /// </summary> public static Vector256<int> ConvertToVector256Int32(Vector128<sbyte> value) => ConvertToVector256Int32(value); /// <summary> - /// __m256i _mm256_cvtepi16_epi32 (__m128i a) - /// VPMOVSXWD ymm, xmm/m128 - /// </summary> - public static Vector256<int> ConvertToVector256Int32(Vector128<short> value) => ConvertToVector256Int32(value); - /// <summary> /// __m256i _mm256_cvtepu8_epi32 (__m128i a) - /// VPMOVZXBD ymm, xmm/m128 + /// VPMOVZXBD ymm, xmm /// </summary> public static Vector256<uint> ConvertToVector256UInt32(Vector128<byte> value) => ConvertToVector256UInt32(value); + public static Vector256<int> ConvertToVector256Int32(Vector128<byte> value) => ConvertToVector256Int32(value); + /// <summary> + /// __m256i _mm256_cvtepi16_epi32 (__m128i a) + /// VPMOVSXWD ymm, xmm + /// </summary> + public static Vector256<int> ConvertToVector256Int32(Vector128<short> value) => ConvertToVector256Int32(value); /// <summary> /// __m256i _mm256_cvtepu16_epi32 (__m128i a) - /// VPMOVZXWD ymm, xmm/m128 + /// VPMOVZXWD ymm, xmm /// </summary> public static Vector256<uint> ConvertToVector256UInt32(Vector128<ushort> value) => ConvertToVector256UInt32(value); + public static Vector256<int> ConvertToVector256Int32(Vector128<ushort> value) => ConvertToVector256Int32(value); /// <summary> /// __m256i _mm256_cvtepi8_epi64 (__m128i a) - /// VPMOVSXBQ ymm, xmm/m128 + /// VPMOVSXBQ ymm, xmm /// </summary> public static Vector256<long> ConvertToVector256Int64(Vector128<sbyte> value) => ConvertToVector256Int64(value); /// <summary> + /// __m256i _mm256_cvtepu8_epi64 (__m128i a) + /// VPMOVZXBQ ymm, xmm + /// </summary> + public static Vector256<ulong> ConvertToVector256UInt64(Vector128<byte> value) => ConvertToVector256UInt64(value); + public static Vector256<long> ConvertToVector256Int64(Vector128<byte> value) => ConvertToVector256Int64(value); + /// <summary> /// __m256i _mm256_cvtepi16_epi64 (__m128i a) - /// VPMOVSXWQ ymm, xmm/m128 + /// VPMOVSXWQ ymm, xmm /// </summary> public static Vector256<long> ConvertToVector256Int64(Vector128<short> value) => ConvertToVector256Int64(value); /// <summary> + /// __m256i _mm256_cvtepu16_epi64 (__m128i a) + /// VPMOVZXWQ ymm, xmm + /// </summary> + public static Vector256<ulong> ConvertToVector256UInt64(Vector128<ushort> value) => ConvertToVector256UInt64(value); + public static Vector256<long> ConvertToVector256Int64(Vector128<ushort> value) => ConvertToVector256Int64(value); + /// <summary> /// __m256i _mm256_cvtepi32_epi64 (__m128i a) - /// VPMOVSXDQ ymm, xmm/m128 + /// VPMOVSXDQ ymm, xmm /// </summary> public static Vector256<long> ConvertToVector256Int64(Vector128<int> value) => ConvertToVector256Int64(value); /// <summary> - /// __m256i _mm256_cvtepu8_epi64 (__m128i a) - /// VPMOVZXBQ ymm, xmm/m128 + /// __m256i _mm256_cvtepu32_epi64 (__m128i a) + /// VPMOVZXDQ ymm, xmm /// </summary> - public static Vector256<ulong> ConvertToVector256UInt64(Vector128<byte> value) => ConvertToVector256UInt64(value); + public static Vector256<ulong> ConvertToVector256UInt64(Vector128<uint> value) => ConvertToVector256UInt64(value); + public static Vector256<long> ConvertToVector256Int64(Vector128<uint> value) => ConvertToVector256Int64(value); + /// <summary> - /// __m256i _mm256_cvtepu16_epi64 (__m128i a) - /// VPMOVZXWQ ymm, xmm/m128 + /// VPMOVSXBW ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. /// </summary> - public static Vector256<ulong> ConvertToVector256UInt64(Vector128<ushort> value) => ConvertToVector256UInt64(value); + public static unsafe Vector256<short> ConvertToVector256Int16(sbyte* address) => ConvertToVector256Int16(address); /// <summary> - /// __m256i _mm256_cvtepu32_epi64 (__m128i a) - /// VPMOVZXDQ ymm, xmm/m128 + /// VPMOVZXBW ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. /// </summary> - public static Vector256<ulong> ConvertToVector256UInt64(Vector128<uint> value) => ConvertToVector256UInt64(value); + public static unsafe Vector256<short> ConvertToVector256Int16(byte* address) => ConvertToVector256Int16(address); + /// <summary> + /// VPMOVSXBD ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<int> ConvertToVector256Int32(sbyte* address) => ConvertToVector256Int32(address); + /// <summary> + /// VPMOVZXBD ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<int> ConvertToVector256Int32(byte* address) => ConvertToVector256Int32(address); + /// <summary> + /// VPMOVSXWD ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<int> ConvertToVector256Int32(short* address) => ConvertToVector256Int32(address); + /// <summary> + /// VPMOVZXWD ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<int> ConvertToVector256Int32(ushort* address) => ConvertToVector256Int32(address); + /// <summary> + /// VPMOVSXBQ ymm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<long> ConvertToVector256Int64(sbyte* address) => ConvertToVector256Int64(address); + /// <summary> + /// VPMOVZXBQ ymm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<long> ConvertToVector256Int64(byte* address) => ConvertToVector256Int64(address); + /// <summary> + /// VPMOVSXWQ ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<long> ConvertToVector256Int64(short* address) => ConvertToVector256Int64(address); + /// <summary> + /// VPMOVZXWQ ymm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<long> ConvertToVector256Int64(ushort* address) => ConvertToVector256Int64(address); + /// <summary> + /// VPMOVSXDQ ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<long> ConvertToVector256Int64(int* address) => ConvertToVector256Int64(address); + /// <summary> + /// VPMOVZXDQ ymm, m128 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector256<long> ConvertToVector256Int64(uint* address) => ConvertToVector256Int64(address); /// <summary> /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs index 5dbbbed88f..80aa680cc6 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs @@ -10,17 +10,17 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// _CMP_EQ_OQ /// </summary> - EqualOrderedNonSignaling = 0, + OrderedEqualNonSignaling = 0, /// <summary> /// _CMP_LT_OS /// </summary> - LessThanOrderedSignaling = 1, + OrderedLessThanSignaling = 1, /// <summary> /// _CMP_LE_OS /// </summary> - LessThanOrEqualOrderedSignaling = 2, + OrderedLessThanOrEqualSignaling = 2, /// <summary> /// _CMP_UNORD_Q @@ -30,17 +30,17 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// _CMP_NEQ_UQ /// </summary> - NotEqualUnorderedNonSignaling = 4, + UnorderedNotEqualNonSignaling = 4, /// <summary> /// _CMP_NLT_US /// </summary> - NotLessThanUnorderedSignaling = 5, + UnorderedNotLessThanSignaling = 5, /// <summary> /// _CMP_NLE_US /// </summary> - NotLessThanOrEqualUnorderedSignaling = 6, + UnorderedNotLessThanOrEqualSignaling = 6, /// <summary> /// _CMP_ORD_Q @@ -50,57 +50,57 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// _CMP_EQ_UQ /// </summary> - EqualUnorderedNonSignaling = 8, + UnorderedEqualNonSignaling = 8, /// <summary> /// _CMP_NGE_US /// </summary> - NotGreaterThanOrEqualUnorderedSignaling = 9, + UnorderedNotGreaterThanOrEqualSignaling = 9, /// <summary> /// _CMP_NGT_US /// </summary> - NotGreaterThanUnorderedSignaling = 10, + UnorderedNotGreaterThanSignaling = 10, /// <summary> /// _CMP_FALSE_OQ /// </summary> - FalseOrderedNonSignaling = 11, + OrderedFalseNonSignaling = 11, /// <summary> /// _CMP_NEQ_OQ /// </summary> - NotEqualOrderedNonSignaling = 12, + OrderedNotEqualNonSignaling = 12, /// <summary> /// _CMP_GE_OS /// </summary> - GreaterThanOrEqualOrderedSignaling = 13, + OrderedGreaterThanOrEqualSignaling = 13, /// <summary> /// _CMP_GT_OS /// </summary> - GreaterThanOrderedSignaling = 14, + OrderedGreaterThanSignaling = 14, /// <summary> /// _CMP_TRUE_UQ /// </summary> - TrueUnorderedNonSignaling = 15, + UnorderedTrueNonSignaling = 15, /// <summary> /// _CMP_EQ_OS /// </summary> - EqualOrderedSignaling = 16, + OrderedEqualSignaling = 16, /// <summary> /// _CMP_LT_OQ /// </summary> - LessThanOrderedNonSignaling = 17, + OrderedLessThanNonSignaling = 17, /// <summary> /// _CMP_LE_OQ /// </summary> - LessThanOrEqualOrderedNonSignaling = 18, + OrderedLessThanOrEqualNonSignaling = 18, /// <summary> /// _CMP_UNORD_S @@ -110,17 +110,17 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// _CMP_NEQ_US /// </summary> - NotEqualUnorderedSignaling = 20, + UnorderedNotEqualSignaling = 20, /// <summary> /// _CMP_NLT_UQ /// </summary> - NotLessThanUnorderedNonSignaling = 21, + UnorderedNotLessThanNonSignaling = 21, /// <summary> /// _CMP_NLE_UQ /// </summary> - NotLessThanOrEqualUnorderedNonSignaling = 22, + UnorderedNotLessThanOrEqualNonSignaling = 22, /// <summary> /// _CMP_ORD_S @@ -130,41 +130,41 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// _CMP_EQ_US /// </summary> - EqualUnorderedSignaling = 24, + UnorderedEqualSignaling = 24, /// <summary> /// _CMP_NGE_UQ /// </summary> - NotGreaterThanOrEqualUnorderedNonSignaling = 25, + UnorderedNotGreaterThanOrEqualNonSignaling = 25, /// <summary> /// _CMP_NGT_UQ /// </summary> - NotGreaterThanUnorderedNonSignaling = 26, + UnorderedNotGreaterThanNonSignaling = 26, /// <summary> /// _CMP_FALSE_OS /// </summary> - FalseOrderedSignaling = 27, + OrderedFalseSignaling = 27, /// <summary> /// _CMP_NEQ_OS /// </summary> - NotEqualOrderedSignaling = 28, + OrderedNotEqualSignaling = 28, /// <summary> /// _CMP_GE_OQ /// </summary> - GreaterThanOrEqualOrderedNonSignaling = 29, + OrderedGreaterThanOrEqualNonSignaling = 29, /// <summary> /// _CMP_GT_OQ /// </summary> - GreaterThanOrderedNonSignaling = 30, + OrderedGreaterThanNonSignaling = 30, /// <summary> /// _CMP_TRUE_US /// </summary> - TrueUnorderedSignaling = 31, + UnorderedTrueSignaling = 31, } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs index 4187dd27df..0a486ac0d7 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs @@ -82,18 +82,21 @@ namespace System.Runtime.Intrinsics.X86 /// COMISS xmm, xmm/m32 /// </summary> public static bool CompareEqualOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// int _mm_ucomieq_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// </summary> public static bool CompareEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmpeq_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(0) /// </summary> public static Vector128<float> CompareEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static Vector128<float> CompareScalarEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmpgt_ps (__m128 a, __m128 b) @@ -106,18 +109,21 @@ namespace System.Runtime.Intrinsics.X86 /// COMISS xmm, xmm/m32 /// </summary> public static bool CompareGreaterThanOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedGreaterThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// int _mm_ucomigt_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// </summary> public static bool CompareGreaterThanUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedGreaterThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmpgt_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(6) /// </summary> public static Vector128<float> CompareGreaterThanScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static Vector128<float> CompareScalarGreaterThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmpge_ps (__m128 a, __m128 b) @@ -130,18 +136,21 @@ namespace System.Runtime.Intrinsics.X86 /// COMISS xmm, xmm/m32 /// </summary> public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// int _mm_ucomige_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// </summary> public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmpge_ss (__m128 a, __m128 b) /// CMPPS xmm, xmm/m32, imm8(5) /// </summary> public static Vector128<float> CompareGreaterThanOrEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static Vector128<float> CompareScalarGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmplt_ps (__m128 a, __m128 b) @@ -154,18 +163,21 @@ namespace System.Runtime.Intrinsics.X86 /// COMISS xmm, xmm/m32 /// </summary> public static bool CompareLessThanOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedLessThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// int _mm_ucomilt_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// </summary> public static bool CompareLessThanUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedLessThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmplt_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(1) /// </summary> public static Vector128<float> CompareLessThanScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static Vector128<float> CompareScalarLessThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmple_ps (__m128 a, __m128 b) @@ -178,18 +190,21 @@ namespace System.Runtime.Intrinsics.X86 /// COMISS xmm, xmm/m32 /// </summary> public static bool CompareLessThanOrEqualOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedLessThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// int _mm_ucomile_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// </summary> public static bool CompareLessThanOrEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedLessThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmple_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(2) /// </summary> public static Vector128<float> CompareLessThanOrEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static Vector128<float> CompareScalarLessThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmpneq_ps (__m128 a, __m128 b) @@ -202,18 +217,21 @@ namespace System.Runtime.Intrinsics.X86 /// COMISS xmm, xmm/m32 /// </summary> public static bool CompareNotEqualOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedNotEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// int _mm_ucomineq_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// </summary> public static bool CompareNotEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedNotEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmpneq_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(4) /// </summary> public static Vector128<float> CompareNotEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static Vector128<float> CompareScalarNotEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmpngt_ps (__m128 a, __m128 b) @@ -226,6 +244,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSS xmm, xmm/m32, imm8(2) /// </summary> public static Vector128<float> CompareNotGreaterThanScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static Vector128<float> CompareScalarNotGreaterThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmpnge_ps (__m128 a, __m128 b) @@ -238,6 +257,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSS xmm, xmm/m32, imm8(1) /// </summary> public static Vector128<float> CompareNotGreaterThanOrEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static Vector128<float> CompareScalarNotGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmpnlt_ps (__m128 a, __m128 b) @@ -250,6 +270,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSS xmm, xmm/m32, imm8(5) /// </summary> public static Vector128<float> CompareNotLessThanScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static Vector128<float> CompareScalarNotLessThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmpnle_ps (__m128 a, __m128 b) @@ -262,6 +283,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSS xmm, xmm/m32, imm8(6) /// </summary> public static Vector128<float> CompareNotLessThanOrEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static Vector128<float> CompareScalarNotLessThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmpord_ps (__m128 a, __m128 b) @@ -274,6 +296,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSS xmm, xmm/m32, imm8(7) /// </summary> public static Vector128<float> CompareOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static Vector128<float> CompareScalarOrdered(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128 _mm_cmpunord_ps (__m128 a, __m128 b) @@ -286,6 +309,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSS xmm, xmm/m32, imm8(3) /// </summary> public static Vector128<float> CompareUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } + public static Vector128<float> CompareScalarUnordered(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); } /// <summary> /// int _mm_cvtss_si32 (__m128 a) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs index f65aedaf81..47daa4dd24 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs @@ -84,18 +84,21 @@ namespace System.Runtime.Intrinsics.X86 /// COMISS xmm, xmm/m32 /// </summary> public static bool CompareEqualOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedEqual(Vector128<float> left, Vector128<float> right) => CompareScalarOrderedEqual(left, right); /// <summary> /// int _mm_ucomieq_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// </summary> public static bool CompareEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedEqual(Vector128<float> left, Vector128<float> right) => CompareScalarUnorderedEqual(left, right); /// <summary> /// __m128 _mm_cmpeq_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(0) /// </summary> public static Vector128<float> CompareEqualScalar(Vector128<float> left, Vector128<float> right) => CompareEqualScalar(left, right); + public static Vector128<float> CompareScalarEqual(Vector128<float> left, Vector128<float> right) => CompareScalarEqual(left, right); /// <summary> /// __m128 _mm_cmpgt_ps (__m128 a, __m128 b) @@ -108,18 +111,21 @@ namespace System.Runtime.Intrinsics.X86 /// COMISS xmm, xmm/m32 /// </summary> public static bool CompareGreaterThanOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrderedScalar(left, right); + public static bool CompareScalarOrderedGreaterThan(Vector128<float> left, Vector128<float> right) => CompareScalarOrderedGreaterThan(left, right); /// <summary> /// int _mm_ucomigt_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// </summary> public static bool CompareGreaterThanUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanUnorderedScalar(left, right); + public static bool CompareScalarUnorderedGreaterThan(Vector128<float> left, Vector128<float> right) => CompareScalarUnorderedGreaterThan(left, right); /// <summary> /// __m128 _mm_cmpgt_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(6) /// </summary> public static Vector128<float> CompareGreaterThanScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanScalar(left, right); + public static Vector128<float> CompareScalarGreaterThan(Vector128<float> left, Vector128<float> right) => CompareScalarGreaterThan(left, right); /// <summary> /// __m128 _mm_cmpge_ps (__m128 a, __m128 b) @@ -132,18 +138,21 @@ namespace System.Runtime.Intrinsics.X86 /// COMISS xmm, xmm/m32 /// </summary> public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareScalarOrderedGreaterThanOrEqual(left, right); /// <summary> /// int _mm_ucomige_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// </summary> public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareScalarUnorderedGreaterThanOrEqual(left, right); /// <summary> /// __m128 _mm_cmpge_ss (__m128 a, __m128 b) /// CMPPS xmm, xmm/m32, imm8(5) /// </summary> public static Vector128<float> CompareGreaterThanOrEqualScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrEqualScalar(left, right); + public static Vector128<float> CompareScalarGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareScalarGreaterThanOrEqual(left, right); /// <summary> /// __m128 _mm_cmplt_ps (__m128 a, __m128 b) @@ -156,18 +165,21 @@ namespace System.Runtime.Intrinsics.X86 /// COMISS xmm, xmm/m32 /// </summary> public static bool CompareLessThanOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanOrderedScalar(left, right); + public static bool CompareScalarOrderedLessThan(Vector128<float> left, Vector128<float> right) => CompareScalarOrderedLessThan(left, right); /// <summary> /// int _mm_ucomilt_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// </summary> public static bool CompareLessThanUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanUnorderedScalar(left, right); + public static bool CompareScalarUnorderedLessThan(Vector128<float> left, Vector128<float> right) => CompareScalarUnorderedLessThan(left, right); /// <summary> /// __m128 _mm_cmplt_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(1) /// </summary> public static Vector128<float> CompareLessThanScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanScalar(left, right); + public static Vector128<float> CompareScalarLessThan(Vector128<float> left, Vector128<float> right) => CompareScalarLessThan(left, right); /// <summary> /// __m128 _mm_cmple_ps (__m128 a, __m128 b) @@ -180,18 +192,21 @@ namespace System.Runtime.Intrinsics.X86 /// COMISS xmm, xmm/m32 /// </summary> public static bool CompareLessThanOrEqualOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanOrEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedLessThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareScalarOrderedLessThanOrEqual(left, right); /// <summary> /// int _mm_ucomile_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// </summary> public static bool CompareLessThanOrEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanOrEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedLessThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareScalarUnorderedLessThanOrEqual(left, right); /// <summary> /// __m128 _mm_cmple_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(2) /// </summary> public static Vector128<float> CompareLessThanOrEqualScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanOrEqualScalar(left, right); + public static Vector128<float> CompareScalarLessThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareScalarLessThanOrEqual(left, right); /// <summary> /// __m128 _mm_cmpneq_ps (__m128 a, __m128 b) @@ -204,18 +219,21 @@ namespace System.Runtime.Intrinsics.X86 /// COMISS xmm, xmm/m32 /// </summary> public static bool CompareNotEqualOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareNotEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedNotEqual(Vector128<float> left, Vector128<float> right) => CompareScalarOrderedNotEqual(left, right); /// <summary> /// int _mm_ucomineq_ss (__m128 a, __m128 b) /// UCOMISS xmm, xmm/m32 /// </summary> public static bool CompareNotEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareNotEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedNotEqual(Vector128<float> left, Vector128<float> right) => CompareScalarUnorderedNotEqual(left, right); /// <summary> /// __m128 _mm_cmpneq_ss (__m128 a, __m128 b) /// CMPSS xmm, xmm/m32, imm8(4) /// </summary> public static Vector128<float> CompareNotEqualScalar(Vector128<float> left, Vector128<float> right) => CompareNotEqualScalar(left, right); + public static Vector128<float> CompareScalarNotEqual(Vector128<float> left, Vector128<float> right) => CompareScalarNotEqual(left, right); /// <summary> /// __m128 _mm_cmpngt_ps (__m128 a, __m128 b) @@ -228,6 +246,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSS xmm, xmm/m32, imm8(2) /// </summary> public static Vector128<float> CompareNotGreaterThanScalar(Vector128<float> left, Vector128<float> right) => CompareNotGreaterThanScalar(left, right); + public static Vector128<float> CompareScalarNotGreaterThan(Vector128<float> left, Vector128<float> right) => CompareScalarNotGreaterThan(left, right); /// <summary> /// __m128 _mm_cmpnge_ps (__m128 a, __m128 b) @@ -240,6 +259,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSS xmm, xmm/m32, imm8(1) /// </summary> public static Vector128<float> CompareNotGreaterThanOrEqualScalar(Vector128<float> left, Vector128<float> right) => CompareNotGreaterThanOrEqualScalar(left, right); + public static Vector128<float> CompareScalarNotGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareScalarNotGreaterThanOrEqual(left, right); /// <summary> /// __m128 _mm_cmpnlt_ps (__m128 a, __m128 b) @@ -252,6 +272,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSS xmm, xmm/m32, imm8(5) /// </summary> public static Vector128<float> CompareNotLessThanScalar(Vector128<float> left, Vector128<float> right) => CompareNotLessThanScalar(left, right); + public static Vector128<float> CompareScalarNotLessThan(Vector128<float> left, Vector128<float> right) => CompareScalarNotLessThan(left, right); /// <summary> /// __m128 _mm_cmpnle_ps (__m128 a, __m128 b) @@ -264,6 +285,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSS xmm, xmm/m32, imm8(6) /// </summary> public static Vector128<float> CompareNotLessThanOrEqualScalar(Vector128<float> left, Vector128<float> right) => CompareNotLessThanOrEqualScalar(left, right); + public static Vector128<float> CompareScalarNotLessThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareScalarNotLessThanOrEqual(left, right); /// <summary> /// __m128 _mm_cmpord_ps (__m128 a, __m128 b) @@ -276,6 +298,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSS xmm, xmm/m32, imm8(7) /// </summary> public static Vector128<float> CompareOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareOrderedScalar(left, right); + public static Vector128<float> CompareScalarOrdered(Vector128<float> left, Vector128<float> right) => CompareScalarOrdered(left, right); /// <summary> /// __m128 _mm_cmpunord_ps (__m128 a, __m128 b) @@ -288,6 +311,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSS xmm, xmm/m32, imm8(3) /// </summary> public static Vector128<float> CompareUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareUnorderedScalar(left, right); + public static Vector128<float> CompareScalarUnordered(Vector128<float> left, Vector128<float> right) => CompareScalarUnordered(left, right); /// <summary> /// int _mm_cvtss_si32 (__m128 a) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs index 7ad61f50c0..ec00fec2a8 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs @@ -301,21 +301,24 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// int _mm_comieq_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// </summary> public static bool CompareEqualOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// int _mm_ucomieq_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// </summary> public static bool CompareEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmpeq_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(0) /// </summary> public static Vector128<double> CompareEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static Vector128<double> CompareScalarEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cmpgt_epi8 (__m128i a, __m128i b) @@ -340,21 +343,24 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// int _mm_comigt_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// </summary> public static bool CompareGreaterThanOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedGreaterThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// int _mm_ucomigt_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// </summary> public static bool CompareGreaterThanUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedGreaterThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmpgt_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(6) /// </summary> public static Vector128<double> CompareGreaterThanScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static Vector128<double> CompareScalarGreaterThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmpge_pd (__m128d a, __m128d b) @@ -364,21 +370,24 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// int _mm_comige_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// </summary> public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// int _mm_ucomige_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// </summary> public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmpge_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(5) /// </summary> public static Vector128<double> CompareGreaterThanOrEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static Vector128<double> CompareScalarGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cmplt_epi8 (__m128i a, __m128i b) @@ -403,21 +412,24 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// int _mm_comilt_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// </summary> public static bool CompareLessThanOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedLessThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// int _mm_ucomilt_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// </summary> public static bool CompareLessThanUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedLessThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmplt_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(1) /// </summary> public static Vector128<double> CompareLessThanScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static Vector128<double> CompareScalarLessThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmple_pd (__m128d a, __m128d b) @@ -427,21 +439,24 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// int _mm_comile_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// </summary> public static bool CompareLessThanOrEqualOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedLessThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// int _mm_ucomile_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// </summary> public static bool CompareLessThanOrEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedLessThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmple_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(2) /// </summary> public static Vector128<double> CompareLessThanOrEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static Vector128<double> CompareScalarLessThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmpneq_pd (__m128d a, __m128d b) @@ -451,21 +466,24 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// int _mm_comineq_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// </summary> public static bool CompareNotEqualOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarOrderedNotEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// int _mm_ucomineq_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// </summary> public static bool CompareNotEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static bool CompareScalarUnorderedNotEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmpneq_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(4) /// </summary> public static Vector128<double> CompareNotEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static Vector128<double> CompareScalarNotEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmpngt_pd (__m128d a, __m128d b) @@ -478,6 +496,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSD xmm, xmm/m64, imm8(2) /// </summary> public static Vector128<double> CompareNotGreaterThanScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static Vector128<double> CompareScalarNotGreaterThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmpnge_pd (__m128d a, __m128d b) @@ -490,6 +509,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSD xmm, xmm/m64, imm8(1) /// </summary> public static Vector128<double> CompareNotGreaterThanOrEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static Vector128<double> CompareScalarNotGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmpnlt_pd (__m128d a, __m128d b) @@ -502,6 +522,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSD xmm, xmm/m64, imm8(5) /// </summary> public static Vector128<double> CompareNotLessThanScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static Vector128<double> CompareScalarNotLessThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmpnle_pd (__m128d a, __m128d b) @@ -514,6 +535,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSD xmm, xmm/m64, imm8(6) /// </summary> public static Vector128<double> CompareNotLessThanOrEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static Vector128<double> CompareScalarNotLessThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmpord_pd (__m128d a, __m128d b) @@ -526,6 +548,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSD xmm, xmm/m64, imm8(7) /// </summary> public static Vector128<double> CompareOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static Vector128<double> CompareScalarOrdered(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128d _mm_cmpunord_pd (__m128d a, __m128d b) @@ -538,6 +561,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSD xmm, xmm/m64, imm8(3) /// </summary> public static Vector128<double> CompareUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } + public static Vector128<double> CompareScalarUnordered(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cvtps_epi32 (__m128 a) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs index d9d1307cc8..a49a07e0c4 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs @@ -303,21 +303,24 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// int _mm_comieq_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// </summary> public static bool CompareEqualOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedEqual(Vector128<double> left, Vector128<double> right) => CompareScalarOrderedEqual(left, right); /// <summary> /// int _mm_ucomieq_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// </summary> public static bool CompareEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedEqual(Vector128<double> left, Vector128<double> right) => CompareScalarUnorderedEqual(left, right); /// <summary> /// __m128d _mm_cmpeq_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(0) /// </summary> public static Vector128<double> CompareEqualScalar(Vector128<double> left, Vector128<double> right) => CompareEqualScalar(left, right); + public static Vector128<double> CompareScalarEqual(Vector128<double> left, Vector128<double> right) => CompareScalarEqual(left, right); /// <summary> /// __m128i _mm_cmpgt_epi8 (__m128i a, __m128i b) @@ -342,21 +345,24 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// int _mm_comigt_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// </summary> public static bool CompareGreaterThanOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrderedScalar(left, right); + public static bool CompareScalarOrderedGreaterThan(Vector128<double> left, Vector128<double> right) => CompareScalarOrderedGreaterThan(left, right); /// <summary> /// int _mm_ucomigt_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// </summary> public static bool CompareGreaterThanUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanUnorderedScalar(left, right); + public static bool CompareScalarUnorderedGreaterThan(Vector128<double> left, Vector128<double> right) => CompareScalarUnorderedGreaterThan(left, right); /// <summary> /// __m128d _mm_cmpgt_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(6) /// </summary> public static Vector128<double> CompareGreaterThanScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanScalar(left, right); + public static Vector128<double> CompareScalarGreaterThan(Vector128<double> left, Vector128<double> right) => CompareScalarGreaterThan(left, right); /// <summary> /// __m128d _mm_cmpge_pd (__m128d a, __m128d b) @@ -366,21 +372,24 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// int _mm_comige_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// </summary> public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareScalarOrderedGreaterThanOrEqual(left, right); /// <summary> /// int _mm_ucomige_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// </summary> public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareScalarUnorderedGreaterThanOrEqual(left, right); /// <summary> /// __m128d _mm_cmpge_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(5) /// </summary> public static Vector128<double> CompareGreaterThanOrEqualScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrEqualScalar(left, right); + public static Vector128<double> CompareScalarGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareScalarGreaterThanOrEqual(left, right); /// <summary> /// __m128i _mm_cmplt_epi8 (__m128i a, __m128i b) @@ -405,21 +414,24 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// int _mm_comilt_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// </summary> public static bool CompareLessThanOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanOrderedScalar(left, right); + public static bool CompareScalarOrderedLessThan(Vector128<double> left, Vector128<double> right) => CompareScalarOrderedLessThan(left, right); /// <summary> /// int _mm_ucomilt_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// </summary> public static bool CompareLessThanUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanUnorderedScalar(left, right); + public static bool CompareScalarUnorderedLessThan(Vector128<double> left, Vector128<double> right) => CompareScalarUnorderedLessThan(left, right); /// <summary> /// __m128d _mm_cmplt_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(1) /// </summary> public static Vector128<double> CompareLessThanScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanScalar(left, right); + public static Vector128<double> CompareScalarLessThan(Vector128<double> left, Vector128<double> right) => CompareScalarLessThan(left, right); /// <summary> /// __m128d _mm_cmple_pd (__m128d a, __m128d b) @@ -429,21 +441,24 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// int _mm_comile_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// </summary> public static bool CompareLessThanOrEqualOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanOrEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedLessThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareScalarOrderedLessThanOrEqual(left, right); /// <summary> /// int _mm_ucomile_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// </summary> public static bool CompareLessThanOrEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanOrEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedLessThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareScalarUnorderedLessThanOrEqual(left, right); /// <summary> /// __m128d _mm_cmple_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(2) /// </summary> public static Vector128<double> CompareLessThanOrEqualScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanOrEqualScalar(left, right); + public static Vector128<double> CompareScalarLessThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareScalarLessThanOrEqual(left, right); /// <summary> /// __m128d _mm_cmpneq_pd (__m128d a, __m128d b) @@ -453,21 +468,24 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// int _mm_comineq_sd (__m128d a, __m128d b) - /// COMISS xmm, xmm/m64 + /// COMISD xmm, xmm/m64 /// </summary> public static bool CompareNotEqualOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareNotEqualOrderedScalar(left, right); + public static bool CompareScalarOrderedNotEqual(Vector128<double> left, Vector128<double> right) => CompareScalarOrderedNotEqual(left, right); /// <summary> /// int _mm_ucomineq_sd (__m128d a, __m128d b) - /// UCOMISS xmm, xmm/m64 + /// UCOMISD xmm, xmm/m64 /// </summary> public static bool CompareNotEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareNotEqualUnorderedScalar(left, right); + public static bool CompareScalarUnorderedNotEqual(Vector128<double> left, Vector128<double> right) => CompareScalarUnorderedNotEqual(left, right); /// <summary> /// __m128d _mm_cmpneq_sd (__m128d a, __m128d b) /// CMPSD xmm, xmm/m64, imm8(4) /// </summary> public static Vector128<double> CompareNotEqualScalar(Vector128<double> left, Vector128<double> right) => CompareNotEqualScalar(left, right); + public static Vector128<double> CompareScalarNotEqual(Vector128<double> left, Vector128<double> right) => CompareScalarNotEqual(left, right); /// <summary> /// __m128d _mm_cmpngt_pd (__m128d a, __m128d b) @@ -480,6 +498,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSD xmm, xmm/m64, imm8(2) /// </summary> public static Vector128<double> CompareNotGreaterThanScalar(Vector128<double> left, Vector128<double> right) => CompareNotGreaterThanScalar(left, right); + public static Vector128<double> CompareScalarNotGreaterThan(Vector128<double> left, Vector128<double> right) => CompareScalarNotGreaterThan(left, right); /// <summary> /// __m128d _mm_cmpnge_pd (__m128d a, __m128d b) @@ -492,6 +511,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSD xmm, xmm/m64, imm8(1) /// </summary> public static Vector128<double> CompareNotGreaterThanOrEqualScalar(Vector128<double> left, Vector128<double> right) => CompareNotGreaterThanOrEqualScalar(left, right); + public static Vector128<double> CompareScalarNotGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareScalarNotGreaterThanOrEqual(left, right); /// <summary> /// __m128d _mm_cmpnlt_pd (__m128d a, __m128d b) @@ -504,6 +524,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSD xmm, xmm/m64, imm8(5) /// </summary> public static Vector128<double> CompareNotLessThanScalar(Vector128<double> left, Vector128<double> right) => CompareNotLessThanScalar(left, right); + public static Vector128<double> CompareScalarNotLessThan(Vector128<double> left, Vector128<double> right) => CompareScalarNotLessThan(left, right); /// <summary> /// __m128d _mm_cmpnle_pd (__m128d a, __m128d b) @@ -516,6 +537,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSD xmm, xmm/m64, imm8(6) /// </summary> public static Vector128<double> CompareNotLessThanOrEqualScalar(Vector128<double> left, Vector128<double> right) => CompareNotLessThanOrEqualScalar(left, right); + public static Vector128<double> CompareScalarNotLessThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareScalarNotLessThanOrEqual(left, right); /// <summary> /// __m128d _mm_cmpord_pd (__m128d a, __m128d b) @@ -528,6 +550,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSD xmm, xmm/m64, imm8(7) /// </summary> public static Vector128<double> CompareOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareOrderedScalar(left, right); + public static Vector128<double> CompareScalarOrdered(Vector128<double> left, Vector128<double> right) => CompareScalarOrdered(left, right); /// <summary> /// __m128d _mm_cmpunord_pd (__m128d a, __m128d b) @@ -540,6 +563,7 @@ namespace System.Runtime.Intrinsics.X86 /// CMPSD xmm, xmm/m64, imm8(3) /// </summary> public static Vector128<double> CompareUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareUnorderedScalar(left, right); + public static Vector128<double> CompareScalarUnordered(Vector128<double> left, Vector128<double> right) => CompareScalarUnordered(left, right); /// <summary> /// __m128i _mm_cvtps_epi32 (__m128 a) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs index dfa5b568c7..d9f67bcb67 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs @@ -181,66 +181,127 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// __m128i _mm_cvtepi8_epi16 (__m128i a) - /// PMOVSXBW xmm, xmm/m64 + /// PMOVSXBW xmm, xmm /// </summary> public static Vector128<short> ConvertToVector128Int16(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cvtepu8_epi16 (__m128i a) - /// PMOVZXBW xmm, xmm/m64 + /// PMOVZXBW xmm, xmm /// </summary> public static Vector128<short> ConvertToVector128Int16(Vector128<byte> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cvtepi8_epi32 (__m128i a) - /// PMOVSXBD xmm, xmm/m32 + /// PMOVSXBD xmm, xmm /// </summary> public static Vector128<int> ConvertToVector128Int32(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cvtepu8_epi32 (__m128i a) - /// PMOVZXBD xmm, xmm/m32 + /// PMOVZXBD xmm, xmm /// </summary> public static Vector128<int> ConvertToVector128Int32(Vector128<byte> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cvtepi16_epi32 (__m128i a) - /// PMOVSXWD xmm, xmm/m64 + /// PMOVSXWD xmm, xmm /// </summary> public static Vector128<int> ConvertToVector128Int32(Vector128<short> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cvtepu16_epi32 (__m128i a) - /// PMOVZXWD xmm, xmm/m64 + /// PMOVZXWD xmm, xmm /// </summary> public static Vector128<int> ConvertToVector128Int32(Vector128<ushort> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cvtepi8_epi64 (__m128i a) - /// PMOVSXBQ xmm, xmm/m16 + /// PMOVSXBQ xmm, xmm /// </summary> public static Vector128<long> ConvertToVector128Int64(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cvtepu8_epi64 (__m128i a) - /// PMOVZXBQ xmm, xmm/m16 + /// PMOVZXBQ xmm, xmm /// </summary> public static Vector128<long> ConvertToVector128Int64(Vector128<byte> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cvtepi16_epi64 (__m128i a) - /// PMOVSXWQ xmm, xmm/m32 + /// PMOVSXWQ xmm, xmm /// </summary> public static Vector128<long> ConvertToVector128Int64(Vector128<short> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cvtepu16_epi64 (__m128i a) - /// PMOVZXWQ xmm, xmm/m32 + /// PMOVZXWQ xmm, xmm /// </summary> public static Vector128<long> ConvertToVector128Int64(Vector128<ushort> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cvtepi32_epi64 (__m128i a) - /// PMOVSXDQ xmm, xmm/m64 + /// PMOVSXDQ xmm, xmm /// </summary> public static Vector128<long> ConvertToVector128Int64(Vector128<int> value) { throw new PlatformNotSupportedException(); } /// <summary> /// __m128i _mm_cvtepu32_epi64 (__m128i a) - /// PMOVZXDQ xmm, xmm/m64 + /// PMOVZXDQ xmm, xmm /// </summary> public static Vector128<long> ConvertToVector128Int64(Vector128<uint> value) { throw new PlatformNotSupportedException(); } /// <summary> + /// PMOVSXBW xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<short> ConvertToVector128Int16(sbyte* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// PMOVZXBW xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<short> ConvertToVector128Int16(byte* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// PMOVSXBD xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<int> ConvertToVector128Int32(sbyte* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// PMOVZXBD xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<int> ConvertToVector128Int32(byte* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// PMOVSXWD xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<int> ConvertToVector128Int32(short* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// PMOVZXWD xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<int> ConvertToVector128Int32(ushort* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// PMOVSXBQ xmm, m16 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<long> ConvertToVector128Int64(sbyte* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// PMOVZXBQ xmm, m16 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<long> ConvertToVector128Int64(byte* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// PMOVSXWQ xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<long> ConvertToVector128Int64(short* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// PMOVZXWQ xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<long> ConvertToVector128Int64(ushort* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// PMOVSXDQ xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<long> ConvertToVector128Int64(int* address) { throw new PlatformNotSupportedException(); } + /// <summary> + /// PMOVZXDQ xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<long> ConvertToVector128Int64(uint* address) { throw new PlatformNotSupportedException(); } + + /// <summary> /// __m128 _mm_dp_ps (__m128 a, __m128 b, const int imm8) /// DPPS xmm, xmm/m128, imm8 /// </summary> diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs index 834b48856f..8fe0a3cf94 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs @@ -183,66 +183,127 @@ namespace System.Runtime.Intrinsics.X86 /// <summary> /// __m128i _mm_cvtepi8_epi16 (__m128i a) - /// PMOVSXBW xmm, xmm/m64 + /// PMOVSXBW xmm, xmm /// </summary> public static Vector128<short> ConvertToVector128Int16(Vector128<sbyte> value) => ConvertToVector128Int16(value); /// <summary> /// __m128i _mm_cvtepu8_epi16 (__m128i a) - /// PMOVZXBW xmm, xmm/m64 + /// PMOVZXBW xmm, xmm /// </summary> public static Vector128<short> ConvertToVector128Int16(Vector128<byte> value) => ConvertToVector128Int16(value); /// <summary> /// __m128i _mm_cvtepi8_epi32 (__m128i a) - /// PMOVSXBD xmm, xmm/m32 + /// PMOVSXBD xmm, xmm /// </summary> public static Vector128<int> ConvertToVector128Int32(Vector128<sbyte> value) => ConvertToVector128Int32(value); /// <summary> /// __m128i _mm_cvtepu8_epi32 (__m128i a) - /// PMOVZXBD xmm, xmm/m32 + /// PMOVZXBD xmm, xmm /// </summary> public static Vector128<int> ConvertToVector128Int32(Vector128<byte> value) => ConvertToVector128Int32(value); /// <summary> /// __m128i _mm_cvtepi16_epi32 (__m128i a) - /// PMOVSXWD xmm, xmm/m64 + /// PMOVSXWD xmm, xmm /// </summary> public static Vector128<int> ConvertToVector128Int32(Vector128<short> value) => ConvertToVector128Int32(value); /// <summary> /// __m128i _mm_cvtepu16_epi32 (__m128i a) - /// PMOVZXWD xmm, xmm/m64 + /// PMOVZXWD xmm, xmm /// </summary> public static Vector128<int> ConvertToVector128Int32(Vector128<ushort> value) => ConvertToVector128Int32(value); /// <summary> /// __m128i _mm_cvtepi8_epi64 (__m128i a) - /// PMOVSXBQ xmm, xmm/m16 + /// PMOVSXBQ xmm, xmm /// </summary> public static Vector128<long> ConvertToVector128Int64(Vector128<sbyte> value) => ConvertToVector128Int64(value); /// <summary> /// __m128i _mm_cvtepu8_epi64 (__m128i a) - /// PMOVZXBQ xmm, xmm/m16 + /// PMOVZXBQ xmm, xmm /// </summary> public static Vector128<long> ConvertToVector128Int64(Vector128<byte> value) => ConvertToVector128Int64(value); /// <summary> /// __m128i _mm_cvtepi16_epi64 (__m128i a) - /// PMOVSXWQ xmm, xmm/m32 + /// PMOVSXWQ xmm, xmm /// </summary> public static Vector128<long> ConvertToVector128Int64(Vector128<short> value) => ConvertToVector128Int64(value); /// <summary> /// __m128i _mm_cvtepu16_epi64 (__m128i a) - /// PMOVZXWQ xmm, xmm/m32 + /// PMOVZXWQ xmm, xmm /// </summary> public static Vector128<long> ConvertToVector128Int64(Vector128<ushort> value) => ConvertToVector128Int64(value); /// <summary> /// __m128i _mm_cvtepi32_epi64 (__m128i a) - /// PMOVSXDQ xmm, xmm/m64 + /// PMOVSXDQ xmm, xmm /// </summary> public static Vector128<long> ConvertToVector128Int64(Vector128<int> value) => ConvertToVector128Int64(value); /// <summary> /// __m128i _mm_cvtepu32_epi64 (__m128i a) - /// PMOVZXDQ xmm, xmm/m64 + /// PMOVZXDQ xmm, xmm /// </summary> public static Vector128<long> ConvertToVector128Int64(Vector128<uint> value) => ConvertToVector128Int64(value); /// <summary> + /// PMOVSXBW xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<short> ConvertToVector128Int16(sbyte* address) => ConvertToVector128Int16(address); + /// <summary> + /// PMOVZXBW xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<short> ConvertToVector128Int16(byte* address) => ConvertToVector128Int16(address); + /// <summary> + /// PMOVSXBD xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<int> ConvertToVector128Int32(sbyte* address) => ConvertToVector128Int32(address); + /// <summary> + /// PMOVZXBD xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<int> ConvertToVector128Int32(byte* address) => ConvertToVector128Int32(address); + /// <summary> + /// PMOVSXWD xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<int> ConvertToVector128Int32(short* address) => ConvertToVector128Int32(address); + /// <summary> + /// PMOVZXWD xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<int> ConvertToVector128Int32(ushort* address) => ConvertToVector128Int32(address); + /// <summary> + /// PMOVSXBQ xmm, m16 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<long> ConvertToVector128Int64(sbyte* address) => ConvertToVector128Int64(address); + /// <summary> + /// PMOVZXBQ xmm, m16 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<long> ConvertToVector128Int64(byte* address) => ConvertToVector128Int64(address); + /// <summary> + /// PMOVSXWQ xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<long> ConvertToVector128Int64(short* address) => ConvertToVector128Int64(address); + /// <summary> + /// PMOVZXWQ xmm, m32 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<long> ConvertToVector128Int64(ushort* address) => ConvertToVector128Int64(address); + /// <summary> + /// PMOVSXDQ xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<long> ConvertToVector128Int64(int* address) => ConvertToVector128Int64(address); + /// <summary> + /// PMOVZXDQ xmm, m64 + /// The native signature does not exist. We provide this additional overload for completeness. + /// </summary> + public static unsafe Vector128<long> ConvertToVector128Int64(uint* address) => ConvertToVector128Int64(address); + + /// <summary> /// __m128 _mm_dp_ps (__m128 a, __m128 b, const int imm8) /// DPPS xmm, xmm/m128, imm8 /// </summary> diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs b/src/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs index 8316e1093e..4efd5dec1d 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Reflection; @@ -31,18 +32,33 @@ namespace System.Runtime.Loader private static readonly Dictionary<long, WeakReference<AssemblyLoadContext>> s_allContexts = new Dictionary<long, WeakReference<AssemblyLoadContext>>(); private static long s_nextId; - // Indicates the state of this ALC (Alive or in Unloading state) - private InternalState _state; - - // Id used by s_allContexts - private readonly long _id; +#region private data members + // If you modify any of these fields, you must also update the + // AssemblyLoadContextBaseObject structure in object.h // synchronization primitive to protect against usage of this instance while unloading private readonly object _unloadLock; + private event Func<Assembly, string, IntPtr> _resolvingUnmanagedDll; + + private event Func<AssemblyLoadContext, AssemblyName, Assembly> _resolving; + + private event Action<AssemblyLoadContext> _unloading; + + private readonly string _name; + // Contains the reference to VM's representation of the AssemblyLoadContext private readonly IntPtr _nativeAssemblyLoadContext; + // Id used by s_allContexts + private readonly long _id; + + // Indicates the state of this ALC (Alive or in Unloading state) + private InternalState _state; + + private readonly bool _isCollectible; +#endregion + protected AssemblyLoadContext() : this(false, false, null) { } @@ -58,9 +74,9 @@ namespace System.Runtime.Loader private protected AssemblyLoadContext(bool representsTPALoadContext, bool isCollectible, string name) { // Initialize the VM side of AssemblyLoadContext if not already done. - IsCollectible = isCollectible; + _isCollectible = isCollectible; - Name = name; + _name = name; // The _unloadLock needs to be assigned after the IsCollectible to ensure proper behavior of the finalizer // even in case the following allocation fails or the thread is aborted between these two lines. @@ -103,7 +119,7 @@ namespace System.Runtime.Loader private void RaiseUnloadEvent() { // Ensure that we raise the Unload event only once - Interlocked.Exchange(ref Unloading, null)?.Invoke(this); + Interlocked.Exchange(ref _unloading, null)?.Invoke(this); } private void InitiateUnload() @@ -153,7 +169,17 @@ namespace System.Runtime.Loader // // Inputs: Invoking assembly, and library name to resolve // Returns: A handle to the loaded native library - public event Func<Assembly, string, IntPtr> ResolvingUnmanagedDll; + public event Func<Assembly, string, IntPtr> ResolvingUnmanagedDll + { + add + { + _resolvingUnmanagedDll += value; + } + remove + { + _resolvingUnmanagedDll -= value; + } + } // Event handler for resolving managed assemblies. // This event is raised if the managed assembly could not be resolved via @@ -161,9 +187,29 @@ namespace System.Runtime.Loader // // Inputs: The AssemblyLoadContext and AssemblyName to be loaded // Returns: The Loaded assembly object. - public event Func<AssemblyLoadContext, AssemblyName, Assembly> Resolving; + public event Func<AssemblyLoadContext, AssemblyName, Assembly> Resolving + { + add + { + _resolving += value; + } + remove + { + _resolving -= value; + } + } - public event Action<AssemblyLoadContext> Unloading; + public event Action<AssemblyLoadContext> Unloading + { + add + { + _unloading += value; + } + remove + { + _unloading -= value; + } + } // Occurs when an Assembly is loaded public static event AssemblyLoadEventHandler AssemblyLoad; @@ -180,9 +226,9 @@ namespace System.Runtime.Loader public static AssemblyLoadContext Default => DefaultAssemblyLoadContext.s_loadContext; - public bool IsCollectible { get; } + public bool IsCollectible { get { return _isCollectible;} } - public string Name { get; } + public string Name { get { return _name;} } public override string ToString() => "\"" + Name + "\" " + GetType().ToString() + " #" + _id; @@ -240,7 +286,7 @@ namespace System.Runtime.Loader // Attempt to load the assembly, using the same ordering as static load, in the current load context. StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return Assembly.Load(assemblyName, ref stackMark, _nativeAssemblyLoadContext); + return Assembly.Load(assemblyName, ref stackMark, this); } // These methods load assemblies into the current AssemblyLoadContext @@ -396,6 +442,110 @@ namespace System.Runtime.Loader throw new InvalidOperationException(SR.AssemblyLoadContext_Verify_NotUnloading); } } + + private static AsyncLocal<AssemblyLoadContext> s_asyncLocalCurrent; + + /// <summary>Nullable current AssemblyLoadContext used for context sensitive reflection APIs</summary> + /// <remarks> + /// This is an advanced setting used in reflection assembly loading scenarios. + /// + /// There are a set of contextual reflection APIs which load managed assemblies through an inferred AssemblyLoadContext. + /// * <see cref="System.Activator.CreateInstance" /> + /// * <see cref="System.Reflection.Assembly.Load" /> + /// * <see cref="System.Reflection.Assembly.GetType" /> + /// * <see cref="System.Type.GetType" /> + /// + /// When CurrentContextualReflectionContext is null, the AssemblyLoadContext is inferred. + /// The inference logic is simple. + /// * For static methods, it is the AssemblyLoadContext which loaded the method caller's assembly. + /// * For instance methods, it is the AssemblyLoadContext which loaded the instance's assembly. + /// + /// When this property is set, the CurrentContextualReflectionContext value is used by these contextual reflection APIs for loading. + /// + /// This property is typically set in a using block by + /// <see cref="System.Runtime.Loader.AssemblyLoadContext.EnterContextualReflection"/>. + /// + /// The property is stored in an AsyncLocal<AssemblyLoadContext>. This means the setting can be unique for every async or thread in the process. + /// + /// For more details see https://github.com/dotnet/coreclr/blob/master/Documentation/design-docs/AssemblyLoadContext.ContextualReflection.md + /// </remarks> + public static AssemblyLoadContext CurrentContextualReflectionContext + { + get { return s_asyncLocalCurrent?.Value; } + } + + private static void SetCurrentContextualReflectionContext(AssemblyLoadContext value) + { + if (s_asyncLocalCurrent == null) + { + Interlocked.CompareExchange(ref s_asyncLocalCurrent, new AsyncLocal<AssemblyLoadContext>(), null); + } + s_asyncLocalCurrent.Value = value; + } + + /// <summary>Enter scope using this AssemblyLoadContext for ContextualReflection</summary> + /// <returns>A disposable ContextualReflectionScope for use in a using block</returns> + /// <remarks> + /// Sets CurrentContextualReflectionContext to this instance. + /// <see cref="System.Runtime.Loader.AssemblyLoadContext.CurrentContextualReflectionContext"/> + /// + /// Returns a disposable ContextualReflectionScope for use in a using block. When the using calls the + /// Dispose() method, it restores the ContextualReflectionScope to its previous value. + /// </remarks> + public ContextualReflectionScope EnterContextualReflection() + { + return new ContextualReflectionScope(this); + } + + /// <summary>Enter scope using this AssemblyLoadContext for ContextualReflection</summary> + /// <param name="activating">Set CurrentContextualReflectionContext to the AssemblyLoadContext which loaded activating.</param> + /// <returns>A disposable ContextualReflectionScope for use in a using block</returns> + /// <remarks> + /// Sets CurrentContextualReflectionContext to to the AssemblyLoadContext which loaded activating. + /// <see cref="System.Runtime.Loader.AssemblyLoadContext.CurrentContextualReflectionContext"/> + /// + /// Returns a disposable ContextualReflectionScope for use in a using block. When the using calls the + /// Dispose() method, it restores the ContextualReflectionScope to its previous value. + /// </remarks> + public static ContextualReflectionScope EnterContextualReflection(Assembly activating) + { + return activating != null ? + GetLoadContext(activating).EnterContextualReflection() : + new ContextualReflectionScope(null); + } + + /// <summary>Opaque disposable struct used to restore CurrentContextualReflectionContext</summary> + /// <remarks> + /// This is an implmentation detail of the AssemblyLoadContext.EnterContextualReflection APIs. + /// It is a struct, to avoid heap allocation. + /// It is required to be public to avoid boxing. + /// <see cref="System.Runtime.Loader.AssemblyLoadContext.EnterContextualReflection"/> + /// </remarks> + [EditorBrowsable(EditorBrowsableState.Never)] + public struct ContextualReflectionScope : IDisposable + { + private readonly AssemblyLoadContext _activated; + private readonly AssemblyLoadContext _predecessor; + private readonly bool _initialized; + + internal ContextualReflectionScope(AssemblyLoadContext activating) + { + _predecessor = AssemblyLoadContext.CurrentContextualReflectionContext; + AssemblyLoadContext.SetCurrentContextualReflectionContext(activating); + _activated = activating; + _initialized = true; + } + + public void Dispose() + { + if (_initialized) + { + // Do not clear initialized. Always restore the _predecessor in Dispose() + // _initialized = false; + AssemblyLoadContext.SetCurrentContextualReflectionContext(_predecessor); + } + } + } } internal sealed class DefaultAssemblyLoadContext : AssemblyLoadContext diff --git a/src/System.Private.CoreLib/shared/System/Threading/TimerQueue.Windows.cs b/src/System.Private.CoreLib/shared/System/Threading/TimerQueue.Windows.cs new file mode 100644 index 0000000000..0bd0cc49cf --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/Threading/TimerQueue.Windows.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. +// See the LICENSE file in the project root for more information. + +using System.Runtime.InteropServices; + +namespace System.Threading +{ + internal partial class TimerQueue + { + private static int TickCount + { + get + { + // We need to keep our notion of time synchronized with the calls to SleepEx that drive + // the underlying native timer. In Win8, SleepEx does not count the time the machine spends + // sleeping/hibernating. Environment.TickCount (GetTickCount) *does* count that time, + // so we will get out of sync with SleepEx if we use that method. + // + // So, on Win8, we use QueryUnbiasedInterruptTime instead; this does not count time spent + // in sleep/hibernate mode. + if (Environment.IsWindows8OrAbove) + { + ulong time100ns; + + bool result = Interop.Kernel32.QueryUnbiasedInterruptTime(out time100ns); + if (!result) + Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error()); + + // convert to 100ns to milliseconds, and truncate to 32 bits. + return (int)(uint)(time100ns / 10000); + } + else + { + return Environment.TickCount; + } + } + } + } +} diff --git a/src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs index d5fea8a751..4514043e70 100644 --- a/src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs @@ -105,40 +105,6 @@ namespace System get; } -#if !FEATURE_PAL - internal static bool IsWindows8OrAbove => WindowsVersion.IsWindows8OrAbove; - - // Seperate type so a .cctor is not created for Enviroment which then would be triggered during startup - private static class WindowsVersion - { - // Cache the value in readonly static that can be optimized out by the JIT - internal readonly static bool IsWindows8OrAbove = GetIsWindows8OrAbove(); - - private static bool GetIsWindows8OrAbove() - { - ulong conditionMask = Interop.Kernel32.VerSetConditionMask(0, Interop.Kernel32.VER_MAJORVERSION, Interop.Kernel32.VER_GREATER_EQUAL); - conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_MINORVERSION, Interop.Kernel32.VER_GREATER_EQUAL); - conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_SERVICEPACKMAJOR, Interop.Kernel32.VER_GREATER_EQUAL); - conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_SERVICEPACKMINOR, Interop.Kernel32.VER_GREATER_EQUAL); - - // Windows 8 version is 6.2 - Interop.Kernel32.OSVERSIONINFOEX version = default; - unsafe - { - version.dwOSVersionInfoSize = sizeof(Interop.Kernel32.OSVERSIONINFOEX); - } - version.dwMajorVersion = 6; - version.dwMinorVersion = 2; - version.wServicePackMajor = 0; - version.wServicePackMinor = 0; - - return Interop.Kernel32.VerifyVersionInfoW(ref version, - Interop.Kernel32.VER_MAJORVERSION | Interop.Kernel32.VER_MINORVERSION | Interop.Kernel32.VER_SERVICEPACKMAJOR | Interop.Kernel32.VER_SERVICEPACKMINOR, - conditionMask); - } - } -#endif - #if FEATURE_COMINTEROP // Seperate type so a .cctor is not created for Enviroment which then would be triggered during startup private static class WinRT diff --git a/src/System.Private.CoreLib/src/System/GC.cs b/src/System.Private.CoreLib/src/System/GC.cs index 4485afe469..dd043e5c67 100644 --- a/src/System.Private.CoreLib/src/System/GC.cs +++ b/src/System.Private.CoreLib/src/System/GC.cs @@ -50,6 +50,56 @@ namespace System NotApplicable = 4 } + public readonly struct GCMemoryInfo + { + /// <summary> + /// High memory load threshold when the last GC occured + /// </summary> + public long HighMemoryLoadThresholdBytes { get; } + + /// <summary> + /// Memory load when the last GC ocurred + /// </summary> + public long MemoryLoadBytes { get; } + + /// <summary> + /// Total available memory for the GC to use when the last GC ocurred. By default this is the physical memory on the machine, but it may be customized by specifying a HardLimit. + /// </summary> + public long TotalAvailableMemoryBytes { get; } + + /// <summary> + /// The total heap size when the last GC ocurred + /// </summary> + public long HeapSizeBytes { get; } + + /// <summary> + /// The total fragmentation when the last GC ocurred + /// + /// Let's take the example below: + /// | OBJ_A | OBJ_B | OBJ_C | OBJ_D | OBJ_E | + /// + /// Let's say OBJ_B, OBJ_C and and OBJ_E are garbage and get collected, but the heap does not get compacted, the resulting heap will look like the following: + /// | OBJ_A | F | OBJ_D | + /// + /// The memory between OBJ_A and OBJ_D marked `F` is considered part of the FragmentedBytes, and will be used to allocate new objects. The memory after OBJ_D will not be + /// considered part of the FragmentedBytes, and will also be used to allocate new objects + /// </summary> + public long FragmentedBytes { get; } + + internal GCMemoryInfo(long highMemoryLoadThresholdBytes, + long memoryLoadBytes, + long totalAvailableMemoryBytes, + long heapSizeBytes, + long fragmentedBytes) + { + HighMemoryLoadThresholdBytes = highMemoryLoadThresholdBytes; + MemoryLoadBytes = memoryLoadBytes; + TotalAvailableMemoryBytes = totalAvailableMemoryBytes; + HeapSizeBytes = heapSizeBytes; + FragmentedBytes = fragmentedBytes; + } + } + public static class GC { [MethodImplAttribute(MethodImplOptions.InternalCall)] @@ -60,6 +110,21 @@ namespace System out UIntPtr lastRecordedHeapSize, out UIntPtr lastRecordedFragmentation); + public static GCMemoryInfo GetGCMemoryInfo() + { + GetMemoryInfo(out uint highMemLoadThreshold, + out ulong totalPhysicalMem, + out uint lastRecordedMemLoad, + out UIntPtr lastRecordedHeapSize, + out UIntPtr lastRecordedFragmentation); + + return new GCMemoryInfo((long)((double)highMemLoadThreshold / 100 * totalPhysicalMem), + (long)((double)lastRecordedMemLoad / 100 * totalPhysicalMem), + (long)totalPhysicalMem, + (long)(ulong)lastRecordedHeapSize, + (long)(ulong)lastRecordedFragmentation); + } + [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] internal static extern int _StartNoGCRegion(long totalSize, bool lohSizeKnown, long lohSize, bool disallowFullBlockingGC); diff --git a/src/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs index 4683b88632..42736a91b8 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs @@ -15,13 +15,13 @@ namespace System.Reflection { public abstract partial class Assembly : ICustomAttributeProvider, ISerializable { - // Locate an assembly by the long form of the assembly name. + // Locate an assembly by the long form of the assembly name. // eg. "Toolbox.dll, version=1.1.10.1220, locale=en, publickey=1234567890123456789012345678901234567890" [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static Assembly Load(string assemblyString) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.InternalLoad(assemblyString, ref stackMark); + return RuntimeAssembly.InternalLoad(assemblyString, ref stackMark, AssemblyLoadContext.CurrentContextualReflectionContext); } // Locate an assembly by its name. The name can be strong or @@ -33,12 +33,12 @@ namespace System.Reflection throw new ArgumentNullException(nameof(assemblyRef)); StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return Load(assemblyRef, ref stackMark, IntPtr.Zero); + return Load(assemblyRef, ref stackMark, AssemblyLoadContext.CurrentContextualReflectionContext); } // Locate an assembly by its name. The name can be strong or // weak. The assembly is loaded into the domain of the caller. - internal static Assembly Load(AssemblyName assemblyRef, ref StackCrawlMark stackMark, IntPtr ptrLoadContextBinder) + internal static Assembly Load(AssemblyName assemblyRef, ref StackCrawlMark stackMark, AssemblyLoadContext assemblyLoadContext) { AssemblyName modifiedAssemblyRef = null; if (assemblyRef.CodeBase != null) @@ -51,7 +51,7 @@ namespace System.Reflection modifiedAssemblyRef = assemblyRef; } - return RuntimeAssembly.InternalLoadAssemblyName(modifiedAssemblyRef, ref stackMark, ptrLoadContextBinder); + return RuntimeAssembly.InternalLoadAssemblyName(modifiedAssemblyRef, ref stackMark, assemblyLoadContext); } [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] diff --git a/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs new file mode 100644 index 0000000000..1f1c6f0f33 --- /dev/null +++ b/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs @@ -0,0 +1,111 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Configuration.Assemblies; +using System.Globalization; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.Serialization; + +namespace System.Reflection +{ + public sealed partial class AssemblyName : ICloneable, IDeserializationCallback, ISerializable + { + public AssemblyName(string assemblyName) + { + if (assemblyName == null) + throw new ArgumentNullException(nameof(assemblyName)); + if ((assemblyName.Length == 0) || + (assemblyName[0] == '\0')) + throw new ArgumentException(SR.Format_StringZeroLength); + + _name = assemblyName; + nInit(out RuntimeAssembly dummy, false); + } + + internal AssemblyName(string name, + byte[] publicKey, + byte[] publicKeyToken, + Version version, + CultureInfo cultureInfo, + AssemblyHashAlgorithm hashAlgorithm, + AssemblyVersionCompatibility versionCompatibility, + string codeBase, + AssemblyNameFlags flags, + StrongNameKeyPair keyPair) // Null if ref, matching Assembly if def + { + _name = name; + _publicKey = publicKey; + _publicKeyToken = publicKeyToken; + _version = version; + _cultureInfo = cultureInfo; + _hashAlgorithm = hashAlgorithm; + _versionCompatibility = versionCompatibility; + _codeBase = codeBase; + _flags = flags; + _strongNameKeyPair = keyPair; + } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern void nInit(out RuntimeAssembly assembly, bool raiseResolveEvent); + + // This call opens and closes the file, but does not add the + // assembly to the domain. + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern AssemblyName nGetFileInformation(string s); + + internal static AssemblyName GetFileInformationCore(string assemblyFile) + { + string fullPath = Path.GetFullPath(assemblyFile); + return nGetFileInformation(fullPath); + } + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern byte[] ComputePublicKeyToken(); + + internal void SetProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm) + { + ProcessorArchitecture = CalculateProcArchIndex(pek, ifm, _flags); + } + + internal static ProcessorArchitecture CalculateProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm, AssemblyNameFlags flags) + { + if (((uint)flags & 0xF0) == 0x70) + return ProcessorArchitecture.None; + + if ((pek & PortableExecutableKinds.PE32Plus) == PortableExecutableKinds.PE32Plus) + { + switch (ifm) + { + case ImageFileMachine.IA64: + return ProcessorArchitecture.IA64; + case ImageFileMachine.AMD64: + return ProcessorArchitecture.Amd64; + case ImageFileMachine.I386: + if ((pek & PortableExecutableKinds.ILOnly) == PortableExecutableKinds.ILOnly) + return ProcessorArchitecture.MSIL; + break; + } + } + else + { + if (ifm == ImageFileMachine.I386) + { + if ((pek & PortableExecutableKinds.Required32Bit) == PortableExecutableKinds.Required32Bit) + return ProcessorArchitecture.X86; + + if ((pek & PortableExecutableKinds.ILOnly) == PortableExecutableKinds.ILOnly) + return ProcessorArchitecture.MSIL; + + return ProcessorArchitecture.X86; + } + if (ifm == ImageFileMachine.ARM) + { + return ProcessorArchitecture.Arm; + } + } + return ProcessorArchitecture.None; + } + } +} diff --git a/src/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index 394a8f3c22..64622f58a8 100644 --- a/src/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -10,6 +10,7 @@ using System.IO; using StringBuilder = System.Text.StringBuilder; using System.Configuration.Assemblies; using StackCrawlMark = System.Threading.StackCrawlMark; +using System.Runtime.Loader; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Runtime.Serialization; @@ -86,11 +87,9 @@ namespace System.Reflection // is returned. public override AssemblyName GetName(bool copiedName) { - AssemblyName an = new AssemblyName(); - string codeBase = GetCodeBase(copiedName); - an.Init(GetSimpleName(), + var an = new AssemblyName(GetSimpleName(), GetPublicKey(), null, // public key token GetVersion(), @@ -151,11 +150,12 @@ namespace System.Reflection [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void GetType(RuntimeAssembly assembly, - string name, - bool throwOnError, - bool ignoreCase, - ObjectHandleOnStack type, - ObjectHandleOnStack keepAlive); + string name, + bool throwOnError, + bool ignoreCase, + ObjectHandleOnStack type, + ObjectHandleOnStack keepAlive, + ObjectHandleOnStack assemblyLoadContext); public override Type GetType(string name, bool throwOnError, bool ignoreCase) { @@ -165,7 +165,15 @@ namespace System.Reflection RuntimeType type = null; object keepAlive = null; - GetType(GetNativeHandle(), name, throwOnError, ignoreCase, JitHelpers.GetObjectHandleOnStack(ref type), JitHelpers.GetObjectHandleOnStack(ref keepAlive)); + AssemblyLoadContext assemblyLoadContextStack = AssemblyLoadContext.CurrentContextualReflectionContext; + + GetType(GetNativeHandle(), + name, + throwOnError, + ignoreCase, + JitHelpers.GetObjectHandleOnStack(ref type), + JitHelpers.GetObjectHandleOnStack(ref keepAlive), + JitHelpers.GetObjectHandleOnStack(ref assemblyLoadContextStack)); GC.KeepAlive(keepAlive); return type; @@ -295,7 +303,7 @@ namespace System.Reflection return CustomAttributeData.GetCustomAttributesInternal(this); } - internal static RuntimeAssembly InternalLoad(string assemblyString, ref StackCrawlMark stackMark) + internal static RuntimeAssembly InternalLoad(string assemblyString, ref StackCrawlMark stackMark, AssemblyLoadContext assemblyLoadContext = null) { RuntimeAssembly assembly; AssemblyName an = CreateAssemblyName(assemblyString, out assembly); @@ -306,7 +314,7 @@ namespace System.Reflection return assembly; } - return InternalLoadAssemblyName(an, ref stackMark); + return InternalLoadAssemblyName(an, ref stackMark, assemblyLoadContext); } // Creates AssemblyName. Fills assembly if AssemblyResolve event has been raised. @@ -329,7 +337,7 @@ namespace System.Reflection return an; } - internal static RuntimeAssembly InternalLoadAssemblyName(AssemblyName assemblyRef, ref StackCrawlMark stackMark, IntPtr ptrLoadContextBinder = default) + internal static RuntimeAssembly InternalLoadAssemblyName(AssemblyName assemblyRef, ref StackCrawlMark stackMark, AssemblyLoadContext assemblyLoadContext = null) { #if FEATURE_APPX if (ApplicationModel.IsUap) @@ -350,7 +358,7 @@ namespace System.Reflection string codeBase = VerifyCodeBase(assemblyRef.CodeBase); - return nLoad(assemblyRef, codeBase, null, ref stackMark, true, ptrLoadContextBinder); + return nLoad(assemblyRef, codeBase, null, ref stackMark, true, assemblyLoadContext); } [MethodImplAttribute(MethodImplOptions.InternalCall)] @@ -359,7 +367,7 @@ namespace System.Reflection RuntimeAssembly assemblyContext, ref StackCrawlMark stackMark, bool throwOnFileNotFound, - IntPtr ptrLoadContextBinder); + AssemblyLoadContext assemblyLoadContext = null); public override bool ReflectionOnly { @@ -649,7 +657,7 @@ namespace System.Reflection // This stack crawl mark is never used because the requesting assembly is explicitly specified, // so the value could be anything. StackCrawlMark unused = default; - RuntimeAssembly retAssembly = nLoad(an, null, this, ref unused, throwOnFileNotFound, IntPtr.Zero); + RuntimeAssembly retAssembly = nLoad(an, null, this, ref unused, throwOnFileNotFound); if (retAssembly == this) { diff --git a/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index 5cabe5158e..c95043b09a 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -104,7 +104,7 @@ namespace System.Runtime.Loader { Assembly resolvedAssembly = null; - Func<AssemblyLoadContext, AssemblyName, Assembly> assemblyResolveHandler = Resolving; + Func<AssemblyLoadContext, AssemblyName, Assembly> assemblyResolveHandler = _resolving; if (assemblyResolveHandler != null) { @@ -200,7 +200,7 @@ namespace System.Runtime.Loader { IntPtr resolvedDll = IntPtr.Zero; - Func<Assembly, string, IntPtr> dllResolveHandler = ResolvingUnmanagedDll; + Func<Assembly, string, IntPtr> dllResolveHandler = _resolvingUnmanagedDll; if (dllResolveHandler != null) { diff --git a/src/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/System.Private.CoreLib/src/System/RuntimeHandles.cs index 56694c63b8..a2da2be1df 100644 --- a/src/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Loader; using System.Runtime.Serialization; using System.Threading; @@ -414,17 +415,17 @@ namespace System [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void GetTypeByName(string name, bool throwOnError, bool ignoreCase, StackCrawlMarkHandle stackMark, - IntPtr pPrivHostBinder, + ObjectHandleOnStack assemblyLoadContext, bool loadTypeFromPartialName, ObjectHandleOnStack type, ObjectHandleOnStack keepalive); // Wrapper function to reduce the need for ifdefs. internal static RuntimeType GetTypeByName(string name, bool throwOnError, bool ignoreCase, ref StackCrawlMark stackMark, bool loadTypeFromPartialName) { - return GetTypeByName(name, throwOnError, ignoreCase, ref stackMark, IntPtr.Zero, loadTypeFromPartialName); + return GetTypeByName(name, throwOnError, ignoreCase, ref stackMark, AssemblyLoadContext.CurrentContextualReflectionContext, loadTypeFromPartialName); } internal static RuntimeType GetTypeByName(string name, bool throwOnError, bool ignoreCase, ref StackCrawlMark stackMark, - IntPtr pPrivHostBinder, + AssemblyLoadContext assemblyLoadContext, bool loadTypeFromPartialName) { if (name == null || name.Length == 0) @@ -438,9 +439,10 @@ namespace System RuntimeType type = null; object keepAlive = null; + AssemblyLoadContext assemblyLoadContextStack = assemblyLoadContext; GetTypeByName(name, throwOnError, ignoreCase, JitHelpers.GetStackCrawlMarkHandle(ref stackMark), - pPrivHostBinder, + JitHelpers.GetObjectHandleOnStack(ref assemblyLoadContextStack), loadTypeFromPartialName, JitHelpers.GetObjectHandleOnStack(ref type), JitHelpers.GetObjectHandleOnStack(ref keepAlive)); GC.KeepAlive(keepAlive); diff --git a/src/System.Private.CoreLib/src/System/Threading/Timer.CoreCLR.cs b/src/System.Private.CoreLib/src/System/Threading/Timer.CoreCLR.cs index 6e8306b74a..ca173d1068 100644 --- a/src/System.Private.CoreLib/src/System/Threading/Timer.CoreCLR.cs +++ b/src/System.Private.CoreLib/src/System/Threading/Timer.CoreCLR.cs @@ -14,37 +14,6 @@ namespace System.Threading { #region interface to native per-AppDomain timer -#if !FEATURE_PAL - private static int TickCount - { - get - { - // We need to keep our notion of time synchronized with the calls to SleepEx that drive - // the underlying native timer. In Win8, SleepEx does not count the time the machine spends - // sleeping/hibernating. Environment.TickCount (GetTickCount) *does* count that time, - // so we will get out of sync with SleepEx if we use that method. - // - // So, on Win8, we use QueryUnbiasedInterruptTime instead; this does not count time spent - // in sleep/hibernate mode. - if (Environment.IsWindows8OrAbove) - { - ulong time100ns; - - bool result = Interop.Kernel32.QueryUnbiasedInterruptTime(out time100ns); - if (!result) - throw Marshal.GetExceptionForHR(Marshal.GetLastWin32Error()); - - // convert to 100ns to milliseconds, and truncate to 32 bits. - return (int)(uint)(time100ns / 10000); - } - else - { - return Environment.TickCount; - } - } - } -#endif - // We use a SafeHandle to ensure that the native timer is destroyed when the AppDomain is unloaded. private sealed class AppDomainTimerSafeHandle : SafeHandleZeroOrMinusOneIsInvalid { diff --git a/src/System.Private.CoreLib/src/System/TypeNameParser.cs b/src/System.Private.CoreLib/src/System/TypeNameParser.cs index 3cd904e8a2..4c96d786fb 100644 --- a/src/System.Private.CoreLib/src/System/TypeNameParser.cs +++ b/src/System.Private.CoreLib/src/System/TypeNameParser.cs @@ -6,12 +6,13 @@ using System; using System.Diagnostics; using System.IO; using System.Reflection; -using System.Security; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Loader; +using System.Runtime.Versioning; +using System.Security; using System.Text; using System.Threading; -using System.Runtime.Versioning; using Microsoft.Win32.SafeHandles; namespace System @@ -192,7 +193,7 @@ namespace System { if (throwOnError) { - assembly = RuntimeAssembly.InternalLoad(asmName, ref stackMark); + assembly = RuntimeAssembly.InternalLoad(asmName, ref stackMark, AssemblyLoadContext.CurrentContextualReflectionContext); } else { @@ -200,7 +201,7 @@ namespace System // Other exceptions like BadImangeFormatException should still fly. try { - assembly = RuntimeAssembly.InternalLoad(asmName, ref stackMark); + assembly = RuntimeAssembly.InternalLoad(asmName, ref stackMark, AssemblyLoadContext.CurrentContextualReflectionContext); } catch (FileNotFoundException) { diff --git a/src/classlibnative/bcltype/system.cpp b/src/classlibnative/bcltype/system.cpp index 12397a330e..38e5bba9ad 100644 --- a/src/classlibnative/bcltype/system.cpp +++ b/src/classlibnative/bcltype/system.cpp @@ -325,13 +325,14 @@ INT32 QCALLTYPE SystemNative::GetProcessorCount() BEGIN_QCALL; +#ifndef FEATURE_PAL CPUGroupInfo::EnsureInitialized(); if(CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) { processorCount = CPUGroupInfo::GetNumActiveProcessors(); } - +#endif // !FEATURE_PAL // Processor count will be 0 if CPU groups are disabled/not supported if(processorCount == 0) { diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 42aa3009ea..e1864c81f7 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -423,6 +423,41 @@ private: ULONG_PTR _actCookie; }; +class ClrInstanceDetails +{ + static void * _currentClrInstance; + static unsigned int _currentAppDomainId; + +public: // static + static HRESULT GetDetails(void **clrInstance, unsigned int *appDomainId) + { + *clrInstance = _currentClrInstance; + *appDomainId = _currentAppDomainId; + return S_OK; + } + +public: + ClrInstanceDetails(void *clrInstance, unsigned int appDomainId) + { + _currentClrInstance = clrInstance; + _currentAppDomainId = appDomainId; + } + + ~ClrInstanceDetails() + { + _currentClrInstance = nullptr; + _currentAppDomainId = 0; + } +}; + +void * ClrInstanceDetails::_currentClrInstance; +unsigned int ClrInstanceDetails::_currentAppDomainId; + +extern "C" __declspec(dllexport) HRESULT __cdecl GetCurrentClrDetails(void **clrInstance, unsigned int *appDomainId) +{ + return ClrInstanceDetails::GetDetails(clrInstance, appDomainId); +} + bool TryLoadHostPolicy(StackSString& hostPolicyPath) { const WCHAR *hostpolicyName = W("hostpolicy.dll"); @@ -666,6 +701,7 @@ bool TryRun(const int argc, const wchar_t* argv[], Logger &log, const bool verbo { ActivationContext cxt{ log, managedAssemblyFullName.GetUnicode() }; + ClrInstanceDetails current{ host, domainId }; hr = host->ExecuteAssembly(domainId, managedAssemblyFullName, argc - 1, (argc - 1) ? &(argv[1]) : NULL, &exitCode); if (FAILED(hr)) diff --git a/src/coreclr/hosts/coreshim/CoreShim.cpp b/src/coreclr/hosts/coreshim/CoreShim.cpp index 7a5c3a1d1c..238e40fb87 100644 --- a/src/coreclr/hosts/coreshim/CoreShim.cpp +++ b/src/coreclr/hosts/coreshim/CoreShim.cpp @@ -334,6 +334,7 @@ HRESULT coreclr::CreateTpaList(_Inout_ std::string &tpaList, _In_opt_z_ const WC coreclr::coreclr(_Inout_ AutoModule hmod) : _hmod{ std::move(hmod) } + , _attached{ false } , _clrInst{ nullptr } , _appDomainId{ std::numeric_limits<uint32_t>::max() } { @@ -349,7 +350,7 @@ coreclr::coreclr(_Inout_ AutoModule hmod) coreclr::~coreclr() { - if (_clrInst != nullptr) + if (_clrInst != nullptr && !_attached) { HRESULT hr = _shutdown(_clrInst, _appDomainId); assert(SUCCEEDED(hr)); @@ -370,6 +371,21 @@ HRESULT coreclr::Initialize( appDomainName = "CoreShim"; HRESULT hr; + + // Check if this is hosted scenario - launched via CoreRun.exe + HMODULE mod = ::GetModuleHandleW(W("CoreRun.exe")); + if (mod != NULL) + { + using GetCurrentClrDetailsFunc = HRESULT(*)(void **clrInstance, unsigned int *appDomainId); + auto getCurrentClrDetails = (GetCurrentClrDetailsFunc)::GetProcAddress(mod, "GetCurrentClrDetails"); + RETURN_IF_FAILED(getCurrentClrDetails(&_clrInst, &_appDomainId)); + if (_clrInst != nullptr) + { + _attached = true; + return S_OK; + } + } + try { const std::wstring exePathW = GetExePath(); diff --git a/src/coreclr/hosts/coreshim/CoreShim.h b/src/coreclr/hosts/coreshim/CoreShim.h index d4c8b0aa6b..5875b457bc 100644 --- a/src/coreclr/hosts/coreshim/CoreShim.h +++ b/src/coreclr/hosts/coreshim/CoreShim.h @@ -174,6 +174,7 @@ public: private: AutoModule _hmod; + bool _attached; void *_clrInst; uint32_t _appDomainId; diff --git a/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp b/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp index 1a6bf118c4..fb155f69bb 100644 --- a/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp +++ b/src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp @@ -466,11 +466,6 @@ int ExecuteManagedAssembly( } } } - - if (dlclose(coreclrLib) != 0) - { - fprintf(stderr, "Warning - dlclose failed\n"); - } } else { diff --git a/src/dlls/mscordac/mscordac_unixexports.src b/src/dlls/mscordac/mscordac_unixexports.src index 3709d55356..9902cb6bb6 100644 --- a/src/dlls/mscordac/mscordac_unixexports.src +++ b/src/dlls/mscordac/mscordac_unixexports.src @@ -123,7 +123,6 @@ nativeStringResourceTable_mscorrc_debug #GetLongPathNameW #GetModuleFileNameW #GetProcAddress -#GetProcessAffinityMask #GetProcessHeap #GetShortPathNameW #GetStdHandle diff --git a/src/gc/env/gcenv.os.h b/src/gc/env/gcenv.os.h index 05dccf7a6d..7fa1ba7062 100644 --- a/src/gc/env/gcenv.os.h +++ b/src/gc/env/gcenv.os.h @@ -167,11 +167,18 @@ class AffinitySet public: + static const size_t BitsetDataSize = MAX_SUPPORTED_CPUS / BitsPerBitsetEntry; + AffinitySet() { memset(m_bitset, 0, sizeof(m_bitset)); } + uintptr_t* GetBitsetData() + { + return m_bitset; + } + // Check if the set contains a processor bool Contains(size_t cpuIndex) const { @@ -477,9 +484,6 @@ public: // Is NUMA support available static bool CanEnableGCNumaAware(); - // Gets the NUMA node for the processor - static bool GetNumaProcessorNode(uint16_t proc_no, uint16_t *node_no); - // Get processor number and optionally its NUMA node number for the specified heap number // Parameters: // heap_number - heap number to get the result for diff --git a/src/gc/unix/gcenv.unix.cpp b/src/gc/unix/gcenv.unix.cpp index c71d211e01..65a20d82f7 100644 --- a/src/gc/unix/gcenv.unix.cpp +++ b/src/gc/unix/gcenv.unix.cpp @@ -55,6 +55,33 @@ #include "globals.h" #include "cgroup.h" +#if HAVE_NUMA_H + +#include <numa.h> +#include <numaif.h> +#include <dlfcn.h> + +// List of all functions from the numa library that are used +#define FOR_ALL_NUMA_FUNCTIONS \ + PER_FUNCTION_BLOCK(mbind) \ + PER_FUNCTION_BLOCK(numa_available) \ + PER_FUNCTION_BLOCK(numa_max_node) \ + PER_FUNCTION_BLOCK(numa_node_of_cpu) + +// Declare pointers to all the used numa functions +#define PER_FUNCTION_BLOCK(fn) extern decltype(fn)* fn##_ptr; +FOR_ALL_NUMA_FUNCTIONS +#undef PER_FUNCTION_BLOCK + +// Redefine all calls to numa functions as calls through pointers that are set +// to the functions of libnuma in the initialization. +#define mbind(...) mbind_ptr(__VA_ARGS__) +#define numa_available() numa_available_ptr() +#define numa_max_node() numa_max_node_ptr() +#define numa_node_of_cpu(...) numa_node_of_cpu_ptr(__VA_ARGS__) + +#endif // HAVE_NUMA_H + #if defined(_ARM_) || defined(_ARM64_) #define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_CONF #else @@ -109,6 +136,74 @@ uint32_t g_pageSizeUnixInl = 0; AffinitySet g_processAffinitySet; +#if HAVE_CPUSET_T +typedef cpuset_t cpu_set_t; +#endif + +// The highest NUMA node available +int g_highestNumaNode = 0; +// Is numa available +bool g_numaAvailable = false; + +void* g_numaHandle = nullptr; + +#if HAVE_NUMA_H +#define PER_FUNCTION_BLOCK(fn) decltype(fn)* fn##_ptr; +FOR_ALL_NUMA_FUNCTIONS +#undef PER_FUNCTION_BLOCK +#endif // HAVE_NUMA_H + + +// Initialize data structures for getting and setting thread affinities to processors and +// querying NUMA related processor information. +// On systems with no NUMA support, it behaves as if there was a single NUMA node with +// a single group of processors. +void NUMASupportInitialize() +{ +#if HAVE_NUMA_H + g_numaHandle = dlopen("libnuma.so", RTLD_LAZY); + if (g_numaHandle == 0) + { + g_numaHandle = dlopen("libnuma.so.1", RTLD_LAZY); + } + if (g_numaHandle != 0) + { + dlsym(g_numaHandle, "numa_allocate_cpumask"); +#define PER_FUNCTION_BLOCK(fn) \ + fn##_ptr = (decltype(fn)*)dlsym(g_numaHandle, #fn); \ + if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from libnuma\n"); abort(); } +FOR_ALL_NUMA_FUNCTIONS +#undef PER_FUNCTION_BLOCK + + if (numa_available() == -1) + { + dlclose(g_numaHandle); + } + else + { + g_numaAvailable = true; + g_highestNumaNode = numa_max_node(); + } + } +#endif // HAVE_NUMA_H + if (!g_numaAvailable) + { + // No NUMA + g_highestNumaNode = 0; + } +} + +// Cleanup of the NUMA support data structures +void NUMASupportCleanup() +{ +#if HAVE_NUMA_H + if (g_numaAvailable) + { + dlclose(g_numaHandle); + } +#endif // HAVE_NUMA_H +} + // Initialize the interface implementation // Return: // true if it has succeeded, false if it has failed @@ -221,6 +316,8 @@ bool GCToOSInterface::Initialize() #endif // HAVE_SCHED_GETAFFINITY + NUMASupportInitialize(); + return true; } @@ -235,6 +332,7 @@ void GCToOSInterface::Shutdown() munmap(g_helperPage, OS_PAGE_SIZE); CleanupCGroup(); + NUMASupportCleanup(); } // Get numeric id of the current thread if possible on the @@ -468,8 +566,29 @@ void* GCToOSInterface::VirtualReserveAndCommitLargePages(size_t size) // true if it has succeeded, false if it has failed bool GCToOSInterface::VirtualCommit(void* address, size_t size, uint16_t node) { - assert(node == NUMA_NODE_UNDEFINED && "Numa allocation is not ported to local GC on unix yet"); - return mprotect(address, size, PROT_WRITE | PROT_READ) == 0; + bool success = mprotect(address, size, PROT_WRITE | PROT_READ) == 0; + +#if HAVE_NUMA_H + if (success && g_numaAvailable && (node != NUMA_NODE_UNDEFINED)) + { + if ((int)node <= g_highestNumaNode) + { + int usedNodeMaskBits = g_highestNumaNode + 1; + int nodeMaskLength = (usedNodeMaskBits + sizeof(unsigned long) - 1) / sizeof(unsigned long); + unsigned long nodeMask[nodeMaskLength]; + memset(nodeMask, 0, sizeof(nodeMask)); + + int index = node / sizeof(unsigned long); + nodeMask[index] = ((unsigned long)1) << (node & (sizeof(unsigned long) - 1)); + + int st = mbind(address, size, MPOL_PREFERRED, nodeMask, usedNodeMaskBits, 0); + assert(st == 0); + // If the mbind fails, we still return the allocated memory since the node is just a hint + } + } +#endif // HAVE_NUMA_H + + return success; } // Decomit virtual memory range. @@ -775,13 +894,7 @@ uint32_t GCToOSInterface::GetTotalProcessorCount() bool GCToOSInterface::CanEnableGCNumaAware() { - return false; -} - -bool GCToOSInterface::GetNumaProcessorNode(uint16_t proc_no, uint16_t *node_no) -{ - assert(!"Numa has not been ported to local GC for unix"); - return false; + return g_numaAvailable; } // Get processor number and optionally its NUMA node number for the specified heap number @@ -803,15 +916,14 @@ bool GCToOSInterface::GetProcessorForHeap(uint16_t heap_number, uint16_t* proc_n if (availableProcNumber == heap_number) { *proc_no = procNumber; - +#if HAVE_NUMA_H if (GCToOSInterface::CanEnableGCNumaAware()) { - if (!GCToOSInterface::GetNumaProcessorNode(procNumber, node_no)) - { - *node_no = NUMA_NODE_UNDEFINED; - } + int result = numa_node_of_cpu(procNumber); + *node_no = (result >= 0) ? (uint16_t)result : NUMA_NODE_UNDEFINED; } else +#endif // HAVE_NUMA_H { *node_no = NUMA_NODE_UNDEFINED; } diff --git a/src/gc/windows/gcenv.windows.cpp b/src/gc/windows/gcenv.windows.cpp index 86bd7038c0..5f6a0ff291 100644 --- a/src/gc/windows/gcenv.windows.cpp +++ b/src/gc/windows/gcenv.windows.cpp @@ -1286,19 +1286,6 @@ bool GCToOSInterface::CanEnableGCNumaAware() return g_fEnableGCNumaAware; } -bool GCToOSInterface::GetNumaProcessorNode(uint16_t proc_no, uint16_t *node_no) -{ - GroupProcNo groupProcNo(proc_no); - - PROCESSOR_NUMBER procNumber; - procNumber.Group = groupProcNo.GetGroup(); - procNumber.Number = (BYTE)groupProcNo.GetProcIndex(); - procNumber.Reserved = 0; - - assert(g_fEnableGCNumaAware); - return ::GetNumaProcessorNodeEx(&procNumber, node_no) != FALSE; -} - // Get processor number and optionally its NUMA node number for the specified heap number // Parameters: // heap_number - heap number to get the result for @@ -1310,53 +1297,66 @@ bool GCToOSInterface::GetProcessorForHeap(uint16_t heap_number, uint16_t* proc_n { bool success = false; - if (CanEnableGCCPUGroups()) + // Locate heap_number-th available processor + uint16_t procIndex; + size_t cnt = heap_number; + for (uint16_t i = 0; i < GCToOSInterface::GetTotalProcessorCount(); i++) { - uint16_t gn, gpn; - GetGroupForProcessor((uint16_t)heap_number, &gn, &gpn); - - *proc_no = GroupProcNo(gn, gpn).GetCombinedValue(); - - if (GCToOSInterface::CanEnableGCNumaAware()) + if (g_processAffinitySet.Contains(i)) { - if (!GCToOSInterface::GetNumaProcessorNode(*proc_no, node_no)) + if (cnt == 0) { - *node_no = NUMA_NODE_UNDEFINED; + procIndex = i; + success = true; + break; } + + cnt--; + } + } + + if (success) + { + WORD gn, gpn; + + if (CanEnableGCCPUGroups()) + { + GetGroupForProcessor(procIndex, &gn, &gpn); } else - { // no numa setting, each cpu group is treated as a node - *node_no = gn; + { + gn = GroupProcNo::NoGroup; + gpn = procIndex; } - success = true; - } - else - { - int bit_number = 0; - uint8_t proc_number = 0; - for (uintptr_t mask = 1; mask != 0; mask <<= 1) + GroupProcNo groupProcNo(gn, gpn); + *proc_no = groupProcNo.GetCombinedValue(); + + if (GCToOSInterface::CanEnableGCNumaAware()) { - if (g_processAffinitySet.Contains(proc_number)) + PROCESSOR_NUMBER procNumber; + + if (CanEnableGCCPUGroups()) { - if (bit_number == heap_number) - { - *proc_no = GroupProcNo(GroupProcNo::NoGroup, proc_number).GetCombinedValue(); + procNumber.Group = gn; + } + else + { + // Get the current processor group + GetCurrentProcessorNumberEx(&procNumber); + } - if (GCToOSInterface::CanEnableGCNumaAware()) - { - if (!GCToOSInterface::GetNumaProcessorNode(proc_number, node_no)) - { - *node_no = NUMA_NODE_UNDEFINED; - } - } + procNumber.Number = (BYTE)gpn; + procNumber.Reserved = 0; - success = true; - break; - } - bit_number++; + if (!GetNumaProcessorNodeEx(&procNumber, node_no)) + { + *node_no = NUMA_NODE_UNDEFINED; } - proc_number++; + } + else + { // no numa setting, each cpu group is treated as a node + *node_no = groupProcNo.GetGroup(); } } diff --git a/src/inc/utilcode.h b/src/inc/utilcode.h index 5b222b1ab9..cf4b8ddf12 100644 --- a/src/inc/utilcode.h +++ b/src/inc/utilcode.h @@ -1331,10 +1331,7 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, // Allocate free memory with specific alignment // LPVOID ClrVirtualAllocAligned(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, SIZE_T alignment); - -//****************************************************************************** -// Returns the number of processors that a process has been configured to run on -//****************************************************************************** + class NumaNodeInfo { private: @@ -1350,10 +1347,16 @@ public: // functions static LPVOID VirtualAllocExNuma(HANDLE hProc, LPVOID lpAddr, SIZE_T size, DWORD allocType, DWORD prot, DWORD node); +#ifndef FEATURE_PAL static BOOL GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, PUSHORT node_no); +#else // !FEATURE_PAL + static BOOL GetNumaProcessorNodeEx(USHORT proc_no, PUSHORT node_no); +#endif // !FEATURE_PAL #endif }; +#ifndef FEATURE_PAL + struct CPU_Group_Info { WORD nr_active; // at most 64 @@ -1413,9 +1416,15 @@ public: } }; -int GetCurrentProcessCpuCount(); DWORD_PTR GetCurrentProcessCpuMask(); +#endif // !FEATURE_PAL + +//****************************************************************************** +// Returns the number of processors that a process has been configured to run on +//****************************************************************************** +int GetCurrentProcessCpuCount(); + uint32_t GetOsPageSize(); diff --git a/src/jit/assertionprop.cpp b/src/jit/assertionprop.cpp index 8bb8ce4418..1b48491e73 100644 --- a/src/jit/assertionprop.cpp +++ b/src/jit/assertionprop.cpp @@ -2388,8 +2388,8 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) } // We want to use the Normal ValueNumber when checking for constants. - ValueNum vnCns = vnStore->VNConservativeNormalValue(tree->gtVNPair); - ValueNum vnLib = vnStore->VNLiberalNormalValue(tree->gtVNPair); + ValueNumPair vnPair = tree->gtVNPair; + ValueNum vnCns = vnStore->VNConservativeNormalValue(vnPair); // Check if node evaluates to a constant. if (!vnStore->IsVNConstant(vnCns)) @@ -2397,7 +2397,7 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) return nullptr; } - GenTree* newTree = tree; + GenTree* conValTree = nullptr; switch (vnStore->TypeOfVN(vnCns)) { case TYP_FLOAT: @@ -2407,20 +2407,13 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) if (tree->TypeGet() == TYP_INT) { // Same sized reinterpretation of bits to integer - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_INT); - tree->gtIntCon.gtIconVal = *(reinterpret_cast<int*>(&value)); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewIconNode(*(reinterpret_cast<int*>(&value))); } else { // Implicit assignment conversion to float or double assert(varTypeIsFloating(tree->TypeGet())); - - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_DBL); - tree->gtDblCon.gtDconVal = value; - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewDconNode(value, tree->TypeGet()); } break; } @@ -2431,21 +2424,13 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) if (tree->TypeGet() == TYP_LONG) { - // Same sized reinterpretation of bits to long - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_NATIVELONG); - tree->gtIntConCommon.SetLngValue(*(reinterpret_cast<INT64*>(&value))); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewLconNode(*(reinterpret_cast<INT64*>(&value))); } else { // Implicit assignment conversion to float or double assert(varTypeIsFloating(tree->TypeGet())); - - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_DBL); - tree->gtDblCon.gtDconVal = value; - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewDconNode(value, tree->TypeGet()); } break; } @@ -2460,9 +2445,7 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) // to be recorded as a relocation with the VM. if (!opts.compReloc) { - newTree = gtNewIconHandleNode(value, vnStore->GetHandleFlags(vnCns)); - newTree->gtVNPair = ValueNumPair(vnLib, vnCns); - newTree = optPrepareTreeForReplacement(tree, newTree); + conValTree = gtNewIconHandleNode(value, vnStore->GetHandleFlags(vnCns)); } } else @@ -2472,18 +2455,12 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) { case TYP_INT: // Implicit assignment conversion to smaller integer - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_INT); - tree->gtIntCon.gtIconVal = (int)value; - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewIconNode(static_cast<int>(value)); break; case TYP_LONG: // Same type no conversion required - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_NATIVELONG); - tree->gtIntConCommon.SetLngValue(value); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewLconNode(value); break; case TYP_FLOAT: @@ -2494,32 +2471,27 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) case TYP_DOUBLE: // Same sized reinterpretation of bits to double - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_DBL); - tree->gtDblCon.gtDconVal = *(reinterpret_cast<double*>(&value)); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewDconNode(*(reinterpret_cast<double*>(&value))); break; default: - return nullptr; + // Do not support such optimization. + break; } } } break; case TYP_REF: - if (tree->TypeGet() != TYP_REF) + { + assert(vnStore->ConstantValue<size_t>(vnCns) == 0); + // Support onle ref(ref(0)), do not support other forms (e.g byref(ref(0)). + if (tree->TypeGet() == TYP_REF) { - return nullptr; + conValTree = gtNewIconNode(0, TYP_REF); } - - assert(vnStore->ConstantValue<size_t>(vnCns) == 0); - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_INT); - tree->gtIntCon.gtIconVal = 0; - tree->ClearIconHandleMask(); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); - break; + } + break; case TYP_INT: { @@ -2531,9 +2503,7 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) // to be recorded as a relocation with the VM. if (!opts.compReloc) { - newTree = gtNewIconHandleNode(value, vnStore->GetHandleFlags(vnCns)); - newTree->gtVNPair = ValueNumPair(vnLib, vnCns); - newTree = optPrepareTreeForReplacement(tree, newTree); + conValTree = gtNewIconHandleNode(value, vnStore->GetHandleFlags(vnCns)); } } else @@ -2544,27 +2514,17 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) case TYP_REF: case TYP_INT: // Same type no conversion required - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_INT); - tree->gtIntCon.gtIconVal = value; - tree->ClearIconHandleMask(); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewIconNode(static_cast<int>(value)); break; case TYP_LONG: // Implicit assignment conversion to larger integer - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_NATIVELONG); - tree->gtIntConCommon.SetLngValue(value); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewLconNode(static_cast<int>(value)); break; case TYP_FLOAT: // Same sized reinterpretation of bits to float - newTree = optPrepareTreeForReplacement(tree, tree); - tree->ChangeOperConst(GT_CNS_DBL); - tree->gtDblCon.gtDconVal = *(reinterpret_cast<float*>(&value)); - tree->gtVNPair = ValueNumPair(vnLib, vnCns); + conValTree = gtNewDconNode(*(reinterpret_cast<float*>(&value)), TYP_FLOAT); break; case TYP_DOUBLE: @@ -2574,16 +2534,45 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) break; default: - return nullptr; + // Do not support (e.g. bool(const int)). + break; } } } break; + case TYP_BYREF: + // Do not support const byref optimization. + break; + default: - return nullptr; + // We do not record constants of other types. + unreached(); + break; + } + + if (conValTree != nullptr) + { + // Were able to optimize. + conValTree->gtVNPair = vnPair; + GenTree* sideEffList = optExtractSideEffListFromConst(tree); + if (sideEffList != nullptr) + { + // Replace as COMMA(side_effects, const value tree); + assert((sideEffList->gtFlags & GTF_SIDE_EFFECT) != 0); + return gtNewOperNode(GT_COMMA, conValTree->TypeGet(), sideEffList, conValTree); + } + else + { + // No side effects, replace as const value tree. + return conValTree; + } + } + else + { + // Was not able to optimize. + return nullptr; } - return newTree; } /******************************************************************************************************* @@ -3897,7 +3886,8 @@ GenTree* Compiler::optAssertionProp_BndsChk(ASSERT_VALARG_TP assertions, GenTree GenTree* Compiler::optAssertionProp_Update(GenTree* newTree, GenTree* tree, GenTreeStmt* stmt) { - noway_assert(newTree != nullptr); + assert(newTree != nullptr); + assert(tree != nullptr); if (stmt == nullptr) { @@ -3908,33 +3898,22 @@ GenTree* Compiler::optAssertionProp_Update(GenTree* newTree, GenTree* tree, GenT noway_assert(!optLocalAssertionProp); // If newTree == tree then we modified the tree in-place otherwise we have to - // locate our parent node and update it so that it points to newTree + // locate our parent node and update it so that it points to newTree. if (newTree != tree) { GenTree** link = gtFindLink(stmt, tree); -#ifdef DEBUG - if (link == nullptr) - { - noway_assert(!"gtFindLink failed!"); - printf("\nCould not find parent of:\n"); - gtDispTree(tree); - printf("\nIn this stmt:\n"); - gtDispTree(stmt); - } -#endif noway_assert(link != nullptr); - noway_assert(tree != nullptr); - if (link != nullptr) - { - // Replace the old operand with the newTree - *link = newTree; - // We only need to ensure that the gtNext field is set as it is used to traverse - // to the next node in the tree. We will re-morph this entire statement in - // optAssertionPropMain(). It will reset the gtPrev and gtNext links for all nodes. + // Replace the old operand with the newTree + *link = newTree; - newTree->gtNext = tree->gtNext; - } + // We only need to ensure that the gtNext field is set as it is used to traverse + // to the next node in the tree. We will re-morph this entire statement in + // optAssertionPropMain(). It will reset the gtPrev and gtNext links for all nodes. + newTree->gtNext = tree->gtNext; + + // Old tree should not be referenced anymore. + DEBUG_DESTROY_NODE(tree); } } @@ -4648,79 +4627,45 @@ struct VNAssertionPropVisitorInfo }; //------------------------------------------------------------------------------ -// optPrepareTreeForReplacement +// optExtractSideEffListFromConst // Extracts side effects from a tree so it can be replaced with a comma -// separated list of side effects + a new tree. +// separated list of side effects + a const tree. // // Note: -// The old and new trees may be the same. In this case, the tree will be -// appended to the side-effect list (if present) and returned. +// The caller expects that the root of the tree has no side effects and it +// won't be extracted. Otherwise the resulting comma tree would be bigger +// than the tree before optimization. // // Arguments: -// oldTree - The tree node to be dropped from the stmt expr. -// newTree - The tree node to append to the side effect list from "oldTree". +// tree - The tree node with constant value to extrace side-effects from. // // Return Value: -// Returns a comma separated list of side-effects present in the "oldTree". -// When "newTree" is non-null: -// 1. When side-effects are present in oldTree, newTree will be appended to the -// comma separated list. -// 2. When no side effects are present, then returns the "newTree" without -// any list. -// When "newTree" is null: -// 1. Returns the extracted side-effects from "oldTree" +// 1. Returns the extracted side-effects from "tree" // 2. When no side-effects are present, returns null. // -// Description: -// Either the "newTree" is returned when no side effects are present or a comma -// separated side effect list with "newTree" is returned. // -GenTree* Compiler::optPrepareTreeForReplacement(GenTree* oldTree, GenTree* newTree) +GenTree* Compiler::optExtractSideEffListFromConst(GenTree* tree) { - // If we have side effects, extract them and append newTree to the list. - GenTree* sideEffList = nullptr; - if ((oldTree->gtFlags & GTF_SIDE_EFFECT) != 0) - { - bool ignoreRoot = false; + assert(vnStore->IsVNConstant(vnStore->VNConservativeNormalValue(tree->gtVNPair))); - if (oldTree == newTree) - { - // If the caller passed the same tree as both old and new then it means - // that it expects that the root of the tree has no side effects and it - // won't be extracted. Otherwise the resulting comma tree would be invalid, - // having both op1 and op2 point to the same tree. - // - // Do a sanity check to ensure persistent side effects aren't discarded and - // tell gtExtractSideEffList to ignore the root of the tree. - assert(!gtNodeHasSideEffects(oldTree, GTF_PERSISTENT_SIDE_EFFECTS)); - // - // Exception side effects may be ignored if the root is known to be a constant - // (e.g. VN may evaluate a DIV/MOD node to a constant and the node may still - // have GTF_EXCEPT set, even if it does not actually throw any exceptions). - assert(!gtNodeHasSideEffects(oldTree, GTF_EXCEPT) || - vnStore->IsVNConstant(vnStore->VNConservativeNormalValue(oldTree->gtVNPair))); - - ignoreRoot = true; - } - - gtExtractSideEffList(oldTree, &sideEffList, GTF_SIDE_EFFECT, ignoreRoot); - } + GenTree* sideEffList = nullptr; - if (sideEffList != nullptr) + // If we have side effects, extract them. + if ((tree->gtFlags & GTF_SIDE_EFFECT) != 0) { - noway_assert((sideEffList->gtFlags & GTF_SIDE_EFFECT) != 0); + // Do a sanity check to ensure persistent side effects aren't discarded and + // tell gtExtractSideEffList to ignore the root of the tree. + assert(!gtNodeHasSideEffects(tree, GTF_PERSISTENT_SIDE_EFFECTS)); - if (newTree != nullptr) - { - newTree = gtNewOperNode(GT_COMMA, newTree->TypeGet(), sideEffList, newTree); - } - else - { - newTree = sideEffList; - } + // Exception side effects may be ignored because the root is known to be a constant + // (e.g. VN may evaluate a DIV/MOD node to a constant and the node may still + // have GTF_EXCEPT set, even if it does not actually throw any exceptions). + bool ignoreRoot = true; + + gtExtractSideEffList(tree, &sideEffList, GTF_SIDE_EFFECT, ignoreRoot); } - return newTree; + return sideEffList; } //------------------------------------------------------------------------------ @@ -4779,7 +4724,7 @@ GenTree* Compiler::optVNConstantPropOnJTrue(BasicBlock* block, GenTree* test) } // Prepare the tree for replacement so any side effects can be extracted. - GenTree* sideEffList = optPrepareTreeForReplacement(test, nullptr); + GenTree* sideEffList = optExtractSideEffListFromConst(relop); // Transform the relop's operands to be both zeroes. ValueNum vnZero = vnStore->VNZeroForType(TYP_INT); diff --git a/src/jit/compiler.h b/src/jit/compiler.h index 24153d6f51..c734b5a96f 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -2864,11 +2864,13 @@ public: #ifdef DEBUG void gtDispNode(GenTree* tree, IndentStack* indentStack, __in_z const char* msg, bool isLIR); - void gtDispVN(GenTree* tree); void gtDispConst(GenTree* tree); void gtDispLeaf(GenTree* tree, IndentStack* indentStack); void gtDispNodeName(GenTree* tree); void gtDispRegVal(GenTree* tree); + void gtDispZeroFieldSeq(GenTree* tree); + void gtDispVN(GenTree* tree); + void gtDispCommonEndLine(GenTree* tree); enum IndentInfo { @@ -6722,7 +6724,7 @@ public: fgWalkResult optVNConstantPropCurStmt(BasicBlock* block, GenTreeStmt* stmt, GenTree* tree); GenTree* optVNConstantPropOnJTrue(BasicBlock* block, GenTree* test); GenTree* optVNConstantPropOnTree(BasicBlock* block, GenTree* tree); - GenTree* optPrepareTreeForReplacement(GenTree* extractTree, GenTree* replaceTree); + GenTree* optExtractSideEffListFromConst(GenTree* tree); AssertionIndex GetAssertionCount() { diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp index 3075cf3bc1..b24ea0e422 100644 --- a/src/jit/flowgraph.cpp +++ b/src/jit/flowgraph.cpp @@ -20067,6 +20067,18 @@ void Compiler::fgTableDispBasicBlock(BasicBlock* block, int ibcColWidth /* = 0 * printf(" "); // + // Display natural loop number + // + if (block->bbNatLoopNum == BasicBlock::NOT_IN_LOOP) + { + printf(" "); + } + else + { + printf("%2d ", block->bbNatLoopNum); + } + + // // Display block IL range // @@ -20326,11 +20338,11 @@ void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, // clang-format off printf("\n"); - printf("------%*s-------------------------------------%*s-----------------------%*s----------------------------------------\n", + printf("------%*s-------------------------------------%*s--------------------------%*s----------------------------------------\n", padWidth, "------------", ibcColWidth, "------------", maxBlockNumWidth, "----"); - printf("BBnum %*sBBid ref try hnd %s weight %*s%s [IL range] [jump]%*s [EH region] [flags]\n", + printf("BBnum %*sBBid ref try hnd %s weight %*s%s lp [IL range] [jump]%*s [EH region] [flags]\n", padWidth, "", fgCheapPredsValid ? "cheap preds" : (fgComputePredsDone ? "preds " @@ -20340,7 +20352,7 @@ void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, : ""), maxBlockNumWidth, "" ); - printf("------%*s-------------------------------------%*s-----------------------%*s----------------------------------------\n", + printf("------%*s-------------------------------------%*s--------------------------%*s----------------------------------------\n", padWidth, "------------", ibcColWidth, "------------", maxBlockNumWidth, "----"); @@ -20364,17 +20376,19 @@ void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, if (block == fgFirstColdBlock) { - printf("~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~" - "~~~~~~~~~~~~~~~~\n", - padWidth, "~~~~~~~~~~~~", ibcColWidth, "~~~~~~~~~~~~", maxBlockNumWidth, "~~~~"); + printf( + "~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~~~%*s~~~~~~~~~~~~~~~~~~~~~~~~" + "~~~~~~~~~~~~~~~~\n", + padWidth, "~~~~~~~~~~~~", ibcColWidth, "~~~~~~~~~~~~", maxBlockNumWidth, "~~~~"); } #if FEATURE_EH_FUNCLETS if (block == fgFirstFuncletBB) { - printf("++++++%*s+++++++++++++++++++++++++++++++++++++%*s+++++++++++++++++++++++%*s++++++++++++++++++++++++" - "++++++++++++++++ funclets follow\n", - padWidth, "++++++++++++", ibcColWidth, "++++++++++++", maxBlockNumWidth, "++++"); + printf( + "++++++%*s+++++++++++++++++++++++++++++++++++++%*s++++++++++++++++++++++++++%*s++++++++++++++++++++++++" + "++++++++++++++++ funclets follow\n", + padWidth, "++++++++++++", ibcColWidth, "++++++++++++", maxBlockNumWidth, "++++"); } #endif // FEATURE_EH_FUNCLETS @@ -20386,9 +20400,10 @@ void Compiler::fgDispBasicBlocks(BasicBlock* firstBlock, BasicBlock* lastBlock, } } - printf("------%*s-------------------------------------%*s-----------------------%*s--------------------------------" - "--------\n", - padWidth, "------------", ibcColWidth, "------------", maxBlockNumWidth, "----"); + printf( + "------%*s-------------------------------------%*s--------------------------%*s--------------------------------" + "--------\n", + padWidth, "------------", ibcColWidth, "------------", maxBlockNumWidth, "----"); if (dumpTrees) { diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index 833d115cb2..45cc22e261 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -7943,15 +7943,15 @@ GenTree* Compiler::gtGetThisArg(GenTreeCall* call) if (call->gtCallLateArgs) { - regNumber thisReg = REG_ARG_0; unsigned argNum = 0; fgArgTabEntry* thisArgTabEntry = gtArgEntryByArgNum(call, argNum); GenTree* result = thisArgTabEntry->node; -#if !FEATURE_FIXED_OUT_ARGS - GenTree* lateArgs = call->gtCallLateArgs; - regList list = call->regArgList; - int index = 0; +#if !FEATURE_FIXED_OUT_ARGS && defined(DEBUG) + regNumber thisReg = REG_ARG_0; + GenTree* lateArgs = call->gtCallLateArgs; + regList list = call->regArgList; + int index = 0; while (lateArgs != NULL) { assert(lateArgs->gtOper == GT_LIST); @@ -7959,16 +7959,13 @@ GenTree* Compiler::gtGetThisArg(GenTreeCall* call) regNumber curArgReg = list[index]; if (curArgReg == thisReg) { - if (optAssertionPropagatedCurrentStmt) - result = lateArgs->gtOp.gtOp1; - assert(result == lateArgs->gtOp.gtOp1); } lateArgs = lateArgs->gtOp.gtOp2; index++; } -#endif +#endif // !FEATURE_FIXED_OUT_ARGS && defined(DEBUG) return result; } } @@ -9223,6 +9220,29 @@ void Compiler::gtDispNodeName(GenTree* tree) } } +//------------------------------------------------------------------------ +// gtDispZeroFieldSeq: If this node has a zero fieldSeq annotation +// then print this Field Sequence +// +void Compiler::gtDispZeroFieldSeq(GenTree* tree) +{ + NodeToFieldSeqMap* map = GetZeroOffsetFieldMap(); + + // THe most common case is having no entries in this map + if (map->GetCount() > 0) + { + FieldSeqNode* fldSeq = nullptr; + if (map->Lookup(tree, &fldSeq)) + { + printf(" Zero"); + gtDispFieldSeq(fldSeq); + } + } +} + +//------------------------------------------------------------------------ +// gtDispVN: Utility function that prints a tree's ValueNumber: gtVNPair +// void Compiler::gtDispVN(GenTree* tree) { if (tree->gtVNPair.GetLiberal() != ValueNumStore::NoVN) @@ -9234,6 +9254,22 @@ void Compiler::gtDispVN(GenTree* tree) } //------------------------------------------------------------------------ +// gtDispCommonEndLine +// Utility function that prints the following node information +// 1: The associated zero field sequence (if any) +// 2. The register assigned to this node (if any) +// 2. The value number assigned (if any) +// 3. A newline character +// +void Compiler::gtDispCommonEndLine(GenTree* tree) +{ + gtDispZeroFieldSeq(tree); + gtDispRegVal(tree); + gtDispVN(tree); + printf("\n"); +} + +//------------------------------------------------------------------------ // gtDispNode: Print a tree to jitstdout. // // Arguments: @@ -10192,8 +10228,6 @@ void Compiler::gtDispConst(GenTree* tree) default: assert(!"unexpected constant node"); } - - gtDispRegVal(tree); } void Compiler::gtDispFieldSeq(FieldSeqNode* pfsn) @@ -10445,8 +10479,6 @@ void Compiler::gtDispLeaf(GenTree* tree, IndentStack* indentStack) default: assert(!"don't know how to display tree leaf node"); } - - gtDispRegVal(tree); } //------------------------------------------------------------------------ @@ -10509,14 +10541,14 @@ void Compiler::gtDispTree(GenTree* tree, if (IsUninitialized(tree)) { /* Value used to initalize nodes */ - printf("Uninitialized tree node!"); + printf("Uninitialized tree node!\n"); return; } if (tree->gtOper >= GT_COUNT) { gtDispNode(tree, indentStack, msg, isLIR); - printf("Bogus operator!"); + printf("Bogus operator!\n"); return; } @@ -10526,8 +10558,8 @@ void Compiler::gtDispTree(GenTree* tree, { gtDispNode(tree, indentStack, msg, isLIR); gtDispLeaf(tree, indentStack); - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); + if (tree->OperIsLocalStore() && !topOnly) { gtDispChild(tree->gtOp.gtOp1, indentStack, IINone); @@ -10574,8 +10606,7 @@ void Compiler::gtDispTree(GenTree* tree, if (tree->OperGet() == GT_PHI) { gtDispNode(tree, indentStack, msg, isLIR); - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); if (!topOnly) { @@ -10816,9 +10847,7 @@ void Compiler::gtDispTree(GenTree* tree, } #endif // FEATURE_HW_INTRINSICS - gtDispRegVal(tree); - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); if (!topOnly && tree->gtOp.gtOp1) { @@ -10869,18 +10898,13 @@ void Compiler::gtDispTree(GenTree* tree, printf(" %s", eeGetFieldName(tree->gtField.gtFldHnd), 0); } + gtDispCommonEndLine(tree); + if (tree->gtField.gtFldObj && !topOnly) { - gtDispVN(tree); - printf("\n"); gtDispChild(tree->gtField.gtFldObj, indentStack, IIArcBottom); } - else - { - gtDispRegVal(tree); - gtDispVN(tree); - printf("\n"); - } + break; case GT_CALL: @@ -10915,12 +10939,7 @@ void Compiler::gtDispTree(GenTree* tree, printf(" (exactContextHnd=0x%p)", dspPtr(call->gtInlineCandidateInfo->exactContextHnd)); } - gtDispVN(call); - if (call->IsMultiRegCall()) - { - gtDispRegVal(call); - } - printf("\n"); + gtDispCommonEndLine(tree); if (!topOnly) { @@ -10991,8 +11010,7 @@ void Compiler::gtDispTree(GenTree* tree, break; case GT_ARR_ELEM: - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); if (!topOnly) { @@ -11008,8 +11026,8 @@ void Compiler::gtDispTree(GenTree* tree, break; case GT_ARR_OFFSET: - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); + if (!topOnly) { gtDispChild(tree->gtArrOffs.gtOffset, indentStack, IIArc, nullptr, topOnly); @@ -11019,8 +11037,8 @@ void Compiler::gtDispTree(GenTree* tree, break; case GT_CMPXCHG: - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); + if (!topOnly) { gtDispChild(tree->gtCmpXchg.gtOpLocation, indentStack, IIArc, nullptr, topOnly); @@ -11036,8 +11054,8 @@ void Compiler::gtDispTree(GenTree* tree, #ifdef FEATURE_HW_INTRINSICS case GT_HW_INTRINSIC_CHK: #endif // FEATURE_HW_INTRINSICS - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); + if (!topOnly) { gtDispChild(tree->gtBoundsChk.gtIndex, indentStack, IIArc, nullptr, topOnly); @@ -11055,8 +11073,8 @@ void Compiler::gtDispTree(GenTree* tree, { printf(" (init)"); } - gtDispVN(tree); - printf("\n"); + gtDispCommonEndLine(tree); + if (!topOnly) { if (tree->gtDynBlk.Data() != nullptr) diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index 0c9b5a70b1..f4a726e89f 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -2450,6 +2450,11 @@ PALAPI PAL_GetLogicalCpuCountFromOS(VOID); PALIMPORT +DWORD +PALAPI +PAL_GetTotalCpuCount(VOID); + +PALIMPORT size_t PALAPI PAL_GetRestrictedPhysicalMemoryLimit(VOID); @@ -3996,88 +4001,6 @@ CreatePipe( // NUMA related APIs // -typedef enum _PROCESSOR_CACHE_TYPE { - CacheUnified, - CacheInstruction, - CacheData, - CacheTrace -} PROCESSOR_CACHE_TYPE; - -typedef struct _PROCESSOR_NUMBER { - WORD Group; - BYTE Number; - BYTE Reserved; -} PROCESSOR_NUMBER, *PPROCESSOR_NUMBER; - -typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP { - RelationProcessorCore, - RelationNumaNode, - RelationCache, - RelationProcessorPackage, - RelationGroup, - RelationAll = 0xffff -} LOGICAL_PROCESSOR_RELATIONSHIP; - -typedef ULONG_PTR KAFFINITY; - -#define ANYSIZE_ARRAY 1 - -typedef struct _GROUP_AFFINITY { - KAFFINITY Mask; - WORD Group; - WORD Reserved[3]; -} GROUP_AFFINITY, *PGROUP_AFFINITY; - -typedef struct _PROCESSOR_GROUP_INFO { - BYTE MaximumProcessorCount; - BYTE ActiveProcessorCount; - BYTE Reserved[38]; - KAFFINITY ActiveProcessorMask; -} PROCESSOR_GROUP_INFO, *PPROCESSOR_GROUP_INFO; - -typedef struct _PROCESSOR_RELATIONSHIP { - BYTE Flags; - BYTE EfficiencyClass; - BYTE Reserved[21]; - WORD GroupCount; - GROUP_AFFINITY GroupMask[ANYSIZE_ARRAY]; -} PROCESSOR_RELATIONSHIP, *PPROCESSOR_RELATIONSHIP; - -typedef struct _GROUP_RELATIONSHIP { - WORD MaximumGroupCount; - WORD ActiveGroupCount; - BYTE Reserved[20]; - PROCESSOR_GROUP_INFO GroupInfo[ANYSIZE_ARRAY]; -} GROUP_RELATIONSHIP, *PGROUP_RELATIONSHIP; - -typedef struct _NUMA_NODE_RELATIONSHIP { - DWORD NodeNumber; - BYTE Reserved[20]; - GROUP_AFFINITY GroupMask; -} NUMA_NODE_RELATIONSHIP, *PNUMA_NODE_RELATIONSHIP; - -typedef struct _CACHE_RELATIONSHIP { - BYTE Level; - BYTE Associativity; - WORD LineSize; - DWORD CacheSize; - PROCESSOR_CACHE_TYPE Type; - BYTE Reserved[20]; - GROUP_AFFINITY GroupMask; -} CACHE_RELATIONSHIP, *PCACHE_RELATIONSHIP; - -typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX { - LOGICAL_PROCESSOR_RELATIONSHIP Relationship; - DWORD Size; - union { - PROCESSOR_RELATIONSHIP Processor; - NUMA_NODE_RELATIONSHIP NumaNode; - CACHE_RELATIONSHIP Cache; - GROUP_RELATIONSHIP Group; - }; -} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX; - - PALIMPORT BOOL PALAPI @@ -4088,10 +4011,7 @@ GetNumaHighestNodeNumber( PALIMPORT BOOL PALAPI -GetNumaProcessorNodeEx( - IN PPROCESSOR_NUMBER Processor, - OUT PUSHORT NodeNumber -); +PAL_GetNumaProcessorNode(WORD procNo, WORD* node); PALIMPORT LPVOID @@ -4108,61 +4028,12 @@ VirtualAllocExNuma( PALIMPORT BOOL PALAPI -GetLogicalProcessorInformationEx( - IN LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, - OUT OPTIONAL PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, - IN OUT PDWORD ReturnedLength -); - -PALIMPORT -DWORD_PTR -PALAPI -SetThreadAffinityMask( - IN HANDLE hThread, - IN DWORD_PTR dwThreadAffinityMask -); - -PALIMPORT -BOOL -PALAPI -SetThreadGroupAffinity( - IN HANDLE hThread, - IN const GROUP_AFFINITY *GroupAffinity, - OUT OPTIONAL PGROUP_AFFINITY PreviousGroupAffinity -); +PAL_SetCurrentThreadAffinity(WORD procNo); PALIMPORT BOOL PALAPI -GetThreadGroupAffinity( - IN HANDLE hThread, - OUT PGROUP_AFFINITY GroupAffinity -); - -PALIMPORT -VOID -PALAPI -GetCurrentProcessorNumberEx( - OUT PPROCESSOR_NUMBER ProcNumber -); - -PALIMPORT -BOOL -PALAPI -GetProcessAffinityMask( - IN HANDLE hProcess, - OUT PDWORD_PTR lpProcessAffinityMask, - OUT PDWORD_PTR lpSystemAffinityMask -); - -PALIMPORT -BOOL -PALAPI -SetThreadIdealProcessorEx( - IN HANDLE hThread, - IN PPROCESSOR_NUMBER lpIdealProcessor, - OUT PPROCESSOR_NUMBER lpPreviousIdealProcessor -); +PAL_GetCurrentThreadAffinitySet(SIZE_T size, UINT_PTR* data); // // The types of events that can be logged. diff --git a/src/pal/src/misc/sysinfo.cpp b/src/pal/src/misc/sysinfo.cpp index 2c14949b95..1a1a12f02f 100644 --- a/src/pal/src/misc/sysinfo.cpp +++ b/src/pal/src/misc/sysinfo.cpp @@ -95,24 +95,13 @@ SET_DEFAULT_DEBUG_CHANNEL(MISC); #endif #endif // __APPLE__ - DWORD PALAPI -PAL_GetLogicalCpuCountFromOS() +PAL_GetTotalCpuCount() { int nrcpus = 0; -#if HAVE_SCHED_GETAFFINITY - - cpu_set_t cpuSet; - int st = sched_getaffinity(0, sizeof(cpu_set_t), &cpuSet); - if (st != 0) - { - ASSERT("sched_getaffinity failed (%d)\n", errno); - } - - nrcpus = CPU_COUNT(&cpuSet); -#elif HAVE_SYSCONF +#if HAVE_SYSCONF #if defined(_ARM_) || defined(_ARM64_) #define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_CONF @@ -139,11 +128,36 @@ PAL_GetLogicalCpuCountFromOS() { ASSERT("sysctl failed for HW_NCPU (%d)\n", errno); } +#else // HAVE_SYSCONF +#error "Don't know how to get total CPU count on this platform" #endif // HAVE_SYSCONF return nrcpus; } +DWORD +PALAPI +PAL_GetLogicalCpuCountFromOS() +{ + int nrcpus = 0; + +#if HAVE_SCHED_GETAFFINITY + + cpu_set_t cpuSet; + int st = sched_getaffinity(0, sizeof(cpu_set_t), &cpuSet); + if (st != 0) + { + ASSERT("sched_getaffinity failed (%d)\n", errno); + } + + nrcpus = CPU_COUNT(&cpuSet); +#else // HAVE_SCHED_GETAFFINITY + nrcpus = PAL_GetTotalCpuCount(); +#endif // HAVE_SCHED_GETAFFINITY + + return nrcpus; +} + /*++ Function: GetSystemInfo diff --git a/src/pal/src/numa/numa.cpp b/src/pal/src/numa/numa.cpp index 9283a044da..4fb2bdb631 100644 --- a/src/pal/src/numa/numa.cpp +++ b/src/pal/src/numa/numa.cpp @@ -25,11 +25,6 @@ SET_DEFAULT_DEBUG_CHANNEL(NUMA); #include "pal/corunix.hpp" #include "pal/thread.hpp" -#if HAVE_PTHREAD_NP_H -#include <pthread_np.h> -#endif - -#include <pthread.h> #include <dlfcn.h> #ifdef __FreeBSD__ #include <stdlib.h> @@ -43,37 +38,6 @@ SET_DEFAULT_DEBUG_CHANNEL(NUMA); using namespace CorUnix; -#if HAVE_CPUSET_T -typedef cpuset_t cpu_set_t; -#endif - -// CPU affinity descriptor -struct CpuAffinity -{ - // NUMA node - BYTE Node; - // CPU number relative to the group the CPU is in - BYTE Number; - // CPU group - WORD Group; -}; - -// Array mapping global CPU index to its affinity -CpuAffinity *g_cpuToAffinity = NULL; - -// Array mapping CPU group and index in the group to the global CPU index -short *g_groupAndIndexToCpu = NULL; -// Array mapping CPU group to the corresponding affinity mask of the CPUs in the group -KAFFINITY *g_groupToCpuMask = NULL; -// Array mapping CPU group to the number of processors in the group -BYTE *g_groupToCpuCount = NULL; - -// Total number of processors in the system -int g_cpuCount = 0; -// Total number of possible processors in the system -int g_possibleCpuCount = 0; -// Total number of CPU groups -int g_groupCount = 0; // The highest NUMA node available int g_highestNumaNode = 0; // Is numa available @@ -87,92 +51,6 @@ FOR_ALL_NUMA_FUNCTIONS #undef PER_FUNCTION_BLOCK #endif // HAVE_NUMA_H -static const int MaxCpusPerGroup = 8 * sizeof(KAFFINITY); -static const WORD NO_GROUP = 0xffff; - -/*++ -Function: - FreeLookupArrays - -Free CPU and group lookup arrays ---*/ -VOID -FreeLookupArrays() -{ - free(g_groupAndIndexToCpu); - free(g_cpuToAffinity); - free(g_groupToCpuMask); - free(g_groupToCpuCount); - - g_groupAndIndexToCpu = NULL; - g_cpuToAffinity = NULL; - g_groupToCpuMask = NULL; - g_groupToCpuCount = NULL; -} - -/*++ -Function: - AllocateLookupArrays - -Allocate CPU and group lookup arrays -Return TRUE if the allocation succeeded ---*/ -BOOL -AllocateLookupArrays() -{ - g_groupAndIndexToCpu = (short*)malloc(g_groupCount * MaxCpusPerGroup * sizeof(short)); - if (g_groupAndIndexToCpu == NULL) - { - goto FAILED; - } - - g_cpuToAffinity = (CpuAffinity*)malloc(g_possibleCpuCount * sizeof(CpuAffinity)); - if (g_cpuToAffinity == NULL) - { - goto FAILED; - } - - g_groupToCpuMask = (KAFFINITY*)malloc(g_groupCount * sizeof(KAFFINITY)); - if (g_groupToCpuMask == NULL) - { - goto FAILED; - } - - g_groupToCpuCount = (BYTE*)malloc(g_groupCount * sizeof(BYTE)); - if (g_groupToCpuCount == NULL) - { - goto FAILED; - } - - memset(g_groupAndIndexToCpu, 0xff, g_groupCount * MaxCpusPerGroup * sizeof(short)); - memset(g_cpuToAffinity, 0xff, g_possibleCpuCount * sizeof(CpuAffinity)); - memset(g_groupToCpuMask, 0, g_groupCount * sizeof(KAFFINITY)); - memset(g_groupToCpuCount, 0, g_groupCount * sizeof(BYTE)); - - return TRUE; - -FAILED: - FreeLookupArrays(); - - return FALSE; -} - -/*++ -Function: - GetFullAffinityMask - -Get affinity mask for the specified number of processors with all -the processors enabled. ---*/ -KAFFINITY GetFullAffinityMask(int cpuCount) -{ - if ((size_t)cpuCount < sizeof(KAFFINITY) * 8) - { - return ((KAFFINITY)1 << (cpuCount)) - 1; - } - - return ~(KAFFINITY)0; -} /*++ Function: @@ -208,73 +86,6 @@ FOR_ALL_NUMA_FUNCTIONS else { g_numaAvailable = true; - - struct bitmask *mask = numa_allocate_cpumask(); - int numaNodesCount = numa_max_node() + 1; - - g_possibleCpuCount = numa_num_possible_cpus(); - g_cpuCount = 0; - g_groupCount = 0; - - for (int i = 0; i < numaNodesCount; i++) - { - int st = numa_node_to_cpus(i, mask); - // The only failure that can happen is that the mask is not large enough - // but that cannot happen since the mask was allocated by numa_allocate_cpumask - _ASSERTE(st == 0); - unsigned int nodeCpuCount = numa_bitmask_weight(mask); - g_cpuCount += nodeCpuCount; - unsigned int nodeGroupCount = (nodeCpuCount + MaxCpusPerGroup - 1) / MaxCpusPerGroup; - g_groupCount += nodeGroupCount; - } - - if (!AllocateLookupArrays()) - { - dlclose(numaHandle); - return FALSE; - } - - WORD currentGroup = 0; - int currentGroupCpus = 0; - - for (int i = 0; i < numaNodesCount; i++) - { - int st = numa_node_to_cpus(i, mask); - // The only failure that can happen is that the mask is not large enough - // but that cannot happen since the mask was allocated by numa_allocate_cpumask - _ASSERTE(st == 0); - unsigned int nodeCpuCount = numa_bitmask_weight(mask); - unsigned int nodeGroupCount = (nodeCpuCount + MaxCpusPerGroup - 1) / MaxCpusPerGroup; - for (int j = 0; j < g_possibleCpuCount; j++) - { - if (numa_bitmask_isbitset(mask, j)) - { - if (currentGroupCpus == MaxCpusPerGroup) - { - g_groupToCpuCount[currentGroup] = MaxCpusPerGroup; - g_groupToCpuMask[currentGroup] = GetFullAffinityMask(MaxCpusPerGroup); - currentGroupCpus = 0; - currentGroup++; - } - g_cpuToAffinity[j].Node = i; - g_cpuToAffinity[j].Group = currentGroup; - g_cpuToAffinity[j].Number = currentGroupCpus; - g_groupAndIndexToCpu[currentGroup * MaxCpusPerGroup + currentGroupCpus] = j; - currentGroupCpus++; - } - } - - if (currentGroupCpus != 0) - { - g_groupToCpuCount[currentGroup] = currentGroupCpus; - g_groupToCpuMask[currentGroup] = GetFullAffinityMask(currentGroupCpus); - currentGroupCpus = 0; - currentGroup++; - } - } - - numa_free_cpumask(mask); - g_highestNumaNode = numa_max_node(); } } @@ -282,21 +93,7 @@ FOR_ALL_NUMA_FUNCTIONS if (!g_numaAvailable) { // No NUMA - g_possibleCpuCount = PAL_GetLogicalCpuCountFromOS(); - g_cpuCount = PAL_GetLogicalCpuCountFromOS(); - g_groupCount = 1; g_highestNumaNode = 0; - - if (!AllocateLookupArrays()) - { - return FALSE; - } - - for (int i = 0; i < g_possibleCpuCount; i++) - { - g_cpuToAffinity[i].Number = i; - g_cpuToAffinity[i].Group = 0; - } } return TRUE; @@ -311,7 +108,6 @@ Cleanup of the NUMA support data structures VOID NUMASupportCleanup() { - FreeLookupArrays(); #if HAVE_NUMA_H if (g_numaAvailable) { @@ -346,493 +142,35 @@ GetNumaHighestNodeNumber( /*++ Function: - GetNumaProcessorNodeEx + PAL_GetNumaProcessorNode -See MSDN doc. ---*/ -BOOL -PALAPI -GetNumaProcessorNodeEx( - IN PPROCESSOR_NUMBER Processor, - OUT PUSHORT NodeNumber -) -{ - PERF_ENTRY(GetNumaProcessorNodeEx); - ENTRY("GetNumaProcessorNodeEx(Processor=%p, NodeNumber=%p)\n", Processor, NodeNumber); - - BOOL success = FALSE; +Abstract + Get NUMA node of a processor - if ((Processor->Group < g_groupCount) && - (Processor->Number < MaxCpusPerGroup) && - (Processor->Reserved == 0)) - { - short cpu = g_groupAndIndexToCpu[Processor->Group * MaxCpusPerGroup + Processor->Number]; - if (cpu != -1) - { - *NodeNumber = g_cpuToAffinity[cpu].Node; - success = TRUE; - } - } +Parameters: + procNo - number of the processor to get the NUMA node for + node - the resulting NUMA node - if (!success) - { - *NodeNumber = 0xffff; - SetLastError(ERROR_INVALID_PARAMETER); - } - - LOGEXIT("GetNumaProcessorNodeEx returns BOOL %d\n", success); - PERF_EXIT(GetNumaProcessorNodeEx); - - return success; -} - -/*++ -Function: - GetLogicalProcessorInformationEx - -See MSDN doc. +Return value: + TRUE if the function was able to get the NUMA node, FALSE if it has failed. --*/ BOOL PALAPI -GetLogicalProcessorInformationEx( - IN LOGICAL_PROCESSOR_RELATIONSHIP RelationshipType, - OUT OPTIONAL PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, - IN OUT PDWORD ReturnedLength -) -{ - PERF_ENTRY(GetLogicalProcessorInformationEx); - ENTRY("GetLogicalProcessorInformationEx(RelationshipType=%d, Buffer=%p, ReturnedLength=%p)\n", RelationshipType, Buffer, ReturnedLength); - - BOOL success = FALSE; - - if (RelationshipType == RelationGroup) - { - size_t requiredSize = __builtin_offsetof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, Group); - requiredSize += __builtin_offsetof(GROUP_RELATIONSHIP, GroupInfo); - requiredSize += g_groupCount * sizeof(PROCESSOR_GROUP_INFO); - - if (*ReturnedLength >= requiredSize) - { - Buffer->Relationship = RelationGroup; - Buffer->Size = requiredSize; - Buffer->Group.MaximumGroupCount = g_groupCount; - Buffer->Group.ActiveGroupCount = g_groupCount; - for (int i = 0; i < g_groupCount; i++) - { - Buffer->Group.GroupInfo[i].MaximumProcessorCount = MaxCpusPerGroup; - Buffer->Group.GroupInfo[i].ActiveProcessorCount = g_groupToCpuCount[i]; - Buffer->Group.GroupInfo[i].ActiveProcessorMask = g_groupToCpuMask[i]; - } - - success = TRUE; - } - else - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - } - - *ReturnedLength = requiredSize; - } - else - { - // We only support the group relationship - SetLastError(ERROR_INVALID_PARAMETER); - } - - LOGEXIT("GetLogicalProcessorInformationEx returns BOOL %d\n", success); - PERF_EXIT(GetLogicalProcessorInformationEx); - - return success; -} - -/*++ -Function: - GetThreadGroupAffinityInternal - -Get the group affinity for the specified pthread ---*/ -BOOL -GetThreadGroupAffinityInternal( - IN pthread_t thread, - OUT PGROUP_AFFINITY GroupAffinity -) +PAL_GetNumaProcessorNode(WORD procNo, WORD* node) { - BOOL success = FALSE; - -#if HAVE_PTHREAD_GETAFFINITY_NP - cpu_set_t cpuSet; - - int st = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuSet); - - if (st == 0) - { - WORD group = NO_GROUP; - KAFFINITY mask = 0; - - for (int i = 0; i < g_possibleCpuCount; i++) - { - if (CPU_ISSET(i, &cpuSet)) - { - WORD g = g_cpuToAffinity[i].Group; - // Unless the thread affinity was already set by SetThreadGroupAffinity, it is possible that - // the current thread has affinity with processors from multiple groups. So we report just the - // first group we find. - if (group == NO_GROUP || g == group) - { - group = g; - mask |= ((KAFFINITY)1) << g_cpuToAffinity[i].Number; - } - } - } - - GroupAffinity->Group = group; - GroupAffinity->Mask = mask; - success = TRUE; - } - else - { - SetLastError(ERROR_GEN_FAILURE); - } -#else // HAVE_PTHREAD_GETAFFINITY_NP - // There is no API to manage thread affinity, so let's return a group affinity - // with all the CPUs on the system. - GroupAffinity->Group = 0; - GroupAffinity->Mask = GetFullAffinityMask(g_possibleCpuCount); - success = TRUE; -#endif // HAVE_PTHREAD_GETAFFINITY_NP - - return success; -} - -/*++ -Function: - GetThreadGroupAffinity - -See MSDN doc. ---*/ -BOOL -PALAPI -GetThreadGroupAffinity( - IN HANDLE hThread, - OUT PGROUP_AFFINITY GroupAffinity -) -{ - PERF_ENTRY(GetThreadGroupAffinity); - ENTRY("GetThreadGroupAffinity(hThread=%p, GroupAffinity=%p)\n", hThread, GroupAffinity); - CPalThread *pCurrentThread = InternalGetCurrentThread(); - CPalThread *pTargetThread = NULL; - IPalObject *pTargetThreadObject = NULL; - - PAL_ERROR palErr = - InternalGetThreadDataFromHandle(pCurrentThread, hThread, - 0, // THREAD_SET_CONTEXT - &pTargetThread, &pTargetThreadObject); - - if (NO_ERROR != palErr) - { - ERROR("Unable to obtain thread data for handle %p (error %x)!\n", hThread, - palErr); - return FALSE; - } - - BOOL success = GetThreadGroupAffinityInternal( - pTargetThread->GetPThreadSelf(), GroupAffinity); - LOGEXIT("GetThreadGroupAffinity returns BOOL %d\n", success); - PERF_EXIT(GetThreadGroupAffinity); - - return success; -} - - -/*++ -Function: - SetThreadGroupAffinity - -See MSDN doc. ---*/ -BOOL -PALAPI -SetThreadGroupAffinity( - IN HANDLE hThread, - IN const GROUP_AFFINITY *GroupAffinity, - OUT OPTIONAL PGROUP_AFFINITY PreviousGroupAffinity -) -{ - PERF_ENTRY(SetThreadGroupAffinity); - ENTRY("SetThreadGroupAffinity(hThread=%p, GroupAffinity=%p, PreviousGroupAffinity=%p)\n", hThread, GroupAffinity, PreviousGroupAffinity); - - CPalThread *pCurrentThread = InternalGetCurrentThread(); - CPalThread *pTargetThread = NULL; - IPalObject *pTargetThreadObject = NULL; - - PAL_ERROR palErr = - InternalGetThreadDataFromHandle(pCurrentThread, hThread, - 0, // THREAD_SET_CONTEXT - &pTargetThread, &pTargetThreadObject); - - if (NO_ERROR != palErr) - { - ERROR("Unable to obtain thread data for handle %p (error %x)!\n", hThread, - palErr); - return FALSE; - } - - pthread_t thread = pTargetThread->GetPThreadSelf(); - - if (PreviousGroupAffinity != NULL) - { - GetThreadGroupAffinityInternal(thread, PreviousGroupAffinity); - } - -#if HAVE_PTHREAD_GETAFFINITY_NP - int groupStartIndex = GroupAffinity->Group * MaxCpusPerGroup; - KAFFINITY mask = 1; - cpu_set_t cpuSet; - CPU_ZERO(&cpuSet); - - for (int i = 0; i < MaxCpusPerGroup; i++, mask <<= 1) - { - if (GroupAffinity->Mask & mask) - { - int cpu = g_groupAndIndexToCpu[groupStartIndex + i]; - if (cpu != -1) - { - CPU_SET(cpu, &cpuSet); - } - } - } - - int st = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuSet); - - if (st != 0) - { - switch (st) - { - case EINVAL: - // There is no processor in the mask that is allowed to execute the process - SetLastError(ERROR_INVALID_PARAMETER); - break; - case ESRCH: - SetLastError(ERROR_INVALID_HANDLE); - break; - default: - SetLastError(ERROR_GEN_FAILURE); - break; - } - } - - BOOL success = (st == 0); -#else // HAVE_PTHREAD_GETAFFINITY_NP - // There is no API to manage thread affinity, so let's ignore the request - BOOL success = TRUE; -#endif // HAVE_PTHREAD_GETAFFINITY_NP - - LOGEXIT("SetThreadGroupAffinity returns BOOL %d\n", success); - PERF_EXIT(SetThreadGroupAffinity); - - return success; -} - -/*++ -Function: - SetThreadAffinityMask - -See MSDN doc. ---*/ -DWORD_PTR -PALAPI -SetThreadAffinityMask( - IN HANDLE hThread, - IN DWORD_PTR dwThreadAffinityMask -) -{ - PERF_ENTRY(SetThreadAffinityMask); - ENTRY("SetThreadAffinityMask(hThread=%p, dwThreadAffinityMask=%p)\n", hThread, dwThreadAffinityMask); - - CPalThread *pCurrentThread = InternalGetCurrentThread(); - CPalThread *pTargetThread = NULL; - IPalObject *pTargetThreadObject = NULL; - - PAL_ERROR palErr = - InternalGetThreadDataFromHandle(pCurrentThread, hThread, - 0, // THREAD_SET_CONTEXT - &pTargetThread, &pTargetThreadObject); - - if (NO_ERROR != palErr) - { - ERROR("Unable to obtain thread data for handle %p (error %x)!\n", hThread, - palErr); - return 0; - } - - pthread_t thread = pTargetThread->GetPThreadSelf(); - -#if HAVE_PTHREAD_GETAFFINITY_NP - cpu_set_t prevCpuSet; - CPU_ZERO(&prevCpuSet); - KAFFINITY prevMask = 0; - - int st = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &prevCpuSet); - - if (st == 0) - { - for (int i = 0; i < std::min(8 * (int)sizeof(KAFFINITY), g_possibleCpuCount); i++) - { - if (CPU_ISSET(i, &prevCpuSet)) - { - prevMask |= ((KAFFINITY)1) << i; - } - } - } - - cpu_set_t cpuSet; - CPU_ZERO(&cpuSet); - - int cpu = 0; - while (dwThreadAffinityMask) - { - if (dwThreadAffinityMask & 1) - { - CPU_SET(cpu, &cpuSet); - } - cpu++; - dwThreadAffinityMask >>= 1; - } - - st = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuSet); - - if (st != 0) - { - switch (st) - { - case EINVAL: - // There is no processor in the mask that is allowed to execute the - // process - SetLastError(ERROR_INVALID_PARAMETER); - break; - case ESRCH: - SetLastError(ERROR_INVALID_HANDLE); - break; - default: - SetLastError(ERROR_GEN_FAILURE); - break; - } - } - - DWORD_PTR ret = (st == 0) ? prevMask : 0; -#else // HAVE_PTHREAD_GETAFFINITY_NP - // There is no API to manage thread affinity, so let's ignore the request - DWORD_PTR ret = 0; -#endif // HAVE_PTHREAD_GETAFFINITY_NP - LOGEXIT("SetThreadAffinityMask returns %lu\n", ret); - PERF_EXIT(SetThreadAffinityMask); - - return ret; -} - -/*++ -Function: - GetCurrentProcessorNumberEx - -See MSDN doc. ---*/ -VOID -PALAPI -GetCurrentProcessorNumberEx( - OUT PPROCESSOR_NUMBER ProcNumber -) -{ - PERF_ENTRY(GetCurrentProcessorNumberEx); - ENTRY("GetCurrentProcessorNumberEx(ProcNumber=%p\n", ProcNumber); - - DWORD cpu = GetCurrentProcessorNumber(); - _ASSERTE((int)cpu < g_possibleCpuCount); - ProcNumber->Group = g_cpuToAffinity[cpu].Group; - ProcNumber->Number = g_cpuToAffinity[cpu].Number; - - LOGEXIT("GetCurrentProcessorNumberEx\n"); - PERF_EXIT(GetCurrentProcessorNumberEx); -} - -/*++ -Function: - GetProcessAffinityMask - -See MSDN doc. ---*/ -BOOL -PALAPI -GetProcessAffinityMask( - IN HANDLE hProcess, - OUT PDWORD_PTR lpProcessAffinityMask, - OUT PDWORD_PTR lpSystemAffinityMask -) -{ - PERF_ENTRY(GetProcessAffinityMask); - ENTRY("GetProcessAffinityMask(hProcess=%p, lpProcessAffinityMask=%p, lpSystemAffinityMask=%p\n", hProcess, lpProcessAffinityMask, lpSystemAffinityMask); - - BOOL success = FALSE; - - if (hProcess == GetCurrentProcess()) +#if HAVE_NUMA_H + if (g_numaAvailable) { - int cpuCountInMask = (g_cpuCount > 64) ? 64 : g_cpuCount; - - DWORD_PTR systemMask = GetFullAffinityMask(cpuCountInMask); - -#if HAVE_SCHED_GETAFFINITY - int pid = getpid(); - cpu_set_t cpuSet; - int st = sched_getaffinity(pid, sizeof(cpu_set_t), &cpuSet); - if (st == 0) - { - DWORD_PTR processMask = 0; - - for (int i = 0; i < cpuCountInMask; i++) - { - if (CPU_ISSET(i, &cpuSet)) - { - processMask |= ((DWORD_PTR)1) << i; - } - } - - success = TRUE; - - *lpProcessAffinityMask = processMask; - *lpSystemAffinityMask = systemMask; - } - else if (errno == EINVAL) + int result = numa_node_of_cpu(procNo); + if (result >= 0) { - // There are more processors than can fit in a cpu_set_t - // return all bits set for all processors (upto 64) for both masks. - *lpProcessAffinityMask = systemMask; - *lpSystemAffinityMask = systemMask; - success = TRUE; + *node = (WORD)result; + return TRUE; } - else - { - // We should not get any of the errors that the sched_getaffinity can return since none - // of them applies for the current thread, so this is an unexpected kind of failure. - SetLastError(ERROR_GEN_FAILURE); - } -#else // HAVE_SCHED_GETAFFINITY - // There is no API to manage thread affinity, so let's return both affinity masks - // with all the CPUs on the system set. - *lpSystemAffinityMask = systemMask; - *lpProcessAffinityMask = systemMask; - - success = TRUE; -#endif // HAVE_SCHED_GETAFFINITY } - else - { - // PAL supports getting affinity mask for the current process only - SetLastError(ERROR_INVALID_PARAMETER); - } - - LOGEXIT("GetProcessAffinityMask returns BOOL %d\n", success); - PERF_EXIT(GetProcessAffinityMask); +#endif // HAVE_NUMA_H - return success; + return FALSE; } /*++ @@ -866,15 +204,15 @@ VirtualAllocExNuma( #if HAVE_NUMA_H if (result != NULL && g_numaAvailable) { - int nodeMaskLength = (g_highestNumaNode + 1 + sizeof(unsigned long) - 1) / sizeof(unsigned long); - unsigned long *nodeMask = (unsigned long*)alloca(nodeMaskLength * sizeof(unsigned long)); - memset(nodeMask, 0, nodeMaskLength); + int usedNodeMaskBits = g_highestNumaNode + 1; + int nodeMaskLength = (usedNodeMaskBits + sizeof(unsigned long) - 1) / sizeof(unsigned long); + unsigned long nodeMask[nodeMaskLength]; + memset(nodeMask, 0, sizeof(nodeMask)); int index = nndPreferred / sizeof(unsigned long); - int mask = ((unsigned long)1) << (nndPreferred & (sizeof(unsigned long) - 1)); - nodeMask[index] = mask; + nodeMask[index] = ((unsigned long)1) << (nndPreferred & (sizeof(unsigned long) - 1)); - int st = mbind(result, dwSize, MPOL_PREFERRED, nodeMask, g_highestNumaNode, 0); + int st = mbind(result, dwSize, MPOL_PREFERRED, nodeMask, usedNodeMaskBits, 0); _ASSERTE(st == 0); // If the mbind fails, we still return the allocated memory since the nndPreferred is just a hint @@ -898,115 +236,3 @@ VirtualAllocExNuma( return result; } - -/*++ -Function: - SetThreadIdealProcessorEx - -See MSDN doc. ---*/ -BOOL -PALAPI -SetThreadIdealProcessorEx( - IN HANDLE hThread, - IN PPROCESSOR_NUMBER lpIdealProcessor, - OUT PPROCESSOR_NUMBER lpPreviousIdealProcessor) -{ - PERF_ENTRY(SetThreadIdealProcessorEx); - ENTRY("SetThreadIdealProcessorEx(hThread=%p, lpIdealProcessor=%p)\n", hThread, lpIdealProcessor); - - CPalThread *pCurrentThread = InternalGetCurrentThread(); - CPalThread *pTargetThread = NULL; - IPalObject *pTargetThreadObject = NULL; - - PAL_ERROR palErr = - InternalGetThreadDataFromHandle(pCurrentThread, hThread, - 0, // THREAD_SET_CONTEXT - &pTargetThread, &pTargetThreadObject); - - if (NO_ERROR != palErr) - { - ERROR("Unable to obtain thread data for handle %p (error %x)!\n", hThread, - palErr); - return 0; - } - - pthread_t thread = pTargetThread->GetPThreadSelf(); - -#if HAVE_PTHREAD_GETAFFINITY_NP - int cpu = -1; - if ((lpIdealProcessor->Group < g_groupCount) && - (lpIdealProcessor->Number < MaxCpusPerGroup) && - (lpIdealProcessor->Reserved == 0)) - { - cpu = g_groupAndIndexToCpu[lpIdealProcessor->Group * MaxCpusPerGroup + lpIdealProcessor->Number]; - } - - if (cpu == -1) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (lpPreviousIdealProcessor != NULL) - { - cpu_set_t prevCpuSet; - CPU_ZERO(&prevCpuSet); - DWORD prevCpu = GetCurrentProcessorNumber(); - - int st = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &prevCpuSet); - - if (st == 0) - { - for (int i = 0; i < g_possibleCpuCount; i++) - { - if (CPU_ISSET(i, &prevCpuSet)) - { - prevCpu = i; - break; - } - } - } - - _ASSERTE((int)prevCpu < g_possibleCpuCount); - lpPreviousIdealProcessor->Group = g_cpuToAffinity[prevCpu].Group; - lpPreviousIdealProcessor->Number = g_cpuToAffinity[prevCpu].Number; - lpPreviousIdealProcessor->Reserved = 0; - } - - cpu_set_t cpuSet; - CPU_ZERO(&cpuSet); - CPU_SET(cpu, &cpuSet); - - int st = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuSet); - - if (st != 0) - { - switch (st) - { - case EINVAL: - // There is no processor in the mask that is allowed to execute the - // process - SetLastError(ERROR_INVALID_PARAMETER); - break; - case ESRCH: - SetLastError(ERROR_INVALID_HANDLE); - break; - default: - SetLastError(ERROR_GEN_FAILURE); - break; - } - } - - BOOL success = (st == 0); - -#else // HAVE_PTHREAD_GETAFFINITY_NP - // There is no API to manage thread affinity, so let's ignore the request - BOOL success = FALSE; -#endif // HAVE_PTHREAD_GETAFFINITY_NP - - LOGEXIT("SetThreadIdealProcessorEx returns BOOL %d\n", success); - PERF_EXIT(SetThreadIdealProcessorEx); - - return success; -} diff --git a/src/pal/src/numa/numashim.h b/src/pal/src/numa/numashim.h index dd7f58d6de..e56cfab9d1 100644 --- a/src/pal/src/numa/numashim.h +++ b/src/pal/src/numa/numashim.h @@ -13,19 +13,12 @@ #include <numa.h> #include <numaif.h> -#define numa_free_cpumask numa_bitmask_free - // List of all functions from the numa library that are used #define FOR_ALL_NUMA_FUNCTIONS \ PER_FUNCTION_BLOCK(numa_available) \ PER_FUNCTION_BLOCK(mbind) \ - PER_FUNCTION_BLOCK(numa_num_possible_cpus) \ PER_FUNCTION_BLOCK(numa_max_node) \ - PER_FUNCTION_BLOCK(numa_allocate_cpumask) \ - PER_FUNCTION_BLOCK(numa_node_to_cpus) \ - PER_FUNCTION_BLOCK(numa_bitmask_weight) \ - PER_FUNCTION_BLOCK(numa_bitmask_isbitset) \ - PER_FUNCTION_BLOCK(numa_bitmask_free) + PER_FUNCTION_BLOCK(numa_node_of_cpu) // Declare pointers to all the used numa functions #define PER_FUNCTION_BLOCK(fn) extern decltype(fn)* fn##_ptr; @@ -36,13 +29,8 @@ FOR_ALL_NUMA_FUNCTIONS // to the functions of libnuma in the initialization. #define numa_available() numa_available_ptr() #define mbind(...) mbind_ptr(__VA_ARGS__) -#define numa_num_possible_cpus() numa_num_possible_cpus_ptr() #define numa_max_node() numa_max_node_ptr() -#define numa_allocate_cpumask() numa_allocate_cpumask_ptr() -#define numa_node_to_cpus(...) numa_node_to_cpus_ptr(__VA_ARGS__) -#define numa_bitmask_weight(...) numa_bitmask_weight_ptr(__VA_ARGS__) -#define numa_bitmask_isbitset(...) numa_bitmask_isbitset_ptr(__VA_ARGS__) -#define numa_bitmask_free(...) numa_bitmask_free_ptr(__VA_ARGS__) +#define numa_node_of_cpu(...) numa_node_of_cpu_ptr(__VA_ARGS__) #endif // HAVE_NUMA_H diff --git a/src/pal/src/thread/thread.cpp b/src/pal/src/thread/thread.cpp index 86a08639c7..ecbf7251cd 100644 --- a/src/pal/src/thread/thread.cpp +++ b/src/pal/src/thread/thread.cpp @@ -64,6 +64,7 @@ SET_DEFAULT_DEBUG_CHANNEL(THREAD); // some headers have code with asserts, so do #include "pal/fakepoll.h" #endif // HAVE_POLL #include <limits.h> +#include <algorithm> #if HAVE_SYS_LWP_H #include <sys/lwp.h> @@ -76,6 +77,10 @@ SET_DEFAULT_DEBUG_CHANNEL(THREAD); // some headers have code with asserts, so do extern "C" int _lwp_self (); #endif +#if HAVE_CPUSET_T +typedef cpuset_t cpu_set_t; +#endif + using namespace CorUnix; @@ -2921,3 +2926,95 @@ int CorUnix::CThreadMachExceptionHandlers::GetIndexOfHandler(exception_mask_t bm } #endif // HAVE_MACH_EXCEPTIONS + +/*++ +Function: + PAL_SetCurrentThreadAffinity + +Abstract + Set affinity of the current thread to the specified processor. + +Parameters: + procNo - number of the processor to affinitize the current thread to + +Return value: + TRUE if the function was able to set the affinity, FALSE if it has failed. +--*/ +BOOL +PALAPI +PAL_SetCurrentThreadAffinity(WORD procNo) +{ +#if HAVE_PTHREAD_GETAFFINITY_NP + cpu_set_t cpuSet; + CPU_ZERO(&cpuSet); + + int st = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuSet); + + if (st == 0) + { + CPU_SET(procNo, &cpuSet); + st = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuSet); + } + + return st == 0; +#else // HAVE_PTHREAD_GETAFFINITY_NP + // There is no API to manage thread affinity, so let's ignore the request + return FALSE; +#endif // HAVE_PTHREAD_GETAFFINITY_NP +} + +/*++ +Function: + PAL_SetCurrentThreadAffinity + +Abstract + Get affinity set of the current thread. The set is represented by an array of "size" entries of UINT_PTR type. + +Parameters: + size - number of entries in the "data" array + data - pointer to the data of the resulting set, the LSB of the first entry in the array represents processor 0 + +Return value: + TRUE if the function was able to get the affinity set, FALSE if it has failed. +--*/ +BOOL +PALAPI +PAL_GetCurrentThreadAffinitySet(SIZE_T size, UINT_PTR* data) +{ +#if HAVE_PTHREAD_GETAFFINITY_NP + cpu_set_t cpuSet; + CPU_ZERO(&cpuSet); + + int st = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuSet); + + if (st == 0) + { + const SIZE_T BitsPerBitsetEntry = 8 * sizeof(UINT_PTR); + int nrcpus = PAL_GetTotalCpuCount(); + + // Get info for as much processors as it is possible to fit into the resulting set + SIZE_T remainingCount = std::min(size * BitsPerBitsetEntry, (SIZE_T)nrcpus); + SIZE_T i = 0; + while (remainingCount != 0) + { + UINT_PTR entry = 0; + SIZE_T bitsToCopy = std::min(remainingCount, BitsPerBitsetEntry); + SIZE_T cpuSetOffset = i * BitsPerBitsetEntry; + for (SIZE_T j = 0; j < bitsToCopy; j++) + { + if (CPU_ISSET(cpuSetOffset + j, &cpuSet)) + { + entry |= (UINT_PTR)1 << j; + } + } + remainingCount -= bitsToCopy; + data[i++] = entry; + } + } + + return st == 0; +#else // HAVE_PTHREAD_GETAFFINITY_NP + // There is no API to manage thread affinity, so let's ignore the request + return FALSE; +#endif // HAVE_PTHREAD_GETAFFINITY_NP +} diff --git a/src/strongname/api/common.h b/src/strongname/api/common.h index 626d9bb720..4347ebae51 100644 --- a/src/strongname/api/common.h +++ b/src/strongname/api/common.h @@ -94,11 +94,11 @@ typedef VPTR(class LoaderAllocator) PTR_LoaderAllocator; typedef VPTR(class AppDomain) PTR_AppDomain; -typedef VPTR(class AppDomainBaseObject) PTR_AppDomainBaseObject; typedef DPTR(class ArrayBase) PTR_ArrayBase; typedef DPTR(class ArrayTypeDesc) PTR_ArrayTypeDesc; typedef DPTR(class Assembly) PTR_Assembly; typedef DPTR(class AssemblyBaseObject) PTR_AssemblyBaseObject; +typedef DPTR(class AssemblyLoadContextBaseObject) PTR_AssemblyLoadContextBaseObject; typedef DPTR(class AssemblyNameBaseObject) PTR_AssemblyNameBaseObject; typedef VPTR(class BaseDomain) PTR_BaseDomain; typedef DPTR(class MscorlibBinder) PTR_MscorlibBinder; diff --git a/src/utilcode/util.cpp b/src/utilcode/util.cpp index 61f41d7a22..e7091604af 100644 --- a/src/utilcode/util.cpp +++ b/src/utilcode/util.cpp @@ -733,10 +733,17 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, return ::VirtualAllocExNuma(hProc, lpAddr, dwSize, allocType, prot, node); } +#ifndef FEATURE_PAL /*static*/ BOOL NumaNodeInfo::GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, PUSHORT node_no) { return ::GetNumaProcessorNodeEx(proc_no, node_no); } +#else // !FEATURE_PAL +/*static*/ BOOL NumaNodeInfo::GetNumaProcessorNodeEx(USHORT proc_no, PUSHORT node_no) +{ + return PAL_GetNumaProcessorNode(proc_no, node_no); +} +#endif // !FEATURE_PAL #endif /*static*/ BOOL NumaNodeInfo::m_enableGCNumaAware = FALSE; @@ -749,15 +756,6 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_GCNumaAware) == 0) return FALSE; -#ifndef FEATURE_PAL - // check if required APIs are supported - HMODULE hMod = GetModuleHandleW(WINDOWS_KERNEL32_DLLNAME_W); -#else - HMODULE hMod = GetCLRModule(); -#endif - if (hMod == NULL) - return FALSE; - // fail to get the highest numa node number if (!::GetNumaHighestNodeNumber(&highest) || (highest == 0)) return FALSE; @@ -778,8 +776,10 @@ BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, m_enableGCNumaAware = InitNumaNodeInfoAPI(); } +#ifndef FEATURE_PAL + //****************************************************************************** -// NumaNodeInfo +// CPUGroupInfo //****************************************************************************** #if !defined(FEATURE_REDHAWK) /*static*/ //CPUGroupInfo::PNTQSIEx CPUGroupInfo::m_pNtQuerySystemInformationEx = NULL; @@ -1187,6 +1187,7 @@ BOOL CPUGroupInfo::GetCPUGroupRange(WORD group_number, WORD* group_begin, WORD* LIMITED_METHOD_CONTRACT; return m_threadUseAllCpuGroups; } +#endif // !FEATURE_PAL //****************************************************************************** // Returns the number of processors that a process has been configured to run on @@ -1206,6 +1207,8 @@ int GetCurrentProcessCpuCount() return cCPUs; unsigned int count = 0; + +#ifndef FEATURE_PAL DWORD_PTR pmask, smask; if (!GetProcessAffinityMask(GetCurrentProcess(), &pmask, &smask)) @@ -1233,18 +1236,20 @@ int GetCurrentProcessCpuCount() count = 64; } -#ifdef FEATURE_PAL - uint32_t cpuLimit; +#else // !FEATURE_PAL + count = PAL_GetLogicalCpuCountFromOS(); + uint32_t cpuLimit; if (PAL_GetCpuLimit(&cpuLimit) && cpuLimit < count) count = cpuLimit; -#endif +#endif // !FEATURE_PAL cCPUs = count; return count; } +#ifndef FEATURE_PAL DWORD_PTR GetCurrentProcessCpuMask() { CONTRACTL @@ -1266,6 +1271,7 @@ DWORD_PTR GetCurrentProcessCpuMask() return 0; #endif } +#endif // !FEATURE_PAL uint32_t GetOsPageSizeUncached() { diff --git a/src/vm/assemblynative.cpp b/src/vm/assemblynative.cpp index 9c1e467f2f..66214a17a3 100644 --- a/src/vm/assemblynative.cpp +++ b/src/vm/assemblynative.cpp @@ -38,22 +38,24 @@ FCIMPL6(Object*, AssemblyNative::Load, AssemblyNameBaseObject* assemblyNameUNSAF AssemblyBaseObject* requestingAssemblyUNSAFE, StackCrawlMark* stackMark, CLR_BOOL fThrowOnFileNotFound, - INT_PTR ptrLoadContextBinder) + AssemblyLoadContextBaseObject *assemblyLoadContextUNSAFE) { FCALL_CONTRACT; struct _gc { - ASSEMBLYNAMEREF assemblyName; - STRINGREF codeBase; - ASSEMBLYREF requestingAssembly; - ASSEMBLYREF rv; + ASSEMBLYNAMEREF assemblyName; + STRINGREF codeBase; + ASSEMBLYREF requestingAssembly; + ASSEMBLYREF rv; + ASSEMBLYLOADCONTEXTREF assemblyLoadContext; } gc; - gc.assemblyName = (ASSEMBLYNAMEREF) assemblyNameUNSAFE; - gc.codeBase = (STRINGREF) codeBaseUNSAFE; - gc.requestingAssembly = (ASSEMBLYREF) requestingAssemblyUNSAFE; - gc.rv = NULL; + gc.assemblyName = (ASSEMBLYNAMEREF) assemblyNameUNSAFE; + gc.codeBase = (STRINGREF) codeBaseUNSAFE; + gc.requestingAssembly = (ASSEMBLYREF) requestingAssemblyUNSAFE; + gc.rv = NULL; + gc.assemblyLoadContext = (ASSEMBLYLOADCONTEXTREF) assemblyLoadContextUNSAFE; HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); @@ -66,6 +68,8 @@ FCIMPL6(Object*, AssemblyNative::Load, AssemblyNameBaseObject* assemblyNameUNSAF DomainAssembly * pParentAssembly = NULL; Assembly * pRefAssembly = NULL; + INT_PTR ptrLoadContextBinder = (gc.assemblyLoadContext != NULL) ? gc.assemblyLoadContext->GetNativeAssemblyLoadContext() : NULL; + if(gc.assemblyName->GetSimpleName() == NULL) { if (gc.codeBase == NULL) @@ -446,7 +450,13 @@ void QCALLTYPE AssemblyNative::LoadTypeForWinRTTypeNameInContext(INT_PTR ptrAsse } #endif -void QCALLTYPE AssemblyNative::GetType(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive) +void QCALLTYPE AssemblyNative::GetType(QCall::AssemblyHandle pAssembly, + LPCWSTR wszName, + BOOL bThrowOnError, + BOOL bIgnoreCase, + QCall::ObjectHandleOnStack retType, + QCall::ObjectHandleOnStack keepAlive, + QCall::ObjectHandleOnStack pAssemblyLoadContext) { CONTRACTL { @@ -464,8 +474,20 @@ void QCALLTYPE AssemblyNative::GetType(QCall::AssemblyHandle pAssembly, LPCWSTR BOOL prohibitAsmQualifiedName = TRUE; + ICLRPrivBinder * pPrivHostBinder = NULL; + + if (*pAssemblyLoadContext.m_ppObject != NULL) + { + GCX_COOP(); + ASSEMBLYLOADCONTEXTREF * pAssemblyLoadContextRef = reinterpret_cast<ASSEMBLYLOADCONTEXTREF *>(pAssemblyLoadContext.m_ppObject); + + INT_PTR nativeAssemblyLoadContext = (*pAssemblyLoadContextRef)->GetNativeAssemblyLoadContext(); + + pPrivHostBinder = reinterpret_cast<ICLRPrivBinder *>(nativeAssemblyLoadContext); + } + // Load the class from this assembly (fail if it is in a different one). - retTypeHandle = TypeName::GetTypeManaged(wszName, pAssembly, bThrowOnError, bIgnoreCase, prohibitAsmQualifiedName, NULL, FALSE, (OBJECTREF*)keepAlive.m_ppObject); + retTypeHandle = TypeName::GetTypeManaged(wszName, pAssembly, bThrowOnError, bIgnoreCase, prohibitAsmQualifiedName, pAssembly->GetAssembly(), FALSE, (OBJECTREF*)keepAlive.m_ppObject, pPrivHostBinder); if (!retTypeHandle.IsNull()) { diff --git a/src/vm/assemblynative.hpp b/src/vm/assemblynative.hpp index 0ce2fb2327..12d4ff8658 100644 --- a/src/vm/assemblynative.hpp +++ b/src/vm/assemblynative.hpp @@ -37,7 +37,7 @@ public: AssemblyBaseObject* requestingAssemblyUNSAFE, StackCrawlMark* stackMark, CLR_BOOL fThrowOnFileNotFound, - INT_PTR ptrLoadContextBinder); + AssemblyLoadContextBaseObject *assemblyLoadContextUNSAFE); // // instance FCALLs @@ -78,7 +78,7 @@ public: void QCALLTYPE GetVersion(QCall::AssemblyHandle pAssembly, INT32* pMajorVersion, INT32* pMinorVersion, INT32*pBuildNumber, INT32* pRevisionNumber); static - void QCALLTYPE GetType(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive); + void QCALLTYPE GetType(QCall::AssemblyHandle pAssembly, LPCWSTR wszName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive, QCall::ObjectHandleOnStack pAssemblyLoadContext); static void QCALLTYPE GetForwardedType(QCall::AssemblyHandle pAssembly, mdToken mdtExternalType, QCall::ObjectHandleOnStack retType); diff --git a/src/vm/assemblyspec.cpp b/src/vm/assemblyspec.cpp index a044456ff9..b44cd26b6c 100644 --- a/src/vm/assemblyspec.cpp +++ b/src/vm/assemblyspec.cpp @@ -587,7 +587,7 @@ void AssemblySpec::AssemblyNameInit(ASSEMBLYNAMEREF* pAsmName, PEImage* pImageIn IfFailThrow(pImageInfo->GetMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, &hashAlgId, NULL, NULL, NULL)); } - MethodDescCallSite init(METHOD__ASSEMBLY_NAME__INIT); + MethodDescCallSite init(METHOD__ASSEMBLY_NAME__CTOR); ARG_SLOT MethodArgs[] = { diff --git a/src/vm/ceeload.cpp b/src/vm/ceeload.cpp index 9011cb8d90..8c86d00ab0 100644 --- a/src/vm/ceeload.cpp +++ b/src/vm/ceeload.cpp @@ -6353,6 +6353,11 @@ static HMODULE GetIJWHostForModule(Module* module) IMAGE_IMPORT_DESCRIPTOR* importDescriptor = (IMAGE_IMPORT_DESCRIPTOR*)pe->GetDirectoryData(pe->GetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_IMPORT)); + if (importDescriptor == nullptr) + { + return nullptr; + } + for(; importDescriptor->Characteristics != 0; importDescriptor++) { IMAGE_THUNK_DATA* importNameTable = (IMAGE_THUNK_DATA*)pe->GetRvaData(importDescriptor->OriginalFirstThunk); diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp index 1b85649d67..9ac0cc6a71 100644 --- a/src/vm/ceemain.cpp +++ b/src/vm/ceemain.cpp @@ -654,8 +654,9 @@ void EEStartupHelper(COINITIEE fFlags) // Need to do this as early as possible. Used by creating object handle // table inside Ref_Initialization() before GC is initialized. NumaNodeInfo::InitNumaNodeInfo(); +#ifndef FEATURE_PAL CPUGroupInfo::EnsureInitialized(); - +#endif // !FEATURE_PAL // Initialize global configuration settings based on startup flags // This needs to be done before the EE has started diff --git a/src/vm/comcallablewrapper.cpp b/src/vm/comcallablewrapper.cpp index 713d7c17b5..3eb9851206 100644 --- a/src/vm/comcallablewrapper.cpp +++ b/src/vm/comcallablewrapper.cpp @@ -918,7 +918,7 @@ void SimpleComCallWrapper::BuildRefCountLogMessage(LPCWSTR wszOperation, StackSS LPCUTF8 pszNamespace; if (SUCCEEDED(m_pMT->GetMDImport()->GetNameOfTypeDef(m_pMT->GetCl(), &pszClassName, &pszNamespace))) { - OBJECTHANDLE handle = GetMainWrapper()->GetRawObjectHandle(); + OBJECTHANDLE handle = GetMainWrapper()->GetObjectHandle(); _UNCHECKED_OBJECTREF obj = NULL; // Force retriving the handle without using OBJECTREF and under cooperative mode @@ -2016,12 +2016,27 @@ void SimpleComCallWrapper::EnumConnectionPoints(IEnumConnectionPoints **ppEnumCP // //-------------------------------------------------------------------------- - //-------------------------------------------------------------------------- -// void ComCallWrapper::MarkHandleWeak() -// mark the wrapper as holding a weak handle to the object +// Check if the wrapper has been deactivated //-------------------------------------------------------------------------- +BOOL ComCallWrapper::IsHandleWeak() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + SimpleComCallWrapper* simpleWrap = GetSimpleWrapper(); + _ASSERTE(simpleWrap); + return simpleWrap->IsHandleWeak(); +} +//-------------------------------------------------------------------------- +// Mark the wrapper as holding a weak handle to the object +//-------------------------------------------------------------------------- void ComCallWrapper::MarkHandleWeak() { CONTRACTL @@ -2032,18 +2047,51 @@ void ComCallWrapper::MarkHandleWeak() } CONTRACTL_END; - SyncBlock* pSyncBlock = GetSyncBlock(); - _ASSERTE(pSyncBlock); + SimpleComCallWrapper* simpleWrap = GetSimpleWrapper(); + _ASSERTE(simpleWrap); + simpleWrap->MarkHandleWeak(); +} + +//-------------------------------------------------------------------------- +// Mark the wrapper as not having a weak handle +//-------------------------------------------------------------------------- +void ComCallWrapper::ResetHandleStrength() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; - GetSimpleWrapper()->MarkHandleWeak(); + SimpleComCallWrapper* simpleWrap = GetSimpleWrapper(); + _ASSERTE(simpleWrap); + simpleWrap->ResetHandleStrength(); } //-------------------------------------------------------------------------- -// void ComCallWrapper::ResetHandleStrength() -// mark the wrapper as not having a weak handle +// Check if the wrapper was activated via COM //-------------------------------------------------------------------------- +BOOL ComCallWrapper::IsComActivated() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; -void ComCallWrapper::ResetHandleStrength() + SimpleComCallWrapper* simpleWrap = GetSimpleWrapper(); + _ASSERTE(simpleWrap); + return simpleWrap->IsComActivated(); +} + +//-------------------------------------------------------------------------- +// Mark the wrapper as being created via COM activation +//-------------------------------------------------------------------------- +VOID ComCallWrapper::MarkComActivated() { CONTRACTL { @@ -2052,11 +2100,10 @@ void ComCallWrapper::ResetHandleStrength() MODE_ANY; } CONTRACTL_END; - - SyncBlock* pSyncBlock = GetSyncBlock(); - _ASSERTE(pSyncBlock); - GetSimpleWrapper()->ResetHandleStrength(); + SimpleComCallWrapper* simpleWrap = GetSimpleWrapper(); + _ASSERTE(simpleWrap); + simpleWrap->MarkComActivated(); } //-------------------------------------------------------------------------- diff --git a/src/vm/comcallablewrapper.h b/src/vm/comcallablewrapper.h index 8ec126fbfc..5773a9d8c8 100644 --- a/src/vm/comcallablewrapper.h +++ b/src/vm/comcallablewrapper.h @@ -997,27 +997,20 @@ private: }; public: - VOID ResetHandleStrength(); + BOOL IsHandleWeak(); VOID MarkHandleWeak(); + VOID ResetHandleStrength(); - BOOL IsHandleWeak(); + BOOL IsComActivated(); + VOID MarkComActivated(); - OBJECTHANDLE GetObjectHandle(); - OBJECTHANDLE GetRawObjectHandle() { LIMITED_METHOD_CONTRACT; return m_ppThis; } // no NULL check + OBJECTHANDLE GetObjectHandle() { LIMITED_METHOD_CONTRACT; return m_ppThis; } -protected: // don't instantiate this class directly - ComCallWrapper() - { - LIMITED_METHOD_CONTRACT; - } - ~ComCallWrapper() - { - LIMITED_METHOD_CONTRACT; - } - - void Init(); + ComCallWrapper() = delete; + ~ComCallWrapper() = delete; +protected: #ifndef DACCESS_COMPILE inline static void SetNext(ComCallWrapper* pWrap, ComCallWrapper* pNextWrapper) { @@ -1438,7 +1431,7 @@ private: enum_IsAggregated = 0x1, enum_IsExtendsCom = 0x2, enum_IsHandleWeak = 0x4, - // unused = 0x8, + enum_IsComActivated = 0x8, // unused = 0x10, enum_IsPegged = 0x80, // unused = 0x100, @@ -1622,6 +1615,18 @@ public: return m_flags & enum_IsExtendsCom; } + BOOL IsComActivated() + { + LIMITED_METHOD_CONTRACT; + return m_flags & enum_IsComActivated; + } + + void MarkComActivated() + { + LIMITED_METHOD_CONTRACT; + FastInterlockOr((ULONG*)&m_flags, enum_IsComActivated); + } + inline BOOL IsPegged() { LIMITED_METHOD_DAC_CONTRACT; @@ -2060,20 +2065,6 @@ private: LONGLONG m_llRefCount; }; -inline OBJECTHANDLE ComCallWrapper::GetObjectHandle() -{ - CONTRACT (OBJECTHANDLE) - { - WRAPPER(THROWS); - WRAPPER(GC_TRIGGERS); - MODE_COOPERATIVE; - POSTCONDITION(CheckPointer(RETVAL)); - } - CONTRACT_END; - - RETURN m_ppThis; -} - //-------------------------------------------------------------------------------- // ComCallWrapper* ComCallWrapper::InlineGetWrapper(OBJECTREF* ppObj, ComCallWrapperTemplate *pTemplate) // returns the wrapper for the object, if not yet created, creates one @@ -2275,8 +2266,6 @@ inline ULONG ComCallWrapper::GetJupiterRefCount() return m_pSimpleWrapper->GetJupiterRefCount(); } - - inline PTR_ComCallWrapper ComCallWrapper::GetWrapperFromIP(PTR_IUnknown pUnk) { CONTRACT (PTR_ComCallWrapper) @@ -2340,27 +2329,6 @@ inline PTR_ComCallWrapperTemplate ComCallWrapper::GetComCallWrapperTemplate() return GetSimpleWrapper()->GetComCallWrapperTemplate(); } -//-------------------------------------------------------------------------- -// BOOL ComCallWrapper::BOOL IsHandleWeak() -// check if the wrapper has been deactivated -// Moved here to make DAC build happy and hopefully get it inlined -//-------------------------------------------------------------------------- -inline BOOL ComCallWrapper::IsHandleWeak() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - - SimpleComCallWrapper* pSimpleWrap = GetSimpleWrapper(); - _ASSERTE(pSimpleWrap); - - return pSimpleWrap->IsHandleWeak(); -} - inline BOOL ComCallWrapper::IsWrapperActive() { CONTRACTL @@ -2384,12 +2352,12 @@ inline BOOL ComCallWrapper::IsWrapperActive() BOOL bHasStrongCOMRefCount = ((cbRef > 0) || bHasJupiterStrongRefCount); - BOOL bIsWrapperActive = (bHasStrongCOMRefCount && !IsHandleWeak()); + BOOL bIsWrapperActive = (bHasStrongCOMRefCount && !m_pSimpleWrapper->IsHandleWeak()); LOG((LF_INTEROP, LL_INFO1000, "CCW 0x%p: cbRef = 0x%x, cbJupiterRef = 0x%x, IsPegged = %d, GlobalPegging = %d, IsHandleWeak = %d\n", this, - cbRef, cbJupiterRef, IsPegged(), RCWWalker::IsGlobalPeggingOn(), IsHandleWeak())); + cbRef, cbJupiterRef, m_pSimpleWrapper->IsPegged(), RCWWalker::IsGlobalPeggingOn(), m_pSimpleWrapper->IsHandleWeak())); LOG((LF_INTEROP, LL_INFO1000, "CCW 0x%p: IsWrapperActive returned %d\n", this, bIsWrapperActive)); return bIsWrapperActive; diff --git a/src/vm/common.h b/src/vm/common.h index 61ba2a7514..6fd5a37ad5 100644 --- a/src/vm/common.h +++ b/src/vm/common.h @@ -114,11 +114,11 @@ typedef VPTR(class LoaderAllocator) PTR_LoaderAllocator; typedef VPTR(class AppDomain) PTR_AppDomain; -typedef VPTR(class AppDomainBaseObject) PTR_AppDomainBaseObject; typedef DPTR(class ArrayBase) PTR_ArrayBase; typedef DPTR(class ArrayTypeDesc) PTR_ArrayTypeDesc; typedef DPTR(class Assembly) PTR_Assembly; typedef DPTR(class AssemblyBaseObject) PTR_AssemblyBaseObject; +typedef DPTR(class AssemblyLoadContextBaseObject) PTR_AssemblyLoadContextBaseObject; typedef DPTR(class AssemblyNameBaseObject) PTR_AssemblyNameBaseObject; typedef VPTR(class BaseDomain) PTR_BaseDomain; typedef DPTR(class ClassLoader) PTR_ClassLoader; diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h index 7f617caca5..ab2da6555d 100644 --- a/src/vm/ecalllist.h +++ b/src/vm/ecalllist.h @@ -536,7 +536,7 @@ FCFuncEnd() FCFuncStart(gAssemblyNameFuncs) FCFuncElement("nInit", AssemblyNameNative::Init) - FCFuncElement("nGetPublicKeyToken", AssemblyNameNative::GetPublicKeyToken) + FCFuncElement("ComputePublicKeyToken", AssemblyNameNative::GetPublicKeyToken) FCFuncElement("nGetFileInformation", AssemblyNameNative::GetFileInformation) FCFuncEnd() diff --git a/src/vm/eeconfig.cpp b/src/vm/eeconfig.cpp index e59a85e1e5..9cb07fc2e8 100644 --- a/src/vm/eeconfig.cpp +++ b/src/vm/eeconfig.cpp @@ -1226,7 +1226,14 @@ HRESULT EEConfig::sync() tieredCompilation_StartupTier_CallCountingDelayMs = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TC_StartupTier_CallCountingDelayMs); - if (CPUGroupInfo::HadSingleProcessorAtStartup()) + +#ifndef FEATURE_PAL + bool hadSingleProcessorAtStartup = CPUGroupInfo::HadSingleProcessorAtStartup(); +#else // !FEATURE_PAL + bool hadSingleProcessorAtStartup = g_SystemInfo.dwNumberOfProcessors == 1; +#endif // !FEATURE_PAL + + if (hadSingleProcessorAtStartup) { DWORD delayMultiplier = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_TC_StartupTier_DelaySingleProcMultiplier); diff --git a/src/vm/gcenv.os.cpp b/src/vm/gcenv.os.cpp index a56215a207..e20c36e48f 100644 --- a/src/vm/gcenv.os.cpp +++ b/src/vm/gcenv.os.cpp @@ -32,6 +32,10 @@ uint32_t g_pageSizeUnixInl = 0; static AffinitySet g_processAffinitySet; +#ifdef FEATURE_PAL +static uint32_t g_currentProcessCpuCount; +#endif // FEATURE_PAL + class GroupProcNo { uint16_t m_groupProc; @@ -106,8 +110,21 @@ bool GCToOSInterface::Initialize() #ifdef FEATURE_PAL g_pageSizeUnixInl = GetOsPageSize(); -#endif + g_currentProcessCpuCount = PAL_GetLogicalCpuCountFromOS(); + if (PAL_GetCurrentThreadAffinitySet(AffinitySet::BitsetDataSize, g_processAffinitySet.GetBitsetData())) + { + assert(g_currentProcessCpuCount == g_processAffinitySet.Count()); + } + else + { + // There is no way to get affinity on the current OS, set the affinity set to reflect all processors + for (size_t i = 0; i < g_currentProcessCpuCount; i++) + { + g_processAffinitySet.Add(i); + } + } +#else // FEATURE_PAL if (CPUGroupInfo::CanEnableGCCPUGroups()) { // When CPU groups are enabled, then the process is not bound by the process affinity set at process launch. @@ -135,6 +152,7 @@ bool GCToOSInterface::Initialize() } } } +#endif // FEATURE_PAL return true; } @@ -175,7 +193,7 @@ bool GCToOSInterface::SetCurrentThreadIdealAffinity(uint16_t srcProcNo, uint16_t LIMITED_METHOD_CONTRACT; bool success = true; - +#ifndef FEATURE_PAL GroupProcNo srcGroupProcNo(srcProcNo); GroupProcNo dstGroupProcNo(dstProcNo); @@ -202,7 +220,6 @@ bool GCToOSInterface::SetCurrentThreadIdealAffinity(uint16_t srcProcNo, uint16_t success = !!SetThreadIdealProcessorEx(GetCurrentThread(), &proc, NULL); } -#if !defined(FEATURE_PAL) else { if (GetThreadIdealProcessorEx(GetCurrentThread(), &proc)) @@ -211,10 +228,13 @@ bool GCToOSInterface::SetCurrentThreadIdealAffinity(uint16_t srcProcNo, uint16_t success = !!SetThreadIdealProcessorEx(GetCurrentThread(), &proc, &proc); } } -#endif // !defined(FEATURE_PAL) -#endif - +#endif // !FEATURE_CORESYSTEM return success; + +#else // !FEATURE_PAL + return GCToOSInterface::SetThreadAffinity(dstProcNo); + +#endif // !FEATURE_PAL } // Get the number of the current processor @@ -472,7 +492,7 @@ size_t GCToOSInterface::GetCacheSizePerLogicalCpu(bool trueSize) bool GCToOSInterface::SetThreadAffinity(uint16_t procNo) { LIMITED_METHOD_CONTRACT; - +#ifndef FEATURE_PAL GroupProcNo groupProcNo(procNo); if (groupProcNo.GetGroup() != GroupProcNo::NoGroup) @@ -489,6 +509,9 @@ bool GCToOSInterface::SetThreadAffinity(uint16_t procNo) { return !!SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR)1 << groupProcNo.GetProcIndex()); } +#else // FEATURE_PAL + return PAL_SetCurrentThreadAffinity(procNo); +#endif // FEATURE_PAL } // Boosts the calling thread's thread priority to a level higher than the default @@ -510,7 +533,9 @@ bool GCToOSInterface::BoostThreadPriority() // set of enabled processors const AffinitySet* GCToOSInterface::SetGCThreadsAffinitySet(uintptr_t configAffinityMask, const AffinitySet* configAffinitySet) { +#ifndef FEATURE_PAL if (CPUGroupInfo::CanEnableGCCPUGroups()) +#endif // !FEATURE_PAL { if (!configAffinitySet->IsEmpty()) { @@ -524,6 +549,7 @@ const AffinitySet* GCToOSInterface::SetGCThreadsAffinitySet(uintptr_t configAffi } } } +#ifndef FEATURE_PAL else { if (configAffinityMask != 0) @@ -538,6 +564,7 @@ const AffinitySet* GCToOSInterface::SetGCThreadsAffinitySet(uintptr_t configAffi } } } +#endif // !FEATURE_PAL return &g_processAffinitySet; } @@ -549,10 +576,14 @@ uint32_t GCToOSInterface::GetCurrentProcessCpuCount() { LIMITED_METHOD_CONTRACT; +#ifndef FEATURE_PAL // GetCurrentProcessCpuCount only returns up to 64 procs. return CPUGroupInfo::CanEnableGCCPUGroups() ? GCToOSInterface::GetTotalProcessorCount(): ::GetCurrentProcessCpuCount(); +#else // !FEATURE_PAL + return g_currentProcessCpuCount; +#endif // !FEATURE_PAL } // Return the size of the user-mode portion of the virtual address space of this process. @@ -887,6 +918,7 @@ uint32_t GCToOSInterface::GetTotalProcessorCount() { LIMITED_METHOD_CONTRACT; +#ifndef FEATURE_PAL if (CPUGroupInfo::CanEnableGCCPUGroups()) { return CPUGroupInfo::GetNumActiveProcessors(); @@ -895,6 +927,9 @@ uint32_t GCToOSInterface::GetTotalProcessorCount() { return g_SystemInfo.dwNumberOfProcessors; } +#else // !FEATURE_PAL + return PAL_GetTotalCpuCount(); +#endif // !FEATURE_PAL } bool GCToOSInterface::CanEnableGCNumaAware() @@ -904,20 +939,6 @@ bool GCToOSInterface::CanEnableGCNumaAware() return NumaNodeInfo::CanEnableGCNumaAware() != FALSE; } -bool GCToOSInterface::GetNumaProcessorNode(uint16_t proc_no, uint16_t *node_no) -{ - LIMITED_METHOD_CONTRACT; - - GroupProcNo groupProcNo(proc_no); - - PROCESSOR_NUMBER procNumber; - procNumber.Group = groupProcNo.GetGroup(); - procNumber.Number = (BYTE)groupProcNo.GetProcIndex(); - procNumber.Reserved = 0; - - return NumaNodeInfo::GetNumaProcessorNodeEx(&procNumber, node_no) != FALSE; -} - // Get processor number and optionally its NUMA node number for the specified heap number // Parameters: // heap_number - heap number to get the result for @@ -929,53 +950,75 @@ bool GCToOSInterface::GetProcessorForHeap(uint16_t heap_number, uint16_t* proc_n { bool success = false; - if (CPUGroupInfo::CanEnableGCCPUGroups()) + // Locate heap_number-th available processor + uint16_t procIndex; + size_t cnt = heap_number; + for (uint16_t i = 0; i < GCToOSInterface::GetTotalProcessorCount(); i++) { - uint16_t gn, gpn; - CPUGroupInfo::GetGroupForProcessor((uint16_t)heap_number, &gn, &gpn); + if (g_processAffinitySet.Contains(i)) + { + if (cnt == 0) + { + procIndex = i; + success = true; + break; + } + + cnt--; + } + } + + if (success) + { +#ifndef FEATURE_PAL + WORD gn, gpn; + + if (CPUGroupInfo::CanEnableGCCPUGroups()) + { + CPUGroupInfo::GetGroupForProcessor(procIndex, &gn, &gpn); + } + else + { + gn = GroupProcNo::NoGroup; + gpn = procIndex; + } + + GroupProcNo groupProcNo(gn, gpn); + *proc_no = groupProcNo.GetCombinedValue(); - *proc_no = GroupProcNo(gn, gpn).GetCombinedValue(); if (GCToOSInterface::CanEnableGCNumaAware()) { - if (!GCToOSInterface::GetNumaProcessorNode(*proc_no, node_no)) + PROCESSOR_NUMBER procNumber; + + if (CPUGroupInfo::CanEnableGCCPUGroups()) + { + procNumber.Group = gn; + } + else + { + // Get the current processor group + GetCurrentProcessorNumberEx(&procNumber); + } + + procNumber.Number = (BYTE)gpn; + procNumber.Reserved = 0; + + if (!NumaNodeInfo::GetNumaProcessorNodeEx(&procNumber, node_no)) { *node_no = NUMA_NODE_UNDEFINED; } } else { // no numa setting, each cpu group is treated as a node - *node_no = gn; + *node_no = groupProcNo.GetGroup(); } - - success = true; - } - else - { - int bit_number = 0; - uint8_t proc_number = 0; - for (uintptr_t mask = 1; mask != 0; mask <<= 1) +#else // !FEATURE_PAL + *proc_no = procIndex; + if (!GCToOSInterface::CanEnableGCNumaAware() || !NumaNodeInfo::GetNumaProcessorNodeEx(procIndex, (WORD*)node_no)) { - if (g_processAffinitySet.Contains(proc_number)) - { - if (bit_number == heap_number) - { - *proc_no = GroupProcNo(GroupProcNo::NoGroup, proc_number).GetCombinedValue(); - - if (GCToOSInterface::CanEnableGCNumaAware()) - { - if (!GCToOSInterface::GetNumaProcessorNode(proc_number, node_no)) - { - *node_no = NUMA_NODE_UNDEFINED; - } - } - - success = true; - break; - } - bit_number++; - } - proc_number++; + *node_no = NUMA_NODE_UNDEFINED; } +#endif // !FEATURE_PAL } return success; @@ -993,6 +1036,7 @@ bool GCToOSInterface::ParseGCHeapAffinitizeRangesEntry(const char** config_strin size_t index_offset = 0; char* number_end; +#ifndef FEATURE_PAL size_t group_number = strtoul(*config_string, &number_end, 10); if ((number_end == *config_string) || (*number_end != ':')) @@ -1011,6 +1055,7 @@ bool GCToOSInterface::ParseGCHeapAffinitizeRangesEntry(const char** config_strin index_offset = group_begin; *config_string = number_end + 1; +#endif // !FEATURE_PAL size_t start, end; if (!ParseIndexOrRange(config_string, &start, &end)) @@ -1018,11 +1063,13 @@ bool GCToOSInterface::ParseGCHeapAffinitizeRangesEntry(const char** config_strin return false; } +#ifndef FEATURE_PAL if ((start >= group_size) || (end >= group_size)) { // Invalid CPU index values or range return false; } +#endif // !FEATURE_PAL *start_index = index_offset + start; *end_index = index_offset + end; diff --git a/src/vm/interopconverter.cpp b/src/vm/interopconverter.cpp index 70b1113cd3..d8bb08d53d 100644 --- a/src/vm/interopconverter.cpp +++ b/src/vm/interopconverter.cpp @@ -414,7 +414,7 @@ IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, REFIID iid, bool throwIfNoComI // GetObjectRefFromComIP // pUnk : input IUnknown // pMTClass : specifies the type of instance to be returned -// NOTE:** As per COM Rules, the IUnknown passed is shouldn't be AddRef'ed +// NOTE:** As per COM Rules, the IUnknown passed in shouldn't be AddRef'ed //+---------------------------------------------------------------------------- void GetObjectRefFromComIP(OBJECTREF* pObjOut, IUnknown **ppUnk, MethodTable *pMTClass, MethodTable *pItfMT, DWORD dwFlags) { @@ -456,24 +456,27 @@ void GetObjectRefFromComIP(OBJECTREF* pObjOut, IUnknown **ppUnk, MethodTable *pM if (pUnk != NULL) { // get CCW for IUnknown - ComCallWrapper* pWrap = GetCCWFromIUnknown(pUnk); - if (pWrap == NULL) + ComCallWrapper *ccw = GetCCWFromIUnknown(pUnk); + if (ccw == NULL) { // could be aggregated scenario HRESULT hr = SafeQueryInterface(pUnk, IID_IUnknown, &pOuter); LogInteropQI(pUnk, IID_IUnknown, hr, "GetObjectRefFromComIP: QI for Outer"); IfFailThrow(hr); - + // store the outer in the auto pointer pAutoOuterUnk = pOuter; - pWrap = GetCCWFromIUnknown(pOuter); + ccw = GetCCWFromIUnknown(pOuter); } - if (pWrap != NULL) - { // our tear-off - _ASSERTE(pWrap != NULL); - AppDomain* pCurrDomain = pThread->GetDomain(); - *pObjOut = pWrap->GetObjectRef(); + // If the CCW was activated via COM, do not unwrap it. + // Unwrapping a CCW would deliver the underlying OBJECTREF, + // but when a managed class is activated via COM it should + // remain a COM object and adhere to COM rules. + if (ccw != NULL + && !ccw->IsComActivated()) + { + *pObjOut = ccw->GetObjectRef(); } if (*pObjOut != NULL) diff --git a/src/vm/mlinfo.cpp b/src/vm/mlinfo.cpp index 2e675fde2a..985eefef1e 100644 --- a/src/vm/mlinfo.cpp +++ b/src/vm/mlinfo.cpp @@ -1652,7 +1652,19 @@ MarshalInfo::MarshalInfo(Module* pModule, } else { - mtype = sig.PeekElemTypeClosed(pModule, pTypeContext); + SigPointer sigtmp = sig; + CorElementType closedElemType = sigtmp.PeekElemTypeClosed(pModule, pTypeContext); + if (closedElemType == ELEMENT_TYPE_VALUETYPE) + { + TypeHandle th = sigtmp.GetTypeHandleThrowing(pModule, pTypeContext); + // If the return type of an instance method is a value-type we need the actual return type. + // However, if the return type is an enum, we can normalize it. + if (!th.IsEnum()) + { + mtype = closedElemType; + } + } + } #endif // _TARGET_X86_ diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h index d2a0ad61fd..ccdec0f110 100644 --- a/src/vm/mscorlib.h +++ b/src/vm/mscorlib.h @@ -120,7 +120,7 @@ DEFINE_FIELD_U(_hashAlgorithmForControl, AssemblyNameBaseObject, _hashAlgorithmF DEFINE_FIELD_U(_versionCompatibility, AssemblyNameBaseObject, _versionCompatibility) DEFINE_FIELD_U(_flags, AssemblyNameBaseObject, _flags) DEFINE_CLASS(ASSEMBLY_NAME, Reflection, AssemblyName) -DEFINE_METHOD(ASSEMBLY_NAME, INIT, Init, IM_Str_ArrB_ArrB_Ver_CI_AHA_AVC_Str_ANF_SNKP_RetV) +DEFINE_METHOD(ASSEMBLY_NAME, CTOR, .ctor, IM_Str_ArrB_ArrB_Ver_CI_AHA_AVC_Str_ANF_SNKP_RetV) DEFINE_METHOD(ASSEMBLY_NAME, SET_PROC_ARCH_INDEX, SetProcArchIndex, IM_PEK_IFM_RetV) DEFINE_CLASS_U(System, Version, VersionBaseObject) @@ -889,6 +889,16 @@ DEFINE_METHOD(UNHANDLED_EVENTARGS, CTOR, .ctor, DEFINE_CLASS(FIRSTCHANCE_EVENTARGS, ExceptionServices, FirstChanceExceptionEventArgs) DEFINE_METHOD(FIRSTCHANCE_EVENTARGS, CTOR, .ctor, IM_Exception_RetVoid) +DEFINE_CLASS_U(Loader, AssemblyLoadContext, AssemblyLoadContextBaseObject) +DEFINE_FIELD_U(_unloadLock, AssemblyLoadContextBaseObject, _unloadLock) +DEFINE_FIELD_U(_resolvingUnmanagedDll, AssemblyLoadContextBaseObject, _resovlingUnmanagedDll) +DEFINE_FIELD_U(_resolving, AssemblyLoadContextBaseObject, _resolving) +DEFINE_FIELD_U(_unloading, AssemblyLoadContextBaseObject, _unloading) +DEFINE_FIELD_U(_name, AssemblyLoadContextBaseObject, _name) +DEFINE_FIELD_U(_nativeAssemblyLoadContext, AssemblyLoadContextBaseObject, _nativeAssemblyLoadContext) +DEFINE_FIELD_U(_id, AssemblyLoadContextBaseObject, _id) +DEFINE_FIELD_U(_state, AssemblyLoadContextBaseObject, _state) +DEFINE_FIELD_U(_isCollectible, AssemblyLoadContextBaseObject, _isCollectible) DEFINE_CLASS(ASSEMBLYLOADCONTEXT, Loader, AssemblyLoadContext) DEFINE_METHOD(ASSEMBLYLOADCONTEXT, RESOLVE, Resolve, SM_IntPtr_AssemblyName_RetAssemblyBase) DEFINE_METHOD(ASSEMBLYLOADCONTEXT, RESOLVEUNMANAGEDDLL, ResolveUnmanagedDll, SM_Str_IntPtr_RetIntPtr) diff --git a/src/vm/object.h b/src/vm/object.h index 590f1e0618..cc0810fc98 100644 --- a/src/vm/object.h +++ b/src/vm/object.h @@ -1610,6 +1610,53 @@ class AssemblyBaseObject : public Object NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, DomainAssembly *pAssembly, OBJECTREF keepAlive); #define FC_RETURN_ASSEMBLY_OBJECT(pAssembly, refKeepAlive) FC_INNER_RETURN(AssemblyBaseObject*, GetRuntimeAssemblyHelper(__me, pAssembly, refKeepAlive)) +// AssemblyLoadContextBaseObject +// This class is the base class for AssemblyLoadContext +// +#if (defined(_TARGET_X86_) || defined(_TARGET_ARM_)) && !defined(FEATURE_PAL) +#include "pshpack4.h" +#endif // (defined(_TARGET_X86_) || defined(_TARGET_ARM_)) && !defined(FEATURE_PAL) +class AssemblyLoadContextBaseObject : public Object +{ + friend class MscorlibBinder; + + protected: + // READ ME: + // Modifying the order or fields of this object may require other changes to the + // classlib class definition of this object. +#ifdef _TARGET_64BIT_ + OBJECTREF _unloadLock; + OBJECTREF _resovlingUnmanagedDll; + OBJECTREF _resolving; + OBJECTREF _unloading; + OBJECTREF _name; + INT_PTR _nativeAssemblyLoadContext; + int64_t _id; // On 64-bit platforms this is a value type so it is placed after references and pointers + DWORD _state; + CLR_BOOL _isCollectible; +#else // _TARGET_64BIT_ + int64_t _id; // On 32-bit platforms this 64-bit value type is larger than a pointer so JIT places it first + OBJECTREF _unloadLock; + OBJECTREF _resovlingUnmanagedDll; + OBJECTREF _resolving; + OBJECTREF _unloading; + OBJECTREF _name; + INT_PTR _nativeAssemblyLoadContext; + DWORD _state; + CLR_BOOL _isCollectible; +#endif // _TARGET_64BIT_ + + protected: + AssemblyLoadContextBaseObject() { LIMITED_METHOD_CONTRACT; } + ~AssemblyLoadContextBaseObject() { LIMITED_METHOD_CONTRACT; } + + public: + INT_PTR GetNativeAssemblyLoadContext() { LIMITED_METHOD_CONTRACT; return _nativeAssemblyLoadContext; } +}; +#if (defined(_TARGET_X86_) || defined(_TARGET_ARM_)) && !defined(FEATURE_PAL) +#include "poppack.h" +#endif // (defined(_TARGET_X86_) || defined(_TARGET_ARM_)) && !defined(FEATURE_PAL) + // AssemblyNameBaseObject // This class is the base class for assembly names // @@ -1700,12 +1747,12 @@ typedef REF<ReflectFieldObject> REFLECTFIELDREF; typedef REF<ThreadBaseObject> THREADBASEREF; -typedef REF<AppDomainBaseObject> APPDOMAINREF; - typedef REF<MarshalByRefObjectBaseObject> MARSHALBYREFOBJECTBASEREF; typedef REF<AssemblyBaseObject> ASSEMBLYREF; +typedef REF<AssemblyLoadContextBaseObject> ASSEMBLYLOADCONTEXTREF; + typedef REF<AssemblyNameBaseObject> ASSEMBLYNAMEREF; typedef REF<VersionBaseObject> VERSIONREF; @@ -1753,6 +1800,7 @@ typedef PTR_ReflectMethodObject REFLECTMETHODREF; typedef PTR_ReflectFieldObject REFLECTFIELDREF; typedef PTR_ThreadBaseObject THREADBASEREF; typedef PTR_AssemblyBaseObject ASSEMBLYREF; +typedef PTR_AssemblyLoadContextBaseObject ASSEMBLYLOADCONTEXTREF; typedef PTR_AssemblyNameBaseObject ASSEMBLYNAMEREF; #ifndef DACCESS_COMPILE diff --git a/src/vm/qcall.cpp b/src/vm/qcall.cpp index 3b35f9089f..1b7bbda3b7 100644 --- a/src/vm/qcall.cpp +++ b/src/vm/qcall.cpp @@ -76,25 +76,3 @@ void QCall::ObjectHandleOnStack::SetGuidArray(const GUID * p, COUNT_T length) memcpyNoGCRefs(arr->GetDataPtr(), p, length * sizeof(GUID)); Set(arr); } - -// -// Helpers for passing an AppDomain to a QCall -// - -#ifdef _DEBUG - -//--------------------------------------------------------------------------------------- -// -// Verify that the AppDomain being passed from the BCL is valid for use in a QCall. Note: some additional -// checks are in System.AppDomain.GetNativeHandle() -// - -void QCall::AppDomainHandle::VerifyDomainHandle() const -{ - LIMITED_METHOD_CONTRACT; - - // System.AppDomain.GetNativeHandle() should ensure that we're not calling through with a null AppDomain pointer. - _ASSERTE(m_pAppDomain); -} - -#endif // _DEBUG diff --git a/src/vm/qcall.h b/src/vm/qcall.h index 3ad328a2e1..dd60bbb158 100644 --- a/src/vm/qcall.h +++ b/src/vm/qcall.h @@ -237,35 +237,6 @@ public: } }; - // AppDomainHandle is used for passing AppDomains into QCalls via System.AppDomainHandle - struct AppDomainHandle - { - AppDomain *m_pAppDomain; - - operator AppDomain *() - { - LIMITED_METHOD_CONTRACT; -#ifdef _DEBUG - VerifyDomainHandle(); -#endif // _DEBUG - return m_pAppDomain; - } - - AppDomain *operator->() const - { - LIMITED_METHOD_CONTRACT; -#ifdef _DEBUG - VerifyDomainHandle(); -#endif // _DEBUG - return m_pAppDomain; - } - - private: -#ifdef _DEBUG - void VerifyDomainHandle() const; -#endif // _DEBUG - }; - struct AssemblyHandle { DomainAssembly * m_pAssembly; diff --git a/src/vm/runtimecallablewrapper.cpp b/src/vm/runtimecallablewrapper.cpp index 540536ef5f..26c2a5cd5d 100644 --- a/src/vm/runtimecallablewrapper.cpp +++ b/src/vm/runtimecallablewrapper.cpp @@ -242,6 +242,12 @@ IUnknown *ComClassFactory::CreateInstanceFromClassFactory(IClassFactory *pClassF ThrowHRMsg(hr, IDS_EE_CREATEINSTANCE_LIC_FAILED); } + // If the activated COM class has a CCW, mark the + // CCW as being activated via COM. + ComCallWrapper *ccw = GetCCWFromIUnknown(pUnk); + if (ccw != NULL) + ccw->MarkComActivated(); + pUnk.SuppressRelease(); RETURN pUnk; } diff --git a/src/vm/runtimehandles.cpp b/src/vm/runtimehandles.cpp index c25bcbf3fe..d0a2b043d9 100644 --- a/src/vm/runtimehandles.cpp +++ b/src/vm/runtimehandles.cpp @@ -1415,7 +1415,7 @@ void QCALLTYPE RuntimeTypeHandle::GetTypeByNameUsingCARules(LPCWSTR pwzClassName void QCALLTYPE RuntimeTypeHandle::GetTypeByName(LPCWSTR pwzClassName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::StackCrawlMarkHandle pStackMark, - ICLRPrivBinder * pPrivHostBinder, + QCall::ObjectHandleOnStack pAssemblyLoadContext, BOOL bLoadTypeFromPartialNameHack, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive) { @@ -1429,6 +1429,19 @@ void QCALLTYPE RuntimeTypeHandle::GetTypeByName(LPCWSTR pwzClassName, BOOL bThro COMPlusThrowArgumentNull(W("className"),W("ArgumentNull_String")); { + ICLRPrivBinder * pPrivHostBinder = NULL; + + if (*pAssemblyLoadContext.m_ppObject != NULL) + { + GCX_COOP(); + ASSEMBLYLOADCONTEXTREF * pAssemblyLoadContextRef = reinterpret_cast<ASSEMBLYLOADCONTEXTREF *>(pAssemblyLoadContext.m_ppObject); + + INT_PTR nativeAssemblyLoadContext = (*pAssemblyLoadContextRef)->GetNativeAssemblyLoadContext(); + + pPrivHostBinder = reinterpret_cast<ICLRPrivBinder *>(nativeAssemblyLoadContext); + } + + typeHandle = TypeName::GetTypeManaged(pwzClassName, NULL, bThrowOnError, bIgnoreCase, /*bProhibitAsmQualifiedName =*/ FALSE, SystemDomain::GetCallersAssembly(pStackMark), bLoadTypeFromPartialNameHack, (OBJECTREF*)keepAlive.m_ppObject, diff --git a/src/vm/runtimehandles.h b/src/vm/runtimehandles.h index 4c2ebdf52d..c83461a8a5 100644 --- a/src/vm/runtimehandles.h +++ b/src/vm/runtimehandles.h @@ -177,7 +177,7 @@ public: static void QCALLTYPE GetTypeByName(LPCWSTR pwzClassName, BOOL bThrowOnError, BOOL bIgnoreCase, QCall::StackCrawlMarkHandle pStackMark, - ICLRPrivBinder * pPrivHostBinder, + QCall::ObjectHandleOnStack pAssemblyLoadContext, BOOL bLoadTypeFromPartialNameHack, QCall::ObjectHandleOnStack retType, QCall::ObjectHandleOnStack keepAlive); diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp index 6890290caa..43976a91ff 100644 --- a/src/vm/threads.cpp +++ b/src/vm/threads.cpp @@ -451,7 +451,7 @@ void Thread::ChooseThreadCPUGroupAffinity() GC_TRIGGERS; } CONTRACTL_END; - +#ifndef FEATURE_PAL if (!CPUGroupInfo::CanEnableGCCPUGroups() || !CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) return; @@ -471,6 +471,7 @@ void Thread::ChooseThreadCPUGroupAffinity() CPUGroupInfo::SetThreadGroupAffinity(GetThreadHandle(), &groupAffinity, NULL); m_wCPUGroup = groupAffinity.Group; m_pAffinityMask = groupAffinity.Mask; +#endif // !FEATURE_PAL } void Thread::ClearThreadCPUGroupAffinity() @@ -481,7 +482,7 @@ void Thread::ClearThreadCPUGroupAffinity() GC_NOTRIGGER; } CONTRACTL_END; - +#ifndef FEATURE_PAL if (!CPUGroupInfo::CanEnableGCCPUGroups() || !CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) return; @@ -499,6 +500,7 @@ void Thread::ClearThreadCPUGroupAffinity() m_wCPUGroup = 0; m_pAffinityMask = 0; +#endif // !FEATURE_PAL } DWORD Thread::StartThread() @@ -1561,8 +1563,10 @@ Thread::Thread() m_fGCSpecial = FALSE; +#ifndef FEATURE_PAL m_wCPUGroup = 0; m_pAffinityMask = 0; +#endif // !FEATURE_PAL m_pAllLoggedTypes = NULL; diff --git a/src/vm/threads.h b/src/vm/threads.h index 94ce275604..e5307d9a5d 100644 --- a/src/vm/threads.h +++ b/src/vm/threads.h @@ -4824,9 +4824,10 @@ public: void SetGCSpecial(bool fGCSpecial); private: +#ifndef FEATURE_PAL WORD m_wCPUGroup; DWORD_PTR m_pAffinityMask; - +#endif // !FEATURE_PAL public: void ChooseThreadCPUGroupAffinity(); void ClearThreadCPUGroupAffinity(); diff --git a/src/vm/typeparse.cpp b/src/vm/typeparse.cpp index 858d9a32d3..0794454be2 100644 --- a/src/vm/typeparse.cpp +++ b/src/vm/typeparse.cpp @@ -1507,20 +1507,23 @@ DomainAssembly * LoadDomainAssembly( spec.SetWindowsRuntimeType(*pssOuterTypeName); } - if (pPrivHostBinder) - { - spec.SetHostBinder(pPrivHostBinder); - } - else if (pRequestingAssembly && (!pRequestingAssembly->IsCollectible())) + if (pRequestingAssembly) { GCX_PREEMP(); spec.SetParentAssembly(pRequestingAssembly->GetDomainAssembly()); } - // If the requesting assembly has Fallback LoadContext binder available, - // then set it up in the AssemblySpec. - if (pRequestingAssembly != NULL) + // Have we been passed the reference to the binder against which this load should be triggered? + // If so, then use it to set the fallback load context binder. + if (pPrivHostBinder != NULL) + { + spec.SetFallbackLoadContextBinderForRequestingAssembly(pPrivHostBinder); + spec.SetPreferFallbackLoadContextBinder(); + } + else if (pRequestingAssembly != NULL) { + // If the requesting assembly has Fallback LoadContext binder available, + // then set it up in the AssemblySpec. PEFile *pRequestingAssemblyManifestFile = pRequestingAssembly->GetManifestFile(); spec.SetFallbackLoadContextBinderForRequestingAssembly(pRequestingAssemblyManifestFile->GetFallbackLoadContextBinder()); } diff --git a/src/vm/vars.hpp b/src/vm/vars.hpp index 2c3d978d02..68473b6c1a 100644 --- a/src/vm/vars.hpp +++ b/src/vm/vars.hpp @@ -162,8 +162,7 @@ class OBJECTREF { class ReflectClassBaseObject* m_asReflectClass; class ExecutionContextObject* m_asExecutionContext; - class AppDomainBaseObject* m_asAppDomainBase; - class PermissionSetObject* m_asPermissionSetObject; + class AssemblyLoadContextBaseObject* m_asAssemblyLoadContextBase; }; public: diff --git a/src/vm/win32threadpool.cpp b/src/vm/win32threadpool.cpp index 29c1d21c99..b5014962d2 100644 --- a/src/vm/win32threadpool.cpp +++ b/src/vm/win32threadpool.cpp @@ -345,12 +345,16 @@ BOOL ThreadpoolMgr::Initialize() UnManagedPerAppDomainTPCount* pADTPCount; pADTPCount = PerAppDomainTPCountList::GetUnmanagedTPCount(); +#ifndef FEATURE_PAL //ThreadPool_CPUGroup CPUGroupInfo::EnsureInitialized(); if (CPUGroupInfo::CanEnableGCCPUGroups() && CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) NumberOfProcessors = CPUGroupInfo::GetNumActiveProcessors(); else NumberOfProcessors = GetCurrentProcessCpuCount(); +#else // !FEATURE_PAL + NumberOfProcessors = GetCurrentProcessCpuCount(); +#endif // !FEATURE_PAL InitPlatformVariables(); EX_TRY @@ -380,20 +384,15 @@ BOOL ThreadpoolMgr::Initialize() RetiredWorkerSemaphore = new CLRLifoSemaphore(); RetiredWorkerSemaphore->Create(0, ThreadCounter::MaxPossibleCount); +#ifndef FEATURE_PAL //ThreadPool_CPUGroup if (CPUGroupInfo::CanEnableGCCPUGroups() && CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) RecycledLists.Initialize( CPUGroupInfo::GetNumActiveProcessors() ); else RecycledLists.Initialize( g_SystemInfo.dwNumberOfProcessors ); - /* - { - SYSTEM_INFO sysInfo; - - ::GetSystemInfo( &sysInfo ); - - RecycledLists.Initialize( sysInfo.dwNumberOfProcessors ); - } - */ +#else // !FEATURE_PAL + RecycledLists.Initialize( PAL_GetTotalCpuCount() ); +#endif // !FEATURE_PAL } EX_CATCH { @@ -405,7 +404,7 @@ BOOL ThreadpoolMgr::Initialize() RetiredCPWakeupEvent = NULL; } - // Note: It is fine to call Destroy on unitialized critical sections + // Note: It is fine to call Destroy on uninitialized critical sections WorkerCriticalSection.Destroy(); WaitThreadsCriticalSection.Destroy(); TimerQueueCriticalSection.Destroy(); @@ -4095,9 +4094,10 @@ DWORD WINAPI ThreadpoolMgr::GateThreadStart(LPVOID lpArgs) return 0; } +#ifndef FEATURE_PAL //GateThread can start before EESetup, so ensure CPU group information is initialized; CPUGroupInfo::EnsureInitialized(); - +#endif // !FEATURE_PAL // initialize CPU usage information structure; prevCPUInfo.idleTime.QuadPart = 0; prevCPUInfo.kernelTime.QuadPart = 0; diff --git a/src/vm/win32threadpool.h b/src/vm/win32threadpool.h index bb6ebc0613..55f321c37f 100644 --- a/src/vm/win32threadpool.h +++ b/src/vm/win32threadpool.h @@ -735,12 +735,22 @@ public: { LIMITED_METHOD_CONTRACT; + DWORD processorNumber = 0; + +#ifndef FEATURE_PAL if (CPUGroupInfo::CanEnableGCCPUGroups() && CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) - return pRecycledListPerProcessor[CPUGroupInfo::CalculateCurrentProcessorNumber()][memType]; + processorNumber = CPUGroupInfo::CalculateCurrentProcessorNumber(); else // Turns out GetCurrentProcessorNumber can return a value greater than the number of processors reported by // GetSystemInfo, if we're running in WOW64 on a machine with >32 processors. - return pRecycledListPerProcessor[GetCurrentProcessorNumber()%NumberOfProcessors][memType]; + processorNumber = GetCurrentProcessorNumber()%NumberOfProcessors; +#else // !FEATURE_PAL + if (PAL_HasGetCurrentProcessorNumber()) + { + processorNumber = GetCurrentProcessorNumber(); + } +#endif // !FEATURE_PAL + return pRecycledListPerProcessor[processorNumber][memType]; } }; diff --git a/tests/issues.targets b/tests/issues.targets index 79e559838d..c540e01dde 100644 --- a/tests/issues.targets +++ b/tests/issues.targets @@ -329,6 +329,9 @@ <ExcludeList Include="$(XunitTestBinBase)/Interop/COM/NETClients/Events/NETClientEvents/*"> <Issue>22784</Issue> </ExcludeList> + <ExcludeList Include="$(XunitTestBinBase)/Interop/COM/NETClients/ConsumeNETServer/ConsumeNETServer/*"> + <Issue>20682</Issue> + </ExcludeList> </ItemGroup> <!-- Windows arm64 specific excludes --> diff --git a/tests/src/Interop/COM/NETClients/Aggregation/NETClientAggregation.csproj b/tests/src/Interop/COM/NETClients/Aggregation/NETClientAggregation.csproj index 182ba923c9..63df657451 100644 --- a/tests/src/Interop/COM/NETClients/Aggregation/NETClientAggregation.csproj +++ b/tests/src/Interop/COM/NETClients/Aggregation/NETClientAggregation.csproj @@ -30,7 +30,7 @@ </PropertyGroup> <ItemGroup> <Compile Include="Program.cs" /> - <Compile Include="../../ServerContracts/NativeServers.cs" /> + <Compile Include="../../ServerContracts/Server.CoClasses.cs" /> <Compile Include="../../ServerContracts/Server.Contracts.cs" /> <Compile Include="../../ServerContracts/ServerGuids.cs" /> </ItemGroup> diff --git a/tests/src/Interop/COM/NETClients/ConsumeNETServer/App.manifest b/tests/src/Interop/COM/NETClients/ConsumeNETServer/App.manifest new file mode 100644 index 0000000000..58fc0a2781 --- /dev/null +++ b/tests/src/Interop/COM/NETClients/ConsumeNETServer/App.manifest @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> + <assemblyIdentity + type="win32" + name="ConsumeNETServer" + version="1.0.0.0" /> + + <dependency> + <dependentAssembly> + <!-- RegFree COM to activate Managed Server --> + <assemblyIdentity + type="win32" + name="CoreShim.X" + version="1.0.0.0"/> + </dependentAssembly> + </dependency> + +</assembly> diff --git a/tests/src/Interop/COM/NETClients/ConsumeNETServer/ConsumeNETServer.csproj b/tests/src/Interop/COM/NETClients/ConsumeNETServer/ConsumeNETServer.csproj new file mode 100644 index 0000000000..9202a9757a --- /dev/null +++ b/tests/src/Interop/COM/NETClients/ConsumeNETServer/ConsumeNETServer.csproj @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <AssemblyName>ConsumeNETServer</AssemblyName> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{4BDB75BD-30D8-4603-98DB-C6CFDC5F6F0E}</ProjectGuid> + <OutputType>Exe</OutputType> + <ProjectTypeGuids>{209912F9-0DA1-4184-9CC1-8D583BAF4A28};{87799F5D-CEBD-499D-BDBA-B2C6105CD766}</ProjectTypeGuids> + <ApplicationManifest>App.manifest</ApplicationManifest> + <CLRTestScriptLocalCoreShim>true</CLRTestScriptLocalCoreShim> + <RequiresMockHostPolicy>true</RequiresMockHostPolicy> + + <!-- Blocked on ILAsm supporting embedding resources. See https://github.com/dotnet/coreclr/issues/20819 --> + <IlrtTestKind>BuildOnly</IlrtTestKind> + + <!-- Blocked on CrossGen.exe supporting embedding resources. See https://github.com/dotnet/coreclr/issues/21006 --> + <CrossGenTest>false</CrossGenTest> + + <!-- Test unsupported outside of windows --> + <TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows> + <DisableProjectBuild Condition="'$(TargetsUnix)' == 'true'">true</DisableProjectBuild> + <!-- This test would require the runincontext.exe to include App.manifest describing the COM interfaces --> + <UnloadabilityIncompatible>true</UnloadabilityIncompatible> + + <!-- Suppress warning about conflicting type names. This occurs because of the reference to NETServer. + The reference is only to ensure the project is built and properly copied. The test itself uses + COM to activate the server rather than typical class activation via 'new' --> + <NoWarn>$(NoWarn),0436</NoWarn> + </PropertyGroup> + <!-- Default configurations to help VS understand the configurations --> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + </PropertyGroup> + <ItemGroup> + <Compile Include="Program.cs" /> + <Compile Include="../../ServerContracts/Server.CoClasses.cs" /> + <Compile Include="../../ServerContracts/Server.Contracts.cs" /> + <Compile Include="../../ServerContracts/ServerGuids.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="../../NETServer/NETServer.csproj" /> + <ProjectReference Include="../../../../Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" /> + </ItemGroup> + <ItemGroup> + <None Include="CoreShim.X.manifest"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project> diff --git a/tests/src/Interop/COM/NETClients/ConsumeNETServer/CoreShim.X.manifest b/tests/src/Interop/COM/NETClients/ConsumeNETServer/CoreShim.X.manifest new file mode 100644 index 0000000000..abb39fbb21 --- /dev/null +++ b/tests/src/Interop/COM/NETClients/ConsumeNETServer/CoreShim.X.manifest @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + +<assemblyIdentity + type="win32" + name="CoreShim.X" + version="1.0.0.0" /> + +<file name="CoreShim.dll"> + <!-- ConsumeNETServerTesting --> + <comClass + clsid="{DE4ACF53-5957-4D31-8BE2-EA6C80683246}" + threadingModel="Both" /> +</file> + +</assembly> diff --git a/tests/src/Interop/COM/NETClients/ConsumeNETServer/Program.cs b/tests/src/Interop/COM/NETClients/ConsumeNETServer/Program.cs new file mode 100644 index 0000000000..1a2aa68d99 --- /dev/null +++ b/tests/src/Interop/COM/NETClients/ConsumeNETServer/Program.cs @@ -0,0 +1,117 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace NetClient +{ + using System; + using System.Collections.Generic; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + + using TestLibrary; + using Server.Contract; + + using CoClass = Server.Contract.Servers; + + class Program + { + static void Validate_Activation() + { + Console.WriteLine($"{nameof(Validate_Activation)}..."); + + var test = new CoClass.ConsumeNETServerTesting(); + test.ReleaseResources(); + + // The CoClass should be the activated type, _not_ the activation interface. + Assert.AreEqual(test.GetType(), typeof(CoClass.ConsumeNETServerTestingClass)); + } + + static void Validate_CCW_Wasnt_Unwrapped() + { + Console.WriteLine($"{nameof(Validate_CCW_Wasnt_Unwrapped)}..."); + + var test = new CoClass.ConsumeNETServerTesting(); + test.ReleaseResources(); + + // The CoClass should be the activated type, _not_ the implementation class. + // This indicates the real implementation class is wrapped in its CCW and exposed + // to the runtime as an RCW. + Assert.AreNotEqual(test.GetType(), typeof(ConsumeNETServerTesting)); + } + + static void Validate_Client_CCW_RCW() + { + Console.WriteLine($"{nameof(Validate_Client_CCW_RCW)}..."); + + IntPtr ccw = IntPtr.Zero; + + // Validate the client side view is consistent + var test = new CoClass.ConsumeNETServerTesting(); + try + { + ccw = test.GetCCW(); + object rcw = Marshal.GetObjectForIUnknown(ccw); + object inst = test.GetRCW(); + Assert.AreEqual(rcw, inst); + } + finally + { + test.ReleaseResources(); + } + } + + static void Validate_Server_CCW_RCW() + { + Console.WriteLine($"{nameof(Validate_Server_CCW_RCW)}..."); + + // Validate the server side view is consistent + var test = new CoClass.ConsumeNETServerTesting(); + try + { + Assert.IsTrue(test.EqualByCCW(test)); + Assert.IsTrue(test.NotEqualByRCW(test)); + } + finally + { + test.ReleaseResources(); + } + } + + static int Main(string[] doNotUse) + { + // RegFree COM is not supported on Windows Nano + if (Utilities.IsWindowsNanoServer) + { + return 100; + } + + // Initialize CoreShim and hostpolicymock + HostPolicyMock.Initialize(Environment.CurrentDirectory, null); + Environment.SetEnvironmentVariable("CORESHIM_COMACT_ASSEMBLYNAME", "NETServer"); + Environment.SetEnvironmentVariable("CORESHIM_COMACT_TYPENAME", "ConsumeNETServerTesting"); + + try + { + using (HostPolicyMock.Mock_corehost_resolve_component_dependencies( + 0, + string.Empty, + string.Empty, + string.Empty)) + { + Validate_Activation(); + Validate_CCW_Wasnt_Unwrapped(); + Validate_Client_CCW_RCW(); + Validate_Server_CCW_RCW(); + } + } + catch (Exception e) + { + Console.WriteLine($"Test Failure: {e}"); + return 101; + } + + return 100; + } + } +} diff --git a/tests/src/Interop/COM/NETClients/Events/NETClientEvents.csproj b/tests/src/Interop/COM/NETClients/Events/NETClientEvents.csproj index fccbee9258..f346a0227e 100644 --- a/tests/src/Interop/COM/NETClients/Events/NETClientEvents.csproj +++ b/tests/src/Interop/COM/NETClients/Events/NETClientEvents.csproj @@ -30,7 +30,7 @@ </PropertyGroup> <ItemGroup> <Compile Include="Program.cs" /> - <Compile Include="../../ServerContracts/NativeServers.cs" /> + <Compile Include="../../ServerContracts/Server.CoClasses.cs" /> <Compile Include="../../ServerContracts/Server.Contracts.cs" /> <Compile Include="../../ServerContracts/Server.Events.cs" /> <Compile Include="../../ServerContracts/ServerGuids.cs" /> diff --git a/tests/src/Interop/COM/NETClients/IDispatch/NETClientIDispatch.csproj b/tests/src/Interop/COM/NETClients/IDispatch/NETClientIDispatch.csproj index 4fd95f6694..a99416ba28 100644 --- a/tests/src/Interop/COM/NETClients/IDispatch/NETClientIDispatch.csproj +++ b/tests/src/Interop/COM/NETClients/IDispatch/NETClientIDispatch.csproj @@ -30,7 +30,7 @@ </PropertyGroup> <ItemGroup> <Compile Include="Program.cs" /> - <Compile Include="../../ServerContracts/NativeServers.cs" /> + <Compile Include="../../ServerContracts/Server.CoClasses.cs" /> <Compile Include="../../ServerContracts/Server.Contracts.cs" /> <Compile Include="../../ServerContracts/ServerGuids.cs" /> </ItemGroup> diff --git a/tests/src/Interop/COM/NETClients/Licensing/NETClientLicense.csproj b/tests/src/Interop/COM/NETClients/Licensing/NETClientLicense.csproj index 52154225c4..a46a2a2619 100644 --- a/tests/src/Interop/COM/NETClients/Licensing/NETClientLicense.csproj +++ b/tests/src/Interop/COM/NETClients/Licensing/NETClientLicense.csproj @@ -30,7 +30,7 @@ </PropertyGroup> <ItemGroup> <Compile Include="Program.cs" /> - <Compile Include="../../ServerContracts/NativeServers.cs" /> + <Compile Include="../../ServerContracts/Server.CoClasses.cs" /> <Compile Include="../../ServerContracts/Server.Contracts.cs" /> <Compile Include="../../ServerContracts/ServerGuids.cs" /> </ItemGroup> diff --git a/tests/src/Interop/COM/NETClients/Primitives/NETClientPrimitives.csproj b/tests/src/Interop/COM/NETClients/Primitives/NETClientPrimitives.csproj index 81c06a3f3c..c1f38576e3 100644 --- a/tests/src/Interop/COM/NETClients/Primitives/NETClientPrimitives.csproj +++ b/tests/src/Interop/COM/NETClients/Primitives/NETClientPrimitives.csproj @@ -35,7 +35,7 @@ <Compile Include="NumericTests.cs" /> <Compile Include="StringTests.cs" /> <Compile Include="ColorTests.cs" /> - <Compile Include="../../ServerContracts/NativeServers.cs" /> + <Compile Include="../../ServerContracts/Server.CoClasses.cs" /> <Compile Include="../../ServerContracts/Server.Contracts.cs" /> <Compile Include="../../ServerContracts/ServerGuids.cs" /> </ItemGroup> diff --git a/tests/src/Interop/COM/NETServer/ConsumeNETServerTesting.cs b/tests/src/Interop/COM/NETServer/ConsumeNETServerTesting.cs new file mode 100644 index 0000000000..d8dba73982 --- /dev/null +++ b/tests/src/Interop/COM/NETServer/ConsumeNETServerTesting.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +[ComVisible(true)] +[Guid(Server.Contract.Guids.ConsumeNETServerTesting)] +public class ConsumeNETServerTesting : Server.Contract.IConsumeNETServer +{ + private IntPtr _ccw; + private object _rcwUnwrapped; + + public ConsumeNETServerTesting() + { + _ccw = Marshal.GetIUnknownForObject(this); + _rcwUnwrapped = Marshal.GetObjectForIUnknown(_ccw); + } + + public IntPtr GetCCW() + { + return _ccw; + } + + public object GetRCW() + { + return _rcwUnwrapped; + } + + public void ReleaseResources() + { + Marshal.Release(_ccw); + _ccw = IntPtr.Zero; + _rcwUnwrapped = null; + } + + public bool EqualByCCW(object obj) + { + IntPtr ccwMaybe = Marshal.GetIUnknownForObject(obj); + bool areEqual = ccwMaybe == _ccw; + Marshal.Release(ccwMaybe); + + return areEqual; + } + + public bool NotEqualByRCW(object obj) + { + return _rcwUnwrapped != obj; + } +} diff --git a/tests/src/Interop/COM/NETServer/NETServer.csproj b/tests/src/Interop/COM/NETServer/NETServer.csproj index aa4e791a6c..e820c0c63f 100644 --- a/tests/src/Interop/COM/NETServer/NETServer.csproj +++ b/tests/src/Interop/COM/NETServer/NETServer.csproj @@ -17,13 +17,7 @@ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> </PropertyGroup> <ItemGroup> - <Compile Include="ImportedTypes.cs" /> - <Compile Include="NumericTesting.cs" /> - <Compile Include="ArrayTesting.cs" /> - <Compile Include="StringTesting.cs" /> - <Compile Include="ErrorMarshalTesting.cs" /> - <Compile Include="ColorTesting.cs" /> - <Compile Include="LicenseTesting.cs" /> + <Compile Include="*.cs" /> <Compile Include="../ServerContracts/Server.Contracts.cs" /> <Compile Include="../ServerContracts/ServerGuids.cs" /> </ItemGroup> diff --git a/tests/src/Interop/COM/ServerContracts/NativeServers.cs b/tests/src/Interop/COM/ServerContracts/Server.CoClasses.cs index 724f7e2bcc..25432a27db 100644 --- a/tests/src/Interop/COM/ServerContracts/NativeServers.cs +++ b/tests/src/Interop/COM/ServerContracts/Server.CoClasses.cs @@ -183,6 +183,31 @@ namespace Server.Contract.Servers { } */ + + /// <summary> + /// Managed definition of CoClass + /// </summary> + /// <remarks> + /// This interface is used to test consumption of the NET server from a NET client only. + /// </remarks> + [ComImport] + [CoClass(typeof(ConsumeNETServerTestingClass))] + [Guid("CCBC1915-3252-4F6B-98AA-411CE6213D94")] + internal interface ConsumeNETServerTesting : Server.Contract.IConsumeNETServer + { + } + + /// <summary> + /// Managed activation for CoClass + /// </summary> + /// <remarks> + /// This interface is used to test consumption of the NET server from a NET client only. + /// </remarks> + [ComImport] + [Guid(Server.Contract.Guids.ConsumeNETServerTesting)] + internal class ConsumeNETServerTestingClass + { + } } #pragma warning restore 618 // Must test deprecated features diff --git a/tests/src/Interop/COM/ServerContracts/Server.Contracts.cs b/tests/src/Interop/COM/ServerContracts/Server.Contracts.cs index 7c198c7138..f32518485c 100644 --- a/tests/src/Interop/COM/ServerContracts/Server.Contracts.cs +++ b/tests/src/Interop/COM/ServerContracts/Server.Contracts.cs @@ -306,6 +306,22 @@ namespace Server.Contract void SetNextLicense([MarshalAs(UnmanagedType.LPWStr)] string lic); } + + /// <remarks> + /// This interface is used to test consumption of the NET server from a NET client only. + /// </remarks> + [ComVisible(true)] + [Guid("CCBC1915-3252-4F6B-98AA-411CE6213D94")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IConsumeNETServer + { + IntPtr GetCCW(); + object GetRCW(); + void ReleaseResources(); + + bool EqualByCCW(object obj); + bool NotEqualByRCW(object obj); + } } #pragma warning restore 618 // Must test deprecated features diff --git a/tests/src/Interop/COM/ServerContracts/ServerGuids.cs b/tests/src/Interop/COM/ServerContracts/ServerGuids.cs index 98ed0aed85..d03eacf708 100644 --- a/tests/src/Interop/COM/ServerContracts/ServerGuids.cs +++ b/tests/src/Interop/COM/ServerContracts/ServerGuids.cs @@ -19,5 +19,6 @@ namespace Server.Contract public const string ColorTesting = "C222F472-DA5A-4FC6-9321-92F4F7053A65"; public const string LicenseTesting = "66DB7882-E2B0-471D-92C7-B2B52A0EA535"; public const string DefaultInterfaceTesting = "FAEF42AE-C1A4-419F-A912-B768AC2679EA"; + public const string ConsumeNETServerTesting = "DE4ACF53-5957-4D31-8BE2-EA6C80683246"; } } diff --git a/tests/src/Loader/ContextualReflection/ContextualReflection.cs b/tests/src/Loader/ContextualReflection/ContextualReflection.cs new file mode 100644 index 0000000000..3356e3df4b --- /dev/null +++ b/tests/src/Loader/ContextualReflection/ContextualReflection.cs @@ -0,0 +1,748 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.Loader; +using System.Runtime.Remoting; +using System.Threading.Tasks; +using TestLibrary; + +namespace ContextualReflectionTest +{ + class AGenericClass<T> + { + } + + class Program : IProgram + { + public AssemblyLoadContext alc { get; set; } + public Assembly alcAssembly { get; set; } + public Type alcProgramType { get; set; } + public IProgram alcProgramInstance { get; set; } + public Assembly defaultAssembly { get; set; } + + public static int Main() + { + Program program = new Program(isolated:false); + + program.RunTests(); + + Console.WriteLine("Success"); + + return 100; + } + + public Program() + { + InitializeIsolation(true); + } + + public Program(bool isolated) + { + InitializeIsolation(isolated); + } + + public void InitializeIsolation(bool isolated) + { + if (isolated == false) + { + alc = new AssemblyLoadContext("Isolated", isCollectible: true); + defaultAssembly = Assembly.GetExecutingAssembly(); + alcAssembly = alc.LoadFromAssemblyPath(defaultAssembly.Location); + + Assert.AreEqual(alcAssembly, alc.LoadFromAssemblyName(alcAssembly.GetName())); + + alcProgramType = alcAssembly.GetType("ContextualReflectionTest.Program"); + + AssemblyLoadContext.Default.Resolving += TestResolve.ResolvingTestDefault; + alc.Resolving += TestResolve.ResolvingTestIsolated; + + alcProgramInstance = (IProgram) Activator.CreateInstance(alcProgramType); + } + else + { + alcAssembly = Assembly.GetExecutingAssembly(); + alc = AssemblyLoadContext.GetLoadContext(alcAssembly); + alcProgramType = typeof(Program); + alcProgramInstance = this; + defaultAssembly = AssemblyLoadContext.Default.LoadFromAssemblyName(alcAssembly.GetName()); + } + } + + void VerifyIsolationDefault() + { + VerifyIsolation(); + Assert.AreEqual(defaultAssembly, Assembly.GetExecutingAssembly()); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly())); + Assert.AreNotEqual(alcProgramType, typeof(Program)); + Assert.AreNotEqual((object)alcProgramInstance, (object)this); + } + + void VerifyIsolationAlc() + { + VerifyIsolation(); + Assert.AreEqual(alcAssembly, Assembly.GetExecutingAssembly()); + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly())); + Assert.AreEqual(alcProgramType, typeof(Program)); + Assert.AreEqual((object)alcProgramInstance, (object)this); + } + + void VerifyIsolation() + { + Assert.AreEqual("Default", AssemblyLoadContext.Default.Name); + + Assert.IsNotNull(alc); + Assert.IsNotNull(alcAssembly); + Assert.IsNotNull(alcProgramType); + Assert.IsNotNull(alcProgramInstance); + + Assert.AreEqual("Isolated", alc.Name); + + Assert.AreNotEqual(defaultAssembly, alcAssembly); + Assert.AreNotEqual(alc, AssemblyLoadContext.Default); + + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(alcProgramInstance.alcAssembly)); + Assert.AreEqual(alcAssembly, alcProgramInstance.alcAssembly); + Assert.AreEqual(alcProgramType, alcProgramInstance.alcProgramType); + Assert.AreEqual(alcProgramInstance, alcProgramInstance.alcProgramInstance); + } + + void VerifyTestResolve() + { + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName("TestDefaultLoad"))); + TestResolve.Assert(ResolveEvents.NoEvent, () => AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName("TestIsolatedLoad"))); + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => alc.LoadFromAssemblyName(new AssemblyName("TestIsolatedLoad"))); + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => alc.LoadFromAssemblyName(new AssemblyName("TestDefaultLoad"))); + + // Make sure failure is not cached + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName("TestDefaultLoad"))); + TestResolve.Assert(ResolveEvents.NoEvent, () => AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName("TestIsolatedLoad"))); + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => alc.LoadFromAssemblyName(new AssemblyName("TestIsolatedLoad"))); + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => alc.LoadFromAssemblyName(new AssemblyName("TestDefaultLoad"))); + } + + void VerifyContextualReflectionProxy() + { + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + + using (ConntextualReflectionProxy.EnterContextualReflection(alc)) + { + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + using (ConntextualReflectionProxy.EnterContextualReflection(AssemblyLoadContext.Default)) + { + Assert.AreEqual(AssemblyLoadContext.Default, ConntextualReflectionProxy.CurrentContextualReflectionContext); + using (ConntextualReflectionProxy.EnterContextualReflection((Assembly)null)) + { + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + using (ConntextualReflectionProxy.EnterContextualReflection(alcAssembly)) + { + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + } + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + } + Assert.AreEqual(AssemblyLoadContext.Default, ConntextualReflectionProxy.CurrentContextualReflectionContext); + } + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + } + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + } + + void VerifyUsingStatementContextualReflectionUsage() + { + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + + { + using IDisposable alcScope = ConntextualReflectionProxy.EnterContextualReflection(alc); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + } + + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + + { + using IDisposable alcScope = ConntextualReflectionProxy.EnterContextualReflection(alc); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + alcScope.Dispose(); + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + } + + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + + { + using IDisposable alcScope = ConntextualReflectionProxy.EnterContextualReflection(alc); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + alcScope.Dispose(); + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + alcScope.Dispose(); + } + + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + + { + using IDisposable alcScope = ConntextualReflectionProxy.EnterContextualReflection(alc); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + { + using IDisposable defaultScope = ConntextualReflectionProxy.EnterContextualReflection(AssemblyLoadContext.Default); + Assert.AreEqual(AssemblyLoadContext.Default, ConntextualReflectionProxy.CurrentContextualReflectionContext); + + } + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + } + + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + + { + using IDisposable alcScope = ConntextualReflectionProxy.EnterContextualReflection(alc); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + try + { + using IDisposable defaultScope = ConntextualReflectionProxy.EnterContextualReflection(AssemblyLoadContext.Default); + Assert.AreEqual(AssemblyLoadContext.Default, ConntextualReflectionProxy.CurrentContextualReflectionContext); + + throw new InvalidOperationException(); + } + catch + { + } + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + } + + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + + { + using IDisposable alcScope = ConntextualReflectionProxy.EnterContextualReflection(alc); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + using IDisposable defaultScope = ConntextualReflectionProxy.EnterContextualReflection(AssemblyLoadContext.Default); + Assert.AreEqual(AssemblyLoadContext.Default, ConntextualReflectionProxy.CurrentContextualReflectionContext); + defaultScope.Dispose(); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + alcScope.Dispose(); + } + + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + } + + void VerifyBadContextualReflectionUsage() + { + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + + { + IDisposable alcScope = ConntextualReflectionProxy.EnterContextualReflection(alc); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + alcScope.Dispose(); + } + + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + + { + IDisposable alcScope = ConntextualReflectionProxy.EnterContextualReflection(alc); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + alcScope.Dispose(); + alcScope.Dispose(); + } + + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + + { + IDisposable alcScope = ConntextualReflectionProxy.EnterContextualReflection(alc); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + IDisposable defaultScope = ConntextualReflectionProxy.EnterContextualReflection(AssemblyLoadContext.Default); + Assert.AreEqual(AssemblyLoadContext.Default, ConntextualReflectionProxy.CurrentContextualReflectionContext); + defaultScope.Dispose(); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + alcScope.Dispose(); + } + + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + + { + IDisposable alcScope = ConntextualReflectionProxy.EnterContextualReflection(alc); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + IDisposable defaultScope = ConntextualReflectionProxy.EnterContextualReflection(AssemblyLoadContext.Default); + Assert.AreEqual(AssemblyLoadContext.Default, ConntextualReflectionProxy.CurrentContextualReflectionContext); + + alcScope.Dispose(); + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + + defaultScope.Dispose(); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + alcScope.Dispose(); + } + + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + + { + IDisposable alcScope = ConntextualReflectionProxy.EnterContextualReflection(alc); + Assert.AreEqual(alc, ConntextualReflectionProxy.CurrentContextualReflectionContext); + try + { + IDisposable defaultScope = ConntextualReflectionProxy.EnterContextualReflection((Assembly)null); + Assert.AreEqual(null, ConntextualReflectionProxy.CurrentContextualReflectionContext); + + throw new InvalidOperationException(); + } + catch + { + } + } + + Assert.IsNull(ConntextualReflectionProxy.CurrentContextualReflectionContext); + } + + void TestResolveMissingAssembly(bool isolated, Action<string> action, bool skipNullIsolated = false) + { + using (ConntextualReflectionProxy.EnterContextualReflection((Assembly)null)) + { + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => action("TestDefaultLoad")); + if (!skipNullIsolated) + TestResolve.Assert(isolated ? ResolveEvents.ExpectedEvent : ResolveEvents.NoEvent, () => action("TestIsolatedLoad")); + } + using (ConntextualReflectionProxy.EnterContextualReflection(AssemblyLoadContext.Default)) + { + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => action("TestDefaultLoad")); + TestResolve.Assert(ResolveEvents.NoEvent, () => action("TestIsolatedLoad")); + } + using (ConntextualReflectionProxy.EnterContextualReflection(alc)) + { + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => action("TestDefaultLoad")); + TestResolve.Assert(ResolveEvents.ExpectedEvent, () => action("TestIsolatedLoad")); + } + } + + void TestAssemblyLoad(bool isolated) + { + TestAssemblyLoad(isolated, (string assemblyName) => Assembly.Load(assemblyName)); + TestAssemblyLoad(isolated, (string assemblyName) => Assembly.Load(new AssemblyName(assemblyName))); + } + + void TestAssemblyLoad(bool isolated, Func<string, Assembly> assemblyLoad) + { + TestResolveMissingAssembly(isolated, (string assemblyName) => assemblyLoad(assemblyName)); + + using (ConntextualReflectionProxy.EnterContextualReflection((Assembly)null)) + { + Assembly assembly = assemblyLoad("ContextualReflection"); + + Assert.AreEqual(isolated ? alc : AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(assembly)); + + Assembly depends = assemblyLoad("ContextualReflectionDependency"); + + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(depends)); + } + using (ConntextualReflectionProxy.EnterContextualReflection(AssemblyLoadContext.Default)) + { + Assembly assembly = assemblyLoad("ContextualReflection"); + + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(assembly)); + + Assembly depends = assemblyLoad("ContextualReflectionDependency"); + + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(depends)); + } + using (ConntextualReflectionProxy.EnterContextualReflection(alc)) + { + Assembly assembly = assemblyLoad("ContextualReflection"); + + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(assembly)); + + Assembly depends = assemblyLoad("ContextualReflectionDependency"); + + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(depends)); + } + } + + void TestTypeGetType(bool isolated) + { + TestTypeGetType(isolated, (string typeName) => Type.GetType(typeName)); + TestTypeGetType(isolated, (string typeName) => Type.GetType(typeName, throwOnError : false)); + TestTypeGetType(isolated, (string typeName) => Type.GetType(typeName, throwOnError : false, ignoreCase : false)); + TestTypeGetType(isolated, (string typeName) => Type.GetType(typeName, assemblyResolver : null, typeResolver : null)); + TestTypeGetType(isolated, (string typeName) => Type.GetType(typeName, assemblyResolver : null, typeResolver : null, throwOnError : false)); + TestTypeGetType(isolated, (string typeName) => Type.GetType(typeName, assemblyResolver : null, typeResolver : null, throwOnError : false, ignoreCase : false)); + } + + void TestTypeGetType(bool isolated, Func<string, System.Type> typeGetType) + { + TestResolveMissingAssembly(isolated, (string assemblyName) => typeGetType(string.Format("MyType, {0}", assemblyName))); + + using (ConntextualReflectionProxy.EnterContextualReflection((Assembly)null)) + { + { + Type p = typeGetType("ContextualReflectionTest.Program"); + + Assembly expectedAssembly = Assembly.GetExecutingAssembly(); + + Assert.IsNotNull(p); + Assert.AreEqual(expectedAssembly, p.Assembly); + Assert.AreEqual(typeof (Program), p); + } + { + Type p = typeGetType("ContextualReflectionTest.Program, ContextualReflection"); + + Assembly expectedAssembly = Assembly.GetExecutingAssembly(); + + Assert.IsNotNull(p); + Assert.AreEqual(expectedAssembly, p.Assembly); + Assert.AreEqual(typeof (Program), p); + } + { + Type g = typeGetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]], ContextualReflection"); + + Assembly expectedAssembly = Assembly.GetExecutingAssembly(); + + Assert.IsNotNull(g); + Assert.AreEqual(expectedAssembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + Assert.AreEqual(isolated ? alc : AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(g.GenericTypeArguments[0].Assembly)); + } + } + using (ConntextualReflectionProxy.EnterContextualReflection(AssemblyLoadContext.Default)) + { + { + Type p = typeGetType("ContextualReflectionTest.Program"); + + Assembly expectedAssembly = Assembly.GetExecutingAssembly(); + + Assert.IsNotNull(p); + Assert.AreEqual(expectedAssembly, p.Assembly); + Assert.AreEqual(typeof (Program), p); + } + { + Type p = typeGetType("ContextualReflectionTest.Program, ContextualReflection"); + + Assembly expectedAssembly = defaultAssembly; + + Assert.IsNotNull(p); + Assert.AreEqual(expectedAssembly, p.Assembly); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(p.Assembly)); + } + { + Type g = typeGetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]], ContextualReflection"); + + Assembly expectedAssembly = defaultAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(expectedAssembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(g.Assembly)); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(g.GenericTypeArguments[0].Assembly)); + } + } + using (ConntextualReflectionProxy.EnterContextualReflection(alc)) + { + { + Type p = typeGetType("ContextualReflectionTest.Program"); + + Assembly expectedAssembly = Assembly.GetExecutingAssembly(); + + Assert.IsNotNull(p); + Assert.AreEqual(expectedAssembly, p.Assembly); + Assert.AreEqual(typeof (Program), p); + } + { + Type p = typeGetType("ContextualReflectionTest.Program, ContextualReflection"); + + Assembly expectedAssembly = alcAssembly; + + Assert.IsNotNull(p); + Assert.AreEqual(expectedAssembly, p.Assembly); + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(p.Assembly)); + } + { + Type g = typeGetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]], ContextualReflection"); + + Assembly expectedAssembly = alcAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(expectedAssembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(g.Assembly)); + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(g.GenericTypeArguments[0].Assembly)); + } + } + } + + void TestAssemblyGetType(bool isolated) + { + Assembly assembly = Assembly.GetExecutingAssembly(); + TestResolveMissingAssembly(isolated, + (string assemblyName) => assembly.GetType(string.Format("ContextualReflectionTest.AGenericClass`1[[MyType, {0}]]", assemblyName))); + + using (ConntextualReflectionProxy.EnterContextualReflection((Assembly)null)) + { + { + Type g = assembly.GetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program]]", throwOnError : false); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + Type g = assembly.GetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]", throwOnError : false); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + Assembly mscorlib = typeof (System.Collections.Generic.List<string>).Assembly; + + Type m = mscorlib.GetType("System.Collections.Generic.List`1[[ContextualReflectionTest.Program, ContextualReflection]]", throwOnError : false); + + Assembly expectedAssembly = mscorlib; + + Assert.IsNotNull(m); + Assert.AreEqual(expectedAssembly, m.Assembly); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(m.GenericTypeArguments[0].Assembly)); + } + } + using (ConntextualReflectionProxy.EnterContextualReflection(AssemblyLoadContext.Default)) + { + { + Type g = assembly.GetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program]]", throwOnError : false); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + Type g = assembly.GetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]", throwOnError : false); + + Assembly expectedAssembly = defaultAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + Assembly mscorlib = typeof (System.Collections.Generic.List<string>).Assembly; + + Type m = mscorlib.GetType("System.Collections.Generic.List`1[[ContextualReflectionTest.Program, ContextualReflection]]", throwOnError : false); + + Assembly expectedAssembly = mscorlib; + + Assert.IsNotNull(m); + Assert.AreEqual(expectedAssembly, m.Assembly); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(m.GenericTypeArguments[0].Assembly)); + } + } + using (ConntextualReflectionProxy.EnterContextualReflection(alc)) + { + { + Type g = assembly.GetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program]]", throwOnError : false); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + Type g = assembly.GetType("ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]", throwOnError : false); + + Assembly expectedAssembly = alcAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + Assembly mscorlib = typeof (System.Collections.Generic.List<string>).Assembly; + + Type m = mscorlib.GetType("System.Collections.Generic.List`1[[ContextualReflectionTest.Program, ContextualReflection]]", throwOnError : false); + + Assembly expectedAssembly = mscorlib; + + Assert.IsNotNull(m); + Assert.AreEqual(expectedAssembly, m.Assembly); + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(m.GenericTypeArguments[0].Assembly)); + } + } + } + + void TestActivatorCreateInstance(bool isolated) + { + TestResolveMissingAssembly(isolated, (string assemblyName) => Activator.CreateInstance(assemblyName, "MyType")); + TestResolveMissingAssembly(isolated, + (string assemblyName) => Activator.CreateInstance("System.Private.CoreLib", string.Format("System.Collections.Generic.List`1[[MyType, {0}]]", assemblyName)), + skipNullIsolated : true); + + TestResolveMissingAssembly(isolated, + (string assemblyName) => Activator.CreateInstance("ContextualReflection", string.Format("ContextualReflectionTest.AGenericClass`1[[MyType, {0}]]", assemblyName))); + + Assembly assembly = Assembly.GetExecutingAssembly(); + + using (ConntextualReflectionProxy.EnterContextualReflection((Assembly)null)) + { + { + ObjectHandle objectHandle = Activator.CreateInstance(null, "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + ObjectHandle objectHandle = Activator.CreateInstance(null, "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + ObjectHandle objectHandle = Activator.CreateInstance("ContextualReflection" , "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assembly expectedAssembly = assembly; + + Assert.IsNotNull(g); + Assert.AreEqual(expectedAssembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + Assembly expectedAssembly = alcAssembly; + + Assembly mscorlib = typeof (System.Collections.Generic.List<string>).Assembly; + + ObjectHandle objectHandle = Activator.CreateInstance(mscorlib.GetName().Name, "System.Collections.Generic.List`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type m = objectHandle.Unwrap().GetType(); + + Assert.IsNotNull(m); + Assert.AreEqual(mscorlib, m.Assembly); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(m.GenericTypeArguments[0].Assembly)); + } + } + using (ConntextualReflectionProxy.EnterContextualReflection(AssemblyLoadContext.Default)) + { + { + ObjectHandle objectHandle = Activator.CreateInstance(null, "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + ObjectHandle objectHandle = Activator.CreateInstance(null, "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assembly expectedAssembly = defaultAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + ObjectHandle objectHandle = Activator.CreateInstance("ContextualReflection" , "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assembly expectedAssembly = defaultAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(expectedAssembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + Assembly mscorlib = typeof (System.Collections.Generic.List<string>).Assembly; + + ObjectHandle objectHandle = Activator.CreateInstance(mscorlib.GetName().Name, "System.Collections.Generic.List`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type m = objectHandle.Unwrap().GetType(); + + Assembly expectedAssembly = mscorlib; + + Assert.IsNotNull(m); + Assert.AreEqual(expectedAssembly, m.Assembly); + Assert.AreEqual(AssemblyLoadContext.Default, AssemblyLoadContext.GetLoadContext(m.GenericTypeArguments[0].Assembly)); + } + } + using (ConntextualReflectionProxy.EnterContextualReflection(alc)) + { + { + ObjectHandle objectHandle = Activator.CreateInstance(null, "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(assembly, g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(Assembly.GetExecutingAssembly(), g.GenericTypeArguments[0].Assembly); + Assert.AreEqual(typeof (Program), g.GenericTypeArguments[0]); + } + { + ObjectHandle objectHandle = Activator.CreateInstance(null, "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assembly expectedAssembly = alcAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(assembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + ObjectHandle objectHandle = Activator.CreateInstance("ContextualReflection" , "ContextualReflectionTest.AGenericClass`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type g = objectHandle.Unwrap().GetType(); + + Assembly expectedAssembly = alcAssembly; + + Assert.IsNotNull(g); + Assert.AreEqual(expectedAssembly, g.Assembly); + Assert.AreEqual(expectedAssembly, g.GenericTypeArguments[0].Assembly); + } + { + Assembly mscorlib = typeof (System.Collections.Generic.List<string>).Assembly; + + ObjectHandle objectHandle = Activator.CreateInstance(mscorlib.GetName().Name, "System.Collections.Generic.List`1[[ContextualReflectionTest.Program, ContextualReflection]]"); + Type m = objectHandle.Unwrap().GetType(); + + Assert.IsNotNull(m); + Assert.AreEqual(mscorlib, m.Assembly); + Assert.AreEqual(alc, AssemblyLoadContext.GetLoadContext(m.GenericTypeArguments[0].Assembly)); + } + } + } + + public void RunTests() + { + VerifyIsolationDefault(); + VerifyTestResolve(); + VerifyContextualReflectionProxy(); + VerifyUsingStatementContextualReflectionUsage(); + VerifyBadContextualReflectionUsage(); + + RunTests(isolated : false); + alcProgramInstance.RunTestsIsolated(); + } + + public void RunTests(bool isolated) + { + TestAssemblyLoad(isolated); + TestTypeGetType(isolated); + TestAssemblyGetType(isolated); + TestActivatorCreateInstance(isolated); + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public void RunTestsIsolated() + { + VerifyIsolationAlc(); + RunTests(isolated : true); + } + } +} + diff --git a/tests/src/Loader/ContextualReflection/ContextualReflection.csproj b/tests/src/Loader/ContextualReflection/ContextualReflection.csproj new file mode 100644 index 0000000000..6f88de3877 --- /dev/null +++ b/tests/src/Loader/ContextualReflection/ContextualReflection.csproj @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <OutputType>Exe</OutputType> + <CLRTestKind>BuildAndRun</CLRTestKind> + <ProjectGuid>{78030DC5-F1A6-4B98-A130-A66F5047FF29}</ProjectGuid> + </PropertyGroup> + <ItemGroup> + <Compile Include="ContextualReflection.cs" /> + <ProjectReference Include="ContextualReflectionDependency.csproj" /> + <ProjectReference Include="../../Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" /> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project> diff --git a/tests/src/Loader/ContextualReflection/ContextualReflectionDependency.cs b/tests/src/Loader/ContextualReflection/ContextualReflectionDependency.cs new file mode 100644 index 0000000000..d8fc8ef014 --- /dev/null +++ b/tests/src/Loader/ContextualReflection/ContextualReflectionDependency.cs @@ -0,0 +1,123 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.Loader; + +namespace ContextualReflectionTest +{ + public interface IProgram + { + AssemblyLoadContext alc { get; } + Assembly alcAssembly { get; } + Type alcProgramType { get; } + IProgram alcProgramInstance { get; } + [MethodImplAttribute(MethodImplOptions.NoInlining)] + void RunTestsIsolated(); + } + + public class ConntextualReflectionProxy + { + public static AssemblyLoadContext CurrentContextualReflectionContext + { + get + { +#if AssemblyLoadContextContextualReflectionFacade + return AssemblyLoadContext.CurrentContextualReflectionContext; +#else + Type t = typeof (AssemblyLoadContext); + + object result = t.InvokeMember("CurrentContextualReflectionContext", + BindingFlags.Public | BindingFlags.Static | BindingFlags.GetProperty, + null, + null, + new object [] {}); + + return (AssemblyLoadContext) result; +#endif + } + } + + static public IDisposable EnterContextualReflection(AssemblyLoadContext alc) + { +#if AssemblyLoadContextContextualReflectionFacade + return alc.EnterContextualReflection(); +#else + Type t = typeof (AssemblyLoadContext); + + object result = t.InvokeMember("EnterContextualReflection", + BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, + null, + alc, + new object [] {}); + + return (IDisposable) result; +#endif + } + + static public IDisposable EnterContextualReflection(Assembly activating) + { +#if AssemblyLoadContextContextualReflectionFacade + return AssemblyLoadContext.EnterContextualReflection(activating); +#else + Type t = typeof (AssemblyLoadContext); + + object result = t.InvokeMember("EnterContextualReflection", + BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, + null, + null, + new object [] {activating}); + + return (IDisposable) result; +#endif + } + } + + public enum ResolveEvents + { + NoEvent, + ExpectedEvent, + }; + + public class TestResolve + { + static public ResolveEvents ResolveEvent { get; set;} + + static public Assembly ResolvingTestDefault(AssemblyLoadContext alc, AssemblyName assemblyName) + { + if (assemblyName.Name.Contains("TestDefaultLoad") && (ResolveEvent == ResolveEvents.NoEvent)) + { + ResolveEvent = ResolveEvents.ExpectedEvent; + } + return null; + } + + static public Assembly ResolvingTestIsolated(AssemblyLoadContext alc, AssemblyName assemblyName) + { + if (assemblyName.Name.Contains("TestIsolatedLoad") && (ResolveEvent == ResolveEvents.NoEvent)) + { + ResolveEvent = ResolveEvents.ExpectedEvent; + } + return null; + } + + static public void Assert(ResolveEvents expected, Action action) + { + ResolveEvent = ResolveEvents.NoEvent; + try + { + action(); + } + catch + { + } + finally + { + TestLibrary.Assert.AreEqual(expected, ResolveEvent); + } + } + } +} diff --git a/tests/src/Loader/ContextualReflection/ContextualReflectionDependency.csproj b/tests/src/Loader/ContextualReflection/ContextualReflectionDependency.csproj new file mode 100644 index 0000000000..1d8fb64087 --- /dev/null +++ b/tests/src/Loader/ContextualReflection/ContextualReflectionDependency.csproj @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <OutputType>Library</OutputType> + <CLRTestKind>BuildOnly</CLRTestKind> + <ProjectGuid>{95DBE3B0-AA86-4366-BB8A-E04B534365F3}</ProjectGuid> + </PropertyGroup> + <ItemGroup> + <Compile Include="ContextualReflectionDependency.cs" /> + <ProjectReference Include="../../Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" /> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project> diff --git a/tests/src/tracing/eventcounter/incrementingpollingcounter.cs b/tests/src/tracing/eventcounter/incrementingpollingcounter.cs index f215460741..2b21ebbf68 100644 --- a/tests/src/tracing/eventcounter/incrementingpollingcounter.cs +++ b/tests/src/tracing/eventcounter/incrementingpollingcounter.cs @@ -21,7 +21,7 @@ namespace BasicEventSourceTests { private object _failureCounter; - public SimpleEventSource(Func<float> getFailureCount, Type IncrementingPollingCounterType) + public SimpleEventSource(Func<double> getFailureCount, Type IncrementingPollingCounterType) { _failureCounter = Activator.CreateInstance(IncrementingPollingCounterType, "failureCount", this, getFailureCount); } @@ -93,7 +93,7 @@ namespace BasicEventSourceTests public static int failureCountCalled = 0; - public static float getFailureCount() + public static double getFailureCount() { failureCountCalled++; return failureCountCalled; diff --git a/tests/src/tracing/eventcounter/pollingcounter.cs b/tests/src/tracing/eventcounter/pollingcounter.cs index ba2369d639..9e8dff2ef4 100644 --- a/tests/src/tracing/eventcounter/pollingcounter.cs +++ b/tests/src/tracing/eventcounter/pollingcounter.cs @@ -22,7 +22,7 @@ namespace BasicEventSourceTests private object _failureCounter; private object _successCounter; - public SimpleEventSource(Func<float> getFailureCount, Func<float> getSuccessCount, Type PollingCounterType) + public SimpleEventSource(Func<double> getFailureCount, Func<double> getSuccessCount, Type PollingCounterType) { _failureCounter = Activator.CreateInstance(PollingCounterType, "failureCount", this, getSuccessCount); _successCounter = Activator.CreateInstance(PollingCounterType, "successCount", this, getFailureCount); @@ -140,13 +140,13 @@ namespace BasicEventSourceTests public static int failureCountCalled = 0; public static int successCountCalled = 0; - public static float getFailureCount() + public static double getFailureCount() { failureCountCalled++; return failureCountCalled; } - public static float getSuccessCount() + public static double getSuccessCount() { successCountCalled++; return successCountCalled; |