summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLevi Broderick <levib@microsoft.com>2019-04-10 22:56:33 -0700
committerLevi Broderick <levib@microsoft.com>2019-04-10 22:56:33 -0700
commiteda0c04f28b9d0ecf3d29fc2c860eac1606d9e6d (patch)
tree0cadf7e159302d9fc6e193420f17f2e4f707dc98
parentbae40fa2c2d8f9acb9b8148b7d6a6b91ace55058 (diff)
parent232ba42911f8266a96f73a77bc1e18f431d96862 (diff)
downloadcoreclr-eda0c04f28b9d0ecf3d29fc2c860eac1606d9e6d.tar.gz
coreclr-eda0c04f28b9d0ecf3d29fc2c860eac1606d9e6d.tar.bz2
coreclr-eda0c04f28b9d0ecf3d29fc2c860eac1606d9e6d.zip
Merge remote-tracking branch 'origin/master' into utf8_validation_apis_3
-rw-r--r--Documentation/building/windows-instructions.md4
-rw-r--r--Documentation/project-docs/profiling-api-status.md6
-rw-r--r--ILAsmVersion.txt2
-rw-r--r--dependencies.props4
-rw-r--r--eng/Version.Details.xml4
-rw-r--r--eng/Versions.props2
-rw-r--r--src/System.Private.CoreLib/ILLinkTrim.xml2
-rw-r--r--src/System.Private.CoreLib/System.Private.CoreLib.csproj5
-rw-r--r--src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems7
-rw-r--r--src/System.Private.CoreLib/shared/System/Activator.RuntimeType.cs3
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Delegate.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterGroup.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterPayload.cs64
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/DiagnosticCounter.cs (renamed from src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/BaseCounter.cs)44
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventCounter.cs54
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSourceException.cs1
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingEventCounter.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IncrementingPollingCounter.cs28
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/PollingCounter.cs23
-rw-r--r--src/System.Private.CoreLib/shared/System/Environment.Win32.cs32
-rw-r--r--src/System.Private.CoreLib/shared/System/Environment.WinRT.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Range.cs26
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/AssemblyName.cs (renamed from src/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs)152
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/RuntimeHelpers.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs111
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs111
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs56
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs24
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs24
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs48
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs48
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs85
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs85
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs178
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/TimerQueue.Windows.cs40
-rw-r--r--src/System.Private.CoreLib/src/System/Environment.CoreCLR.cs34
-rw-r--r--src/System.Private.CoreLib/src/System/GC.cs65
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs10
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs111
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs38
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs4
-rw-r--r--src/System.Private.CoreLib/src/System/RuntimeHandles.cs10
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Timer.CoreCLR.cs31
-rw-r--r--src/System.Private.CoreLib/src/System/TypeNameParser.cs9
-rw-r--r--src/classlibnative/bcltype/system.cpp3
-rw-r--r--src/coreclr/hosts/corerun/corerun.cpp36
-rw-r--r--src/coreclr/hosts/coreshim/CoreShim.cpp18
-rw-r--r--src/coreclr/hosts/coreshim/CoreShim.h1
-rw-r--r--src/coreclr/hosts/unixcoreruncommon/coreruncommon.cpp5
-rw-r--r--src/dlls/mscordac/mscordac_unixexports.src1
-rw-r--r--src/gc/env/gcenv.os.h10
-rw-r--r--src/gc/unix/gcenv.unix.cpp140
-rw-r--r--src/gc/windows/gcenv.windows.cpp94
-rw-r--r--src/inc/utilcode.h19
-rw-r--r--src/jit/assertionprop.cpp237
-rw-r--r--src/jit/compiler.h6
-rw-r--r--src/jit/flowgraph.cpp39
-rw-r--r--src/jit/gentree.cpp110
-rw-r--r--src/pal/inc/pal.h145
-rw-r--r--src/pal/src/misc/sysinfo.cpp40
-rw-r--r--src/pal/src/numa/numa.cpp820
-rw-r--r--src/pal/src/numa/numashim.h16
-rw-r--r--src/pal/src/thread/thread.cpp97
-rw-r--r--src/strongname/api/common.h2
-rw-r--r--src/utilcode/util.cpp32
-rw-r--r--src/vm/assemblynative.cpp44
-rw-r--r--src/vm/assemblynative.hpp4
-rw-r--r--src/vm/assemblyspec.cpp2
-rw-r--r--src/vm/ceeload.cpp5
-rw-r--r--src/vm/ceemain.cpp3
-rw-r--r--src/vm/comcallablewrapper.cpp75
-rw-r--r--src/vm/comcallablewrapper.h78
-rw-r--r--src/vm/common.h2
-rw-r--r--src/vm/ecalllist.h2
-rw-r--r--src/vm/eeconfig.cpp9
-rw-r--r--src/vm/gcenv.os.cpp157
-rw-r--r--src/vm/interopconverter.cpp23
-rw-r--r--src/vm/mlinfo.cpp14
-rw-r--r--src/vm/mscorlib.h12
-rw-r--r--src/vm/object.h52
-rw-r--r--src/vm/qcall.cpp22
-rw-r--r--src/vm/qcall.h29
-rw-r--r--src/vm/runtimecallablewrapper.cpp6
-rw-r--r--src/vm/runtimehandles.cpp15
-rw-r--r--src/vm/runtimehandles.h2
-rw-r--r--src/vm/threads.cpp8
-rw-r--r--src/vm/threads.h3
-rw-r--r--src/vm/typeparse.cpp19
-rw-r--r--src/vm/vars.hpp3
-rw-r--r--src/vm/win32threadpool.cpp22
-rw-r--r--src/vm/win32threadpool.h14
-rw-r--r--tests/issues.targets3
-rw-r--r--tests/src/Interop/COM/NETClients/Aggregation/NETClientAggregation.csproj2
-rw-r--r--tests/src/Interop/COM/NETClients/ConsumeNETServer/App.manifest18
-rw-r--r--tests/src/Interop/COM/NETClients/ConsumeNETServer/ConsumeNETServer.csproj54
-rw-r--r--tests/src/Interop/COM/NETClients/ConsumeNETServer/CoreShim.X.manifest16
-rw-r--r--tests/src/Interop/COM/NETClients/ConsumeNETServer/Program.cs117
-rw-r--r--tests/src/Interop/COM/NETClients/Events/NETClientEvents.csproj2
-rw-r--r--tests/src/Interop/COM/NETClients/IDispatch/NETClientIDispatch.csproj2
-rw-r--r--tests/src/Interop/COM/NETClients/Licensing/NETClientLicense.csproj2
-rw-r--r--tests/src/Interop/COM/NETClients/Primitives/NETClientPrimitives.csproj2
-rw-r--r--tests/src/Interop/COM/NETServer/ConsumeNETServerTesting.cs51
-rw-r--r--tests/src/Interop/COM/NETServer/NETServer.csproj8
-rw-r--r--tests/src/Interop/COM/ServerContracts/Server.CoClasses.cs (renamed from tests/src/Interop/COM/ServerContracts/NativeServers.cs)25
-rw-r--r--tests/src/Interop/COM/ServerContracts/Server.Contracts.cs16
-rw-r--r--tests/src/Interop/COM/ServerContracts/ServerGuids.cs1
-rw-r--r--tests/src/Loader/ContextualReflection/ContextualReflection.cs748
-rw-r--r--tests/src/Loader/ContextualReflection/ContextualReflection.csproj18
-rw-r--r--tests/src/Loader/ContextualReflection/ContextualReflectionDependency.cs123
-rw-r--r--tests/src/Loader/ContextualReflection/ContextualReflectionDependency.csproj17
-rw-r--r--tests/src/tracing/eventcounter/incrementingpollingcounter.cs4
-rw-r--r--tests/src/tracing/eventcounter/pollingcounter.cs6
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&lt;AssemblyLoadContext&gt;. 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;