From e24179e775a2666dd4b7e0154f95305308c6a400 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Fi=C5=A1era?= <mara@neptuo.com>
Date: Fri, 19 Jan 2024 09:35:16 +0100
Subject: [PATCH 01/36] [release/8.0-staging] [browser] Use whole assembly name
 when looking for already loaded assemblies (#97144)

---
 .../Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs  |  4 ++++
 .../TestAppScenarios/LazyLoadingTests.cs              |  2 +-
 src/mono/wasm/runtime/lazyLoading.ts                  |  2 +-
 src/mono/wasm/runtime/loader/assets.ts                |  2 +-
 .../WasmBasicTestApp/{ => App}/AppSettingsTest.cs     |  0
 .../WasmBasicTestApp/{ => App}/Common/Program.cs      |  0
 .../WasmBasicTestApp/{ => App}/Common/TestOutput.cs   |  0
 .../WasmBasicTestApp/{ => App}/LazyLoadingTest.cs     |  3 +--
 .../{ => App}/LibraryInitializerTest.cs               |  0
 .../{ => App}/Properties/AssemblyInfo.cs              |  0
 .../{ => App}/SatelliteAssembliesTest.cs              |  0
 .../{ => App}/WasmBasicTestApp.csproj                 |  6 +++++-
 .../{ => App}/runtimeconfig.template.json             |  0
 .../WasmBasicTestApp/{ => App}/words.es-ES.resx       |  0
 .../testassets/WasmBasicTestApp/{ => App}/words.resx  |  0
 .../{ => App}/wwwroot/WasmBasicTestApp.lib.module.js  |  0
 .../{ => App}/wwwroot/appsettings.Development.json    |  0
 .../{ => App}/wwwroot/appsettings.Production.json     |  0
 .../{ => App}/wwwroot/appsettings.json                |  0
 .../WasmBasicTestApp/{ => App}/wwwroot/index.html     |  0
 .../WasmBasicTestApp/{ => App}/wwwroot/main.js        |  2 +-
 .../wasm/testassets/WasmBasicTestApp/Library/Json.cs  | 11 +++++++++++
 .../testassets/WasmBasicTestApp/Library/Json.csproj   |  8 ++++++++
 23 files changed, 33 insertions(+), 7 deletions(-)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/AppSettingsTest.cs (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/Common/Program.cs (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/Common/TestOutput.cs (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/LazyLoadingTest.cs (91%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/LibraryInitializerTest.cs (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/Properties/AssemblyInfo.cs (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/SatelliteAssembliesTest.cs (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/WasmBasicTestApp.csproj (70%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/runtimeconfig.template.json (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/words.es-ES.resx (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/words.resx (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/wwwroot/WasmBasicTestApp.lib.module.js (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/wwwroot/appsettings.Development.json (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/wwwroot/appsettings.Production.json (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/wwwroot/appsettings.json (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/wwwroot/index.html (100%)
 rename src/mono/wasm/testassets/WasmBasicTestApp/{ => App}/wwwroot/main.js (97%)
 create mode 100644 src/mono/wasm/testassets/WasmBasicTestApp/Library/Json.cs
 create mode 100644 src/mono/wasm/testassets/WasmBasicTestApp/Library/Json.csproj

diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs
index 444d70228b08fa..dc6fb9b490e7f3 100644
--- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/AppTestBase.cs
@@ -30,6 +30,10 @@ protected void CopyTestAsset(string assetName, string generatedProjectNamePrefix
 
         LogPath = Path.Combine(s_buildEnv.LogRootPath, Id);
         Utils.DirectoryCopy(Path.Combine(BuildEnvironment.TestAssetsPath, assetName), Path.Combine(_projectDir!));
+
+        // WasmBasicTestApp consists of App + Library projects
+        if (assetName == "WasmBasicTestApp")
+            _projectDir = Path.Combine(_projectDir!, "App");
     }
 
     protected void BuildProject(string configuration)
diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs
index d2219e9f9e50da..8f37a47e18860a 100644
--- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs
+++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs
@@ -42,6 +42,6 @@ public async Task FailOnMissingLazyAssembly()
             BrowserQueryString: new Dictionary<string, string> { ["loadRequiredAssembly"] = "false" },
             ExpectedExitCode: 1
         ));
-        Assert.True(result.ConsoleOutput.Any(m => m.Contains("Could not load file or assembly") && m.Contains("System.Text.Json")), "The lazy loading test didn't emit expected error message");
+        Assert.True(result.ConsoleOutput.Any(m => m.Contains("Could not load file or assembly") && m.Contains("Json")), "The lazy loading test didn't emit expected error message");
     }
 }
diff --git a/src/mono/wasm/runtime/lazyLoading.ts b/src/mono/wasm/runtime/lazyLoading.ts
index 59c153a9d62365..55bcfd67101e8c 100644
--- a/src/mono/wasm/runtime/lazyLoading.ts
+++ b/src/mono/wasm/runtime/lazyLoading.ts
@@ -21,7 +21,7 @@ export async function loadLazyAssembly(assemblyNameToLoad: string): Promise<bool
         behavior: "assembly",
     };
 
-    if (loaderHelpers.loadedAssemblies.some(f => f.includes(assemblyNameToLoad))) {
+    if (loaderHelpers.loadedAssemblies.includes(assemblyNameToLoad)) {
         return false;
     }
 
diff --git a/src/mono/wasm/runtime/loader/assets.ts b/src/mono/wasm/runtime/loader/assets.ts
index 02e05b1f8a9622..8730988193ffd0 100644
--- a/src/mono/wasm/runtime/loader/assets.ts
+++ b/src/mono/wasm/runtime/loader/assets.ts
@@ -598,7 +598,7 @@ function download_resource(asset: AssetEntryInternal): LoadingResource {
         totalResources.add(asset.name!);
         response.response.then(() => {
             if (asset.behavior == "assembly") {
-                loaderHelpers.loadedAssemblies.push(asset.resolvedUrl!);
+                loaderHelpers.loadedAssemblies.push(asset.name);
             }
 
             resourcesLoaded++;
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/AppSettingsTest.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/AppSettingsTest.cs
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/AppSettingsTest.cs
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/AppSettingsTest.cs
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/Common/Program.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/Common/Program.cs
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/Common/Program.cs
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/Common/Program.cs
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/Common/TestOutput.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/Common/TestOutput.cs
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/Common/TestOutput.cs
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/Common/TestOutput.cs
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/LazyLoadingTest.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/LazyLoadingTest.cs
similarity index 91%
rename from src/mono/wasm/testassets/WasmBasicTestApp/LazyLoadingTest.cs
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/LazyLoadingTest.cs
index 0d68b1216816c3..5aba6b1ee48a0f 100644
--- a/src/mono/wasm/testassets/WasmBasicTestApp/LazyLoadingTest.cs
+++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/LazyLoadingTest.cs
@@ -1,6 +1,7 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using Library;
 using System;
 using System.Text.Json;
 using System.Runtime.InteropServices.JavaScript;
@@ -15,6 +16,4 @@ public static void Run()
         var text = JsonSerializer.Serialize(new Person("John", "Doe"));
         TestOutput.WriteLine(text);
     }
-
-    public record Person(string FirstName, string LastName);
 }
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/LibraryInitializerTest.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/LibraryInitializerTest.cs
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/LibraryInitializerTest.cs
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/LibraryInitializerTest.cs
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/Properties/AssemblyInfo.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/Properties/AssemblyInfo.cs
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/Properties/AssemblyInfo.cs
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/Properties/AssemblyInfo.cs
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/SatelliteAssembliesTest.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/SatelliteAssembliesTest.cs
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/SatelliteAssembliesTest.cs
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/SatelliteAssembliesTest.cs
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/WasmBasicTestApp.csproj b/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj
similarity index 70%
rename from src/mono/wasm/testassets/WasmBasicTestApp/WasmBasicTestApp.csproj
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj
index 761ac6354ce861..a3b9364d4fce80 100644
--- a/src/mono/wasm/testassets/WasmBasicTestApp/WasmBasicTestApp.csproj
+++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj
@@ -8,6 +8,10 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <BlazorWebAssemblyLazyLoad Include="System.Text.Json$(WasmAssemblyExtension)" />
+    <ProjectReference Include="..\Library\Json.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <BlazorWebAssemblyLazyLoad Include="Json$(WasmAssemblyExtension)" />
   </ItemGroup>
 </Project>
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/runtimeconfig.template.json b/src/mono/wasm/testassets/WasmBasicTestApp/App/runtimeconfig.template.json
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/runtimeconfig.template.json
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/runtimeconfig.template.json
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/words.es-ES.resx b/src/mono/wasm/testassets/WasmBasicTestApp/App/words.es-ES.resx
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/words.es-ES.resx
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/words.es-ES.resx
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/words.resx b/src/mono/wasm/testassets/WasmBasicTestApp/App/words.resx
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/words.resx
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/words.resx
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/wwwroot/WasmBasicTestApp.lib.module.js b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/WasmBasicTestApp.lib.module.js
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/wwwroot/WasmBasicTestApp.lib.module.js
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/WasmBasicTestApp.lib.module.js
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/wwwroot/appsettings.Development.json b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/appsettings.Development.json
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/wwwroot/appsettings.Development.json
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/appsettings.Development.json
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/wwwroot/appsettings.Production.json b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/appsettings.Production.json
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/wwwroot/appsettings.Production.json
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/appsettings.Production.json
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/wwwroot/appsettings.json b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/appsettings.json
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/wwwroot/appsettings.json
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/appsettings.json
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/wwwroot/index.html b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/index.html
similarity index 100%
rename from src/mono/wasm/testassets/WasmBasicTestApp/wwwroot/index.html
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/index.html
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/wwwroot/main.js b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js
similarity index 97%
rename from src/mono/wasm/testassets/WasmBasicTestApp/wwwroot/main.js
rename to src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js
index 8d537cbdfb4041..076f37a62a6d87 100644
--- a/src/mono/wasm/testassets/WasmBasicTestApp/wwwroot/main.js
+++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js
@@ -79,7 +79,7 @@ try {
             break;
         case "LazyLoadingTest":
             if (params.get("loadRequiredAssembly") !== "false") {
-                await INTERNAL.loadLazyAssembly(`System.Text.Json${assemblyExtension}`);
+                await INTERNAL.loadLazyAssembly(`Json${assemblyExtension}`);
             }
             exports.LazyLoadingTest.Run();
             exit(0);
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/Library/Json.cs b/src/mono/wasm/testassets/WasmBasicTestApp/Library/Json.cs
new file mode 100644
index 00000000000000..cd496b96a3fc9e
--- /dev/null
+++ b/src/mono/wasm/testassets/WasmBasicTestApp/Library/Json.cs
@@ -0,0 +1,11 @@
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Library;
+
+public record Person(string FirstName, string LastName);
+
+[JsonSerializable(typeof(Person))]
+public partial class PersonJsonSerializerContext : JsonSerializerContext
+{
+}
\ No newline at end of file
diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/Library/Json.csproj b/src/mono/wasm/testassets/WasmBasicTestApp/Library/Json.csproj
new file mode 100644
index 00000000000000..87c4a405521efe
--- /dev/null
+++ b/src/mono/wasm/testassets/WasmBasicTestApp/Library/Json.csproj
@@ -0,0 +1,8 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <!-- The name of the assembly is important, one the lazy loading checks is that when System.Text.Json(.dll) is already loaded, we can lazy load Json(.dll) -->
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <OutputType>Library</OutputType>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+</Project>

From 5e9e29f6bb2e76f24bb80e72d39813ee6d3909a1 Mon Sep 17 00:00:00 2001
From: Pavel Savara <pavel.savara@gmail.com>
Date: Tue, 23 Jan 2024 15:50:09 +0100
Subject: [PATCH 02/36] [release/8.0][browser] BrowserWebSocket.ReceiveAsync
 after server initiated close (#97002)

---
 .../Net/WebSockets/WebSocketValidate.cs       | 11 ++-
 .../Handlers/EchoWebSocketHandler.cs          | 17 +++-
 .../BrowserWebSockets/BrowserWebSocket.cs     | 87 ++++++++++++-------
 .../tests/CloseTest.cs                        | 81 ++++++++++++++---
 .../tests/SendReceiveTest.cs                  |  2 +-
 src/mono/wasm/runtime/web-socket.ts           | 68 ++++++++++++---
 6 files changed, 205 insertions(+), 61 deletions(-)

diff --git a/src/libraries/Common/src/System/Net/WebSockets/WebSocketValidate.cs b/src/libraries/Common/src/System/Net/WebSockets/WebSocketValidate.cs
index 7c97c082d26f89..e087677be4608e 100644
--- a/src/libraries/Common/src/System/Net/WebSockets/WebSocketValidate.cs
+++ b/src/libraries/Common/src/System/Net/WebSockets/WebSocketValidate.cs
@@ -23,10 +23,15 @@ internal static partial class WebSocketValidate
         internal const int MaxDeflateWindowBits = 15;
 
         internal const int MaxControlFramePayloadLength = 123;
+#if TARGET_BROWSER
+        private const int ValidCloseStatusCodesFrom = 3000;
+        private const int ValidCloseStatusCodesTo = 4999;
+#else
         private const int CloseStatusCodeAbort = 1006;
         private const int CloseStatusCodeFailedTLSHandshake = 1015;
         private const int InvalidCloseStatusCodesFrom = 0;
         private const int InvalidCloseStatusCodesTo = 999;
+#endif
 
         // [0x21, 0x7E] except separators "()<>@,;:\\\"/[]?={} ".
         private static readonly SearchValues<char> s_validSubprotocolChars =
@@ -84,11 +89,15 @@ internal static void ValidateCloseStatus(WebSocketCloseStatus closeStatus, strin
             }
 
             int closeStatusCode = (int)closeStatus;
-
+#if TARGET_BROWSER
+            // as defined in https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code
+            if (closeStatus != WebSocketCloseStatus.NormalClosure && (closeStatusCode < ValidCloseStatusCodesFrom || closeStatusCode > ValidCloseStatusCodesTo))
+#else
             if ((closeStatusCode >= InvalidCloseStatusCodesFrom &&
                 closeStatusCode <= InvalidCloseStatusCodesTo) ||
                 closeStatusCode == CloseStatusCodeAbort ||
                 closeStatusCode == CloseStatusCodeFailedTLSHandshake)
+#endif
             {
                 // CloseStatus 1006 means Aborted - this will never appear on the wire and is reflected by calling WebSocket.Abort
                 throw new ArgumentException(SR.Format(SR.net_WebSockets_InvalidCloseStatusCode,
diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/Handlers/EchoWebSocketHandler.cs b/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/Handlers/EchoWebSocketHandler.cs
index f4e5562600015d..8304f2d1156072 100644
--- a/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/Handlers/EchoWebSocketHandler.cs
+++ b/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/Handlers/EchoWebSocketHandler.cs
@@ -24,11 +24,11 @@ public static async Task InvokeAsync(HttpContext context)
 
             if (context.Request.QueryString.HasValue && context.Request.QueryString.Value.Contains("delay10sec"))
             {
-                Thread.Sleep(10000);
+                await Task.Delay(10000);
             }
             else if (context.Request.QueryString.HasValue && context.Request.QueryString.Value.Contains("delay20sec"))
             {
-                Thread.Sleep(20000);
+                await Task.Delay(20000);
             }
 
             try
@@ -124,14 +124,15 @@ await socket.CloseAsync(
                 }
 
                 bool sendMessage = false;
+                string receivedMessage = null;
                 if (receiveResult.MessageType == WebSocketMessageType.Text)
                 {
-                    string receivedMessage = Encoding.UTF8.GetString(receiveBuffer, 0, offset);
+                    receivedMessage = Encoding.UTF8.GetString(receiveBuffer, 0, offset);
                     if (receivedMessage == ".close")
                     {
                         await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, receivedMessage, CancellationToken.None);
                     }
-                    if (receivedMessage == ".shutdown")
+                    else if (receivedMessage == ".shutdown")
                     {
                         await socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, receivedMessage, CancellationToken.None);
                     }
@@ -161,6 +162,14 @@ await socket.SendAsync(
                             !replyWithPartialMessages,
                             CancellationToken.None);
                 }
+                if (receivedMessage == ".closeafter")
+                {
+                    await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, receivedMessage, CancellationToken.None);
+                }
+                else if (receivedMessage == ".shutdownafter")
+                {
+                    await socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, receivedMessage, CancellationToken.None);
+                }
             }
         }
     }
diff --git a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/BrowserWebSockets/BrowserWebSocket.cs b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/BrowserWebSockets/BrowserWebSocket.cs
index 121fa8595c65d5..879d45ca0da57c 100644
--- a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/BrowserWebSockets/BrowserWebSocket.cs
+++ b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/BrowserWebSockets/BrowserWebSocket.cs
@@ -24,6 +24,8 @@ internal sealed class BrowserWebSocket : WebSocket
         private WebSocketState _state;
         private bool _disposed;
         private bool _aborted;
+        private bool _closeReceived;
+        private bool _closeSent;
         private int[] responseStatus = new int[3];
         private MemoryHandle? responseStatusHandle;
 
@@ -37,7 +39,7 @@ public override WebSocketState State
                 lock (_thisLock)
                 {
 #endif
-                    if (_innerWebSocket == null || _disposed || (_state != WebSocketState.Connecting && _state != WebSocketState.Open && _state != WebSocketState.CloseSent))
+                    if (_innerWebSocket == null || _disposed || _state == WebSocketState.Aborted || _state == WebSocketState.Closed)
                     {
                         return _state;
                     }
@@ -46,15 +48,9 @@ public override WebSocketState State
 #endif
 
 #if FEATURE_WASM_THREADS
-                return FastState = _innerWebSocket!.SynchronizationContext.Send(static (BrowserWebSocket self) =>
-                {
-                    lock (self._thisLock)
-                    {
-                        return GetReadyState(self._innerWebSocket!);
-                    } //lock
-                }, this);
+                return _innerWebSocket!.SynchronizationContext.Send(GetReadyState, this);
 #else
-                return FastState = GetReadyState(_innerWebSocket!);
+                return GetReadyState(this);
 #endif
             }
         }
@@ -148,7 +144,7 @@ public override Task SendAsync(ArraySegment<byte> buffer, WebSocketMessageType m
             ThrowIfDisposed();
 
             // fast check of previous _state instead of GetReadyState(), the readyState would be validated on JS side
-            if (FastState != WebSocketState.Open)
+            if (FastState != WebSocketState.Open && FastState != WebSocketState.CloseReceived)
             {
                 throw new InvalidOperationException(SR.net_WebSockets_NotConnected);
             }
@@ -240,7 +236,7 @@ public override Task CloseOutputAsync(WebSocketCloseStatus closeStatus, string?
                     {
                         throw new WebSocketException(WebSocketError.InvalidState, SR.Format(SR.net_WebSockets_InvalidState, state, "Connecting, Open, CloseSent, Aborted"));
                     }
-                    if(state != WebSocketState.Open && state != WebSocketState.Connecting && state != WebSocketState.Aborted)
+                    if (state == WebSocketState.CloseSent)
                     {
                         return Task.CompletedTask;
                     }
@@ -280,10 +276,6 @@ public override Task CloseAsync(WebSocketCloseStatus closeStatus, string? status
                     {
                         throw new WebSocketException(WebSocketError.InvalidState, SR.Format(SR.net_WebSockets_InvalidState, state, "Connecting, Open, CloseSent, Aborted"));
                     }
-                    if (state != WebSocketState.Open && state != WebSocketState.Connecting && state != WebSocketState.Aborted && state != WebSocketState.CloseSent)
-                    {
-                        return Task.CompletedTask;
-                    }
 
 #if FEATURE_WASM_THREADS
                     promise = CloseAsyncCore(closeStatus, statusDescription, state != WebSocketState.Aborted, cancellationToken);
@@ -387,12 +379,13 @@ private void CreateCore(Uri uri, List<string>? requestedSubProtocols)
                 string[]? subProtocols = requestedSubProtocols?.ToArray();
                 var onClose = (int code, string reason) =>
                 {
-                    _closeStatus = (WebSocketCloseStatus)code;
-                    _closeStatusDescription = reason;
 #if FEATURE_WASM_THREADS
                     lock (_thisLock)
                     {
 #endif
+                        _closeStatus = (WebSocketCloseStatus)code;
+                        _closeStatusDescription = reason;
+                        _closeReceived = true;
                         WebSocketState state = State;
                         if (state == WebSocketState.Connecting || state == WebSocketState.Open || state == WebSocketState.CloseSent)
                         {
@@ -545,6 +538,8 @@ private static WebSocketReceiveResult ConvertResponse(BrowserWebSocket self)
             WebSocketMessageType messageType = (WebSocketMessageType)self.responseStatus[typeIndex];
             if (messageType == WebSocketMessageType.Close)
             {
+                self._closeReceived = true;
+                self.FastState = self._closeSent ? WebSocketState.Closed : WebSocketState.CloseReceived;
                 return new WebSocketReceiveResult(self.responseStatus[countIndex], messageType, self.responseStatus[endIndex] != 0, self.CloseStatus, self.CloseStatusDescription);
             }
             return new WebSocketReceiveResult(self.responseStatus[countIndex], messageType, self.responseStatus[endIndex] != 0);
@@ -552,8 +547,12 @@ private static WebSocketReceiveResult ConvertResponse(BrowserWebSocket self)
 
         private async Task CloseAsyncCore(WebSocketCloseStatus closeStatus, string? statusDescription, bool waitForCloseReceived, CancellationToken cancellationToken)
         {
-            _closeStatus = closeStatus;
-            _closeStatusDescription = statusDescription;
+            if (!_closeReceived)
+            {
+                _closeStatus = closeStatus;
+                _closeStatusDescription = statusDescription;
+            }
+            _closeSent = true;
 
             var closeTask = BrowserInterop.WebSocketClose(_innerWebSocket!, (int)closeStatus, statusDescription, waitForCloseReceived) ?? Task.CompletedTask;
             await CancelationHelper(closeTask, cancellationToken, FastState).ConfigureAwait(true);
@@ -562,6 +561,10 @@ private async Task CloseAsyncCore(WebSocketCloseStatus closeStatus, string? stat
             lock (_thisLock)
             {
 #endif
+                if (waitForCloseReceived)
+                {
+                    _closeReceived = true;
+                }
                 var state = State;
                 if (state == WebSocketState.Open || state == WebSocketState.Connecting || state == WebSocketState.CloseSent)
                 {
@@ -614,18 +617,42 @@ private async Task CancelationHelper(Task jsTask, CancellationToken cancellation
             }
         }
 
-        private static WebSocketState GetReadyState(JSObject innerWebSocket)
+        private static WebSocketState GetReadyState(BrowserWebSocket self)
         {
-            var readyState = BrowserInterop.GetReadyState(innerWebSocket);
-            // https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
-            return readyState switch
-            {
-                0 => WebSocketState.Connecting, // 0 (CONNECTING)
-                1 => WebSocketState.Open, // 1 (OPEN)
-                2 => WebSocketState.CloseSent, // 2 (CLOSING)
-                3 => WebSocketState.Closed, // 3 (CLOSED)
-                _ => WebSocketState.None
-            };
+#if FEATURE_WASM_THREADS
+            lock (self._thisLock)
+            {
+#endif
+                var readyState = BrowserInterop.GetReadyState(self._innerWebSocket);
+                // https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
+                var st = readyState switch
+                {
+                    0 => WebSocketState.Connecting, // 0 (CONNECTING)
+                    1 => WebSocketState.Open, // 1 (OPEN)
+                    2 => WebSocketState.CloseSent, // 2 (CLOSING)
+                    3 => WebSocketState.Closed, // 3 (CLOSED)
+                    _ => WebSocketState.None
+                };
+                if (st == WebSocketState.Closed || st == WebSocketState.CloseSent)
+                {
+                    if (self._closeReceived && self._closeSent)
+                    {
+                        st = WebSocketState.Closed;
+                    }
+                    else if (self._closeReceived && !self._closeSent)
+                    {
+                        st = WebSocketState.CloseReceived;
+                    }
+                    else if (!self._closeReceived && self._closeSent)
+                    {
+                        st = WebSocketState.CloseSent;
+                    }
+                }
+                self.FastState = st;
+                return st;
+#if FEATURE_WASM_THREADS
+            } //lock
+#endif
         }
 
         #endregion
diff --git a/src/libraries/System.Net.WebSockets.Client/tests/CloseTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/CloseTest.cs
index 9e33810098f7da..6f1e6faa490192 100644
--- a/src/libraries/System.Net.WebSockets.Client/tests/CloseTest.cs
+++ b/src/libraries/System.Net.WebSockets.Client/tests/CloseTest.cs
@@ -33,12 +33,12 @@ public class CloseTest : ClientWebSocketTestBase
         public CloseTest(ITestOutputHelper output) : base(output) { }
 
 
-        [ActiveIssue("https://github.com/dotnet/runtime/issues/28957")]
+        [ActiveIssue("https://github.com/dotnet/runtime/issues/28957", typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
         [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))]
         [ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServersAndBoolean))]
         public async Task CloseAsync_ServerInitiatedClose_Success(Uri server, bool useCloseOutputAsync)
         {
-            const string closeWebSocketMetaCommand = ".close";
+            const string shutdownWebSocketMetaCommand = ".shutdown";
 
             using (ClientWebSocket cws = await GetConnectedWebSocket(server, TimeOutMilliseconds, _output))
             {
@@ -46,7 +46,7 @@ public async Task CloseAsync_ServerInitiatedClose_Success(Uri server, bool useCl
 
                 _output.WriteLine("SendAsync starting.");
                 await cws.SendAsync(
-                    WebSocketData.GetBufferFromText(closeWebSocketMetaCommand),
+                    WebSocketData.GetBufferFromText(shutdownWebSocketMetaCommand),
                     WebSocketMessageType.Text,
                     true,
                     cts.Token);
@@ -59,26 +59,27 @@ await cws.SendAsync(
 
                 // Verify received server-initiated close message.
                 Assert.Equal(WebSocketCloseStatus.NormalClosure, recvResult.CloseStatus);
-                Assert.Equal(closeWebSocketMetaCommand, recvResult.CloseStatusDescription);
+                Assert.Equal(shutdownWebSocketMetaCommand, recvResult.CloseStatusDescription);
                 Assert.Equal(WebSocketMessageType.Close, recvResult.MessageType);
 
                 // Verify current websocket state as CloseReceived which indicates only partial close.
                 Assert.Equal(WebSocketState.CloseReceived, cws.State);
                 Assert.Equal(WebSocketCloseStatus.NormalClosure, cws.CloseStatus);
-                Assert.Equal(closeWebSocketMetaCommand, cws.CloseStatusDescription);
+                Assert.Equal(shutdownWebSocketMetaCommand, cws.CloseStatusDescription);
 
                 // Send back close message to acknowledge server-initiated close.
                 _output.WriteLine("Close starting.");
+                var closeStatus = PlatformDetection.IsNotBrowser ? WebSocketCloseStatus.InvalidMessageType : (WebSocketCloseStatus)3210;
                 await (useCloseOutputAsync ?
-                    cws.CloseOutputAsync(WebSocketCloseStatus.InvalidMessageType, string.Empty, cts.Token) :
-                    cws.CloseAsync(WebSocketCloseStatus.InvalidMessageType, string.Empty, cts.Token));
+                    cws.CloseOutputAsync(closeStatus, string.Empty, cts.Token) :
+                    cws.CloseAsync(closeStatus, string.Empty, cts.Token));
                 _output.WriteLine("Close done.");
                 Assert.Equal(WebSocketState.Closed, cws.State);
 
                 // Verify that there is no follow-up echo close message back from the server by
                 // making sure the close code and message are the same as from the first server close message.
                 Assert.Equal(WebSocketCloseStatus.NormalClosure, cws.CloseStatus);
-                Assert.Equal(closeWebSocketMetaCommand, cws.CloseStatusDescription);
+                Assert.Equal(shutdownWebSocketMetaCommand, cws.CloseStatusDescription);
             }
         }
 
@@ -233,8 +234,7 @@ public async Task CloseOutputAsync_ClientInitiated_CanReceive_CanClose(Uri serve
             {
                 var cts = new CancellationTokenSource(TimeOutMilliseconds);
 
-                // See issue for Browser websocket differences https://github.com/dotnet/runtime/issues/45538
-                var closeStatus = PlatformDetection.IsBrowser ? WebSocketCloseStatus.NormalClosure : WebSocketCloseStatus.InvalidPayloadData;
+                var closeStatus = PlatformDetection.IsNotBrowser ? WebSocketCloseStatus.InvalidPayloadData : (WebSocketCloseStatus)3210;
                 string closeDescription = "CloseOutputAsync_Client_InvalidPayloadData";
 
                 await cws.SendAsync(WebSocketData.GetBufferFromText(message), WebSocketMessageType.Text, true, cts.Token);
@@ -262,7 +262,64 @@ public async Task CloseOutputAsync_ClientInitiated_CanReceive_CanClose(Uri serve
             }
         }
 
-        [ActiveIssue("https://github.com/dotnet/runtime/issues/28957")]
+        [ActiveIssue("https://github.com/dotnet/runtime/issues/28957", typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+        [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))]
+        [ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServers))]
+        public async Task CloseOutputAsync_ServerInitiated_CanReceive(Uri server)
+        {
+            string message = "Hello WebSockets!";
+            var expectedCloseStatus = WebSocketCloseStatus.NormalClosure;
+            var expectedCloseDescription = ".shutdownafter";
+
+            using (ClientWebSocket cws = await GetConnectedWebSocket(server, TimeOutMilliseconds, _output))
+            {
+                var cts = new CancellationTokenSource(TimeOutMilliseconds);
+
+                await cws.SendAsync(
+                    WebSocketData.GetBufferFromText(expectedCloseDescription),
+                    WebSocketMessageType.Text,
+                    true,
+                    cts.Token);
+
+                // Should be able to receive the message echoed by the server.
+                var recvBuffer = new byte[100];
+                var segmentRecv = new ArraySegment<byte>(recvBuffer);
+                WebSocketReceiveResult recvResult = await cws.ReceiveAsync(segmentRecv, cts.Token);
+                Assert.Equal(expectedCloseDescription.Length, recvResult.Count);
+                segmentRecv = new ArraySegment<byte>(segmentRecv.Array, 0, recvResult.Count);
+                Assert.Equal(expectedCloseDescription, WebSocketData.GetTextFromBuffer(segmentRecv));
+                Assert.Null(recvResult.CloseStatus);
+                Assert.Null(recvResult.CloseStatusDescription);
+
+                // Should be able to receive a shutdown message.
+                segmentRecv = new ArraySegment<byte>(recvBuffer);
+                recvResult = await cws.ReceiveAsync(segmentRecv, cts.Token);
+                Assert.Equal(0, recvResult.Count);
+                Assert.Equal(expectedCloseStatus, recvResult.CloseStatus);
+                Assert.Equal(expectedCloseDescription, recvResult.CloseStatusDescription);
+
+                // Verify WebSocket state
+                Assert.Equal(expectedCloseStatus, cws.CloseStatus);
+                Assert.Equal(expectedCloseDescription, cws.CloseStatusDescription);
+
+                Assert.Equal(WebSocketState.CloseReceived, cws.State);
+
+                // Should be able to send.
+                await cws.SendAsync(WebSocketData.GetBufferFromText(message), WebSocketMessageType.Text, true, cts.Token);
+
+                // Cannot change the close status/description with the final close.
+                var closeStatus = PlatformDetection.IsNotBrowser ? WebSocketCloseStatus.InvalidPayloadData : (WebSocketCloseStatus)3210;
+                var closeDescription = "CloseOutputAsync_Client_Description";
+
+                await cws.CloseAsync(closeStatus, closeDescription, cts.Token);
+
+                Assert.Equal(expectedCloseStatus, cws.CloseStatus);
+                Assert.Equal(expectedCloseDescription, cws.CloseStatusDescription);
+                Assert.Equal(WebSocketState.Closed, cws.State);
+            }
+        }
+
+        [ActiveIssue("https://github.com/dotnet/runtime/issues/28957", typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
         [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))]
         [ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServers))]
         public async Task CloseOutputAsync_ServerInitiated_CanSend(Uri server)
@@ -299,7 +356,7 @@ await cws.SendAsync(
                 await cws.SendAsync(WebSocketData.GetBufferFromText(message), WebSocketMessageType.Text, true, cts.Token);
 
                 // Cannot change the close status/description with the final close.
-                var closeStatus = WebSocketCloseStatus.InvalidPayloadData;
+                var closeStatus = PlatformDetection.IsNotBrowser ? WebSocketCloseStatus.InvalidPayloadData : (WebSocketCloseStatus)3210;
                 var closeDescription = "CloseOutputAsync_Client_Description";
 
                 await cws.CloseAsync(closeStatus, closeDescription, cts.Token);
diff --git a/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs
index 18694fcd97a1a9..f45ed7fd9c14ca 100644
--- a/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs
+++ b/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs
@@ -249,7 +249,7 @@ public async Task SendAsync_MultipleOutstandingSendOperations_Throws(Uri server)
         [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))]
         [ConditionalTheory(nameof(WebSocketsSupported)), MemberData(nameof(EchoServers))]
         // This will also pass when no exception is thrown. Current implementation doesn't throw.
-        [ActiveIssue("https://github.com/dotnet/runtime/issues/83517", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))]
+        [ActiveIssue("https://github.com/dotnet/runtime/issues/83517", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))]
         public async Task ReceiveAsync_MultipleOutstandingReceiveOperations_Throws(Uri server)
         {
             using (ClientWebSocket cws = await GetConnectedWebSocket(server, TimeOutMilliseconds, _output))
diff --git a/src/mono/wasm/runtime/web-socket.ts b/src/mono/wasm/runtime/web-socket.ts
index 7469d27cd7501e..5cf400aca536a9 100644
--- a/src/mono/wasm/runtime/web-socket.ts
+++ b/src/mono/wasm/runtime/web-socket.ts
@@ -5,7 +5,7 @@ import MonoWasmThreads from "consts:monoWasmThreads";
 
 import { prevent_timer_throttling } from "./scheduling";
 import { Queue } from "./queue";
-import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, createPromiseController, mono_assert } from "./globals";
+import { ENVIRONMENT_IS_NODE, ENVIRONMENT_IS_SHELL, createPromiseController, loaderHelpers, mono_assert } from "./globals";
 import { setI32, localHeapViewU8 } from "./memory";
 import { VoidPtr } from "./types/emscripten";
 import { PromiseController } from "./types/internal";
@@ -19,12 +19,15 @@ const wasm_ws_pending_send_buffer_type = Symbol.for("wasm ws_pending_send_buffer
 const wasm_ws_pending_receive_event_queue = Symbol.for("wasm ws_pending_receive_event_queue");
 const wasm_ws_pending_receive_promise_queue = Symbol.for("wasm ws_pending_receive_promise_queue");
 const wasm_ws_pending_open_promise = Symbol.for("wasm ws_pending_open_promise");
+const wasm_ws_pending_open_promise_used = Symbol.for("wasm wasm_ws_pending_open_promise_used");
 const wasm_ws_pending_close_promises = Symbol.for("wasm ws_pending_close_promises");
 const wasm_ws_pending_send_promises = Symbol.for("wasm ws_pending_send_promises");
 const wasm_ws_is_aborted = Symbol.for("wasm ws_is_aborted");
 const wasm_ws_on_closed = Symbol.for("wasm ws_on_closed");
+const wasm_ws_close_sent = Symbol.for("wasm wasm_ws_close_sent");
+const wasm_ws_close_received = Symbol.for("wasm wasm_ws_close_received");
 const wasm_ws_receive_status_ptr = Symbol.for("wasm ws_receive_status_ptr");
-let mono_wasm_web_socket_close_warning = false;
+
 const ws_send_buffer_blocking_threshold = 65536;
 const emptyBuffer = new Uint8Array();
 
@@ -58,18 +61,22 @@ export function ws_wasm_create(uri: string, sub_protocols: string[] | null, rece
     ws.binaryType = "arraybuffer";
     const local_on_open = () => {
         if (ws[wasm_ws_is_aborted]) return;
+        if (loaderHelpers.is_exited()) return;
         open_promise_control.resolve(ws);
         prevent_timer_throttling();
     };
     const local_on_message = (ev: MessageEvent) => {
         if (ws[wasm_ws_is_aborted]) return;
+        if (loaderHelpers.is_exited()) return;
         _mono_wasm_web_socket_on_message(ws, ev);
         prevent_timer_throttling();
     };
     const local_on_close = (ev: CloseEvent) => {
         ws.removeEventListener("message", local_on_message);
         if (ws[wasm_ws_is_aborted]) return;
+        if (loaderHelpers.is_exited()) return;
 
+        ws[wasm_ws_close_received] = true;
         onClosed(ev.code, ev.reason);
 
         // this reject would not do anything if there was already "open" before it.
@@ -93,6 +100,7 @@ export function ws_wasm_create(uri: string, sub_protocols: string[] | null, rece
     };
     const local_on_error = (ev: any) => {
         if (ws[wasm_ws_is_aborted]) return;
+        if (loaderHelpers.is_exited()) return;
         ws.removeEventListener("message", local_on_message);
         const error = new Error(ev.message || "WebSocket error");
         mono_log_warn("WebSocket error", error);
@@ -116,12 +124,23 @@ export function ws_wasm_create(uri: string, sub_protocols: string[] | null, rece
 export function ws_wasm_open(ws: WebSocketExtension): Promise<WebSocketExtension> | null {
     mono_assert(!!ws, "ERR17: expected ws instance");
     const open_promise_control = ws[wasm_ws_pending_open_promise];
+    ws[wasm_ws_pending_open_promise_used] = true;
     return open_promise_control.promise;
 }
 
 export function ws_wasm_send(ws: WebSocketExtension, buffer_ptr: VoidPtr, buffer_length: number, message_type: number, end_of_message: boolean): Promise<void> | null {
     mono_assert(!!ws, "ERR17: expected ws instance");
 
+    if (ws[wasm_ws_is_aborted] || ws[wasm_ws_close_sent]) {
+        return Promise.reject(new Error("InvalidState: The WebSocket is not connected."));
+    }
+
+    if (ws.readyState === WebSocket.CLOSED) {
+        // this is server initiated close but not partial close
+        // because CloseOutputAsync_ServerInitiated_CanSend expectations, we don't fail here
+        return null;
+    }
+
     const buffer_view = new Uint8Array(localHeapViewU8().buffer, <any>buffer_ptr, buffer_length);
     const whole_buffer = _mono_wasm_web_socket_send_buffering(ws, buffer_view, message_type, end_of_message);
 
@@ -135,14 +154,18 @@ export function ws_wasm_send(ws: WebSocketExtension, buffer_ptr: VoidPtr, buffer
 export function ws_wasm_receive(ws: WebSocketExtension, buffer_ptr: VoidPtr, buffer_length: number): Promise<void> | null {
     mono_assert(!!ws, "ERR18: expected ws instance");
 
+    // we can't quickly return if wasm_ws_close_received==true, because there could be pending messages
+    if (ws[wasm_ws_is_aborted]) {
+        const receive_status_ptr = ws[wasm_ws_receive_status_ptr];
+        setI32(receive_status_ptr, 0); // count
+        setI32(<any>receive_status_ptr + 4, 2); // type:close
+        setI32(<any>receive_status_ptr + 8, 1);// end_of_message: true
+        return null;
+    }
+
     const receive_event_queue = ws[wasm_ws_pending_receive_event_queue];
     const receive_promise_queue = ws[wasm_ws_pending_receive_promise_queue];
 
-    const readyState = ws.readyState;
-    if (readyState != WebSocket.OPEN && readyState != WebSocket.CLOSING) {
-        throw new Error(`InvalidState: ${readyState} The WebSocket is not connected.`);
-    }
-
     if (receive_event_queue.getLength()) {
         mono_assert(receive_promise_queue.getLength() == 0, "ERR20: Invalid WS state");
 
@@ -151,6 +174,16 @@ export function ws_wasm_receive(ws: WebSocketExtension, buffer_ptr: VoidPtr, buf
 
         return null;
     }
+
+    const readyState = ws.readyState;
+    if (readyState == WebSocket.CLOSED) {
+        const receive_status_ptr = ws[wasm_ws_receive_status_ptr];
+        setI32(receive_status_ptr, 0); // count
+        setI32(<any>receive_status_ptr + 4, 2); // type:close
+        setI32(<any>receive_status_ptr + 8, 1);// end_of_message: true
+        return null;
+    }
+
     const { promise, promise_control } = createPromiseController<void>();
     const receive_promise_control = promise_control as ReceivePromiseControl;
     receive_promise_control.buffer_ptr = buffer_ptr;
@@ -163,10 +196,11 @@ export function ws_wasm_receive(ws: WebSocketExtension, buffer_ptr: VoidPtr, buf
 export function ws_wasm_close(ws: WebSocketExtension, code: number, reason: string | null, wait_for_close_received: boolean): Promise<void> | null {
     mono_assert(!!ws, "ERR19: expected ws instance");
 
-    if (ws.readyState == WebSocket.CLOSED) {
+    if (ws[wasm_ws_is_aborted] || ws[wasm_ws_close_sent] || ws.readyState == WebSocket.CLOSED) {
         return null;
     }
 
+    ws[wasm_ws_close_sent] = true;
     if (wait_for_close_received) {
         const { promise, promise_control } = createPromiseController<void>();
         ws[wasm_ws_pending_close_promises].push(promise_control);
@@ -179,10 +213,6 @@ export function ws_wasm_close(ws: WebSocketExtension, code: number, reason: stri
         return promise;
     }
     else {
-        if (!mono_wasm_web_socket_close_warning) {
-            mono_wasm_web_socket_close_warning = true;
-            mono_log_warn("WARNING: Web browsers do not support closing the output side of a WebSocket. CloseOutputAsync has closed the socket and discarded any incoming messages.");
-        }
         if (typeof reason === "string") {
             ws.close(code, reason);
         } else {
@@ -195,6 +225,10 @@ export function ws_wasm_close(ws: WebSocketExtension, code: number, reason: stri
 export function ws_wasm_abort(ws: WebSocketExtension): void {
     mono_assert(!!ws, "ERR18: expected ws instance");
 
+    if (ws[wasm_ws_is_aborted] || ws[wasm_ws_close_sent]) {
+        return;
+    }
+
     ws[wasm_ws_is_aborted] = true;
     reject_promises(ws, new Error("OperationCanceledException"));
 
@@ -211,7 +245,12 @@ export function ws_wasm_abort(ws: WebSocketExtension): void {
 
 function reject_promises(ws: WebSocketExtension, error: Error) {
     const open_promise_control = ws[wasm_ws_pending_open_promise];
-    if (open_promise_control) {
+    const open_promise_used = ws[wasm_ws_pending_open_promise_used];
+
+    // when `open_promise_used` is false, we should not reject it,
+    // because it would be unhandled rejection. Nobody is subscribed yet.
+    // The subscription comes on the next call, which is `ws_wasm_open`, but cancelation/abort could happen in the meantime.
+    if (open_promise_control && open_promise_used) {
         open_promise_control.reject(error);
     }
     for (const close_promise_control of ws[wasm_ws_pending_close_promises]) {
@@ -399,10 +438,13 @@ type WebSocketExtension = WebSocket & {
     [wasm_ws_pending_receive_event_queue]: Queue<Message>;
     [wasm_ws_pending_receive_promise_queue]: Queue<ReceivePromiseControl>;
     [wasm_ws_pending_open_promise]: PromiseController<WebSocketExtension>
+    [wasm_ws_pending_open_promise_used]: boolean
     [wasm_ws_pending_send_promises]: PromiseController<void>[]
     [wasm_ws_pending_close_promises]: PromiseController<void>[]
     [wasm_ws_is_aborted]: boolean
     [wasm_ws_on_closed]: IDisposable
+    [wasm_ws_close_received]: boolean
+    [wasm_ws_close_sent]: boolean
     [wasm_ws_receive_status_ptr]: VoidPtr
     [wasm_ws_pending_send_buffer_offset]: number
     [wasm_ws_pending_send_buffer_type]: number

From fe443a9f8fdbb19cdb6a955a65c4b700d261ef3d Mon Sep 17 00:00:00 2001
From: Thays Grazia <thaystg@gmail.com>
Date: Wed, 24 Jan 2024 15:47:46 -0300
Subject: [PATCH 03/36] [release/8.0][mono][debugger] Debugger improvements on
 .net8 (#97160)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* [mono][hotreload] Generate seq_points if we don't have pdb information from HotReload (#93039)

* Generating seq_points if we don't have pdb information from HotReload

* Apply suggestions from code review

Co-authored-by: Aleksey Kliger (λgeek) <akliger@gmail.com>

* Addressing @lambdageek comments

---------

Co-authored-by: Aleksey Kliger (λgeek) <akliger@gmail.com>

* Fix CMD_OBJECT_REF_GET_VALUES_BY_FIELD_TOKEN behavior (#93363)

* [mono] Simplify of OffsetToStringData as it's done on coreclr (#93987)

* Change implementation of OffsetToStringData as it's done on coreclr

* Fix comment

* Remove more comments

* completely remove the comments

* Update RuntimeHelpers.Mono.cs

* Addressing comments

* Addressing @lambdageek comment.

* [mono] Trying to fix performance regression. (#94358)

* Trying to fix performance regression.

* Fix performance issue

* [mono][debugger] Improve debugger features (#94066)

* Creating new messages, changing some olds, and fixing when jit_end is called while running a invoke_method

* Fix compilation error

* Fix compilation

* Applying suggestions from @lambdageek and adding more changes.

* Addressing @lambdageek suggestions.

* Addressing @lambdageek comment

* Addressing @lambdageek comments

* adding mono_component_api to function added.

* Bump protocol version to check if we are in correct version that has all the things to make icordebug work. (#97161)

---------

Co-authored-by: Aleksey Kliger (λgeek) <akliger@gmail.com>
---
 .../CompilerServices/RuntimeHelpers.Mono.cs   |   6 +-
 .../src/System/String.Mono.cs                 |   6 +
 src/mono/mono/component/debugger-agent.c      | 193 ++++++++++++------
 src/mono/mono/component/debugger-engine.c     |  28 ++-
 src/mono/mono/component/debugger-engine.h     |   2 +
 src/mono/mono/component/debugger-protocol.h   |   8 +-
 src/mono/mono/metadata/class-internals.h      |   2 +-
 src/mono/mono/metadata/debug-internals.h      |   2 +
 src/mono/mono/metadata/icall.c                |  11 +-
 src/mono/mono/metadata/mono-debug.c           |  15 ++
 src/mono/mono/metadata/object-internals.h     |   3 +
 src/mono/mono/metadata/object.c               |  14 ++
 src/mono/mono/mini/interp/transform.c         |  21 +-
 src/mono/mono/mini/intrinsics.c               |   5 +-
 14 files changed, 229 insertions(+), 87 deletions(-)

diff --git a/src/mono/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs
index 8fa80262e4903c..1564b301210bf2 100644
--- a/src/mono/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs
+++ b/src/mono/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs
@@ -30,11 +30,7 @@ public static void InitializeArray(Array array, RuntimeFieldHandle fldHandle)
         }
 
         [Obsolete("OffsetToStringData has been deprecated. Use string.GetPinnableReference() instead.")]
-        public static int OffsetToStringData
-        {
-            [Intrinsic]
-            get => OffsetToStringData;
-        }
+        public static int OffsetToStringData => string.OFFSET_TO_STRING;
 
         [MethodImplAttribute(MethodImplOptions.InternalCall)]
         private static extern int InternalGetHashCode(object? o);
diff --git a/src/mono/System.Private.CoreLib/src/System/String.Mono.cs b/src/mono/System.Private.CoreLib/src/System/String.Mono.cs
index 35e2aef4f2fbbf..7314504aff9a22 100644
--- a/src/mono/System.Private.CoreLib/src/System/String.Mono.cs
+++ b/src/mono/System.Private.CoreLib/src/System/String.Mono.cs
@@ -30,6 +30,12 @@ public static string IsInterned(string str)
         [MethodImplAttribute(MethodImplOptions.InternalCall)]
         private static extern string InternalIntern(string str);
 
+#if TARGET_64BIT
+        internal const int OFFSET_TO_STRING = 20;
+#else
+        internal const int OFFSET_TO_STRING = 12;
+#endif
+
         // TODO: Should be pointing to Buffer instead
         #region Runtime method-to-ir dependencies
 
diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c
index 1e8e27686a287e..7cc565cbf5ffd2 100644
--- a/src/mono/mono/component/debugger-agent.c
+++ b/src/mono/mono/component/debugger-agent.c
@@ -3812,7 +3812,7 @@ process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx
 	default:
 		g_assert_not_reached ();
 	}
-#ifdef HOST_WASI	
+	#ifdef HOST_WASI	
 	resumed_from_wasi = FALSE;
 	while (suspend_policy != SUSPEND_POLICY_NONE && !resumed_from_wasi)
 	{
@@ -4147,7 +4147,14 @@ jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)
 		dbg_unlock ();
 
 		if (assembly) {
-			process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, assembly);
+			DebuggerTlsData *tls;
+			tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id);
+			if (tls->invoke == NULL) {
+				process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, assembly);
+			} else {
+				assembly_load(prof, assembly); //send later
+				break;
+			}
 		} else {
 			break;
 		}
@@ -5068,20 +5075,16 @@ buffer_add_info_for_null_value (Buffer* buf, MonoType* t, MonoDomain* domain)
 {
 	buffer_add_byte (buf, t->type);
 	switch (t->type) {
-	case MONO_TYPE_CLASS:
-	case MONO_TYPE_STRING:
-		buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
-		break;
-	case MONO_TYPE_SZARRAY:
-	case MONO_TYPE_ARRAY:
-		buffer_add_byte (buf, m_class_get_byval_arg (m_class_get_element_class (mono_class_from_mono_type_internal (t)))->type);
-		buffer_add_int (buf, m_class_get_rank (mono_class_from_mono_type_internal (t)));
-		if (m_class_get_byval_arg (m_class_get_element_class (mono_class_from_mono_type_internal (t)))->type == MONO_TYPE_CLASS)
-			buffer_add_typeid (buf, domain, m_class_get_element_class (mono_class_from_mono_type_internal (t)));
-		buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
-		break;
-	default:
-		buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
+		case MONO_TYPE_SZARRAY:
+		case MONO_TYPE_ARRAY:
+			buffer_add_byte (buf, m_class_get_byval_arg (m_class_get_element_class (mono_class_from_mono_type_internal (t)))->type);
+			buffer_add_int (buf, m_class_get_rank (mono_class_from_mono_type_internal (t)));
+			if (m_class_get_byval_arg (m_class_get_element_class (mono_class_from_mono_type_internal (t)))->type == MONO_TYPE_CLASS)
+				buffer_add_typeid (buf, domain, m_class_get_element_class (mono_class_from_mono_type_internal (t)));
+			buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
+			break;
+		default:
+			buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (t));
 	}
 }
 /*
@@ -5098,6 +5101,9 @@ buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain,
 	MonoObject *obj;
 	gboolean boxed_vtype = FALSE;
 
+	if (CHECK_ICORDBG (TRUE))
+		buffer_add_byte (buf, !!m_type_is_byref (t));
+
 	if (m_type_is_byref (t)) {
 		if (!(*(void**)addr)) {
 			/* This can happen with compiler generated locals */
@@ -5298,6 +5304,8 @@ buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain,
 			if (mono_vtype_get_field_addr (addr, f) == addr && mono_class_from_mono_type_internal (t) == mono_class_from_mono_type_internal (f->type) && !boxed_vtype) //to avoid infinite recursion 
 			{
 				gssize val = *(gssize*)addr;
+				if (CHECK_ICORDBG (TRUE))
+					buffer_add_byte (buf, !!m_type_is_byref (f->type));
 				buffer_add_byte (buf, MONO_TYPE_PTR);
 				buffer_add_long (buf, val);
 				if (CHECK_PROTOCOL_VERSION(2, 46))
@@ -7097,6 +7105,8 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
 		minor_version = decode_int (p, &p, end);
 		if (p < end)
 			using_icordbg = decode_byte (p, &p, end);
+		if (using_icordbg)
+			mono_de_set_using_icordbg ();
 		protocol_version_set = TRUE;
 		PRINT_DEBUG_MSG (1, "[dbg] Protocol version %d.%d, client protocol version %d.%d.\n", MAJOR_VERSION, MINOR_VERSION, major_version, minor_version);
 		break;
@@ -7120,7 +7130,7 @@ vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
 		wait_for_suspend ();
 		break;
 	case CMD_VM_RESUME:
-#ifndef HOST_WASI	
+		#ifndef HOST_WASI	
 		if (suspend_count == 0) {
 			if (agent_config.defer && !agent_config.suspend)
 				// Workaround for issue in debugger-libs when running in defer attach mode.
@@ -7708,7 +7718,7 @@ event_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
 
 		if (req->event_kind == EVENT_KIND_BREAKPOINT) {
 			g_assert (method);
-
+			
 			req->info = mono_de_set_breakpoint (method, location, req, error);
 			if (!is_ok (error)) {
 				g_free (req);
@@ -7945,6 +7955,42 @@ domain_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
 		buffer_add_objid (buf, o);
 		break;
 	}
+	case MDBGPROT_CMD_APPDOMAIN_GET_ARRAY_OR_POINTER_TYPE: {
+		MonoClass *klass;
+		domain = decode_domainid (p, &p, end, NULL, &err);
+		MonoTypeEnum type = decode_int (p, &p, end);
+		klass = decode_typeid (p, &p, end, NULL, &err);
+		int rank = decode_int (p, &p, end);
+		if (type == MONO_TYPE_SZARRAY || type == MONO_TYPE_ARRAY)
+			klass = mono_class_create_array (klass, rank);
+		else
+			return ERR_INVALID_ARGUMENT;
+		buffer_add_typeid (buf, domain, klass);
+		break;
+	}
+
+	case MDBGPROT_CMD_APPDOMAIN_CREATE_ARRAY: {
+		ERROR_DECL (error);
+		MonoClass *klass;
+		MonoArray *arr;
+		domain = decode_domainid (p, &p, end, NULL, &err);
+		klass = decode_typeid (p, &p, end, NULL, &err);
+		int rank = decode_int (p, &p, end);
+		uintptr_t *lengths = g_newa (uintptr_t, rank);
+		intptr_t *lower_bounds = g_newa (intptr_t, rank);		
+		for (int i = 0 ; i < rank; i++)
+		{
+			lengths [i] = decode_int (p, &p, end);
+		}
+		for (int i = 0 ; i < rank; i++)
+		{
+			lower_bounds [i] = decode_int (p, &p, end);
+		}
+		arr = mono_array_new_full_checked (klass, lengths, lower_bounds, error);
+		buffer_add_objid (buf, (MonoObject*) arr);
+		break;
+	}
+
 	default:
 		return ERR_NOT_IMPLEMENTED;
 	}
@@ -8287,6 +8333,21 @@ field_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
 		}
 		break;
 	}
+	case MDBGPROT_CMD_FIELD_GET_TOKEN_AND_TYPE: {
+		MonoClassField *f = decode_fieldid (p, &p, end, &domain, &err);
+		if (G_UNLIKELY (!f->type)) {
+			ERROR_DECL(field_error);
+			mono_field_resolve_type (f, field_error);
+			mono_error_cleanup (field_error);
+			if (!f->type)
+				return ERR_INVALID_OBJECT;
+		}
+		buffer_add_int (buf, mono_class_get_field_token (f));
+		buffer_add_byte(buf, GINT_TO_UINT8(m_class_is_valuetype (mono_class_from_mono_type_internal (f->type))));
+		buffer_add_int (buf, f->type->type);
+		buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (f->type));
+		break;
+	}
 	default:
 		return ERR_NOT_IMPLEMENTED;
 	}
@@ -8476,6 +8537,19 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint
 				buffer_add_int (buf, 0);
 			}
 		}
+		if (CHECK_ICORDBG (TRUE))
+		{
+			if (type->type == MONO_TYPE_FNPTR)
+			{
+				buffer_add_int (buf, 1 + type->data.method->param_count);
+				buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (type->data.method->ret));
+				for (int j = 0; j < type->data.method->param_count; ++j) {
+					buffer_add_typeid (buf, domain, mono_class_from_mono_type_internal (type->data.method->params[j]));
+				}
+			} else {
+				buffer_add_int (buf, 0);
+			}
+		}
 		break;
 	}
 	case CMD_TYPE_GET_METHODS: {
@@ -8890,44 +8964,9 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint
 		buffer_add_objid (buf, obj);
 		if (CHECK_ICORDBG (TRUE))
 		{
-			buffer_add_byte(buf, m_class_is_valuetype (klass));
-			if (m_class_is_valuetype (klass))
-			{
-				int nfields = 0;
-				gpointer iter = NULL;
-				while ((f = mono_class_get_fields_internal (klass, &iter))) {
-					if (G_UNLIKELY (!f->type)) {
-						ERROR_DECL(field_error);
-						mono_field_resolve_type (f, field_error);
-						mono_error_cleanup (field_error);
-						if (!f->type)
-							continue;
-					}
-					if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
-						continue;
-					if (mono_field_is_deleted (f))
-						continue;
-					nfields ++;
-				}
-				buffer_add_int (buf, nfields);
-
-				iter = NULL;
-				while ((f = mono_class_get_fields_internal (klass, &iter))) {
-					if (G_UNLIKELY (!f->type)) {
-						ERROR_DECL(field_error);
-						mono_field_resolve_type (f, field_error);
-						mono_error_cleanup (field_error);
-						if (!f->type)
-							continue;
-					}
-					if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
-						continue;
-					if (mono_field_is_deleted (f))
-						continue;
-					buffer_add_int (buf, mono_class_get_field_token (f));
-					buffer_add_byte (buf, f->type->type);
-				}
-			}
+			buffer_add_byte(buf, GINT_TO_UINT8(m_class_is_valuetype (klass)));
+			buffer_add_int (buf, m_class_get_byval_arg (klass)->type);
+			buffer_add_typeid (buf, domain, klass);
 		}
 		break;
 	}
@@ -9007,6 +9046,33 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint
 		buffer_add_byte (buf, m_class_get_rank (klass));
 		break;
 	}
+	case MDBGPROT_CMD_TYPE_GET_FIELD_RVA: 
+	{
+		gpointer iter = NULL;
+		int field_token = decode_int (p, &p, end);
+		while ((f = mono_class_get_fields_internal (klass, &iter))) {
+			if (mono_class_get_field_token (f) == field_token)
+			{
+				if (G_UNLIKELY (!f->type)) {
+					ERROR_DECL(field_error);
+					mono_field_resolve_type (f, field_error);
+					mono_error_cleanup (field_error);
+					if (!f->type)
+						continue;
+				}
+				if (f->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)
+				{
+					gint32 count = 0;
+					const char* arr = mono_get_span_data_from_field (f, f->type, f->type, &count);
+					m_dbgprot_buffer_add_byte_array (buf, (uint8_t *)arr, count);
+					err = ERR_NONE;
+					goto exit;
+				}
+			}
+		}
+		m_dbgprot_buffer_add_int (buf, 0);
+		break;
+	}
 	default:
 		err = ERR_NOT_IMPLEMENTED;
 		goto exit;
@@ -10186,7 +10252,7 @@ array_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
 			MonoTypeEnum type = m_class_get_byval_arg (m_class_get_element_class (arr->obj.vtable->klass))->type;
 			buffer_add_byte(buf, type);
 			buffer_add_int (buf, m_class_get_rank (arr->obj.vtable->klass));
-			if (type == MONO_TYPE_CLASS || type == MONO_TYPE_GENERICINST || type == MONO_TYPE_OBJECT)
+			if (type == MONO_TYPE_CLASS || type == MONO_TYPE_GENERICINST || type == MONO_TYPE_OBJECT || (CHECK_ICORDBG (TRUE) && (type == MONO_TYPE_VALUETYPE || type == MONO_TYPE_PTR)))
 			{
 				buffer_add_typeid (buf, arr->obj.vtable->domain, m_class_get_element_class (arr->obj.vtable->klass));
 				if (CHECK_ICORDBG (TRUE))
@@ -10385,13 +10451,20 @@ object_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
 	case CMD_OBJECT_REF_GET_VALUES_BY_FIELD_TOKEN: {
 		len = 1;
 		i = 0;
-		MonoClass* klass =  decode_typeid (p, &p, end, NULL, &err);
+		int class_token =  decode_int (p, &p, end);
 		int field_token =  decode_int (p, &p, end);
 		gpointer iter = NULL;
 
-		while ((f = mono_class_get_fields_internal (klass, &iter))) {
-			if (mono_class_get_field_token (f) == field_token)
+		for (k = obj_type; k; k = m_class_get_parent (k)) {
+			if (m_class_get_type_token (k) == class_token) {
+				break;
+			}
+		}
+
+		while ((f = mono_class_get_fields_internal (k, &iter))) {
+			if (mono_class_get_field_token (f) == field_token) {
 				goto get_field_value;
+			}
 		}
 		goto invalid_fieldid;
 	}
diff --git a/src/mono/mono/component/debugger-engine.c b/src/mono/mono/component/debugger-engine.c
index 02f7eb090f6aec..5ec3e68b62aee4 100644
--- a/src/mono/mono/component/debugger-engine.c
+++ b/src/mono/mono/component/debugger-engine.c
@@ -35,6 +35,7 @@ static DebuggerEngineCallbacks rt_callbacks;
 static int log_level;
 static FILE *log_file;
 
+static bool using_icordbg = FALSE;
 
 /*
  * Locking
@@ -160,6 +161,19 @@ insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo
 		}
 	}
 
+	if (!it_has_sp && using_icordbg)
+	{
+		mono_seq_point_iterator_init (&it, seq_points);
+		while (mono_seq_point_iterator_next (&it)) {
+			if (it.seq_point.il_offset != METHOD_ENTRY_IL_OFFSET &&
+				it.seq_point.il_offset != METHOD_EXIT_IL_OFFSET &&
+				it.seq_point.il_offset > bp->il_offset) {
+				it_has_sp = TRUE;
+				break;
+			}
+		}
+	}
+
 	if (!it_has_sp) {
 		char *s = g_strdup_printf ("Unable to insert breakpoint at %s:%ld", mono_method_full_name (jinfo_get_method (ji), TRUE), bp->il_offset);
 
@@ -581,10 +595,10 @@ ss_req_cleanup (void)
 void
 mono_de_start_single_stepping (void)
 {
-	int val = mono_atomic_inc_i32 (&ss_count);
+		int val = mono_atomic_inc_i32 (&ss_count);
 
 	if (val == 1) {
-#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
+		#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
 		mono_arch_start_single_stepping ();
 #endif
 		mini_get_interp_callbacks_api ()->start_single_stepping ();
@@ -594,10 +608,10 @@ mono_de_start_single_stepping (void)
 void
 mono_de_stop_single_stepping (void)
 {
-	int val = mono_atomic_dec_i32 (&ss_count);
+		int val = mono_atomic_dec_i32 (&ss_count);
 
 	if (val == 0) {
-#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
+		#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
 		mono_arch_stop_single_stepping ();
 #endif
 		mini_get_interp_callbacks_api ()->stop_single_stepping ();
@@ -1534,6 +1548,12 @@ mono_de_set_log_level (int level, FILE *file)
 	log_file = file;
 }
 
+void
+mono_de_set_using_icordbg ()
+{
+	using_icordbg = TRUE;
+}
+
 /*
  * mono_de_init:
  *
diff --git a/src/mono/mono/component/debugger-engine.h b/src/mono/mono/component/debugger-engine.h
index b0f6c5ca729b38..d3c9b0696be5d1 100644
--- a/src/mono/mono/component/debugger-engine.h
+++ b/src/mono/mono/component/debugger-engine.h
@@ -345,6 +345,8 @@ mono_debugger_get_thread_state (DebuggerTlsData *ref);
 void mono_de_cleanup (void);
 void mono_de_set_log_level (int level, FILE *file);
 
+void mono_de_set_using_icordbg (void);
+
 //locking - we expose the lock object from the debugging engine to ensure we keep the same locking semantics of sdb.
 void mono_de_lock (void);
 void mono_de_unlock (void);
diff --git a/src/mono/mono/component/debugger-protocol.h b/src/mono/mono/component/debugger-protocol.h
index 9fe3c690c93e72..5948cef59c2c1a 100644
--- a/src/mono/mono/component/debugger-protocol.h
+++ b/src/mono/mono/component/debugger-protocol.h
@@ -11,7 +11,7 @@
  */
 
 #define MAJOR_VERSION 2
-#define MINOR_VERSION 65
+#define MINOR_VERSION 66
 
 typedef enum {
 	MDBGPROT_CMD_COMPOSITE = 100
@@ -132,6 +132,8 @@ typedef enum {
 	MDBGPROT_CMD_APPDOMAIN_GET_CORLIB = 6,
 	MDBGPROT_CMD_APPDOMAIN_CREATE_BOXED_VALUE = 7,
 	MDBGPROT_CMD_APPDOMAIN_CREATE_BYTE_ARRAY = 8,
+	MDBGPROT_CMD_APPDOMAIN_GET_ARRAY_OR_POINTER_TYPE = 9,
+	MDBGPROT_CMD_APPDOMAIN_CREATE_ARRAY = 10
 } MdbgProtCmdAppDomain;
 
 typedef enum {
@@ -162,6 +164,7 @@ typedef enum {
 
 typedef enum {
 	MDBGPROT_CMD_FIELD_GET_INFO = 1,
+	MDBGPROT_CMD_FIELD_GET_TOKEN_AND_TYPE = 2
 } MdbgProtCmdField;
 
 typedef enum {
@@ -215,7 +218,8 @@ typedef enum {
 	MDBGPROT_CMD_TYPE_BIND_GENERIC_PARAMETERS = 24,
 	MDBGPROT_CMD_TYPE_ELEMENT_TYPE = 25,
 	MDBGPROT_CMD_TYPE_RANK = 26,
-	MDBGPROT_CMD_TYPE_SET_VALUES_BY_FIELD_TOKEN = 27
+	MDBGPROT_CMD_TYPE_SET_VALUES_BY_FIELD_TOKEN = 27,
+	MDBGPROT_CMD_TYPE_GET_FIELD_RVA = 28
 } MdbgProtCmdType;
 
 typedef enum {
diff --git a/src/mono/mono/metadata/class-internals.h b/src/mono/mono/metadata/class-internals.h
index 3b758b2acf6658..7a6a8ddc0080aa 100644
--- a/src/mono/mono/metadata/class-internals.h
+++ b/src/mono/mono/metadata/class-internals.h
@@ -1450,7 +1450,7 @@ mono_class_get_object_finalize_slot (void);
 MonoMethod *
 mono_class_get_default_finalize_method (void);
 
-const char *
+MONO_COMPONENT_API const char *
 mono_field_get_rva (MonoClassField *field, int swizzle);
 
 MONO_COMPONENT_API void
diff --git a/src/mono/mono/metadata/debug-internals.h b/src/mono/mono/metadata/debug-internals.h
index e08b767b4c3748..e03c2cffb9f35d 100644
--- a/src/mono/mono/metadata/debug-internals.h
+++ b/src/mono/mono/metadata/debug-internals.h
@@ -112,4 +112,6 @@ mono_debug_lookup_source_location_by_il (MonoMethod *method, guint32 il_offset,
 MONO_COMPONENT_API char*
 mono_debug_image_get_sourcelink (MonoImage *image);
 
+mono_bool
+mono_debug_generate_enc_seq_points_without_debug_info (MonoDebugMethodInfo *minfo);
 #endif /* __DEBUG_INTERNALS_H__ */
diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c
index f3ef9b74f26c65..2f612be9859985 100644
--- a/src/mono/mono/metadata/icall.c
+++ b/src/mono/mono/metadata/icall.c
@@ -989,16 +989,7 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetSpanDataFrom (MonoCl
 		mono_error_set_argument (error, "array", "Cannot initialize array of non-primitive type");
 		return NULL;
 	}
-
-	int swizzle = 1;
-	int align;
-#if G_BYTE_ORDER != G_LITTLE_ENDIAN
-	swizzle = mono_type_size (type, &align);
-#endif
-
-	int dummy;
-	*count = mono_type_size (field_type, &dummy)/mono_type_size (type, &align);
-	return (gpointer)mono_field_get_rva (field_handle, swizzle);
+	return mono_get_span_data_from_field (field_handle, field_type, type, count);
 }
 
 void
diff --git a/src/mono/mono/metadata/mono-debug.c b/src/mono/mono/metadata/mono-debug.c
index e49089b3e4652c..392581889def56 100644
--- a/src/mono/mono/metadata/mono-debug.c
+++ b/src/mono/mono/metadata/mono-debug.c
@@ -1149,6 +1149,21 @@ mono_debug_enabled (void)
 	return mono_debug_format != MONO_DEBUG_FORMAT_NONE;
 }
 
+
+//Returns true if the method has updates but doesn't have ppdb information then we should generate the seq points using the coreclr rules
+mono_bool
+mono_debug_generate_enc_seq_points_without_debug_info (MonoDebugMethodInfo *minfo)
+{
+	MonoImage* img = m_class_get_image (minfo->method->klass);
+	if (G_UNLIKELY (img->has_updates)) {
+		guint32 idx = mono_metadata_token_index (minfo->method->token);
+		MonoDebugInformationEnc *mdie = (MonoDebugInformationEnc *) mono_metadata_update_get_updated_method_ppdb (img, idx);
+		if (mdie == NULL)
+			return TRUE;
+	}
+	return FALSE;
+}
+
 void
 mono_debug_get_seq_points (MonoDebugMethodInfo *minfo, char **source_file, GPtrArray **source_file_list, int **source_files, MonoSymSeqPoint **seq_points, int *n_seq_points)
 {
diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h
index 2f62c2530e8e46..1909411c7d03ef 100644
--- a/src/mono/mono/metadata/object-internals.h
+++ b/src/mono/mono/metadata/object-internals.h
@@ -2161,4 +2161,7 @@ mono_method_get_unmanaged_wrapper_ftnptr_internal (MonoMethod *method, gboolean
 void
 mono_runtime_run_startup_hooks (void);
 
+MONO_COMPONENT_API gpointer
+mono_get_span_data_from_field (MonoClassField *field_handle, MonoType *field_type, MonoType *target_type, gint32 *count);
+
 #endif /* __MONO_OBJECT_INTERNALS_H__ */
diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c
index a99369f8bfce5f..36be06dca981d0 100644
--- a/src/mono/mono/metadata/object.c
+++ b/src/mono/mono/metadata/object.c
@@ -8178,6 +8178,20 @@ mono_runtime_run_startup_hooks (void)
 	mono_error_raise_exception_deprecated (error);
 }
 
+gpointer
+mono_get_span_data_from_field (MonoClassField *field_handle, MonoType *field_type, MonoType *target_type, gint32 *count)
+{
+	int swizzle = 1;
+	int align;
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+	swizzle = mono_type_size (target_type, &align);
+#endif
+
+	int dummy;
+	*count = mono_type_size (field_type, &dummy)/mono_type_size (target_type, &align);
+	return (gpointer)mono_field_get_rva (field_handle, swizzle);
+}
+
 #if NEVER_DEFINED
 /*
  * The following section is purely to declare prototypes and
diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c
index 67034e9c59c81c..06396bc063fbcf 100644
--- a/src/mono/mono/mini/interp/transform.c
+++ b/src/mono/mono/mini/interp/transform.c
@@ -4786,6 +4786,19 @@ is_ip_protected (MonoMethodHeader *header, int offset)
 	return FALSE;
 }
 
+static gboolean
+should_insert_seq_point (TransformData *td)
+{
+	//following the CoreCLR's algorithm for adding the sequence points
+	if ((*td->ip == CEE_NOP) ||
+		(*td->ip == CEE_CALLVIRT) ||
+		(*td->ip == CEE_CALLI) ||
+		(*td->ip == CEE_CALL) ||
+		(GPTRDIFF_TO_INT (td->sp - td->stack) == 0))
+		return TRUE;
+	return FALSE;
+}
+
 static gboolean
 generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, MonoGenericContext *generic_context, MonoError *error)
 {
@@ -4817,6 +4830,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
 	gboolean save_last_error = FALSE;
 	gboolean link_bblocks = TRUE;
 	gboolean inlining = td->method != method;
+	gboolean generate_enc_seq_points_without_debug_info = FALSE;
 	InterpBasicBlock *exit_bb = NULL;
 
 	original_bb = bb = mono_basic_block_split (method, error, header);
@@ -4863,6 +4877,8 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
 			int n_il_offsets;
 
 			mono_debug_get_seq_points (minfo, NULL, NULL, NULL, &sps, &n_il_offsets);
+			if (n_il_offsets == 0)
+				generate_enc_seq_points_without_debug_info = mono_debug_generate_enc_seq_points_without_debug_info (minfo);
 			// FIXME: Free
 			seq_point_locs = mono_bitset_mem_new (mono_mempool_alloc0 (td->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
 			sym_seq_points = TRUE;
@@ -5092,6 +5108,9 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
 			WRITE64_INS (td->last_ins, 0, &counter);
 		}
 
+		if (G_UNLIKELY (generate_enc_seq_points_without_debug_info) && should_insert_seq_point (td))
+			last_seq_point = interp_add_ins (td, MINT_SDB_SEQ_POINT);
+
 		switch (*td->ip) {
 		case CEE_NOP:
 			/* lose it */
@@ -5361,7 +5380,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
 			if (!interp_transform_call (td, method, NULL, generic_context, constrained_class, readonly, error, TRUE, save_last_error, tailcall))
 				goto exit;
 
-			if (need_seq_point) {
+			if (need_seq_point && !generate_enc_seq_points_without_debug_info) {
 				// check if it is a nested call and remove the MONO_INST_NONEMPTY_STACK of the last breakpoint, only for non native methods
 				if (!(method->flags & METHOD_IMPL_ATTRIBUTE_NATIVE)) {
 					if (emitted_funccall_seq_point)	{
diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c
index ef77b7dc89f2ee..eca90a0e6abbf9 100644
--- a/src/mono/mono/mini/intrinsics.c
+++ b/src/mono/mono/mini/intrinsics.c
@@ -934,10 +934,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
 		} else
 			return NULL;
 	} else if (cmethod->klass == runtime_helpers_class) {
-		if (strcmp (cmethod->name, "get_OffsetToStringData") == 0 && fsig->param_count == 0) {
-			EMIT_NEW_ICONST (cfg, ins, MONO_STRUCT_OFFSET (MonoString, chars));
-			return ins;
-		} else if (!strcmp (cmethod->name, "GetRawData")) {
+		if (!strcmp (cmethod->name, "GetRawData")) {
 			int dreg = alloc_preg (cfg);
 			EMIT_NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, dreg, args [0]->dreg, MONO_ABI_SIZEOF (MonoObject));
 			return ins;

From d7a411899645fd5385b4c0efea4e0ec02f6b9ade Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 25 Jan 2024 16:36:11 -0800
Subject: [PATCH 04/36] [release/8.0-staging] Add additionalSize for the
 DisableOptData (#97479)

* add additionalSize for the DisableOptData

* adding STRESS_LOG

---------

Co-authored-by: Mikelle <mirogers@microsoft.com>
---
 src/coreclr/debug/shared/dbgtransportsession.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/coreclr/debug/shared/dbgtransportsession.cpp b/src/coreclr/debug/shared/dbgtransportsession.cpp
index fa8b06618362d9..8b8ca6203c9571 100644
--- a/src/coreclr/debug/shared/dbgtransportsession.cpp
+++ b/src/coreclr/debug/shared/dbgtransportsession.cpp
@@ -2499,9 +2499,11 @@ DWORD DbgTransportSession::GetEventSize(DebuggerIPCEvent *pEvent)
         break;
 
     case DB_IPCE_DISABLE_OPTS:
+        cbAdditionalSize = sizeof(pEvent->DisableOptData);
+        break;
 
     default:
-        printf("Unknown debugger event type: 0x%x\n", (pEvent->type & DB_IPCE_TYPE_MASK));
+        STRESS_LOG1(LF_CORDB, LL_INFO1000, "Unknown debugger event type: 0x%x\n", (pEvent->type & DB_IPCE_TYPE_MASK));
         _ASSERTE(!"Unknown debugger event type");
     }
 

From 1901707289706ad9ffdc00be86e2b73bd9aa4898 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 26 Jan 2024 17:46:38 +0100
Subject: [PATCH 05/36] [release/8.0-staging] Bump to new Ubuntu 22.04 queue
 for PPC64 (#97555)

* Bump to new Ubuntu 22.04 queue for PPC64

* ActiveIssue for PPC64 generally, not limited to Ubuntu 20.04

This test errors out on the new 22.04 queue as well, it is not 20.04 specific

---------

Co-authored-by: Jo Shields <directhex@apebox.org>
---
 eng/pipelines/libraries/helix-queues-setup.yml                  | 2 +-
 .../tests/FunctionalTests/MsQuicPlatformDetectionTests.cs       | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml
index dd80cdc85095ad..5b37825df0867d 100644
--- a/eng/pipelines/libraries/helix-queues-setup.yml
+++ b/eng/pipelines/libraries/helix-queues-setup.yml
@@ -87,7 +87,7 @@ jobs:
 
     # Linux PPC64le
     - ${{ if eq(parameters.platform, 'linux_ppc64le') }}:
-        - Ubuntu.2004.PPC64le.Experimental.Open
+        - Ubuntu.2204.PPC64le.Experimental.Open
 
     # OSX arm64
     - ${{ if eq(parameters.platform, 'osx_arm64') }}:
diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicPlatformDetectionTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicPlatformDetectionTests.cs
index 8dd026596c77fc..16f267fc719535 100644
--- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicPlatformDetectionTests.cs
+++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicPlatformDetectionTests.cs
@@ -57,7 +57,7 @@ public async Task SupportedLinuxPlatformsWithMsQuic_IsSupportedIsTrue()
         }
 
         [ActiveIssue("https://github.com/dotnet/runtime/issues/82154", typeof(PlatformDetection), nameof(PlatformDetection.IsRaspbian10), nameof(PlatformDetection.IsArmv6Process), nameof(PlatformDetection.IsInContainer))]
-        [ActiveIssue("https://github.com/dotnet/runtime/issues/82154", typeof(PlatformDetection), nameof(PlatformDetection.IsUbuntu2004), nameof(PlatformDetection.IsPpc64leProcess))]
+        [ActiveIssue("https://github.com/dotnet/runtime/issues/82154", typeof(PlatformDetection), nameof(PlatformDetection.IsPpc64leProcess))]
         [ActiveIssue("https://github.com/dotnet/runtime/issues/82154", typeof(PlatformDetection), nameof(PlatformDetection.IsUbuntu2004), nameof(PlatformDetection.IsS390xProcess))]
         [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsInHelix))]
         [PlatformSpecific(TestPlatforms.Linux)]

From b54886b4b7e4b8617b1710459efc3a75b8c24235 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 31 Jan 2024 09:30:40 -0800
Subject: [PATCH 06/36] [release/8.0-staging] Fix compilation error with
 generic type attributes (#97717)

* Fix compilation error with generic type attributes

Strip generic type parameter attributes from partial classes emitted by the logging source generated to avoid CS0579 errors from duplicate attributes.
Fixes #97498.

* Update comment

Update comment as suggested by code review.

* Verify type parameters retained

Verify that attributes on generic type parameters are not lost.

* Add package authoring

---------

Co-authored-by: martincostello <martin@martincostello.com>
Co-authored-by: Tarek Mahmoud Sayed <tarekms@microsoft.com>
---
 .../gen/LoggerMessageGenerator.Parser.cs      | 27 ++++++++++++-
 ...oft.Extensions.Logging.Abstractions.csproj |  2 +
 ...thGenericTypesWithAttributes.generated.txt | 24 ++++++++++++
 .../LoggerMessageGeneratorEmitterTests.cs     | 36 +++++++++++++++++-
 .../LoggerMessageGeneratorParserTests.cs      | 38 +++++++++++++++++++
 .../TestClasses/NestedClassTestsExtensions.cs | 29 ++++++++++++++
 6 files changed, 153 insertions(+), 3 deletions(-)
 create mode 100644 src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClassWithGenericTypesWithAttributes.generated.txt

diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs
index 038b71bef0759b..1bc6ff6c323873 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs
@@ -536,7 +536,7 @@ potentialNamespaceParent is not NamespaceDeclarationSyntax
                                         {
                                             Keyword = classDec.Keyword.ValueText,
                                             Namespace = nspace,
-                                            Name = classDec.Identifier.ToString() + classDec.TypeParameterList,
+                                            Name = GenerateClassName(classDec),
                                             ParentClass = null,
                                         };
 
@@ -554,7 +554,7 @@ static bool IsAllowedKind(SyntaxKind kind) =>
                                             {
                                                 Keyword = parentLoggerClass.Keyword.ValueText,
                                                 Namespace = nspace,
-                                                Name = parentLoggerClass.Identifier.ToString() + parentLoggerClass.TypeParameterList,
+                                                Name = GenerateClassName(parentLoggerClass),
                                                 ParentClass = null,
                                             };
 
@@ -601,6 +601,29 @@ static bool IsAllowedKind(SyntaxKind kind) =>
                 return results;
             }
 
+            private static string GenerateClassName(TypeDeclarationSyntax typeDeclaration)
+            {
+                if (typeDeclaration.TypeParameterList != null &&
+                    typeDeclaration.TypeParameterList.Parameters.Count != 0)
+                {
+                    // The source generator produces a partial class that the compiler merges with the original
+                    // class definition in the user code. If the user applies attributes to the generic types
+                    // of the class, it is necessary to remove these attribute annotations from the generated
+                    // code. Failure to do so may result in a compilation error (CS0579: Duplicate attribute).
+                    for (int i = 0; i < typeDeclaration.TypeParameterList.Parameters.Count; i++)
+                    {
+                        TypeParameterSyntax parameter = typeDeclaration.TypeParameterList.Parameters[i];
+
+                        if (parameter.AttributeLists.Count > 0)
+                        {
+                            typeDeclaration = typeDeclaration.ReplaceNode(parameter, parameter.WithAttributeLists([]));
+                        }
+                    }
+                }
+
+                return typeDeclaration.Identifier.ToString() + typeDeclaration.TypeParameterList;
+            }
+
             private (string? loggerField, bool multipleLoggerFields) FindLoggerField(SemanticModel sm, TypeDeclarationSyntax classDec, ITypeSymbol loggerSymbol)
             {
                 string? loggerField = null;
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj
index 085cade3966b96..052e5b9e0c0f60 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj
@@ -5,6 +5,8 @@
     <EnableDefaultItems>true</EnableDefaultItems>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <IsPackable>true</IsPackable>
+    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
+    <ServicingVersion>1</ServicingVersion>
     <PackageDescription>Logging abstractions for Microsoft.Extensions.Logging.
 
 Commonly Used Types:
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClassWithGenericTypesWithAttributes.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClassWithGenericTypesWithAttributes.generated.txt
new file mode 100644
index 00000000000000..c7ddd086fcf27e
--- /dev/null
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClassWithGenericTypesWithAttributes.generated.txt
@@ -0,0 +1,24 @@
+// <auto-generated/>
+#nullable enable
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+    partial class GenericTypeWithAttribute<A, B, C>
+    {
+        partial class Log<D>
+        {
+            [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
+            private static readonly global::System.Action<global::Microsoft.Extensions.Logging.ILogger, A, B, C, global::System.Exception?> __M0Callback =
+                global::Microsoft.Extensions.Logging.LoggerMessage.Define<A, B, C>(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(42, nameof(M0)), "a = {a}; b = {b}; c = {c}", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true }); 
+
+            [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
+            public static partial void M0(global::Microsoft.Extensions.Logging.ILogger logger, A a, B b, C c)
+            {
+                if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Debug))
+                {
+                    __M0Callback(logger, a, b, c, null);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs
index b1d767536653f5..30cf036fdd8606 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs
@@ -3,8 +3,8 @@
 
 using System;
 using System.IO;
+using System.Reflection;
 using System.Threading.Tasks;
-using Microsoft.CodeAnalysis.Text;
 using SourceGenerators.Tests;
 using Xunit;
 
@@ -163,6 +163,40 @@ internal static partial class TestWithDefaultValues
         }
 #endif
 
+        [Fact]
+        public async Task TestBaseline_TestWithNestedClassWithGenericTypesWithAttributes_Success()
+        {
+            string testSourceCode = @"
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+    public partial class GenericTypeWithAttribute<[Foo] A, [Bar] B, C>
+    {
+        public void M0<D>(A a, B b, C c, ILogger logger) => Log<D>.M0(logger, a, b, c);
+        private static partial class Log<[Foo] D>
+        {
+            [LoggerMessage(EventId = 42, Level = LogLevel.Debug, Message = ""a = {a}; b = {b}; c = {c}"")]
+            public static partial void M0(ILogger logger, A a, B b, C c);
+        }
+    }
+
+    [AttributeUsage(AttributeTargets.GenericParameter)]
+    public sealed class FooAttribute : Attribute { }
+    [AttributeUsage(AttributeTargets.GenericParameter)]
+    public sealed class BarAttribute : Attribute { }
+}";
+            await VerifyAgainstBaselineUsingFile("TestWithNestedClassWithGenericTypesWithAttributes.generated.txt", testSourceCode);
+        }
+
+        [Fact]
+        public void GenericTypeParameterAttributesAreRetained()
+        {
+            var type = typeof(TestClasses.NestedClassWithGenericTypesWithAttributesTestsExtensions<,,>).GetTypeInfo();
+
+            Assert.Equal(3, type.GenericTypeParameters.Length);
+            Assert.NotNull(type.GenericTypeParameters[0].GetCustomAttribute<TestClasses.FooAttribute>());
+            Assert.NotNull(type.GenericTypeParameters[1].GetCustomAttribute<TestClasses.BarAttribute>());
+        }
+
         private async Task VerifyAgainstBaselineUsingFile(string filename, string testSourceCode)
         {
             string baseline = LineEndingsHelper.Normalize(await File.ReadAllTextAsync(Path.Combine("Baselines", filename)).ConfigureAwait(false));
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs
index dc677e81cfc4a0..d0d5fc30af573f 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs
@@ -359,6 +359,44 @@ public partial class Nested
             Assert.Empty(diagnostics);
         }
 
+        [Fact]
+        public async Task NestedTypeWithGenericParameterOK()
+        {
+            IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+                partial class C<T>
+                {
+                    public partial class Nested<U>
+                    {
+                        [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+                        static partial void M1(ILogger logger);
+                    }
+                }
+            ");
+
+            Assert.Empty(diagnostics);
+        }
+
+        [Fact]
+        public async Task NestedTypeWithGenericParameterWithAttributeOK()
+        {
+            IReadOnlyList<Diagnostic> diagnostics = await RunGenerator(@"
+                using System;
+                using System.Diagnostics.CodeAnalysis;
+                partial class C<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>
+                {
+                    public partial class Nested<[MarkerAttribute] U>
+                    {
+                        [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+                        static partial void M1(ILogger logger);
+                    }
+                }
+                [AttributeUsage(AttributeTargets.GenericParameter)]
+                class MarkerAttribute : Attribute { }
+            ");
+
+            Assert.Empty(diagnostics);
+        }
+
 #if ROSLYN4_0_OR_GREATER
         [Fact]
         public async Task FileScopedNamespaceOK()
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/NestedClassTestsExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/NestedClassTestsExtensions.cs
index ba6b87f6d5308a..ea8cde78d566df 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/NestedClassTestsExtensions.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/NestedClassTestsExtensions.cs
@@ -3,8 +3,20 @@
 
 namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
 {
+    using System;
     using NamespaceForABC;
 
+    public partial class NestedClassWithNoTypeConstraintTestsExtensions<T>
+    {
+        public void M7(ILogger logger) => Log.M7(logger);
+
+        private static partial class Log
+        {
+            [LoggerMessage(EventId = 7, Level = LogLevel.Debug, Message = "M7")]
+            public static partial void M7(ILogger logger);
+        }
+    }
+
     internal static partial class NestedClassTestsExtensions<T> where T : ABC
     {
         internal static partial class NestedMiddleParentClass
@@ -61,6 +73,23 @@ internal static partial class Logger
             }
         }
     }
+
+    public partial class NestedClassWithGenericTypesWithAttributesTestsExtensions<[Foo] A, [Bar] B, C>
+    {
+        public void M13<D>(A a, B b, C c, ILogger logger) => Log<D>.M13(logger, a, b, c);
+
+        private static partial class Log<[Foo] D>
+        {
+            [LoggerMessage(EventId = 13, Level = LogLevel.Debug, Message = "M13: A = {a}; B = {b}; C = {c}")]
+            public static partial void M13(ILogger logger, A a, B b, C c);
+        }
+    }
+
+    [AttributeUsage(AttributeTargets.GenericParameter)]
+    public sealed class FooAttribute : Attribute { }
+
+    [AttributeUsage(AttributeTargets.GenericParameter)]
+    public sealed class BarAttribute : Attribute { }
 }
 
 namespace NamespaceForABC

From e6d8079d09491f4779a28e22f6b1702e9d98fe56 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 6 Feb 2024 09:03:20 -0800
Subject: [PATCH 07/36] Remove use of NewHolder as field. (#97843)

Co-authored-by: Aaron R Robinson <arobins@microsoft.com>
---
 src/coreclr/vm/syncblk.cpp | 4 ++++
 src/coreclr/vm/syncblk.h   | 4 ++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/coreclr/vm/syncblk.cpp b/src/coreclr/vm/syncblk.cpp
index bd235093b2d9c9..d0743994b7a86c 100644
--- a/src/coreclr/vm/syncblk.cpp
+++ b/src/coreclr/vm/syncblk.cpp
@@ -69,6 +69,10 @@ InteropSyncBlockInfo::~InteropSyncBlockInfo()
     CONTRACTL_END;
 
     FreeUMEntryThunk();
+
+#if defined(FEATURE_COMWRAPPERS)
+    delete m_managedObjectComWrapperMap;
+#endif // FEATURE_COMWRAPPERS
 }
 
 #ifndef TARGET_UNIX
diff --git a/src/coreclr/vm/syncblk.h b/src/coreclr/vm/syncblk.h
index 7fba11541532ff..c5464e73f24bb8 100644
--- a/src/coreclr/vm/syncblk.h
+++ b/src/coreclr/vm/syncblk.h
@@ -826,7 +826,7 @@ class InteropSyncBlockInfo
         if (m_managedObjectComWrapperMap == NULL)
         {
             NewHolder<ManagedObjectComWrapperByIdMap> map = new ManagedObjectComWrapperByIdMap();
-            if (InterlockedCompareExchangeT((ManagedObjectComWrapperByIdMap**)&m_managedObjectComWrapperMap, (ManagedObjectComWrapperByIdMap *)map, NULL) == NULL)
+            if (InterlockedCompareExchangeT(&m_managedObjectComWrapperMap, (ManagedObjectComWrapperByIdMap *)map, NULL) == NULL)
             {
                 map.SuppressRelease();
             }
@@ -917,7 +917,7 @@ class InteropSyncBlockInfo
     void* m_externalComObjectContext;
 
     CrstExplicitInit m_managedObjectComWrapperLock;
-    NewHolder<ManagedObjectComWrapperByIdMap> m_managedObjectComWrapperMap;
+    ManagedObjectComWrapperByIdMap* m_managedObjectComWrapperMap;
 #endif // FEATURE_COMWRAPPERS
 
 #ifdef FEATURE_OBJCMARSHAL

From b0025c75590df174971f4c69c26a7380849c634d Mon Sep 17 00:00:00 2001
From: "dotnet-maestro[bot]"
 <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date: Tue, 6 Feb 2024 22:01:01 -0800
Subject: [PATCH 08/36] [release/8.0-staging] Update dependencies from
 dotnet/runtime-assets (#97212)

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

* Update dependencies from https://github.com/dotnet/runtime-assets build 20240118.2

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24060.2 -> To Version 8.0.0-beta.24068.2

---------

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
---
 NuGet.config            |  3 +++
 eng/Version.Details.xml | 56 ++++++++++++++++++++---------------------
 eng/Versions.props      | 28 ++++++++++-----------
 3 files changed, 45 insertions(+), 42 deletions(-)

diff --git a/NuGet.config b/NuGet.config
index 76ed5a30293c3a..12fa8c8879cdb6 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -10,6 +10,9 @@
     <!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
     <!--  Begin: Package sources from dotnet-emsdk -->
     <add key="darc-pub-dotnet-emsdk-2fc2ffd" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-2fc2ffd9/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-2fc2ffd-3" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-2fc2ffd9-3/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-2fc2ffd-2" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-2fc2ffd9-2/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-2fc2ffd-1" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-2fc2ffd9-1/nuget/v3/index.json" />
     <!--  End: Package sources from dotnet-emsdk -->
     <!--  Begin: Package sources from dotnet-sdk -->
     <!--  End: Package sources from dotnet-sdk -->
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 95c24b9f3675f5..d9219e152c7cad 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -185,57 +185,57 @@
       <Uri>https://github.com/dotnet/arcade</Uri>
       <Sha>61ae141d2bf3534619265c8f691fd55dc3e75147</Sha>
     </Dependency>
-    <Dependency Name="System.ComponentModel.TypeConverter.TestData" Version="8.0.0-beta.24060.2">
+    <Dependency Name="System.ComponentModel.TypeConverter.TestData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
-    <Dependency Name="System.Data.Common.TestData" Version="8.0.0-beta.24060.2">
+    <Dependency Name="System.Data.Common.TestData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
-    <Dependency Name="System.Drawing.Common.TestData" Version="8.0.0-beta.24060.2">
+    <Dependency Name="System.Drawing.Common.TestData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
-    <Dependency Name="System.Formats.Tar.TestData" Version="8.0.0-beta.24060.2">
+    <Dependency Name="System.Formats.Tar.TestData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
-    <Dependency Name="System.IO.Compression.TestData" Version="8.0.0-beta.24060.2">
+    <Dependency Name="System.IO.Compression.TestData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
-    <Dependency Name="System.IO.Packaging.TestData" Version="8.0.0-beta.24060.2">
+    <Dependency Name="System.IO.Packaging.TestData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
-    <Dependency Name="System.Net.TestData" Version="8.0.0-beta.24060.2">
+    <Dependency Name="System.Net.TestData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
-    <Dependency Name="System.Private.Runtime.UnicodeData" Version="8.0.0-beta.24060.2">
+    <Dependency Name="System.Private.Runtime.UnicodeData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
-    <Dependency Name="System.Runtime.TimeZoneData" Version="8.0.0-beta.24060.2">
+    <Dependency Name="System.Runtime.TimeZoneData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
-    <Dependency Name="System.Security.Cryptography.X509Certificates.TestData" Version="8.0.0-beta.24060.2">
+    <Dependency Name="System.Security.Cryptography.X509Certificates.TestData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
-    <Dependency Name="System.Text.RegularExpressions.TestData" Version="8.0.0-beta.24060.2">
+    <Dependency Name="System.Text.RegularExpressions.TestData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
-    <Dependency Name="System.Windows.Extensions.TestData" Version="8.0.0-beta.24060.2">
+    <Dependency Name="System.Windows.Extensions.TestData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.DotNet.CilStrip.Sources" Version="8.0.0-beta.24060.2">
+    <Dependency Name="Microsoft.DotNet.CilStrip.Sources" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
     <Dependency Name="runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk" Version="16.0.5-alpha.1.23566.1" CoherentParentDependency="Microsoft.NET.Workload.Emscripten.Current.Manifest-8.0.100">
       <Uri>https://github.com/dotnet/llvm-project</Uri>
@@ -358,9 +358,9 @@
       <Uri>https://github.com/dotnet/hotreload-utils</Uri>
       <Sha>3b7da338c73b31b943c5512dcf0e2f6dd75f601c</Sha>
     </Dependency>
-    <Dependency Name="System.Runtime.Numerics.TestData" Version="8.0.0-beta.24060.2">
+    <Dependency Name="System.Runtime.Numerics.TestData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>3b165c269b12cc194f48fde6a1a7694bece8931b</Sha>
+      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
     </Dependency>
     <Dependency Name="Microsoft.Net.Compilers.Toolset" Version="4.8.0-7.23566.2">
       <Uri>https://github.com/dotnet/roslyn</Uri>
diff --git a/eng/Versions.props b/eng/Versions.props
index 55ce55ada067df..90ba26b4c2823c 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -143,20 +143,20 @@
     <SystemValueTupleVersion>4.5.0</SystemValueTupleVersion>
     <runtimenativeSystemIOPortsVersion>8.0.0-rc.1.23406.6</runtimenativeSystemIOPortsVersion>
     <!-- Runtime-Assets dependencies -->
-    <SystemRuntimeNumericsTestDataVersion>8.0.0-beta.24060.2</SystemRuntimeNumericsTestDataVersion>
-    <SystemComponentModelTypeConverterTestDataVersion>8.0.0-beta.24060.2</SystemComponentModelTypeConverterTestDataVersion>
-    <SystemDataCommonTestDataVersion>8.0.0-beta.24060.2</SystemDataCommonTestDataVersion>
-    <SystemDrawingCommonTestDataVersion>8.0.0-beta.24060.2</SystemDrawingCommonTestDataVersion>
-    <SystemFormatsTarTestDataVersion>8.0.0-beta.24060.2</SystemFormatsTarTestDataVersion>
-    <SystemIOCompressionTestDataVersion>8.0.0-beta.24060.2</SystemIOCompressionTestDataVersion>
-    <SystemIOPackagingTestDataVersion>8.0.0-beta.24060.2</SystemIOPackagingTestDataVersion>
-    <SystemNetTestDataVersion>8.0.0-beta.24060.2</SystemNetTestDataVersion>
-    <SystemPrivateRuntimeUnicodeDataVersion>8.0.0-beta.24060.2</SystemPrivateRuntimeUnicodeDataVersion>
-    <SystemRuntimeTimeZoneDataVersion>8.0.0-beta.24060.2</SystemRuntimeTimeZoneDataVersion>
-    <SystemSecurityCryptographyX509CertificatesTestDataVersion>8.0.0-beta.24060.2</SystemSecurityCryptographyX509CertificatesTestDataVersion>
-    <SystemTextRegularExpressionsTestDataVersion>8.0.0-beta.24060.2</SystemTextRegularExpressionsTestDataVersion>
-    <SystemWindowsExtensionsTestDataVersion>8.0.0-beta.24060.2</SystemWindowsExtensionsTestDataVersion>
-    <MicrosoftDotNetCilStripSourcesVersion>8.0.0-beta.24060.2</MicrosoftDotNetCilStripSourcesVersion>
+    <SystemRuntimeNumericsTestDataVersion>8.0.0-beta.24068.2</SystemRuntimeNumericsTestDataVersion>
+    <SystemComponentModelTypeConverterTestDataVersion>8.0.0-beta.24068.2</SystemComponentModelTypeConverterTestDataVersion>
+    <SystemDataCommonTestDataVersion>8.0.0-beta.24068.2</SystemDataCommonTestDataVersion>
+    <SystemDrawingCommonTestDataVersion>8.0.0-beta.24068.2</SystemDrawingCommonTestDataVersion>
+    <SystemFormatsTarTestDataVersion>8.0.0-beta.24068.2</SystemFormatsTarTestDataVersion>
+    <SystemIOCompressionTestDataVersion>8.0.0-beta.24068.2</SystemIOCompressionTestDataVersion>
+    <SystemIOPackagingTestDataVersion>8.0.0-beta.24068.2</SystemIOPackagingTestDataVersion>
+    <SystemNetTestDataVersion>8.0.0-beta.24068.2</SystemNetTestDataVersion>
+    <SystemPrivateRuntimeUnicodeDataVersion>8.0.0-beta.24068.2</SystemPrivateRuntimeUnicodeDataVersion>
+    <SystemRuntimeTimeZoneDataVersion>8.0.0-beta.24068.2</SystemRuntimeTimeZoneDataVersion>
+    <SystemSecurityCryptographyX509CertificatesTestDataVersion>8.0.0-beta.24068.2</SystemSecurityCryptographyX509CertificatesTestDataVersion>
+    <SystemTextRegularExpressionsTestDataVersion>8.0.0-beta.24068.2</SystemTextRegularExpressionsTestDataVersion>
+    <SystemWindowsExtensionsTestDataVersion>8.0.0-beta.24068.2</SystemWindowsExtensionsTestDataVersion>
+    <MicrosoftDotNetCilStripSourcesVersion>8.0.0-beta.24068.2</MicrosoftDotNetCilStripSourcesVersion>
     <!-- dotnet-optimization dependencies -->
     <optimizationwindows_ntx64MIBCRuntimeVersion>1.0.0-prerelease.23566.3</optimizationwindows_ntx64MIBCRuntimeVersion>
     <optimizationwindows_ntx86MIBCRuntimeVersion>1.0.0-prerelease.23566.3</optimizationwindows_ntx86MIBCRuntimeVersion>

From d8042d4384ca9ce5a6118a1bd87c6073a5f1052f Mon Sep 17 00:00:00 2001
From: "dotnet-maestro[bot]"
 <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date: Tue, 6 Feb 2024 22:01:39 -0800
Subject: [PATCH 09/36] Update dependencies from
 https://github.com/dotnet/hotreload-utils build 20240122.2 (#97322)

Microsoft.DotNet.HotReload.Utils.Generator.BuildTool
 From Version 8.0.0-alpha.0.24060.1 -> To Version 8.0.0-alpha.0.24072.2

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
---
 eng/Version.Details.xml | 4 ++--
 eng/Versions.props      | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index d9219e152c7cad..1e47771d2b3a7c 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -354,9 +354,9 @@
       <Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-optimization</Uri>
       <Sha>67613417f5e1af250e6ddfba79f8f2885d8e90fb</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.DotNet.HotReload.Utils.Generator.BuildTool" Version="8.0.0-alpha.0.24060.1">
+    <Dependency Name="Microsoft.DotNet.HotReload.Utils.Generator.BuildTool" Version="8.0.0-alpha.0.24072.2">
       <Uri>https://github.com/dotnet/hotreload-utils</Uri>
-      <Sha>3b7da338c73b31b943c5512dcf0e2f6dd75f601c</Sha>
+      <Sha>bc857c64c5c5f1fc73048261e8f471c3310224d2</Sha>
     </Dependency>
     <Dependency Name="System.Runtime.Numerics.TestData" Version="8.0.0-beta.24068.2">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
diff --git a/eng/Versions.props b/eng/Versions.props
index 90ba26b4c2823c..907392a3ee011d 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -186,7 +186,7 @@
     <MicrosoftDotNetXHarnessTestRunnersCommonVersion>8.0.0-prerelease.24060.1</MicrosoftDotNetXHarnessTestRunnersCommonVersion>
     <MicrosoftDotNetXHarnessTestRunnersXunitVersion>8.0.0-prerelease.24060.1</MicrosoftDotNetXHarnessTestRunnersXunitVersion>
     <MicrosoftDotNetXHarnessCLIVersion>8.0.0-prerelease.24060.1</MicrosoftDotNetXHarnessCLIVersion>
-    <MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>8.0.0-alpha.0.24060.1</MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>
+    <MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>8.0.0-alpha.0.24072.2</MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>
     <XUnitVersion>2.4.2</XUnitVersion>
     <XUnitAnalyzersVersion>1.0.0</XUnitAnalyzersVersion>
     <XUnitRunnerVisualStudioVersion>2.4.5</XUnitRunnerVisualStudioVersion>

From c2415d7e96f1bbc8864a2bbb7035fbcac2eb5100 Mon Sep 17 00:00:00 2001
From: Eirik Tsarpalis <eirik.tsarpalis@gmail.com>
Date: Thu, 8 Feb 2024 09:46:07 +0000
Subject: [PATCH 10/36] [release/8.0] Fix STJ SG regression in handling of
 property names that are reserved keywords. (#98082)

* Fix #98050. (#98058)

* bump servicing version
---
 .../gen/JsonSourceGenerator.Emitter.cs        |  2 +-
 .../src/System.Text.Json.csproj               |  2 +-
 .../JsonSourceGeneratorTests.cs               | 27 +++++++++++++++++++
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs
index 90575721c507d7..692f90741b0373 100644
--- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs
+++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs
@@ -798,7 +798,7 @@ private void GenerateFastPathFuncForObject(SourceWriter writer, ContextGeneratio
                     if (defaultCheckType != DefaultCheckType.None)
                     {
                         // Use temporary variable to evaluate property value only once
-                        string localVariableName =  $"__value_{propertyGenSpec.NameSpecifiedInSourceCode}";
+                        string localVariableName =  $"__value_{propertyGenSpec.NameSpecifiedInSourceCode.TrimStart('@')}";
                         writer.WriteLine($"{propertyGenSpec.PropertyType.FullyQualifiedName} {localVariableName} = {objectExpr}.{propertyGenSpec.NameSpecifiedInSourceCode};");
                         propValueExpr = localVariableName;
                     }
diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj
index 29409f7f886293..9c492f0c6e0348 100644
--- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj
+++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj
@@ -9,7 +9,7 @@
     <IncludeInternalObsoleteAttribute>true</IncludeInternalObsoleteAttribute>
     <IsPackable>true</IsPackable>
     <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
-    <ServicingVersion>2</ServicingVersion>
+    <ServicingVersion>3</ServicingVersion>
     <PackageDescription>Provides high-performance and low-allocating types that serialize objects to JavaScript Object Notation (JSON) text and deserialize JSON text to objects, with UTF-8 support built-in. Also provides types to read and write JSON text encoded as UTF-8, and to create an in-memory document object model (DOM), that is read-only, for random access of the JSON elements within a structured view of the data.
 
 The System.Text.Json library is built-in as part of the shared framework in .NET Runtime. The package can be installed when you need to use it in other target frameworks.</PackageDescription>
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs
index ce27630b6ab692..332f718ce3ff49 100644
--- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs
+++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs
@@ -737,5 +737,32 @@ public class MyClass
             Compilation compilation = CompilationHelper.CreateCompilation(source, parseOptions: CompilationHelper.CreateParseOptions(languageVersion));
             CompilationHelper.RunJsonSourceGenerator(compilation);
         }
+
+        [Fact]
+        public void FastPathWithReservedKeywordPropertyNames_CompilesSuccessfully()
+        {
+            // Regression test for https://github.com/dotnet/runtime/issues/98050
+
+            string source = """
+                using System.Text.Json.Serialization;
+
+                public class Model
+                {
+                    public string type { get; set; }
+                    public string alias { get; set; }
+                    public string @class { get; set; }
+                    public string @struct { get; set; }
+                }
+
+                [JsonSourceGenerationOptions(DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
+                [JsonSerializable(typeof(Model))]
+                internal partial class ModelContext : JsonSerializerContext
+                {
+                }
+                """;
+
+            Compilation compilation = CompilationHelper.CreateCompilation(source);
+            CompilationHelper.RunJsonSourceGenerator(compilation);
+        }
     }
 }

From 2663ba64a5a75eabb467da29fc9fad68393efdb5 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 8 Feb 2024 14:31:55 -0800
Subject: [PATCH 11/36] Update SystemDataSqlClientVersion from 4.8.5 -> 4.8.6
 for component governance warning. (#97882)

Co-authored-by: Parker Bibus <parkerbibus@microsoft.com>
---
 eng/Versions.props | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/eng/Versions.props b/eng/Versions.props
index 907392a3ee011d..c50a1008b5f25f 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -126,7 +126,7 @@
     <SystemBuffersVersion>4.5.1</SystemBuffersVersion>
     <SystemCollectionsImmutableVersion>7.0.0</SystemCollectionsImmutableVersion>
     <SystemComponentModelAnnotationsVersion>5.0.0</SystemComponentModelAnnotationsVersion>
-    <SystemDataSqlClientVersion>4.8.5</SystemDataSqlClientVersion>
+    <SystemDataSqlClientVersion>4.8.6</SystemDataSqlClientVersion>
     <SystemDrawingCommonVersion>8.0.0</SystemDrawingCommonVersion>
     <SystemIOFileSystemAccessControlVersion>5.0.0</SystemIOFileSystemAccessControlVersion>
     <SystemMemoryVersion>4.5.5</SystemMemoryVersion>

From d62ff0ba2487e15b0d62ecadb7471019682b61d0 Mon Sep 17 00:00:00 2001
From: Katelyn Gadd <kg@luminance.org>
Date: Thu, 8 Feb 2024 15:11:29 -0800
Subject: [PATCH 12/36] Disable jiterpreter_do_jit_call to address issues with
 disabling Wasm EH on 8.0. (#98051)

---
 src/mono/mono/mini/interp/interp.c      | 13 -------------
 src/mono/mono/mini/interp/jiterpreter.c | 15 ++-------------
 src/mono/mono/mini/interp/jiterpreter.h |  6 ------
 3 files changed, 2 insertions(+), 32 deletions(-)

diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c
index 6fb6bdd582d29d..c7d47719714de1 100644
--- a/src/mono/mono/mini/interp/interp.c
+++ b/src/mono/mono/mini/interp/interp.c
@@ -2726,21 +2726,8 @@ do_jit_call (ThreadContext *context, stackval *ret_sp, stackval *sp, InterpFrame
 	interp_push_lmf (&ext, frame);
 
 	if (mono_aot_mode == MONO_AOT_MODE_LLVMONLY_INTERP) {
-#if JITERPRETER_ENABLE_SPECIALIZED_JIT_CALL
-		/*
-		 * invoke jit_call_cb via a single indirect function call that dispatches to
-		 *  either a specialized JS implementation or a specialized WASM EH version
-		 * see jiterpreter-jit-call.ts and do-jit-call.wat
-		 * NOTE: the first argument must ALWAYS be jit_call_cb for the specialization.
-		 *  the actual implementation cannot verify this at runtime, so get it right
-		 * this is faster than mono_llvm_cpp_catch_exception by avoiding the use of
-		 *  emscripten invoke_vi to find and invoke jit_call_cb indirectly
-		 */
-		jiterpreter_do_jit_call(jit_call_cb, &cb_data, &thrown);
-#else
 		/* Catch the exception thrown by the native code using a try-catch */
 		mono_llvm_cpp_catch_exception (jit_call_cb, &cb_data, &thrown);
-#endif
 	} else {
 		jit_call_cb (&cb_data);
 	}
diff --git a/src/mono/mono/mini/interp/jiterpreter.c b/src/mono/mono/mini/interp/jiterpreter.c
index d3deb54f825659..82930e5737ac9c 100644
--- a/src/mono/mono/mini/interp/jiterpreter.c
+++ b/src/mono/mono/mini/interp/jiterpreter.c
@@ -53,10 +53,6 @@ void jiterp_preserve_module (void);
 static gint32 jiterpreter_abort_counts[MINT_LASTOP + 1] = { 0 };
 static int64_t jiterp_trace_bailout_counts[256] = { 0 };
 
-// This function pointer is used by interp.c to invoke jit_call_cb for exception handling purposes
-// See jiterpreter-jit-call.ts mono_jiterp_do_jit_call_indirect
-WasmDoJitCall jiterpreter_do_jit_call = mono_jiterp_do_jit_call_indirect;
-
 // We disable this diagnostic because EMSCRIPTEN_KEEPALIVE makes it a false alarm, the keepalive
 //  functions are being used externally. Having a bunch of prototypes is pointless since these
 //  functions are not consumed by C anywhere else
@@ -951,15 +947,8 @@ mono_jiterp_get_options_as_json ()
 EMSCRIPTEN_KEEPALIVE void
 mono_jiterp_update_jit_call_dispatcher (WasmDoJitCall dispatcher)
 {
-	// If we received a 0 dispatcher that means the TS side failed to compile
-	//  any kind of dispatcher - this likely indicates that content security policy
-	//  blocked the use of Module.addFunction
-	if (!dispatcher)
-		dispatcher = (WasmDoJitCall)mono_llvm_cpp_catch_exception;
-	else if (((int)(void*)dispatcher)==-1)
-		dispatcher = mono_jiterp_do_jit_call_indirect;
-
-	jiterpreter_do_jit_call = dispatcher;
+	// Disabled in 8.0 to address issues when building with Wasm EH disabled.
+	// This system is entirely gone in 9.0. -kg
 }
 
 EMSCRIPTEN_KEEPALIVE int
diff --git a/src/mono/mono/mini/interp/jiterpreter.h b/src/mono/mono/mini/interp/jiterpreter.h
index 2f4d9a632a664b..a1b4cfd8e59570 100644
--- a/src/mono/mono/mini/interp/jiterpreter.h
+++ b/src/mono/mono/mini/interp/jiterpreter.h
@@ -5,12 +5,8 @@
 
 #ifdef DISABLE_THREADS
 #define JITERPRETER_ENABLE_JIT_CALL_TRAMPOLINES 1
-// enables specialized mono_llvm_cpp_catch_exception replacement (see jiterpreter-jit-call.ts)
-// works even if the jiterpreter is otherwise disabled.
-#define JITERPRETER_ENABLE_SPECIALIZED_JIT_CALL 1
 #else
 #define JITERPRETER_ENABLE_JIT_CALL_TRAMPOLINES 0
-#define JITERPRETER_ENABLE_SPECIALIZED_JIT_CALL 0
 #endif // DISABLE_THREADS
 
 // mono_interp_tier_prepare_jiterpreter will return these special values if it doesn't
@@ -149,8 +145,6 @@ mono_jiterp_monitor_trace (const guint16 *ip, void *frame, void *locals);
 
 #endif // __MONO_MINI_INTERPRETER_INTERNALS_H__
 
-extern WasmDoJitCall jiterpreter_do_jit_call;
-
 #endif // HOST_BROWSER
 
 #endif // __MONO_MINI_JITERPRETER_H__

From 53c1d13c3a4f9fdf368bbff950da39ec71396525 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 8 Feb 2024 20:25:45 -0600
Subject: [PATCH 13/36] Fixes exception while debugging on Chrome as IDE
 (#97871)

Co-authored-by: Thays Grazia <thaystg@gmail.com>
---
 src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs
index bbf199f0e79b63..d072301f84259c 100644
--- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs
+++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs
@@ -1591,7 +1591,8 @@ internal virtual async Task OnSourceFileAdded(SessionId sessionId, SourceFile so
             await SendEvent(sessionId, "Debugger.scriptParsed", scriptSource, token);
             if (!resolveBreakpoints)
                 return;
-            foreach (var req in context.BreakpointRequests.Values)
+            var breakpointRequests = context.BreakpointRequests.Values.ToList<BreakpointRequest>(); //this can be changed while we are looping it and cause an exception
+            foreach (var req in breakpointRequests)
             {
                 if (req.TryResolve(source))
                 {

From ea2b2e86419f2879c38f80a940b7d9f81209e7b5 Mon Sep 17 00:00:00 2001
From: Thays Grazia <thaystg@gmail.com>
Date: Thu, 8 Feb 2024 23:28:50 -0300
Subject: [PATCH 14/36] Backport #97418 (#97568)

---
 src/mono/mono/component/debugger-agent.c      | 59 ++++++++++--
 .../BrowserDebugProxy/JObjectValueCreator.cs  | 95 ++++++++++++++++++-
 .../BrowserDebugProxy/ValueTypeClass.cs       | 20 +++-
 .../EvaluateOnCallFrame2Tests.cs              | 23 +++++
 .../debugger-test/debugger-evaluate-test.cs   | 46 +++++++++
 5 files changed, 230 insertions(+), 13 deletions(-)

diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c
index 7cc565cbf5ffd2..c9199635d15d59 100644
--- a/src/mono/mono/component/debugger-agent.c
+++ b/src/mono/mono/component/debugger-agent.c
@@ -5477,6 +5477,52 @@ decode_fixed_size_array_internal (MonoType *t, int type, MonoDomain *domain, gui
 	return err;
 }
 
+static int 
+decode_fixed_size_array_compute_size_internal (MonoType *t, int type, MonoDomain *domain, guint8 *buf, guint8 **endbuf, guint8 *limit)
+{
+	int ret = 0;
+	int fixedSizeLen = 1;
+	int newType = MONO_TYPE_END;
+	if (CHECK_PROTOCOL_VERSION (2, 53)) {
+		newType = decode_byte (buf, &buf, limit);
+		fixedSizeLen = decode_int (buf, &buf, limit);
+		//t->type = newType;
+	}
+	for (int i = 0 ; i < fixedSizeLen; i++) {
+		switch (newType) {
+			case MONO_TYPE_BOOLEAN:
+			case MONO_TYPE_I1:
+			case MONO_TYPE_U1:
+				decode_int (buf, &buf, limit);
+				ret += sizeof(guint8);
+				break;
+			case MONO_TYPE_CHAR:
+				decode_int (buf, &buf, limit);
+				ret += sizeof(gunichar2);
+				break;
+			case MONO_TYPE_I2:
+			case MONO_TYPE_U2:
+				decode_int (buf, &buf, limit);
+				ret += sizeof(guint16);
+				break;
+			case MONO_TYPE_I4:
+			case MONO_TYPE_U4:
+			case MONO_TYPE_R4:
+				decode_int (buf, &buf, limit);
+				ret += sizeof(guint32);
+				break;
+			case MONO_TYPE_I8:
+			case MONO_TYPE_U8:	
+			case MONO_TYPE_R8:
+				decode_long (buf, &buf, limit);
+				ret += sizeof(guint64);
+				break;
+		}
+	}
+	*endbuf = buf;
+	return ret;
+}
+
 static int
 decode_vtype_compute_size (MonoType *t, MonoDomain *domain, gpointer void_buf, guint8 **endbuf, guint8 *limit, gboolean from_by_ref_value_type)
 {
@@ -5540,7 +5586,6 @@ decode_value_compute_size (MonoType *t, int type, MonoDomain *domain, guint8 *bu
 	if (type == 0)
 		type = decode_byte (buf, &buf, limit);
 	int ret = 0;
-	ErrorCode err;
 	if (type != t->type && !MONO_TYPE_IS_REFERENCE (t) &&
 		!(t->type == MONO_TYPE_I && type == MONO_TYPE_VALUETYPE) &&
 		!(type == VALUE_TYPE_ID_FIXED_ARRAY) &&
@@ -5555,7 +5600,7 @@ decode_value_compute_size (MonoType *t, int type, MonoDomain *domain, guint8 *bu
 		goto end;
 	}
 	if (type == VALUE_TYPE_ID_FIXED_ARRAY && t->type != MONO_TYPE_VALUETYPE) {
-		//decode_fixed_size_array_internal (t, type, domain, addr, buf, endbuf, limit, check_field_datatype);
+		ret += decode_fixed_size_array_compute_size_internal (t, type, domain, buf, &buf, limit);
 		goto end;
 	}
 	switch (t->type) {
@@ -5626,13 +5671,6 @@ decode_value_compute_size (MonoType *t, int type, MonoDomain *domain, guint8 *bu
 					decode_int (buf, &buf, limit); //not used
 				}
 			} else if (type == MONO_TYPE_VALUETYPE) {
-				MonoDomain *d;
-				decode_byte (buf, &buf, limit);
-				if (CHECK_PROTOCOL_VERSION(2, 61))
-					decode_byte (buf, &buf, limit); //ignore is boxed
-				if (CHECK_PROTOCOL_VERSION(2, 65))
-					decode_int (buf, &buf, limit); //ignore inline array
-				decode_typeid (buf, &buf, limit, &d, &err);
 				ret += decode_vtype_compute_size (NULL, domain, buf, &buf, limit, from_by_ref_value_type);
 			} else {
 				goto end;
@@ -5678,7 +5716,8 @@ decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr,
 		return ERR_INVALID_ARGUMENT;
 	}
 	if (type == VALUE_TYPE_ID_FIXED_ARRAY && t->type != MONO_TYPE_VALUETYPE) {
-		decode_fixed_size_array_internal (t, type, domain, addr, buf, endbuf, limit, check_field_datatype);
+		decode_fixed_size_array_internal (t, type, domain, addr, buf, &buf, limit, check_field_datatype);
+		*endbuf = buf;
 		return ERR_NONE;
 	}
 
diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/JObjectValueCreator.cs b/src/mono/wasm/debugger/BrowserDebugProxy/JObjectValueCreator.cs
index 4231ac31967fa9..722c5a4aac3660 100644
--- a/src/mono/wasm/debugger/BrowserDebugProxy/JObjectValueCreator.cs
+++ b/src/mono/wasm/debugger/BrowserDebugProxy/JObjectValueCreator.cs
@@ -104,7 +104,6 @@ public async Task<JObject> ReadAsVariableValue(
             case ElementType.U:
             case ElementType.Void:
             case (ElementType)ValueTypeId.VType:
-            case (ElementType)ValueTypeId.FixedArray:
                 ret = Create(value: "void", type: "void", description: "void");
                 break;
             case ElementType.Boolean:
@@ -419,4 +418,98 @@ private async Task<JObject> ReadAsArray(MonoBinaryReader retDebuggerCmdReader, C
                               objectId: "dotnet:array:" + objectId,
                               subtype: length.Rank == 1 ? "array" : null);
     }
+
+    public async Task<JObject> CreateFixedArrayElement(MonoBinaryReader retDebuggerCmdReader, ElementType etype, string name, CancellationToken token)
+    {
+        JObject ret = null;
+        switch (etype)
+        {
+            case ElementType.I:
+            case ElementType.U:
+            case ElementType.Void:
+            case (ElementType)ValueTypeId.VType:
+                ret = Create(value: "void", type: "void", description: "void");
+                break;
+            case ElementType.Boolean:
+                {
+                    var value = retDebuggerCmdReader.ReadInt32();
+                    ret = CreateFromPrimitiveType(value == 1);
+                    break;
+                }
+            case ElementType.I1:
+                {
+                    var value = retDebuggerCmdReader.ReadSByte();
+                    ret = CreateJObjectForNumber<int>(value);
+                    break;
+                }
+            case ElementType.I2:
+            case ElementType.I4:
+                {
+                    var value = retDebuggerCmdReader.ReadInt32();
+                    ret = CreateJObjectForNumber<int>(value);
+                    break;
+                }
+            case ElementType.U1:
+                {
+                    var value = retDebuggerCmdReader.ReadUByte();
+                    ret = CreateJObjectForNumber<int>(value);
+                    break;
+                }
+            case ElementType.U2:
+                {
+                    var value = retDebuggerCmdReader.ReadUShort();
+                    ret = CreateJObjectForNumber<int>(value);
+                    break;
+                }
+            case ElementType.U4:
+                {
+                    var value = retDebuggerCmdReader.ReadUInt32();
+                    ret = CreateJObjectForNumber<uint>(value);
+                    break;
+                }
+            case ElementType.R4:
+                {
+                    float value = retDebuggerCmdReader.ReadSingle();
+                    ret = CreateJObjectForNumber<float>(value);
+                    break;
+                }
+            case ElementType.Char:
+                {
+                    var value = retDebuggerCmdReader.ReadInt32();
+                    ret = CreateJObjectForChar(value);
+                    break;
+                }
+            case ElementType.I8:
+                {
+                    long value = retDebuggerCmdReader.ReadInt64();
+                    ret = CreateJObjectForNumber<long>(value);
+                    break;
+                }
+            case ElementType.U8:
+                {
+                    ulong value = retDebuggerCmdReader.ReadUInt64();
+                    ret = CreateJObjectForNumber<ulong>(value);
+                    break;
+                }
+            case ElementType.R8:
+                {
+                    double value = retDebuggerCmdReader.ReadDouble();
+                    ret = CreateJObjectForNumber<double>(value);
+                    break;
+                }
+            case ElementType.FnPtr:
+            case ElementType.Ptr:
+                {
+                    ret = await ReadAsPtrValue(etype, retDebuggerCmdReader, name, token);
+                    break;
+                }
+            default:
+                {
+                    _logger.LogDebug($"Could not evaluate CreateFixedArrayElement invalid type {etype}");
+                    break;
+                }
+        }
+        ret["name"] = name;
+        return ret;
+    }
 }
diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/ValueTypeClass.cs b/src/mono/wasm/debugger/BrowserDebugProxy/ValueTypeClass.cs
index 59bc7b580ead93..85050d584f4279 100644
--- a/src/mono/wasm/debugger/BrowserDebugProxy/ValueTypeClass.cs
+++ b/src/mono/wasm/debugger/BrowserDebugProxy/ValueTypeClass.cs
@@ -83,8 +83,24 @@ public static async Task<ValueTypeClass> CreateFromReader(
                     && !f.Attributes.HasFlag(FieldAttributes.Static));
             foreach (var field in writableFields)
             {
-                lastWritableFieldValue = await sdbAgent.ValueCreator.ReadAsVariableValue(cmdReader, field.Name, token, isOwn: true, field.TypeId, forDebuggerDisplayAttribute: false);
-                fields.Add(GetFieldWithMetadata(field, lastWritableFieldValue, isStatic: false));
+                //check if it's fixed size array and behave as a inline array
+                ElementType etype = (ElementType)cmdReader.ReadByte();
+                if (etype == (ElementType)ValueTypeId.FixedArray && writableFields.Count() == 1)
+                {
+                    ElementType elementType = (ElementType)cmdReader.ReadByte();
+                    var arraySize = cmdReader.ReadInt32();
+                    inlineArray = new(arraySize + 1);
+                    for (int i = 0; i < arraySize; i++)
+                    {
+                        inlineArray.Add(await sdbAgent.ValueCreator.CreateFixedArrayElement(cmdReader, elementType, $"{i}", token));
+                    }
+                }
+                else
+                {
+                    cmdReader.BaseStream.Position-=sizeof(byte);
+                    lastWritableFieldValue = await sdbAgent.ValueCreator.ReadAsVariableValue(cmdReader, field.Name, token, isOwn: true, field.TypeId, forDebuggerDisplayAttribute: false);
+                    fields.Add(GetFieldWithMetadata(field, lastWritableFieldValue, isStatic: false));
+                }
             }
             if (inlineArraySize > 0)
             {
diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrame2Tests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrame2Tests.cs
index b1a79b28ceeefe..ed034d91468665 100644
--- a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrame2Tests.cs
+++ b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrame2Tests.cs
@@ -749,5 +749,28 @@ await EvaluateOnCallFrameAndCheck(id,
                    ("f[f.numArray[f.numList[0]], f.numArray[f.numArray[i]]]", TNumber("4"))
                 ); 
            });
+
+        [Fact]
+        public async Task EvaluateValueTypeWithFixedArrayAndMoreFields() => await CheckInspectLocalsAtBreakpointSite(
+            "DebuggerTests.EvaluateValueTypeWithFixedArray", "run", 3, "DebuggerTests.EvaluateValueTypeWithFixedArray.run",
+            "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateValueTypeWithFixedArray:run'); })",
+            wait_for_event_fn: async (pause_location) =>
+           {
+               await RuntimeEvaluateAndCheck(
+                   ("myVar.MyMethod()", TNumber(13)),
+                   ("myVar.myIntArray[0]", TNumber(1)),
+                   ("myVar.myIntArray[1]", TNumber(2)),
+                   ("myVar.myCharArray[2]", TChar('a')));
+           });
+
+        [Fact]
+        public async Task EvaluateValueTypeWithObjectValueType() => await CheckInspectLocalsAtBreakpointSite(
+            "DebuggerTests.EvaluateValueTypeWithObjectValueType", "run", 3, "DebuggerTests.EvaluateValueTypeWithObjectValueType.run",
+            "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateValueTypeWithObjectValueType:run'); })",
+            wait_for_event_fn: async (pause_location) =>
+           {
+               await RuntimeEvaluateAndCheck(
+                   ("myVar.MyMethod()", TNumber(10)));
+           });
     }
 }
diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs
index e46177ecc925b5..4f36197af79b42 100644
--- a/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs
+++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs
@@ -2182,4 +2182,50 @@ public static void run()
             Console.WriteLine(dt);
         }
     }
+    public unsafe struct EvaluateValueTypeWithFixedArray
+    {
+        private fixed int myIntArray[4];
+        private fixed char myCharArray[3];
+        double myDouble;
+        public EvaluateValueTypeWithFixedArray()
+        {
+            myDouble = 10;
+            myIntArray[0] = 1;
+            myIntArray[1] = 2;
+            myCharArray[2] = 'a';
+        }
+        public int MyMethod()
+        {
+            Console.WriteLine(myDouble);
+            return myIntArray[0] + myIntArray[1] + (int)myDouble;
+        }
+        public static void run()
+        {
+            var myVar = new EvaluateValueTypeWithFixedArray();
+            Console.WriteLine("pause here");
+            myVar.MyMethod();
+        }
+    }
+
+    public struct EvaluateValueTypeWithObjectValueType
+    {
+        private object myObject;
+        double myDouble;
+        public EvaluateValueTypeWithObjectValueType()
+        {
+            myObject = new int();
+            myDouble = 10;
+        }
+        public int MyMethod()
+        {
+            Console.WriteLine(myDouble);
+            return (int)myObject + (int)myDouble;
+        }
+        public static void run()
+        {
+            var myVar = new EvaluateValueTypeWithObjectValueType();
+            Console.WriteLine("pause here");
+            myVar.MyMethod();
+        }
+    }
 }
\ No newline at end of file

From 279fe234c7dda7faaaa693644f7de4e029e77c29 Mon Sep 17 00:00:00 2001
From: "dotnet-maestro[bot]"
 <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date: Fri, 9 Feb 2024 10:42:06 -0800
Subject: [PATCH 15/36] Update dependencies from
 https://github.com/dotnet/runtime-assets build 20240208.4 (#98224)

Microsoft.DotNet.CilStrip.Sources , System.ComponentModel.TypeConverter.TestData , System.Data.Common.TestData , System.Drawing.Common.TestData , System.Formats.Tar.TestData , System.IO.Compression.TestData , System.IO.Packaging.TestData , System.Net.TestData , System.Private.Runtime.UnicodeData , System.Runtime.Numerics.TestData , System.Runtime.TimeZoneData , System.Security.Cryptography.X509Certificates.TestData , System.Text.RegularExpressions.TestData , System.Windows.Extensions.TestData
 From Version 8.0.0-beta.24068.2 -> To Version 8.0.0-beta.24108.4

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
---
 eng/Version.Details.xml | 56 ++++++++++++++++++++---------------------
 eng/Versions.props      | 28 ++++++++++-----------
 2 files changed, 42 insertions(+), 42 deletions(-)

diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 1e47771d2b3a7c..04a7792f12c29a 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -185,57 +185,57 @@
       <Uri>https://github.com/dotnet/arcade</Uri>
       <Sha>61ae141d2bf3534619265c8f691fd55dc3e75147</Sha>
     </Dependency>
-    <Dependency Name="System.ComponentModel.TypeConverter.TestData" Version="8.0.0-beta.24068.2">
+    <Dependency Name="System.ComponentModel.TypeConverter.TestData" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
-    <Dependency Name="System.Data.Common.TestData" Version="8.0.0-beta.24068.2">
+    <Dependency Name="System.Data.Common.TestData" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
-    <Dependency Name="System.Drawing.Common.TestData" Version="8.0.0-beta.24068.2">
+    <Dependency Name="System.Drawing.Common.TestData" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
-    <Dependency Name="System.Formats.Tar.TestData" Version="8.0.0-beta.24068.2">
+    <Dependency Name="System.Formats.Tar.TestData" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
-    <Dependency Name="System.IO.Compression.TestData" Version="8.0.0-beta.24068.2">
+    <Dependency Name="System.IO.Compression.TestData" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
-    <Dependency Name="System.IO.Packaging.TestData" Version="8.0.0-beta.24068.2">
+    <Dependency Name="System.IO.Packaging.TestData" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
-    <Dependency Name="System.Net.TestData" Version="8.0.0-beta.24068.2">
+    <Dependency Name="System.Net.TestData" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
-    <Dependency Name="System.Private.Runtime.UnicodeData" Version="8.0.0-beta.24068.2">
+    <Dependency Name="System.Private.Runtime.UnicodeData" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
-    <Dependency Name="System.Runtime.TimeZoneData" Version="8.0.0-beta.24068.2">
+    <Dependency Name="System.Runtime.TimeZoneData" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
-    <Dependency Name="System.Security.Cryptography.X509Certificates.TestData" Version="8.0.0-beta.24068.2">
+    <Dependency Name="System.Security.Cryptography.X509Certificates.TestData" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
-    <Dependency Name="System.Text.RegularExpressions.TestData" Version="8.0.0-beta.24068.2">
+    <Dependency Name="System.Text.RegularExpressions.TestData" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
-    <Dependency Name="System.Windows.Extensions.TestData" Version="8.0.0-beta.24068.2">
+    <Dependency Name="System.Windows.Extensions.TestData" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.DotNet.CilStrip.Sources" Version="8.0.0-beta.24068.2">
+    <Dependency Name="Microsoft.DotNet.CilStrip.Sources" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
     <Dependency Name="runtime.linux-arm64.Microsoft.NETCore.Runtime.Mono.LLVM.Sdk" Version="16.0.5-alpha.1.23566.1" CoherentParentDependency="Microsoft.NET.Workload.Emscripten.Current.Manifest-8.0.100">
       <Uri>https://github.com/dotnet/llvm-project</Uri>
@@ -358,9 +358,9 @@
       <Uri>https://github.com/dotnet/hotreload-utils</Uri>
       <Sha>bc857c64c5c5f1fc73048261e8f471c3310224d2</Sha>
     </Dependency>
-    <Dependency Name="System.Runtime.Numerics.TestData" Version="8.0.0-beta.24068.2">
+    <Dependency Name="System.Runtime.Numerics.TestData" Version="8.0.0-beta.24108.4">
       <Uri>https://github.com/dotnet/runtime-assets</Uri>
-      <Sha>15009138ff960446092497b67a13cc3dc00445f7</Sha>
+      <Sha>ca6c46012f68934198ce0d303196c3ae179230f5</Sha>
     </Dependency>
     <Dependency Name="Microsoft.Net.Compilers.Toolset" Version="4.8.0-7.23566.2">
       <Uri>https://github.com/dotnet/roslyn</Uri>
diff --git a/eng/Versions.props b/eng/Versions.props
index c50a1008b5f25f..05d877f78822fa 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -143,20 +143,20 @@
     <SystemValueTupleVersion>4.5.0</SystemValueTupleVersion>
     <runtimenativeSystemIOPortsVersion>8.0.0-rc.1.23406.6</runtimenativeSystemIOPortsVersion>
     <!-- Runtime-Assets dependencies -->
-    <SystemRuntimeNumericsTestDataVersion>8.0.0-beta.24068.2</SystemRuntimeNumericsTestDataVersion>
-    <SystemComponentModelTypeConverterTestDataVersion>8.0.0-beta.24068.2</SystemComponentModelTypeConverterTestDataVersion>
-    <SystemDataCommonTestDataVersion>8.0.0-beta.24068.2</SystemDataCommonTestDataVersion>
-    <SystemDrawingCommonTestDataVersion>8.0.0-beta.24068.2</SystemDrawingCommonTestDataVersion>
-    <SystemFormatsTarTestDataVersion>8.0.0-beta.24068.2</SystemFormatsTarTestDataVersion>
-    <SystemIOCompressionTestDataVersion>8.0.0-beta.24068.2</SystemIOCompressionTestDataVersion>
-    <SystemIOPackagingTestDataVersion>8.0.0-beta.24068.2</SystemIOPackagingTestDataVersion>
-    <SystemNetTestDataVersion>8.0.0-beta.24068.2</SystemNetTestDataVersion>
-    <SystemPrivateRuntimeUnicodeDataVersion>8.0.0-beta.24068.2</SystemPrivateRuntimeUnicodeDataVersion>
-    <SystemRuntimeTimeZoneDataVersion>8.0.0-beta.24068.2</SystemRuntimeTimeZoneDataVersion>
-    <SystemSecurityCryptographyX509CertificatesTestDataVersion>8.0.0-beta.24068.2</SystemSecurityCryptographyX509CertificatesTestDataVersion>
-    <SystemTextRegularExpressionsTestDataVersion>8.0.0-beta.24068.2</SystemTextRegularExpressionsTestDataVersion>
-    <SystemWindowsExtensionsTestDataVersion>8.0.0-beta.24068.2</SystemWindowsExtensionsTestDataVersion>
-    <MicrosoftDotNetCilStripSourcesVersion>8.0.0-beta.24068.2</MicrosoftDotNetCilStripSourcesVersion>
+    <SystemRuntimeNumericsTestDataVersion>8.0.0-beta.24108.4</SystemRuntimeNumericsTestDataVersion>
+    <SystemComponentModelTypeConverterTestDataVersion>8.0.0-beta.24108.4</SystemComponentModelTypeConverterTestDataVersion>
+    <SystemDataCommonTestDataVersion>8.0.0-beta.24108.4</SystemDataCommonTestDataVersion>
+    <SystemDrawingCommonTestDataVersion>8.0.0-beta.24108.4</SystemDrawingCommonTestDataVersion>
+    <SystemFormatsTarTestDataVersion>8.0.0-beta.24108.4</SystemFormatsTarTestDataVersion>
+    <SystemIOCompressionTestDataVersion>8.0.0-beta.24108.4</SystemIOCompressionTestDataVersion>
+    <SystemIOPackagingTestDataVersion>8.0.0-beta.24108.4</SystemIOPackagingTestDataVersion>
+    <SystemNetTestDataVersion>8.0.0-beta.24108.4</SystemNetTestDataVersion>
+    <SystemPrivateRuntimeUnicodeDataVersion>8.0.0-beta.24108.4</SystemPrivateRuntimeUnicodeDataVersion>
+    <SystemRuntimeTimeZoneDataVersion>8.0.0-beta.24108.4</SystemRuntimeTimeZoneDataVersion>
+    <SystemSecurityCryptographyX509CertificatesTestDataVersion>8.0.0-beta.24108.4</SystemSecurityCryptographyX509CertificatesTestDataVersion>
+    <SystemTextRegularExpressionsTestDataVersion>8.0.0-beta.24108.4</SystemTextRegularExpressionsTestDataVersion>
+    <SystemWindowsExtensionsTestDataVersion>8.0.0-beta.24108.4</SystemWindowsExtensionsTestDataVersion>
+    <MicrosoftDotNetCilStripSourcesVersion>8.0.0-beta.24108.4</MicrosoftDotNetCilStripSourcesVersion>
     <!-- dotnet-optimization dependencies -->
     <optimizationwindows_ntx64MIBCRuntimeVersion>1.0.0-prerelease.23566.3</optimizationwindows_ntx64MIBCRuntimeVersion>
     <optimizationwindows_ntx86MIBCRuntimeVersion>1.0.0-prerelease.23566.3</optimizationwindows_ntx86MIBCRuntimeVersion>

From eded9a50a7ba49dfb371d5d3a0eb0845b9339a69 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 9 Feb 2024 12:01:13 -0800
Subject: [PATCH 16/36] [release/8.0-staging] Ensure that the Create(Dot(...))
 optimization doesn't kick in for Vector2 pre SSE4.1 (#97074)

* Ensure that the Create(Dot(...)) optimization doesn't kick in for Vector2 pre SSE4.1

* Make sure to use #if defined(...)

* Add missing using

* Fix a type in the test

---------

Co-authored-by: Tanner Gooding <tagoo@outlook.com>
---
 src/coreclr/jit/morph.cpp                     | 10 +++++
 .../JitBlue/Runtime_96939/Runtime_96939.cs    | 38 +++++++++++++++++++
 .../Runtime_96939/Runtime_96939.csproj        | 10 +++++
 3 files changed, 58 insertions(+)
 create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_96939/Runtime_96939.cs
 create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_96939/Runtime_96939.csproj

diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp
index 3deada8eec085b..b20cd585882b87 100644
--- a/src/coreclr/jit/morph.cpp
+++ b/src/coreclr/jit/morph.cpp
@@ -10724,6 +10724,16 @@ GenTree* Compiler::fgOptimizeHWIntrinsic(GenTreeHWIntrinsic* node)
                 break;
             }
 
+#if defined(TARGET_XARCH)
+            if ((node->GetSimdSize() == 8) && !compOpportunisticallyDependsOn(InstructionSet_SSE41))
+            {
+                // When SSE4.1 isn't supported then Vector2 only needs a single horizontal add
+                // which means the result isn't broadcast across the entire vector and we can't
+                // optimize
+                break;
+            }
+#endif // TARGET_XARCH
+
             GenTree* op1      = node->Op(1);
             GenTree* sqrt     = nullptr;
             GenTree* toScalar = nullptr;
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_96939/Runtime_96939.cs b/src/tests/JIT/Regression/JitBlue/Runtime_96939/Runtime_96939.cs
new file mode 100644
index 00000000000000..ac26af680eea80
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_96939/Runtime_96939.cs
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+using Xunit;
+
+public static class Runtime_96939
+{
+    [Fact]
+    [MethodImpl(MethodImplOptions.AggressiveOptimization)]
+    public static void Problem()
+    {
+        Assert.Equal(new Vector2(13), TestVector2(new Vector2(2, 3)));
+        Assert.Equal(new Vector3(29), TestVector3(new Vector3(2, 3, 4)));
+        Assert.Equal(new Vector4(54), TestVector4(new Vector4(2, 3, 4, 5)));
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
+    public static Vector2 TestVector2(Vector2 value)
+    {
+        return Vector2.Dot(value, value) * new Vector2(1, 1);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
+    public static Vector3 TestVector3(Vector3 value)
+    {
+        return Vector3.Dot(value, value) * new Vector3(1, 1, 1);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
+    public static Vector4 TestVector4(Vector4 value)
+    {
+        return Vector4.Dot(value, value) * new Vector4(1, 1, 1, 1);
+    }
+}
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_96939/Runtime_96939.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_96939/Runtime_96939.csproj
new file mode 100644
index 00000000000000..596f2374a8fb3b
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_96939/Runtime_96939.csproj
@@ -0,0 +1,10 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <Optimize>True</Optimize>
+    <DebugType>None</DebugType>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildProjectName).cs" />
+  </ItemGroup>
+</Project>

From a143568343ac8956caf9f64264af877e2cf288e8 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 9 Feb 2024 12:01:23 -0800
Subject: [PATCH 17/36] Don't clean up thread list on shutdown (#97188)

Co-authored-by: David Mason <davmason@microsoft.com>
---
 src/native/eventpipe/ep-thread.c | 13 -------------
 src/native/eventpipe/ep-thread.h |  3 ---
 src/native/eventpipe/ep.c        | 15 ---------------
 3 files changed, 31 deletions(-)

diff --git a/src/native/eventpipe/ep-thread.c b/src/native/eventpipe/ep-thread.c
index 93c87d4b8b4965..b720bf592d0c4d 100644
--- a/src/native/eventpipe/ep-thread.c
+++ b/src/native/eventpipe/ep-thread.c
@@ -93,19 +93,6 @@ ep_thread_init (void)
 		EP_UNREACHABLE ("Failed to allocate threads list.");
 }
 
-void
-ep_thread_fini (void)
-{
-	// If threads are still included in list (depending on runtime shutdown order),
-	// don't clean up since TLS destructor migh callback freeing items, no new
-	// threads should however not be added to list at this stage.
-	if (dn_list_empty (_ep_threads)) {
-		dn_list_free (_ep_threads);
-		_ep_threads = NULL;
-		ep_rt_spin_lock_free (&_ep_threads_lock);
-	}
-}
-
 bool
 ep_thread_register (EventPipeThread *thread)
 {
diff --git a/src/native/eventpipe/ep-thread.h b/src/native/eventpipe/ep-thread.h
index c3f8fd7cd71a74..44c683b52d57f8 100644
--- a/src/native/eventpipe/ep-thread.h
+++ b/src/native/eventpipe/ep-thread.h
@@ -92,9 +92,6 @@ ep_thread_release (EventPipeThread *thread);
 void
 ep_thread_init (void);
 
-void
-ep_thread_fini (void);
-
 bool
 ep_thread_register (EventPipeThread *thread);
 
diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c
index d007702dde463f..34c84e874458aa 100644
--- a/src/native/eventpipe/ep.c
+++ b/src/native/eventpipe/ep.c
@@ -1453,21 +1453,6 @@ ep_shutdown (void)
 	dn_vector_free (_ep_deferred_disable_session_ids);
 	_ep_deferred_disable_session_ids = NULL;
 
-	ep_thread_fini ();
-
-	// dotnet/coreclr: issue 24850: EventPipe shutdown race conditions
-	// Deallocating providers/events here might cause AV if a WriteEvent
-	// was to occur. Thus, we are not doing this cleanup.
-
-	/*EP_LOCK_ENTER (section1)
-		ep_sample_profiler_shutdown ();
-	EP_LOCK_EXIT (section1)*/
-
-	// // Remove EventPipeEventSource first since it tries to use the data structures that we remove below.
-	// // We need to do this after disabling sessions since those try to write to EventPipeEventSource.
-	// ep_event_source_fini (ep_event_source_get ());
-	// ep_config_shutdown (ep_config_get ());
-
 ep_on_exit:
 	ep_requires_lock_not_held ();
 	ep_rt_shutdown ();

From 2767a15a0817dd9858a3cc90ac3aa44f37e8e7da Mon Sep 17 00:00:00 2001
From: Vlad Brezae <brezaevlad@gmail.com>
Date: Fri, 9 Feb 2024 22:01:52 +0200
Subject: [PATCH 18/36] [mono][interp] Fix inlining of ldarga (#97650)

When inlining a method, all arguments are first copied to new vars. Ldarga is going to be applied on these copies. We were loading the address of the wrong var due to typo.
---
 src/mono/mono/mini/interp/transform.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c
index 06396bc063fbcf..0d5ef5380de266 100644
--- a/src/mono/mono/mini/interp/transform.c
+++ b/src/mono/mono/mini/interp/transform.c
@@ -8018,7 +8018,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
 				} else {
 					int loc_n = arg_locals [n];
 					interp_add_ins (td, MINT_LDLOCA_S);
-					interp_ins_set_sreg (td->last_ins, n);
+					interp_ins_set_sreg (td->last_ins, loc_n);
 					td->locals [loc_n].indirects++;
 				}
 				push_simple_type (td, STACK_TYPE_MP);

From ef1b0d681999223ad6ecd493fbc02792346861f3 Mon Sep 17 00:00:00 2001
From: Zoltan Varga <vargaz@gmail.com>
Date: Fri, 9 Feb 2024 15:02:02 -0500
Subject: [PATCH 19/36] [release/8.0-staging] [mono][jit] Fix passing of byref
 arguments in mono_gsharedvt_constrained_call (). (#97721) (#97850)

Fixes https://github.com/dotnet/runtime/issues/97625.

Co-authored-by: Larry Ewing <lewing@microsoft.com>
---
 src/mono/mono/mini/jit-icalls.c               |  3 ++-
 .../JitBlue/Runtime_97625/Runtime_97625.cs    | 23 +++++++++++++++++++
 .../Runtime_97625/Runtime_97625.csproj        |  8 +++++++
 3 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_97625/Runtime_97625.cs
 create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_97625/Runtime_97625.csproj

diff --git a/src/mono/mono/mini/jit-icalls.c b/src/mono/mono/mini/jit-icalls.c
index 628d18abe35cfd..24ec1b65dcf566 100644
--- a/src/mono/mono/mini/jit-icalls.c
+++ b/src/mono/mono/mini/jit-icalls.c
@@ -1482,7 +1482,8 @@ mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *kl
 		g_assert (fsig->param_count < 16);
 		memcpy (new_args, args, fsig->param_count * sizeof (gpointer));
 		for (int i = 0; i < fsig->param_count; ++i) {
-			if (deref_args [i])
+			// If the argument is not a vtype or nullable, deref it
+			if (deref_args [i] && (deref_args [i] != MONO_GSHAREDVT_BOX_TYPE_VTYPE && deref_args [i] != MONO_GSHAREDVT_BOX_TYPE_NULLABLE))
 				new_args [i] = *(gpointer*)new_args [i];
 		}
 		args = new_args;
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_97625/Runtime_97625.cs b/src/tests/JIT/Regression/JitBlue/Runtime_97625/Runtime_97625.cs
new file mode 100644
index 00000000000000..2a2ad6b87873a1
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_97625/Runtime_97625.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Xunit;
+
+public static class Runtime_97625
+{
+    public class CustomModel
+    {
+        public decimal Cost { get; set; }
+    }
+
+    [Fact]
+    public static int Test()
+    {
+        List<CustomModel> models = new List<CustomModel>();
+        models.Add(new CustomModel { Cost = 1 });
+        return models.Average (x => x.Cost) == 1 ? 100 : -1;
+    }
+}
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_97625/Runtime_97625.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_97625/Runtime_97625.csproj
new file mode 100644
index 00000000000000..15edd99711a1a4
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_97625/Runtime_97625.csproj
@@ -0,0 +1,8 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildProjectName).cs" />
+  </ItemGroup>
+</Project>
\ No newline at end of file

From 4b040aa6f0ed16c9c75e02e9d71a22b2afe49383 Mon Sep 17 00:00:00 2001
From: Elinor Fung <elfung@microsoft.com>
Date: Fri, 9 Feb 2024 12:02:11 -0800
Subject: [PATCH 20/36] Stop trying to format HOST_RUNTIME_CONTRACT property
 with locale settings (#97891)

---
 src/native/corehost/hostpolicy/deps_resolver.cpp      | 3 ++-
 src/native/corehost/hostpolicy/hostpolicy_context.cpp | 6 +++---
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/native/corehost/hostpolicy/deps_resolver.cpp b/src/native/corehost/hostpolicy/deps_resolver.cpp
index beedcef62cd06b..66d44f0c17dae0 100644
--- a/src/native/corehost/hostpolicy/deps_resolver.cpp
+++ b/src/native/corehost/hostpolicy/deps_resolver.cpp
@@ -280,7 +280,8 @@ bool deps_resolver_t::probe_deps_entry(const deps_entry_t& entry, const pal::str
 
     for (const auto& config : m_probes)
     {
-        trace::verbose(_X("  Using probe config: %s"), config.as_str().c_str());
+        if (trace::is_enabled())
+            trace::verbose(_X("  Using probe config: %s"), config.as_str().c_str());
 
         if (config.is_servicing() && !entry.is_serviceable)
         {
diff --git a/src/native/corehost/hostpolicy/hostpolicy_context.cpp b/src/native/corehost/hostpolicy/hostpolicy_context.cpp
index f8d220d8130e07..1ceb961f8df367 100644
--- a/src/native/corehost/hostpolicy/hostpolicy_context.cpp
+++ b/src/native/corehost/hostpolicy/hostpolicy_context.cpp
@@ -378,9 +378,9 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c
         }
 
         host_contract.get_runtime_property = &get_runtime_property;
-        pal::stringstream_t ptr_stream;
-        ptr_stream << "0x" << std::hex << (size_t)(&host_contract);
-        if (!coreclr_properties.add(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT), ptr_stream.str().c_str()))
+        pal::char_t buffer[STRING_LENGTH("0xffffffffffffffff")];
+        pal::snwprintf(buffer, ARRAY_SIZE(buffer), _X("0x%zx"), (size_t)(&host_contract));
+        if (!coreclr_properties.add(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT), buffer))
         {
             log_duplicate_property_error(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT));
             return StatusCode::LibHostDuplicateProperty;

From 6cd0eddba867045259663f3c83b9567eb7dc3b46 Mon Sep 17 00:00:00 2001
From: David Wrighton <davidwr@microsoft.com>
Date: Fri, 9 Feb 2024 12:02:38 -0800
Subject: [PATCH 21/36] Backport of Handle open types to appear in interface
 maps (#97733) to release/8.0-staging (#98182)

- Reflection IsAssignableFrom api
- As well as constraint checking
---
 src/coreclr/vm/methodtable.cpp                | 13 +--
 src/coreclr/vm/methodtable.h                  | 15 +++-
 src/coreclr/vm/methodtable.inl                |  3 +-
 src/coreclr/vm/methodtablebuilder.cpp         |  5 ++
 .../CuriouslyRecurringThroughInterface.cs     | 85 ++++++++++++++++++-
 5 files changed, 107 insertions(+), 14 deletions(-)

diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp
index 688bf29079e08d..76aab1f8b2d312 100644
--- a/src/coreclr/vm/methodtable.cpp
+++ b/src/coreclr/vm/methodtable.cpp
@@ -1433,7 +1433,7 @@ BOOL MethodTable::CanCastToInterface(MethodTable *pTargetMT, TypeHandlePairList
         if (CanCastByVarianceToInterfaceOrDelegate(pTargetMT, pVisited))
             return TRUE;
 
-        if (pTargetMT->IsSpecialMarkerTypeForGenericCasting())
+        if (pTargetMT->IsSpecialMarkerTypeForGenericCasting() && !GetWriteableData()->MayHaveOpenInterfacesInInterfaceMap())
             return FALSE; // The special marker types cannot be cast to (at this time, they are the open generic types, so they are however, valid input to this method).
 
         InterfaceMapIterator it = IterateInterfaceMap();
@@ -1470,7 +1470,7 @@ BOOL MethodTable::CanCastByVarianceToInterfaceOrDelegate(MethodTable *pTargetMT,
 
     // Shortcut for generic approx type scenario
     if (pMTInterfaceMapOwner != NULL &&
-        !pMTInterfaceMapOwner->ContainsGenericVariables() &&
+        !pMTInterfaceMapOwner->GetWriteableData()->MayHaveOpenInterfacesInInterfaceMap() &&
         IsSpecialMarkerTypeForGenericCasting() &&
         GetTypeDefRid() == pTargetMT->GetTypeDefRid() &&
         GetModule() == pTargetMT->GetModule() &&
@@ -1497,7 +1497,7 @@ BOOL MethodTable::CanCastByVarianceToInterfaceOrDelegate(MethodTable *pTargetMT,
         for (DWORD i = 0; i < inst.GetNumArgs(); i++)
         {
             TypeHandle thArg = inst[i];
-            if (IsSpecialMarkerTypeForGenericCasting() && pMTInterfaceMapOwner && !pMTInterfaceMapOwner->ContainsGenericVariables())
+            if (IsSpecialMarkerTypeForGenericCasting() && pMTInterfaceMapOwner && !pMTInterfaceMapOwner->GetWriteableData()->MayHaveOpenInterfacesInInterfaceMap())
             {
                 thArg = pMTInterfaceMapOwner;
             }
@@ -1957,7 +1957,7 @@ NOINLINE BOOL MethodTable::ImplementsInterface(MethodTable *pInterface)
 {
     WRAPPER_NO_CONTRACT;
 
-    if (pInterface->IsSpecialMarkerTypeForGenericCasting())
+    if (pInterface->IsSpecialMarkerTypeForGenericCasting() && !GetWriteableData()->MayHaveOpenInterfacesInInterfaceMap())
         return FALSE; // The special marker types cannot be cast to (at this time, they are the open generic types, so they are however, valid input to this method).
 
     return ImplementsInterfaceInline(pInterface);
@@ -1974,7 +1974,7 @@ BOOL MethodTable::ImplementsEquivalentInterface(MethodTable *pInterface)
     }
     CONTRACTL_END;
 
-    if (pInterface->IsSpecialMarkerTypeForGenericCasting())
+    if (pInterface->IsSpecialMarkerTypeForGenericCasting() && !GetWriteableData()->MayHaveOpenInterfacesInInterfaceMap())
         return FALSE; // The special marker types cannot be cast to (at this time, they are the open generic types, so they are however, valid input to this method).
 
     // look for exact match first (optimize for success)
@@ -9568,12 +9568,13 @@ PTR_MethodTable MethodTable::InterfaceMapIterator::GetInterface(MethodTable* pMT
         GC_TRIGGERS;
         THROWS;
         PRECONDITION(m_i != (DWORD) -1 && m_i < m_count);
+        PRECONDITION(CheckPointer(pMTOwner));
         POSTCONDITION(CheckPointer(RETVAL));
     }
     CONTRACT_END;
 
     MethodTable *pResult = m_pMap->GetMethodTable();
-    if (pResult->IsSpecialMarkerTypeForGenericCasting() && !pMTOwner->ContainsGenericVariables())
+    if (pResult->IsSpecialMarkerTypeForGenericCasting() && !pMTOwner->GetWriteableData()->MayHaveOpenInterfacesInInterfaceMap())
     {
         TypeHandle ownerAsInst[MaxGenericParametersForSpecialMarkerType];
         for (DWORD i = 0; i < MaxGenericParametersForSpecialMarkerType; i++)
diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h
index 69f16bec6ebdd4..f30fd7190f93c5 100644
--- a/src/coreclr/vm/methodtable.h
+++ b/src/coreclr/vm/methodtable.h
@@ -302,7 +302,7 @@ struct MethodTableWriteableData
         enum_flag_IsNotFullyLoaded          = 0x00000040,
         enum_flag_DependenciesLoaded        = 0x00000080,     // class and all dependencies loaded up to CLASS_LOADED_BUT_NOT_VERIFIED
 
-        // enum_unused                      = 0x00000100,
+        enum_flag_MayHaveOpenInterfaceInInterfaceMap = 0x00000100,
 
         enum_flag_CanCompareBitsOrUseFastGetHashCode       = 0x00000200,     // Is any field type or sub field type overrode Equals or GetHashCode
         enum_flag_HasCheckedCanCompareBitsOrUseFastGetHashCode   = 0x00000400,  // Whether we have checked the overridden Equals or GetHashCode
@@ -393,6 +393,17 @@ struct MethodTableWriteableData
         m_dwFlags &= ~(MethodTableWriteableData::enum_flag_HasApproxParent);
 
     }
+
+    inline void SetMayHaveOpenInterfacesInInterfaceMap()
+    {
+        LIMITED_METHOD_CONTRACT;
+        InterlockedOr((LONG*)&m_dwFlags, MethodTableWriteableData::enum_flag_MayHaveOpenInterfaceInInterfaceMap);
+    }
+
+    inline bool MayHaveOpenInterfacesInInterfaceMap() const
+    {
+        return !!(m_dwFlags & MethodTableWriteableData::enum_flag_MayHaveOpenInterfaceInInterfaceMap);
+    }
 };  // struct MethodTableWriteableData
 
 typedef DPTR(MethodTableWriteableData) PTR_MethodTableWriteableData;
@@ -1970,7 +1981,7 @@ class MethodTable
                 if (pCurrentMethodTable->HasSameTypeDefAs(pMT) &&
                     pMT->HasInstantiation() &&
                     pCurrentMethodTable->IsSpecialMarkerTypeForGenericCasting() &&
-                    !pMTOwner->ContainsGenericVariables() &&
+                    !pMTOwner->GetWriteableData()->MayHaveOpenInterfacesInInterfaceMap() &&
                     pMT->GetInstantiation().ContainsAllOneType(pMTOwner))
                 {
                     exactMatch = true;
diff --git a/src/coreclr/vm/methodtable.inl b/src/coreclr/vm/methodtable.inl
index 777080c7590179..f8b62de3e35d44 100644
--- a/src/coreclr/vm/methodtable.inl
+++ b/src/coreclr/vm/methodtable.inl
@@ -1395,7 +1395,6 @@ FORCEINLINE BOOL MethodTable::ImplementsInterfaceInline(MethodTable *pInterface)
         NOTHROW;
         GC_NOTRIGGER;
         PRECONDITION(pInterface->IsInterface()); // class we are looking up should be an interface
-        PRECONDITION(!pInterface->IsSpecialMarkerTypeForGenericCasting());
     }
     CONTRACTL_END;
 
@@ -1428,7 +1427,7 @@ FORCEINLINE BOOL MethodTable::ImplementsInterfaceInline(MethodTable *pInterface)
     while (--numInterfaces);
 
     // Second scan, looking for the curiously recurring generic scenario
-    if (pInterface->HasInstantiation() && !ContainsGenericVariables() && pInterface->GetInstantiation().ContainsAllOneType(this))
+    if (pInterface->HasInstantiation() && !GetWriteableData()->MayHaveOpenInterfacesInInterfaceMap() && pInterface->GetInstantiation().ContainsAllOneType(this))
     {
         numInterfaces = GetNumInterfaces();
         pInfo = GetInterfaceMap();
diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp
index 47024106985eee..76ac3e7601768c 100644
--- a/src/coreclr/vm/methodtablebuilder.cpp
+++ b/src/coreclr/vm/methodtablebuilder.cpp
@@ -9341,6 +9341,10 @@ MethodTableBuilder::LoadExactInterfaceMap(MethodTable *pMT)
     // to represent a type instantiated over its own generic variables, and the special marker type is currently the open type
     // and we make this case distinguishable by simply disallowing the optimization in those cases.
     bool retryWithExactInterfaces = !pMT->IsValueType() || pMT->IsSharedByGenericInstantiations() || pMT->ContainsGenericVariables();
+    if (retryWithExactInterfaces)
+    {
+        pMT->GetWriteableDataForWrite()->SetMayHaveOpenInterfacesInInterfaceMap();
+    }
 
     DWORD nAssigned = 0;
     do
@@ -9407,6 +9411,7 @@ MethodTableBuilder::LoadExactInterfaceMap(MethodTable *pMT)
 
         if (retry)
         {
+            pMT->GetWriteableDataForWrite()->SetMayHaveOpenInterfacesInInterfaceMap();
             retryWithExactInterfaces = true;
         }
     } while (retry);
diff --git a/src/tests/Loader/classloader/generics/Instantiation/Positive/CuriouslyRecurringThroughInterface.cs b/src/tests/Loader/classloader/generics/Instantiation/Positive/CuriouslyRecurringThroughInterface.cs
index 0a091e138a876b..e74a23632c7b9a 100644
--- a/src/tests/Loader/classloader/generics/Instantiation/Positive/CuriouslyRecurringThroughInterface.cs
+++ b/src/tests/Loader/classloader/generics/Instantiation/Positive/CuriouslyRecurringThroughInterface.cs
@@ -1,3 +1,9 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.CompilerServices;
+
 namespace CuriouslyRecurringPatternThroughInterface
 {
     interface IGeneric<T_IGeneric>
@@ -10,14 +16,85 @@ class CuriouslyRecurringThroughInterface<T_CuriouslyRecurringThroughInterface> :
     {
     }
 
-    class Program
+    class BaseClassWhereAImplementsB<A,B> where A : B {}
+    interface ICuriouslyRecurring2<T_ICuriouslyRecurring> : IGeneric<DerivedCuriouslyRecurringThroughInterface<T_ICuriouslyRecurring>>
+    {
+    }
+    class DerivedCuriouslyRecurringThroughInterface<T_CuriouslyRecurringThroughInterface> : BaseClassWhereAImplementsB<DerivedCuriouslyRecurringThroughInterface<T_CuriouslyRecurringThroughInterface>,ICuriouslyRecurring2<T_CuriouslyRecurringThroughInterface>>, ICuriouslyRecurring2<T_CuriouslyRecurringThroughInterface>
+    {
+    }
+
+    public class Program
     {
         static object _o;
-        static int Main()
+
+        public static int Main()
+        {
+            TestIfCuriouslyRecurringInterfaceCanBeLoaded();
+            TestIfCuriouslyRecurringInterfaceCanCast();
+            TestIfCuriouslyRecurringInterfaceCanBeUsedAsConstraint();
+            TestIfCuriouslyRecurringInterfaceCanBeUsedAsConstraintWorker();
+            return 100; // Failures cause exceptions
+        }
+
+        public static void TestIfCuriouslyRecurringInterfaceCanBeLoaded()
         {
+            Console.WriteLine("TestIfCuriouslyRecurringInterfaceCanBeLoaded");
+
             // Test that the a generic using a variant of the curiously recurring pattern involving an interface can be loaded.
             _o = typeof(CuriouslyRecurringThroughInterface<int>);
-            return 100;
+            Console.WriteLine("Found type: {0}", _o);
+            Console.WriteLine("Curiously recurring interface: {0}", typeof(ICuriouslyRecurring<>));
+            Console.WriteLine("typeof(ICuriouslyRecurring<>).GetGenericArguments()[0]: {0}", typeof(ICuriouslyRecurring<>).GetGenericArguments()[0]);
+            Console.WriteLine("typeof(ICuriouslyRecurring<>).GetInterfaces().Length: {0}", typeof(ICuriouslyRecurring<>).GetInterfaces().Length);
+            Console.WriteLine("typeof(ICuriouslyRecurring<>).GetInterfaces()[0]: {0}", typeof(ICuriouslyRecurring<>).GetInterfaces()[0]);
+            Console.WriteLine("typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments().Length: {0}", typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments().Length);
+            Console.WriteLine("typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0]: {0}", typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0]);
+            Console.WriteLine("typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetGenericArguments()[0]: {0}", typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetGenericArguments()[0]);
+            Console.WriteLine("typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetGenericArguments()[0]==typeof(ICuriouslyRecurring<>).GetGenericArguments()[0]: {0}", typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetGenericArguments()[0]==typeof(ICuriouslyRecurring<>).GetGenericArguments()[0]);
+            if (!(typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetGenericArguments()[0]==typeof(ICuriouslyRecurring<>).GetGenericArguments()[0]))
+            {
+                throw new Exception("Fail checking for condition that should be true - 2");
+            }
+
+            Console.WriteLine("typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetInterfaces().Length: {0}", typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetInterfaces().Length);
+
+            // On CoreCLR this gets the Open type, which isn't really correct, but it has been that way for a very long time
+            Console.WriteLine("typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetInterfaces()[0]: {0}", typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetInterfaces()[0]);
+            Console.WriteLine("typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetInterfaces()[0]==typeof(ICuriouslyRecurring<>): {0}", typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetInterfaces()[0]==typeof(ICuriouslyRecurring<>));
+
+            Console.WriteLine("typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetInterfaces()[0].GetGenericTypeDefinition()==typeof(ICuriouslyRecurring<>): {0}", typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetInterfaces()[0].GetGenericTypeDefinition()==typeof(ICuriouslyRecurring<>));
+
+            Console.WriteLine("typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetInterfaces()[0].GetGenericArguments()[0]==typeof(ICuriouslyRecurring<>)GetGenericArguments()[0]: {0}", typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetInterfaces()[0].GetGenericArguments()[0]==typeof(ICuriouslyRecurring<>).GetGenericArguments()[0]);
+            if (!(typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0].GetInterfaces()[0].GetGenericArguments()[0]==typeof(ICuriouslyRecurring<>).GetGenericArguments()[0]))
+            {
+                throw new Exception("Fail checking for condition that should be true - 2");
+            }
+        }
+
+        public static void TestIfCuriouslyRecurringInterfaceCanCast()
+        {
+            Console.WriteLine("TestIfCuriouslyRecurringInterfaceCanCast");
+            Console.WriteLine("typeof(ICuriouslyRecurring<>).MakeGenericType(typeof(ICuriouslyRecurring<>).GetGenericArguments()[0]).IsAssignableFrom(typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0]): {0}", typeof(ICuriouslyRecurring<>).MakeGenericType(typeof(ICuriouslyRecurring<>).GetGenericArguments()[0]).IsAssignableFrom(typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0]));
+            if (!(typeof(ICuriouslyRecurring<>).MakeGenericType(typeof(ICuriouslyRecurring<>).GetGenericArguments()[0]).IsAssignableFrom(typeof(ICuriouslyRecurring<>).GetInterfaces()[0].GetGenericArguments()[0])))
+            {
+                throw new Exception("Fail");
+            }
+        }
+
+        public static void TestIfCuriouslyRecurringInterfaceCanBeUsedAsConstraint()
+        {
+            Console.WriteLine("TestIfCuriouslyRecurringInterfaceCanBeUsedAsConstraint");
+            TestIfCuriouslyRecurringInterfaceCanBeUsedAsConstraintWorker();
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private static void TestIfCuriouslyRecurringInterfaceCanBeUsedAsConstraintWorker()
+        {
+            // Test that the a generic using a variant of the curiously recurring pattern involving an interface and constraint can be loaded.
+            // This test is just like TestIfCuriouslyRecurringInterfaceCanBeLoaded, except that it is structured so that we perform a cast via a constraint at type load time
+            _o = typeof(DerivedCuriouslyRecurringThroughInterface<int>);
+            Console.WriteLine("Found type: {0}", _o);
         }
     }
-}
\ No newline at end of file
+}

From c804f58a6e594202c711a25281c80249e16079c2 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Fri, 9 Feb 2024 12:24:41 -0800
Subject: [PATCH 22/36] [release/8.0-staging] Move a lock to protect
 m_pDynamicStaticsInfo (#97352)

* Move a lock to protect m_pDynamicStaticsInfo

* apply feedback

* cast to LONG

* Fix access to m_pDynamicStaticsInfo (#97353)

- Remove race condition where it is possible that an updated dynamic statics info pointer is published without ensuring that the data is also considered written.
- Use VolatileLoadWithoutBarrier at the read site (where locks are not taken) to ensure that there are no difficult to examine reads of this pointer.

---------

Co-authored-by: Hyungju Lee <leee.lee@samsung.com>
Co-authored-by: David Wrighton <davidwr@microsoft.com>
---
 src/coreclr/vm/ceeload.cpp | 30 +++++++++++++-----------------
 src/coreclr/vm/ceeload.inl |  2 +-
 2 files changed, 14 insertions(+), 18 deletions(-)

diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp
index 709ec1e5042984..f6e1cf37e4ebb5 100644
--- a/src/coreclr/vm/ceeload.cpp
+++ b/src/coreclr/vm/ceeload.cpp
@@ -1550,29 +1550,25 @@ DWORD Module::AllocateDynamicEntry(MethodTable *pMT)
     }
     CONTRACTL_END;
 
-    DWORD newId = InterlockedExchangeAdd((LONG*)&m_cDynamicEntries, 1);
+    CrstHolder ch(&m_Crst);
+    DWORD newId = (LONG)m_cDynamicEntries++;
 
-    if (newId >= VolatileLoad(&m_maxDynamicEntries))
+    if (newId >= m_maxDynamicEntries)
     {
-        CrstHolder ch(&m_Crst);
-
-        if (newId >= m_maxDynamicEntries)
+        SIZE_T maxDynamicEntries = max(16, m_maxDynamicEntries);
+        while (maxDynamicEntries <= newId)
         {
-            SIZE_T maxDynamicEntries = max(16, m_maxDynamicEntries);
-            while (maxDynamicEntries <= newId)
-            {
-                maxDynamicEntries *= 2;
-            }
+            maxDynamicEntries *= 2;
+        }
 
-            DynamicStaticsInfo* pNewDynamicStaticsInfo = (DynamicStaticsInfo*)
-                (void*)GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(DynamicStaticsInfo)) * S_SIZE_T(maxDynamicEntries));
+        DynamicStaticsInfo* pNewDynamicStaticsInfo = (DynamicStaticsInfo*)
+            (void*)GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(DynamicStaticsInfo)) * S_SIZE_T(maxDynamicEntries));
 
-            if (m_pDynamicStaticsInfo)
-                memcpy(pNewDynamicStaticsInfo, m_pDynamicStaticsInfo, sizeof(DynamicStaticsInfo) * m_maxDynamicEntries);
+        if (m_pDynamicStaticsInfo)
+            memcpy(pNewDynamicStaticsInfo, m_pDynamicStaticsInfo, sizeof(DynamicStaticsInfo) * m_maxDynamicEntries);
 
-            m_pDynamicStaticsInfo = pNewDynamicStaticsInfo;
-            VolatileStore(&m_maxDynamicEntries, maxDynamicEntries);
-        }
+        VolatileStore(&m_pDynamicStaticsInfo, pNewDynamicStaticsInfo);
+        m_maxDynamicEntries = maxDynamicEntries;
     }
 
     m_pDynamicStaticsInfo[newId].pEnclosingMT = pMT;
diff --git a/src/coreclr/vm/ceeload.inl b/src/coreclr/vm/ceeload.inl
index 8cd5189791b8c0..10bc879927a166 100644
--- a/src/coreclr/vm/ceeload.inl
+++ b/src/coreclr/vm/ceeload.inl
@@ -463,7 +463,7 @@ inline MethodTable* Module::GetDynamicClassMT(DWORD dynamicClassID)
 {
     LIMITED_METHOD_CONTRACT;
     _ASSERTE(m_cDynamicEntries > dynamicClassID);
-    return m_pDynamicStaticsInfo[dynamicClassID].pEnclosingMT;
+    return VolatileLoadWithoutBarrier(&m_pDynamicStaticsInfo)[dynamicClassID].pEnclosingMT;
 }
 
 #ifdef FEATURE_CODE_VERSIONING

From f4075f3df6bc17138b591f99a151def41a7aa907 Mon Sep 17 00:00:00 2001
From: Tanner Gooding <tagoo@outlook.com>
Date: Sat, 10 Feb 2024 09:32:52 -0800
Subject: [PATCH 23/36] Ensure that constant folding for SIMD shifts on xarch
 follow the correct behavior on overshift (#98001) (#98066)

* Ensure that constant folding for SIMD shifts on xarch follow the correct behavior on overshift

* Ensure we test Sse2.IsSupported
---
 src/coreclr/jit/hwintrinsicxarch.cpp          |  2 +-
 src/coreclr/jit/simd.h                        | 54 ++++++++++++-
 src/coreclr/jit/valuenum.cpp                  | 75 +++++++++++++++++++
 .../JitBlue/Runtime_93698/Runtime_93698.cs    | 49 ++++++++++++
 .../Runtime_93698/Runtime_93698.csproj        |  8 ++
 5 files changed, 184 insertions(+), 4 deletions(-)
 create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_93698/Runtime_93698.cs
 create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_93698/Runtime_93698.csproj

diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp
index 065999982a87a9..3c8410a47ae353 100644
--- a/src/coreclr/jit/hwintrinsicxarch.cpp
+++ b/src/coreclr/jit/hwintrinsicxarch.cpp
@@ -924,7 +924,7 @@ GenTree* Compiler::impNonConstFallback(NamedIntrinsic intrinsic, var_types simdT
             GenTree* op2 = impPopStack().val;
             GenTree* op1 = impSIMDPopStack();
 
-            GenTree* tmpOp = gtNewSimdCreateScalarUnsafeNode(TYP_SIMD16, op2, CORINFO_TYPE_INT, 16);
+            GenTree* tmpOp = gtNewSimdCreateScalarNode(TYP_SIMD16, op2, CORINFO_TYPE_INT, 16);
             return gtNewSimdHWIntrinsicNode(simdType, op1, tmpOp, intrinsic, simdBaseJitType, genTypeSize(simdType));
         }
 
diff --git a/src/coreclr/jit/simd.h b/src/coreclr/jit/simd.h
index 478b0a1af4f4a3..9e8781714dbc41 100644
--- a/src/coreclr/jit/simd.h
+++ b/src/coreclr/jit/simd.h
@@ -453,7 +453,23 @@ void EvaluateUnarySimd(genTreeOps oper, bool scalar, var_types baseType, TSimd*
 template <typename TBase>
 TBase EvaluateBinaryScalarRSZ(TBase arg0, TBase arg1)
 {
-    return arg0 >> (arg1 & ((sizeof(TBase) * 8) - 1));
+#if defined(TARGET_XARCH)
+    if ((arg1 < 0) || (arg1 >= (sizeof(TBase) * 8)))
+    {
+        // For SIMD, xarch allows overshifting and treats
+        // it as zeroing. So ensure we do the same here.
+        //
+        // The xplat APIs ensure the shiftAmount is masked
+        // to be within range, so we can't hit this for them.
+
+        return static_cast<TBase>(0);
+    }
+#else
+    // Other platforms enforce masking in their encoding
+    assert((arg1 >= 0) && (arg1 < (sizeof(TBase) * 8)));
+#endif
+
+    return arg0 >> arg1;
 }
 
 template <>
@@ -513,7 +529,22 @@ TBase EvaluateBinaryScalarSpecialized(genTreeOps oper, TBase arg0, TBase arg1)
 
         case GT_LSH:
         {
-            return arg0 << (arg1 & ((sizeof(TBase) * 8) - 1));
+#if defined(TARGET_XARCH)
+            if ((arg1 < 0) || (arg1 >= (sizeof(TBase) * 8)))
+            {
+                // For SIMD, xarch allows overshifting and treats
+                // it as zeroing. So ensure we do the same here.
+                //
+                // The xplat APIs ensure the shiftAmount is masked
+                // to be within range, so we can't hit this for them.
+
+                return static_cast<TBase>(0);
+            }
+#else
+            // Other platforms enforce masking in their encoding
+            assert((arg1 >= 0) && (arg1 < (sizeof(TBase) * 8)));
+#endif
+            return arg0 << arg1;
         }
 
         case GT_OR:
@@ -535,7 +566,24 @@ TBase EvaluateBinaryScalarSpecialized(genTreeOps oper, TBase arg0, TBase arg1)
 
         case GT_RSH:
         {
-            return arg0 >> (arg1 & ((sizeof(TBase) * 8) - 1));
+#if defined(TARGET_XARCH)
+            if ((arg1 < 0) || (arg1 >= (sizeof(TBase) * 8)))
+            {
+                // For SIMD, xarch allows overshifting and treats
+                // it as propagating the sign bit (returning Zero
+                // or AllBitsSet). So ensure we do the same here.
+                //
+                // The xplat APIs ensure the shiftAmount is masked
+                // to be within range, so we can't hit this for them.
+
+                arg0 >>= ((sizeof(TBase) * 8) - 1);
+                arg1 = static_cast<TBase>(1);
+            }
+#else
+            // Other platforms enforce masking in their encoding
+            assert((arg1 >= 0) && (arg1 < (sizeof(TBase) * 8)));
+#endif
+            return arg0 >> arg1;
         }
 
         case GT_RSZ:
diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp
index 6943c3c5e07e26..259305a6aac7b1 100644
--- a/src/coreclr/jit/valuenum.cpp
+++ b/src/coreclr/jit/valuenum.cpp
@@ -7518,6 +7518,31 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary(var_types      type,
             case NI_AVX512BW_ShiftLeftLogical:
 #endif
             {
+#ifdef TARGET_XARCH
+                if (TypeOfVN(arg1VN) == TYP_SIMD16)
+                {
+                    // The xarch shift instructions support taking the shift amount as
+                    // a simd16, in which case they take the shift amount from the lower
+                    // 64-bits.
+
+                    uint64_t shiftAmount = GetConstantSimd16(arg1VN).u64[0];
+
+                    if (genTypeSize(baseType) != 8)
+                    {
+                        if (shiftAmount > INT_MAX)
+                        {
+                            // Ensure we don't lose track the the amount is an overshift
+                            shiftAmount = -1;
+                        }
+                        arg1VN = VNForIntCon(static_cast<int32_t>(shiftAmount));
+                    }
+                    else
+                    {
+                        arg1VN = VNForLongCon(static_cast<int64_t>(shiftAmount));
+                    }
+                }
+#endif // TARGET_XARCH
+
                 return EvaluateBinarySimd(this, GT_LSH, /* scalar */ false, type, baseType, arg0VN, arg1VN);
             }
 
@@ -7531,6 +7556,31 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary(var_types      type,
             case NI_AVX512BW_ShiftRightArithmetic:
 #endif
             {
+#ifdef TARGET_XARCH
+                if (TypeOfVN(arg1VN) == TYP_SIMD16)
+                {
+                    // The xarch shift instructions support taking the shift amount as
+                    // a simd16, in which case they take the shift amount from the lower
+                    // 64-bits.
+
+                    uint64_t shiftAmount = GetConstantSimd16(arg1VN).u64[0];
+
+                    if (genTypeSize(baseType) != 8)
+                    {
+                        if (shiftAmount > INT_MAX)
+                        {
+                            // Ensure we don't lose track the the amount is an overshift
+                            shiftAmount = -1;
+                        }
+                        arg1VN = VNForIntCon(static_cast<int32_t>(shiftAmount));
+                    }
+                    else
+                    {
+                        arg1VN = VNForLongCon(static_cast<int64_t>(shiftAmount));
+                    }
+                }
+#endif // TARGET_XARCH
+
                 return EvaluateBinarySimd(this, GT_RSH, /* scalar */ false, type, baseType, arg0VN, arg1VN);
             }
 
@@ -7543,6 +7593,31 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary(var_types      type,
             case NI_AVX512BW_ShiftRightLogical:
 #endif
             {
+#ifdef TARGET_XARCH
+                if (TypeOfVN(arg1VN) == TYP_SIMD16)
+                {
+                    // The xarch shift instructions support taking the shift amount as
+                    // a simd16, in which case they take the shift amount from the lower
+                    // 64-bits.
+
+                    uint64_t shiftAmount = GetConstantSimd16(arg1VN).u64[0];
+
+                    if (genTypeSize(baseType) != 8)
+                    {
+                        if (shiftAmount > INT_MAX)
+                        {
+                            // Ensure we don't lose track the the amount is an overshift
+                            shiftAmount = -1;
+                        }
+                        arg1VN = VNForIntCon(static_cast<int32_t>(shiftAmount));
+                    }
+                    else
+                    {
+                        arg1VN = VNForLongCon(static_cast<int64_t>(shiftAmount));
+                    }
+                }
+#endif // TARGET_XARCH
+
                 return EvaluateBinarySimd(this, GT_RSZ, /* scalar */ false, type, baseType, arg0VN, arg1VN);
             }
 
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_93698/Runtime_93698.cs b/src/tests/JIT/Regression/JitBlue/Runtime_93698/Runtime_93698.cs
new file mode 100644
index 00000000000000..012387e9c656bc
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_93698/Runtime_93698.cs
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+using Xunit;
+
+public static class Runtime_93698
+{
+    [Fact]
+    public static void TestShiftLeftLogicalOvershift()
+    {
+        if (Sse2.IsSupported)
+        {
+            var result1 = Sse2.ShiftLeftLogical(Vector128.Create(-1, +2, -3, +4), 32);
+            Assert.Equal(Vector128<int>.Zero, result1);
+
+            var result2 = Sse2.ShiftLeftLogical(Vector128.Create(-5, +6, -7, +8), Vector128.Create(0, 32, 0, 0));
+            Assert.Equal(Vector128<int>.Zero, result2);
+        }
+    }
+
+    [Fact]
+    public static void TestShiftRightLogicalOvershift()
+    {
+        if (Sse2.IsSupported)
+        {
+            var result1 = Sse2.ShiftRightLogical(Vector128.Create(-1, +2, -3, +4), 32);
+            Assert.Equal(Vector128<int>.Zero, result1);
+
+            var result2 = Sse2.ShiftRightLogical(Vector128.Create(-5, +6, -7, +8), Vector128.Create(0, 32, 0, 0));
+            Assert.Equal(Vector128<int>.Zero, result2);
+        }
+    }
+
+    [Fact]
+    public static void TestShiftRightArithmeticOvershift()
+    {
+        if (Sse2.IsSupported)
+        {
+            var result1 = Sse2.ShiftRightArithmetic(Vector128.Create(-1, +2, -3, +4), 32);
+            Assert.Equal(Vector128.Create(-1, 0, -1, 0), result1);
+
+            var result2 = Sse2.ShiftRightArithmetic(Vector128.Create(-5, +6, -7, +8), Vector128.Create(0, 32, 0, 0));
+            Assert.Equal(Vector128.Create(-1, 0, -1, 0), result2);
+        }
+    }
+}
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_93698/Runtime_93698.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_93698/Runtime_93698.csproj
new file mode 100644
index 00000000000000..15edd99711a1a4
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_93698/Runtime_93698.csproj
@@ -0,0 +1,8 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildProjectName).cs" />
+  </ItemGroup>
+</Project>
\ No newline at end of file

From d45a5762713620f859f6f671cd39cdccc0bb1497 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Sat, 10 Feb 2024 18:33:08 +0100
Subject: [PATCH 24/36] [release/8.0-staging] Ensure that the various
 `Max*Number` and `Min*Number` APIs optimize correctly (#98159)

* Ensure that the various `Max*Number` and `Min*Number` APIs optimize correctly

* Don't mark the test methods as AO

* Add a missing using statement to the test

---------

Co-authored-by: Tanner Gooding <tagoo@outlook.com>
---
 src/coreclr/jit/importercalls.cpp             |   3 +-
 .../JitBlue/Runtime_98068/Runtime_98068.cs    | 753 ++++++++++++++++++
 .../Runtime_98068/Runtime_98068.csproj        |   8 +
 3 files changed, 763 insertions(+), 1 deletion(-)
 create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_98068/Runtime_98068.cs
 create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_98068/Runtime_98068.csproj

diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp
index fc2d2376541445..e0c5cbb94e4733 100644
--- a/src/coreclr/jit/importercalls.cpp
+++ b/src/coreclr/jit/importercalls.cpp
@@ -8290,7 +8290,8 @@ GenTree* Compiler::impMinMaxIntrinsic(CORINFO_METHOD_HANDLE method,
 
                 if (isNumber)
                 {
-                    std::swap(op1, op2);
+                    // Swap the operands so that the cnsNode is op1, this prevents
+                    // the unknown value (which could be NaN) from being selected.
 
                     retNode->AsHWIntrinsic()->Op(1) = op2;
                     retNode->AsHWIntrinsic()->Op(2) = op1;
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_98068/Runtime_98068.cs b/src/tests/JIT/Regression/JitBlue/Runtime_98068/Runtime_98068.cs
new file mode 100644
index 00000000000000..26efaba4fd2d05
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_98068/Runtime_98068.cs
@@ -0,0 +1,753 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+public static class Runtime_98068
+{
+    [Fact]
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static void TestMax()
+    {
+        // Double
+
+        Assert.Equal(Max(double.NaN, +1.0), Max_Value_One(double.NaN));
+        Assert.Equal(Max(double.NaN, +0.0), Max_Value_Zero(double.NaN));
+        Assert.Equal(Max(double.NaN, -0.0), Max_Value_NegZero(double.NaN));
+
+        Assert.Equal(Max(+1.0, double.NaN), Max_Value_NaN(+1.0));
+        Assert.Equal(Max(+0.0, double.NaN), Max_Value_NaN(+0.0));
+        Assert.Equal(Max(-0.0, double.NaN), Max_Value_NaN(-0.0));
+
+        // Single
+
+        Assert.Equal(Max(float.NaN, +1.0f), Max_Value_One(float.NaN));
+        Assert.Equal(Max(float.NaN, +0.0f), Max_Value_Zero(float.NaN));
+        Assert.Equal(Max(float.NaN, -0.0f), Max_Value_NegZero(float.NaN));
+
+        Assert.Equal(Max(+1.0f, float.NaN), Max_Value_NaN(+1.0f));
+        Assert.Equal(Max(+0.0f, float.NaN), Max_Value_NaN(+0.0f));
+        Assert.Equal(Max(-0.0f, float.NaN), Max_Value_NaN(-0.0f));
+    }
+
+    [Fact]
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static void TestMaxMagnitude()
+    {
+        // Double
+
+        Assert.Equal(MaxMagnitude(double.NaN, +1.0), MaxMagnitude_Value_One(double.NaN));
+        Assert.Equal(MaxMagnitude(double.NaN, +0.0), MaxMagnitude_Value_Zero(double.NaN));
+        Assert.Equal(MaxMagnitude(double.NaN, -0.0), MaxMagnitude_Value_NegZero(double.NaN));
+
+        Assert.Equal(MaxMagnitude(+1.0, double.NaN), MaxMagnitude_Value_NaN(+1.0));
+        Assert.Equal(MaxMagnitude(+0.0, double.NaN), MaxMagnitude_Value_NaN(+0.0));
+        Assert.Equal(MaxMagnitude(-0.0, double.NaN), MaxMagnitude_Value_NaN(-0.0));
+
+        // Single
+
+        Assert.Equal(MaxMagnitude(float.NaN, +1.0f), MaxMagnitude_Value_One(float.NaN));
+        Assert.Equal(MaxMagnitude(float.NaN, +0.0f), MaxMagnitude_Value_Zero(float.NaN));
+        Assert.Equal(MaxMagnitude(float.NaN, -0.0f), MaxMagnitude_Value_NegZero(float.NaN));
+
+        Assert.Equal(MaxMagnitude(+1.0f, float.NaN), MaxMagnitude_Value_NaN(+1.0f));
+        Assert.Equal(MaxMagnitude(+0.0f, float.NaN), MaxMagnitude_Value_NaN(+0.0f));
+        Assert.Equal(MaxMagnitude(-0.0f, float.NaN), MaxMagnitude_Value_NaN(-0.0f));
+    }
+
+    [Fact]
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static void TestMaxMagnitudeNumber()
+    {
+        // Double
+
+        Assert.Equal(MaxMagnitudeNumber(double.NaN, +1.0), MaxMagnitudeNumber_Value_One(double.NaN));
+        Assert.Equal(MaxMagnitudeNumber(double.NaN, +0.0), MaxMagnitudeNumber_Value_Zero(double.NaN));
+        Assert.Equal(MaxMagnitudeNumber(double.NaN, -0.0), MaxMagnitudeNumber_Value_NegZero(double.NaN));
+
+        Assert.Equal(MaxMagnitudeNumber(+1.0, double.NaN), MaxMagnitudeNumber_Value_NaN(+1.0));
+        Assert.Equal(MaxMagnitudeNumber(+0.0, double.NaN), MaxMagnitudeNumber_Value_NaN(+0.0));
+        Assert.Equal(MaxMagnitudeNumber(-0.0, double.NaN), MaxMagnitudeNumber_Value_NaN(-0.0));
+
+        // Single
+
+        Assert.Equal(MaxMagnitudeNumber(float.NaN, +1.0f), MaxMagnitudeNumber_Value_One(float.NaN));
+        Assert.Equal(MaxMagnitudeNumber(float.NaN, +0.0f), MaxMagnitudeNumber_Value_Zero(float.NaN));
+        Assert.Equal(MaxMagnitudeNumber(float.NaN, -0.0f), MaxMagnitudeNumber_Value_NegZero(float.NaN));
+
+        Assert.Equal(MaxMagnitudeNumber(+1.0f, float.NaN), MaxMagnitudeNumber_Value_NaN(+1.0f));
+        Assert.Equal(MaxMagnitudeNumber(+0.0f, float.NaN), MaxMagnitudeNumber_Value_NaN(+0.0f));
+        Assert.Equal(MaxMagnitudeNumber(-0.0f, float.NaN), MaxMagnitudeNumber_Value_NaN(-0.0f));
+    }
+
+    [Fact]
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static void TestMaxNumber()
+    {
+        // Double
+
+        Assert.Equal(MaxNumber(double.NaN, +1.0), MaxNumber_Value_One(double.NaN));
+        Assert.Equal(MaxNumber(double.NaN, +0.0), MaxNumber_Value_Zero(double.NaN));
+        Assert.Equal(MaxNumber(double.NaN, -0.0), MaxNumber_Value_NegZero(double.NaN));
+
+        Assert.Equal(MaxNumber(+1.0, double.NaN), MaxNumber_Value_NaN(+1.0));
+        Assert.Equal(MaxNumber(+0.0, double.NaN), MaxNumber_Value_NaN(+0.0));
+        Assert.Equal(MaxNumber(-0.0, double.NaN), MaxNumber_Value_NaN(-0.0));
+
+        // Single
+
+        Assert.Equal(MaxNumber(float.NaN, +1.0f), MaxNumber_Value_One(float.NaN));
+        Assert.Equal(MaxNumber(float.NaN, +0.0f), MaxNumber_Value_Zero(float.NaN));
+        Assert.Equal(MaxNumber(float.NaN, -0.0f), MaxNumber_Value_NegZero(float.NaN));
+
+        Assert.Equal(MaxNumber(+1.0f, float.NaN), MaxNumber_Value_NaN(+1.0f));
+        Assert.Equal(MaxNumber(+0.0f, float.NaN), MaxNumber_Value_NaN(+0.0f));
+        Assert.Equal(MaxNumber(-0.0f, float.NaN), MaxNumber_Value_NaN(-0.0f));
+    }
+
+    [Fact]
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static void TestMin()
+    {
+        // Double
+
+        Assert.Equal(Min(double.NaN, +1.0), Min_Value_One(double.NaN));
+        Assert.Equal(Min(double.NaN, +0.0), Min_Value_Zero(double.NaN));
+        Assert.Equal(Min(double.NaN, -0.0), Min_Value_NegZero(double.NaN));
+
+        Assert.Equal(Min(+1.0, double.NaN), Min_Value_NaN(+1.0));
+        Assert.Equal(Min(+0.0, double.NaN), Min_Value_NaN(+0.0));
+        Assert.Equal(Min(-0.0, double.NaN), Min_Value_NaN(-0.0));
+
+        // Single
+
+        Assert.Equal(Min(float.NaN, +1.0f), Min_Value_One(float.NaN));
+        Assert.Equal(Min(float.NaN, +0.0f), Min_Value_Zero(float.NaN));
+        Assert.Equal(Min(float.NaN, -0.0f), Min_Value_NegZero(float.NaN));
+
+        Assert.Equal(Min(+1.0f, float.NaN), Min_Value_NaN(+1.0f));
+        Assert.Equal(Min(+0.0f, float.NaN), Min_Value_NaN(+0.0f));
+        Assert.Equal(Min(-0.0f, float.NaN), Min_Value_NaN(-0.0f));
+    }
+
+    [Fact]
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static void TestMinMagnitude()
+    {
+        // Double
+
+        Assert.Equal(MinMagnitude(double.NaN, +1.0), MinMagnitude_Value_One(double.NaN));
+        Assert.Equal(MinMagnitude(double.NaN, +0.0), MinMagnitude_Value_Zero(double.NaN));
+        Assert.Equal(MinMagnitude(double.NaN, -0.0), MinMagnitude_Value_NegZero(double.NaN));
+
+        Assert.Equal(MinMagnitude(+1.0, double.NaN), MinMagnitude_Value_NaN(+1.0));
+        Assert.Equal(MinMagnitude(+0.0, double.NaN), MinMagnitude_Value_NaN(+0.0));
+        Assert.Equal(MinMagnitude(-0.0, double.NaN), MinMagnitude_Value_NaN(-0.0));
+
+        // Single
+
+        Assert.Equal(MinMagnitude(float.NaN, +1.0f), MinMagnitude_Value_One(float.NaN));
+        Assert.Equal(MinMagnitude(float.NaN, +0.0f), MinMagnitude_Value_Zero(float.NaN));
+        Assert.Equal(MinMagnitude(float.NaN, -0.0f), MinMagnitude_Value_NegZero(float.NaN));
+
+        Assert.Equal(MinMagnitude(+1.0f, float.NaN), MinMagnitude_Value_NaN(+1.0f));
+        Assert.Equal(MinMagnitude(+0.0f, float.NaN), MinMagnitude_Value_NaN(+0.0f));
+        Assert.Equal(MinMagnitude(-0.0f, float.NaN), MinMagnitude_Value_NaN(-0.0f));
+    }
+
+    [Fact]
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static void TestMinMagnitudeNumber()
+    {
+        // Double
+
+        Assert.Equal(MinMagnitudeNumber(double.NaN, +1.0), MinMagnitudeNumber_Value_One(double.NaN));
+        Assert.Equal(MinMagnitudeNumber(double.NaN, +0.0), MinMagnitudeNumber_Value_Zero(double.NaN));
+        Assert.Equal(MinMagnitudeNumber(double.NaN, -0.0), MinMagnitudeNumber_Value_NegZero(double.NaN));
+
+        Assert.Equal(MinMagnitudeNumber(+1.0, double.NaN), MinMagnitudeNumber_Value_NaN(+1.0));
+        Assert.Equal(MinMagnitudeNumber(+0.0, double.NaN), MinMagnitudeNumber_Value_NaN(+0.0));
+        Assert.Equal(MinMagnitudeNumber(-0.0, double.NaN), MinMagnitudeNumber_Value_NaN(-0.0));
+
+        // Single
+
+        Assert.Equal(MinMagnitudeNumber(float.NaN, +1.0f), MinMagnitudeNumber_Value_One(float.NaN));
+        Assert.Equal(MinMagnitudeNumber(float.NaN, +0.0f), MinMagnitudeNumber_Value_Zero(float.NaN));
+        Assert.Equal(MinMagnitudeNumber(float.NaN, -0.0f), MinMagnitudeNumber_Value_NegZero(float.NaN));
+
+        Assert.Equal(MinMagnitudeNumber(+1.0f, float.NaN), MinMagnitudeNumber_Value_NaN(+1.0f));
+        Assert.Equal(MinMagnitudeNumber(+0.0f, float.NaN), MinMagnitudeNumber_Value_NaN(+0.0f));
+        Assert.Equal(MinMagnitudeNumber(-0.0f, float.NaN), MinMagnitudeNumber_Value_NaN(-0.0f));
+    }
+
+    [Fact]
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static void TestMinNumber()
+    {
+        // Double
+
+        Assert.Equal(MinNumber(double.NaN, +1.0), MinNumber_Value_One(double.NaN));
+        Assert.Equal(MinNumber(double.NaN, +0.0), MinNumber_Value_Zero(double.NaN));
+        Assert.Equal(MinNumber(double.NaN, -0.0), MinNumber_Value_NegZero(double.NaN));
+
+        Assert.Equal(MinNumber(+1.0, double.NaN), MinNumber_Value_NaN(+1.0));
+        Assert.Equal(MinNumber(+0.0, double.NaN), MinNumber_Value_NaN(+0.0));
+        Assert.Equal(MinNumber(-0.0, double.NaN), MinNumber_Value_NaN(-0.0));
+
+        // Single
+
+        Assert.Equal(MinNumber(float.NaN, +1.0f), MinNumber_Value_One(float.NaN));
+        Assert.Equal(MinNumber(float.NaN, +0.0f), MinNumber_Value_Zero(float.NaN));
+        Assert.Equal(MinNumber(float.NaN, -0.0f), MinNumber_Value_NegZero(float.NaN));
+
+        Assert.Equal(MinNumber(+1.0f, float.NaN), MinNumber_Value_NaN(+1.0f));
+        Assert.Equal(MinNumber(+0.0f, float.NaN), MinNumber_Value_NaN(+0.0f));
+        Assert.Equal(MinNumber(-0.0f, float.NaN), MinNumber_Value_NaN(-0.0f));
+    }
+
+    //
+    // Max.Double
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double Max(double left, double right)
+    {
+        return double.Max(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static double Max_Value_One(double value)
+    {
+        return double.Max(value, +1.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double Max_Value_NaN(double value)
+    {
+        return double.Max(value, double.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double Max_Value_NegZero(double value)
+    {
+        return double.Max(value, -0.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double Max_Value_Zero(double value)
+    {
+        return double.Max(value, +0.0);
+    }
+
+    //
+    // Max.Single
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float Max(float left, float right)
+    {
+        return float.Max(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static float Max_Value_One(float value)
+    {
+        return float.Max(value, +1.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float Max_Value_NaN(float value)
+    {
+        return float.Max(value, float.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float Max_Value_NegZero(float value)
+    {
+        return float.Max(value, -0.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float Max_Value_Zero(float value)
+    {
+        return float.Max(value, +0.0f);
+    }
+
+    //
+    // MaxMagnitude.Double
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MaxMagnitude(double left, double right)
+    {
+        return double.MaxMagnitude(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static double MaxMagnitude_Value_One(double value)
+    {
+        return double.MaxMagnitude(value, +1.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MaxMagnitude_Value_NaN(double value)
+    {
+        return double.MaxMagnitude(value, double.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MaxMagnitude_Value_NegZero(double value)
+    {
+        return double.MaxMagnitude(value, -0.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MaxMagnitude_Value_Zero(double value)
+    {
+        return double.MaxMagnitude(value, +0.0);
+    }
+
+    //
+    // MaxMagnitude.Single
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MaxMagnitude(float left, float right)
+    {
+        return float.MaxMagnitude(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static float MaxMagnitude_Value_One(float value)
+    {
+        return float.MaxMagnitude(value, +1.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MaxMagnitude_Value_NaN(float value)
+    {
+        return float.MaxMagnitude(value, float.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MaxMagnitude_Value_NegZero(float value)
+    {
+        return float.MaxMagnitude(value, -0.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MaxMagnitude_Value_Zero(float value)
+    {
+        return float.MaxMagnitude(value, +0.0f);
+    }
+
+    //
+    // MaxMagnitudeNumber.Double
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MaxMagnitudeNumber(double left, double right)
+    {
+        return double.MaxMagnitudeNumber(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static double MaxMagnitudeNumber_Value_One(double value)
+    {
+        return double.MaxMagnitudeNumber(value, +1.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MaxMagnitudeNumber_Value_NaN(double value)
+    {
+        return double.MaxMagnitudeNumber(value, double.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MaxMagnitudeNumber_Value_NegZero(double value)
+    {
+        return double.MaxMagnitudeNumber(value, -0.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MaxMagnitudeNumber_Value_Zero(double value)
+    {
+        return double.MaxMagnitudeNumber(value, +0.0);
+    }
+
+    //
+    // MaxMagnitudeNumber.Single
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MaxMagnitudeNumber(float left, float right)
+    {
+        return float.MaxMagnitudeNumber(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static float MaxMagnitudeNumber_Value_One(float value)
+    {
+        return float.MaxMagnitudeNumber(value, +1.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MaxMagnitudeNumber_Value_NaN(float value)
+    {
+        return float.MaxMagnitudeNumber(value, float.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MaxMagnitudeNumber_Value_NegZero(float value)
+    {
+        return float.MaxMagnitudeNumber(value, -0.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MaxMagnitudeNumber_Value_Zero(float value)
+    {
+        return float.MaxMagnitudeNumber(value, +0.0f);
+    }
+
+    //
+    // MaxNumber.Double
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MaxNumber(double left, double right)
+    {
+        return double.MaxNumber(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static double MaxNumber_Value_One(double value)
+    {
+        return double.MaxNumber(value, +1.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MaxNumber_Value_NaN(double value)
+    {
+        return double.MaxNumber(value, double.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MaxNumber_Value_NegZero(double value)
+    {
+        return double.MaxNumber(value, -0.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MaxNumber_Value_Zero(double value)
+    {
+        return double.MaxNumber(value, +0.0);
+    }
+
+    //
+    // MaxNumber.Single
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MaxNumber(float left, float right)
+    {
+        return float.MaxNumber(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static float MaxNumber_Value_One(float value)
+    {
+        return float.MaxNumber(value, +1.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MaxNumber_Value_NaN(float value)
+    {
+        return float.MaxNumber(value, float.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MaxNumber_Value_NegZero(float value)
+    {
+        return float.MaxNumber(value, -0.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MaxNumber_Value_Zero(float value)
+    {
+        return float.MaxNumber(value, +0.0f);
+    }
+
+    //
+    // Min.Double
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double Min(double left, double right)
+    {
+        return double.Min(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static double Min_Value_One(double value)
+    {
+        return double.Min(value, +1.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double Min_Value_NaN(double value)
+    {
+        return double.Min(value, double.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double Min_Value_NegZero(double value)
+    {
+        return double.Min(value, -0.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double Min_Value_Zero(double value)
+    {
+        return double.Min(value, +0.0);
+    }
+
+    //
+    // Min.Single
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float Min(float left, float right)
+    {
+        return float.Min(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static float Min_Value_One(float value)
+    {
+        return float.Min(value, +1.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float Min_Value_NaN(float value)
+    {
+        return float.Min(value, float.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float Min_Value_NegZero(float value)
+    {
+        return float.Min(value, -0.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float Min_Value_Zero(float value)
+    {
+        return float.Min(value, +0.0f);
+    }
+
+    //
+    // MinMagnitude.Double
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MinMagnitude(double left, double right)
+    {
+        return double.MinMagnitude(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static double MinMagnitude_Value_One(double value)
+    {
+        return double.MinMagnitude(value, +1.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MinMagnitude_Value_NaN(double value)
+    {
+        return double.MinMagnitude(value, double.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MinMagnitude_Value_NegZero(double value)
+    {
+        return double.MinMagnitude(value, -0.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MinMagnitude_Value_Zero(double value)
+    {
+        return double.MinMagnitude(value, +0.0);
+    }
+
+    //
+    // MinMagnitude.Single
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MinMagnitude(float left, float right)
+    {
+        return float.MinMagnitude(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static float MinMagnitude_Value_One(float value)
+    {
+        return float.MinMagnitude(value, +1.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MinMagnitude_Value_NaN(float value)
+    {
+        return float.MinMagnitude(value, float.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MinMagnitude_Value_NegZero(float value)
+    {
+        return float.MinMagnitude(value, -0.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MinMagnitude_Value_Zero(float value)
+    {
+        return float.MinMagnitude(value, +0.0f);
+    }
+
+    //
+    // MinMagnitudeNumber.Double
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MinMagnitudeNumber(double left, double right)
+    {
+        return double.MinMagnitudeNumber(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static double MinMagnitudeNumber_Value_One(double value)
+    {
+        return double.MinMagnitudeNumber(value, +1.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MinMagnitudeNumber_Value_NaN(double value)
+    {
+        return double.MinMagnitudeNumber(value, double.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MinMagnitudeNumber_Value_NegZero(double value)
+    {
+        return double.MinMagnitudeNumber(value, -0.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MinMagnitudeNumber_Value_Zero(double value)
+    {
+        return double.MinMagnitudeNumber(value, +0.0);
+    }
+
+    //
+    // MinMagnitudeNumber.Single
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MinMagnitudeNumber(float left, float right)
+    {
+        return float.MinMagnitudeNumber(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static float MinMagnitudeNumber_Value_One(float value)
+    {
+        return float.MinMagnitudeNumber(value, +1.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MinMagnitudeNumber_Value_NaN(float value)
+    {
+        return float.MinMagnitudeNumber(value, float.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MinMagnitudeNumber_Value_NegZero(float value)
+    {
+        return float.MinMagnitudeNumber(value, -0.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MinMagnitudeNumber_Value_Zero(float value)
+    {
+        return float.MinMagnitudeNumber(value, +0.0f);
+    }
+
+    //
+    // MinNumber.Double
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MinNumber(double left, double right)
+    {
+        return double.MinNumber(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static double MinNumber_Value_One(double value)
+    {
+        return double.MinNumber(value, +1.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MinNumber_Value_NaN(double value)
+    {
+        return double.MinNumber(value, double.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MinNumber_Value_NegZero(double value)
+    {
+        return double.MinNumber(value, -0.0);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static double MinNumber_Value_Zero(double value)
+    {
+        return double.MinNumber(value, +0.0);
+    }
+
+    //
+    // MinNumber.Single
+    //
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MinNumber(float left, float right)
+    {
+        return float.MinNumber(left, right);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining| MethodImplOptions.AggressiveOptimization)]
+    public static float MinNumber_Value_One(float value)
+    {
+        return float.MinNumber(value, +1.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MinNumber_Value_NaN(float value)
+    {
+        return float.MinNumber(value, float.NaN);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MinNumber_Value_NegZero(float value)
+    {
+        return float.MinNumber(value, -0.0f);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    public static float MinNumber_Value_Zero(float value)
+    {
+        return float.MinNumber(value, +0.0f);
+    }
+}
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_98068/Runtime_98068.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_98068/Runtime_98068.csproj
new file mode 100644
index 00000000000000..15edd99711a1a4
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_98068/Runtime_98068.csproj
@@ -0,0 +1,8 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildProjectName).cs" />
+  </ItemGroup>
+</Project>
\ No newline at end of file

From ff4e048ecabcac608e2cd10281efc3f043b7c6fd Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Sun, 11 Feb 2024 15:46:22 -0800
Subject: [PATCH 25/36] Define installer-owned directories (#98241)

Co-authored-by: Nikola Milosavljevic <nikolam@microsoft.com>
---
 .../Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.props    | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.props
index 6907e829c384f3..b9af46ba7258bf 100644
--- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.props
+++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.props
@@ -61,6 +61,7 @@
       <LinuxPackageDependency Include="dotnet-hostfxr-$(MajorVersion).$(MinorVersion);dotnet-runtime-deps-$(MajorVersion).$(MinorVersion)" Version="$(InstallerPackageVersion)" />
       <!-- We build on an image with LTTNGv0, but we package on distros that have v1. Ignore inspecting dependencies on our LLTNG provider to ensure we can package. -->
       <DebJsonProperty Include="debian_ignored_libraries" Object="[&quot;libcoreclrtraceptprovider.so&quot;]" />
+      <RpmJsonProperty Include="directories" Object="[ &quot;/usr/share/dotnet/shared/$(MicrosoftNetCoreAppFrameworkName)&quot; ]" />
     </ItemGroup>
   </Target>
 

From 2190e9be7e942f8037cd7318527086805a305150 Mon Sep 17 00:00:00 2001
From: Filip Navara <filip.navara@gmail.com>
Date: Mon, 12 Feb 2024 09:26:16 +0100
Subject: [PATCH 26/36] Fix Windows implementation of
 NegotiateAuthenticationPal.GetMIC (#98031)

---
 .../src/System/Net/NegotiateAuthenticationPal.Windows.cs    | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/libraries/System.Net.Security/src/System/Net/NegotiateAuthenticationPal.Windows.cs b/src/libraries/System.Net.Security/src/System/Net/NegotiateAuthenticationPal.Windows.cs
index 07e8dea22baa9c..6a136c4a1c59df 100644
--- a/src/libraries/System.Net.Security/src/System/Net/NegotiateAuthenticationPal.Windows.cs
+++ b/src/libraries/System.Net.Security/src/System/Net/NegotiateAuthenticationPal.Windows.cs
@@ -566,7 +566,7 @@ public override unsafe void GetMIC(ReadOnlySpan<byte> message, IBufferWriter<byt
                     bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, _securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES, ref sizes);
                     Debug.Assert(success);
 
-                    Span<byte> signatureBuffer = signature.GetSpan(sizes.cbSecurityTrailer);
+                    Span<byte> signatureBuffer = signature.GetSpan(sizes.cbMaxSignature);
 
                     fixed (byte* messagePtr = message)
                     fixed (byte* signaturePtr = signatureBuffer)
@@ -577,7 +577,7 @@ public override unsafe void GetMIC(ReadOnlySpan<byte> message, IBufferWriter<byt
                         Interop.SspiCli.SecBuffer* dataBuffer = &unmanagedBuffer[1];
                         tokenBuffer->BufferType = SecurityBufferType.SECBUFFER_TOKEN;
                         tokenBuffer->pvBuffer = (IntPtr)signaturePtr;
-                        tokenBuffer->cbBuffer = sizes.cbSecurityTrailer;
+                        tokenBuffer->cbBuffer = sizes.cbMaxSignature;
                         dataBuffer->BufferType = SecurityBufferType.SECBUFFER_DATA;
                         dataBuffer->pvBuffer = (IntPtr)messagePtr;
                         dataBuffer->cbBuffer = message.Length;
@@ -597,7 +597,7 @@ public override unsafe void GetMIC(ReadOnlySpan<byte> message, IBufferWriter<byt
                             throw new Win32Exception(errorCode);
                         }
 
-                        signature.Advance(signatureBuffer.Length);
+                        signature.Advance(tokenBuffer->cbBuffer);
                     }
                 }
                 finally

From dedae5e0a7cdeb2b86243d3fe48268b7b5e065ed Mon Sep 17 00:00:00 2001
From: Jakob Botsch Nielsen <Jakob.botsch.nielsen@gmail.com>
Date: Mon, 12 Feb 2024 17:59:08 +0100
Subject: [PATCH 27/36] [release/8.0-staging] Fix constant folding for arm64
 MultiplyByScalar operations involving Vector2.One (#98150)

MultiplyByScalar on ARM64 should not be handled by the same path
as other multiplications since it has different behavior.
---
 src/coreclr/jit/valuenum.cpp                  | 32 +++++++++++++++++--
 .../JitBlue/Runtime_93876/Runtime_93876.cs    | 25 +++++++++++++++
 .../Runtime_93876/Runtime_93876.csproj        |  8 +++++
 3 files changed, 63 insertions(+), 2 deletions(-)
 create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_93876/Runtime_93876.cs
 create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_93876/Runtime_93876.csproj

diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp
index 259305a6aac7b1..fa60633afbc233 100644
--- a/src/coreclr/jit/valuenum.cpp
+++ b/src/coreclr/jit/valuenum.cpp
@@ -7809,10 +7809,38 @@ ValueNum ValueNumStore::EvalHWIntrinsicFunBinary(var_types      type,
             }
 
 #ifdef TARGET_ARM64
-            case NI_AdvSimd_Multiply:
             case NI_AdvSimd_MultiplyByScalar:
-            case NI_AdvSimd_Arm64_Multiply:
             case NI_AdvSimd_Arm64_MultiplyByScalar:
+            {
+                if (!varTypeIsFloating(baseType))
+                {
+                    // Handle `x * 0 == 0` and `0 * x == 0`
+                    // Not safe for floating-point when x == -0.0, NaN, +Inf, -Inf
+                    ValueNum zeroVN = VNZeroForType(TypeOfVN(cnsVN));
+
+                    if (cnsVN == zeroVN)
+                    {
+                        return VNZeroForType(type);
+                    }
+                }
+
+                assert((TypeOfVN(arg0VN) == type) && (TypeOfVN(arg1VN) == TYP_SIMD8));
+
+                // Handle x * 1 => x, but only if the scalar RHS is <1, ...>.
+                if (IsVNConstant(arg1VN))
+                {
+                    if (EvaluateSimdGetElement(this, TYP_SIMD8, baseType, arg1VN, 0) == VNOneForType(baseType))
+                    {
+                        return arg0VN;
+                    }
+                }
+                break;
+            }
+#endif
+
+#ifdef TARGET_ARM64
+            case NI_AdvSimd_Multiply:
+            case NI_AdvSimd_Arm64_Multiply:
 #else
             case NI_SSE_Multiply:
             case NI_SSE2_Multiply:
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_93876/Runtime_93876.cs b/src/tests/JIT/Regression/JitBlue/Runtime_93876/Runtime_93876.cs
new file mode 100644
index 00000000000000..760cd04a594e3e
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_93876/Runtime_93876.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+using System.Numerics;
+using Xunit;
+
+public static class Runtime_93876
+{
+    [Fact]
+    public static void Problem()
+    {
+        Vector4 v = Mul(0, 1);
+        Assert.Equal(Vector4.One, v);
+        Vector64<float> v64 = Mul64(0, 1);
+        Assert.Equal(Vector64<float>.One, v64);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    private static Vector4 Mul(float a, float b) => Vector4.Multiply(a + b, Vector4.One);
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    private static Vector64<float> Mul64(float a, float b) => Vector64.Multiply(a + b, Vector64<float>.One);
+}
diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_93876/Runtime_93876.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_93876/Runtime_93876.csproj
new file mode 100644
index 00000000000000..15edd99711a1a4
--- /dev/null
+++ b/src/tests/JIT/Regression/JitBlue/Runtime_93876/Runtime_93876.csproj
@@ -0,0 +1,8 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildProjectName).cs" />
+  </ItemGroup>
+</Project>
\ No newline at end of file

From bb540a87535a1d51828eed38d0f04998e1fb8f55 Mon Sep 17 00:00:00 2001
From: Vladimir Sadov <vsadov@microsoft.com>
Date: Mon, 12 Feb 2024 07:05:42 -1000
Subject: [PATCH 28/36] [NativeAOT][8.0] Use ld_classic in ILC build and in
 build integration (#97856)

* use ld_classic in ILC build and in build integration

* PR feedback

* Maybe fix the build for non-apple

* Update src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets

PR feedback

Co-authored-by: Jan Kotas <jkotas@microsoft.com>

---------

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
---
 .../Microsoft.NETCore.Native.Unix.targets           | 13 +++++++++++++
 src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj  | 13 +++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
index 71acdacdadd10a..c9ae3083cf5cd4 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
@@ -166,6 +166,19 @@ The .NET Foundation licenses this file to you under the MIT license.
       <LinkerArg Include="-Wl,--eh-frame-hdr" Condition="'$(_IsApplePlatform)' != 'true'" />
     </ItemGroup>
 
+    <Exec Command="xcodebuild -version" Condition="'$(_IsApplePlatform)' == 'true'" IgnoreExitCode="true" StandardOutputImportance="Low" ConsoleToMSBuild="true">
+      <Output TaskParameter="ExitCode" PropertyName="_XcodeVersionStringExitCode" />
+      <Output TaskParameter="ConsoleOutput" PropertyName="_XcodeVersionString" />
+    </Exec>
+
+    <PropertyGroup Condition="('$(_XcodeVersionStringExitCode)' == '0' or '$(_XcodeVersionStringExitCode)' == '1') and '$(_XcodeVersionString)' != ''">
+      <_XcodeVersion>$([System.Text.RegularExpressions.Regex]::Match($(_XcodeVersionString), '[1-9]\d*'))</_XcodeVersion>
+    </PropertyGroup>
+
+    <ItemGroup Condition="'$(UseLdClassicXCodeLinker)' != 'false' and '$(_IsApplePlatform)' == 'true'">
+      <CustomLinkerArg Condition="'$(_XcodeVersion)' &gt;= '15'" Include="-ld_classic" />
+    </ItemGroup>
+
     <PropertyGroup>
       <_CommandProbe>command -v</_CommandProbe>
       <_CommandProbe Condition="$([MSBuild]::IsOSPlatform('Windows'))">where /Q</_CommandProbe>
diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj
index 7122c81034ff31..7c25444f209c33 100644
--- a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj
+++ b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj
@@ -70,6 +70,19 @@
       <Output TaskParameter="ConsoleOutput" PropertyName="_CC_LDFLAGS" />
     </Exec>
 
+    <Exec Command="xcodebuild -version" Condition="'$(_IsApplePlatform)' == 'true'" IgnoreExitCode="true" StandardOutputImportance="Low" ConsoleToMSBuild="true">
+      <Output TaskParameter="ExitCode" PropertyName="_XcodeVersionStringExitCode" />
+      <Output TaskParameter="ConsoleOutput" PropertyName="_XcodeVersionString" />
+    </Exec>
+
+    <PropertyGroup Condition="('$(_XcodeVersionStringExitCode)' == '0' or '$(_XcodeVersionStringExitCode)' == '1') and '$(_XcodeVersionString)' != ''">
+      <_XcodeVersion>$([System.Text.RegularExpressions.Regex]::Match($(_XcodeVersionString), '[1-9]\d*'))</_XcodeVersion>
+    </PropertyGroup>
+
+    <ItemGroup Condition="'$(NativeAotSupported)' == 'true' and '$(_IsApplePlatform)' == 'true'">
+      <CustomLinkerArg Condition="'$(_XcodeVersion)' &gt;= '15'" Include="-ld_classic" />
+    </ItemGroup>
+
     <PropertyGroup>
       <CppLinker>$(_CC_LDFLAGS.SubString(0, $(_CC_LDFLAGS.IndexOf(';'))))</CppLinker>
       <_LDFLAGS>$(_CC_LDFLAGS.SubString($([MSBuild]::Add($(_CC_LDFLAGS.IndexOf(';')), 1))))</_LDFLAGS>

From ba68cf1d1091526397a2c655ff931f6678d1262f Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 12 Feb 2024 14:35:43 -0300
Subject: [PATCH 29/36] Fix side effect of only not sending assembly_load while
 invoking methods. (#98254)

Co-authored-by: Thays Grazia <thaystg@gmail.com>
---
 src/mono/mono/component/debugger-agent.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c
index c9199635d15d59..80918c38876824 100644
--- a/src/mono/mono/component/debugger-agent.c
+++ b/src/mono/mono/component/debugger-agent.c
@@ -4149,7 +4149,7 @@ jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo)
 		if (assembly) {
 			DebuggerTlsData *tls;
 			tls = (DebuggerTlsData *)mono_native_tls_get_value (debugger_tls_id);
-			if (tls->invoke == NULL) {
+			if (!CHECK_ICORDBG (TRUE) || tls->invoke == NULL) {
 				process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, assembly);
 			} else {
 				assembly_load(prof, assembly); //send later

From 6dec8dd10ca45d925fb3577be9cfd44a4822b7fc Mon Sep 17 00:00:00 2001
From: Elinor Fung <elfung@microsoft.com>
Date: Mon, 12 Feb 2024 09:47:17 -0800
Subject: [PATCH 30/36] Fix polluted CompareState when comparing element types
 in a signature (#98249)

We were propagating state from each type in the method signature to the
comparisons for the next type. This resulted in type equivalence checks
being disabled for any parameters that came after a generic parameter.
---
 src/coreclr/vm/siginfo.cpp                    | 12 +--
 .../typeequivalence/contracts/Types.cs        |  6 ++
 .../typeequivalence/impl/Impls.cs             | 12 +++
 .../typeequivalence/simple/Simple.cs          | 87 ++++++++++---------
 4 files changed, 68 insertions(+), 49 deletions(-)

diff --git a/src/coreclr/vm/siginfo.cpp b/src/coreclr/vm/siginfo.cpp
index eb35f3a372538f..3342a27178f50c 100644
--- a/src/coreclr/vm/siginfo.cpp
+++ b/src/coreclr/vm/siginfo.cpp
@@ -4204,8 +4204,6 @@ MetaSig::CompareTypeDefsUnderSubstitutions(
     SigPointer inst1 = pSubst1->GetInst();
     SigPointer inst2 = pSubst2->GetInst();
 
-    TokenPairList visited { pVisited };
-    CompareState state{ &visited };
     for (DWORD i = 0; i < pTypeDef1->GetNumGenericArgs(); i++)
     {
         PCCOR_SIGNATURE startInst1 = inst1.GetPtr();
@@ -4214,6 +4212,8 @@ MetaSig::CompareTypeDefsUnderSubstitutions(
         PCCOR_SIGNATURE startInst2 = inst2.GetPtr();
         IfFailThrow(inst2.SkipExactlyOne());
         PCCOR_SIGNATURE endInst2ptr = inst2.GetPtr();
+        TokenPairList visited{ pVisited };
+        CompareState state{ &visited };
         if (!CompareElementType(
                 startInst1,
                 startInst2,
@@ -4382,8 +4382,6 @@ MetaSig::CompareMethodSigs(
     IfFailThrow(CorSigUncompressData_EndPtr(pSig1, pEndSig1, &ArgCount1));
     IfFailThrow(CorSigUncompressData_EndPtr(pSig2, pEndSig2, &ArgCount2));
 
-    TokenPairList visited{ pVisited };
-
     if (ArgCount1 != ArgCount2)
     {
         if ((callConv & IMAGE_CEE_CS_CALLCONV_MASK) != IMAGE_CEE_CS_CALLCONV_VARARG)
@@ -4405,7 +4403,6 @@ MetaSig::CompareMethodSigs(
         // to correctly handle overloads, where there are a number of varargs methods
         // to pick from, like m1(int,...) and m2(int,int,...), etc.
 
-        CompareState state{ &visited };
         // <= because we want to include a check of the return value!
         for (i = 0; i <= ArgCount1; i++)
         {
@@ -4437,6 +4434,8 @@ MetaSig::CompareMethodSigs(
             else
             {
                 // We are in bounds on both sides.  Compare the element.
+                TokenPairList visited{ pVisited };
+                CompareState state{ &visited };
                 if (!CompareElementType(
                     pSig1,
                     pSig2,
@@ -4461,7 +4460,6 @@ MetaSig::CompareMethodSigs(
     }
 
     // do return type as well
-    CompareState state{ &visited };
     for (i = 0; i <= ArgCount1; i++)
     {
         if (i == 0 && skipReturnTypeSig)
@@ -4476,6 +4474,8 @@ MetaSig::CompareMethodSigs(
         }
         else
         {
+            TokenPairList visited{ pVisited };
+            CompareState state{ &visited };
             if (!CompareElementType(
                 pSig1,
                 pSig2,
diff --git a/src/tests/baseservices/typeequivalence/contracts/Types.cs b/src/tests/baseservices/typeequivalence/contracts/Types.cs
index a9fc0270a1bdd0..539e83318fc506 100644
--- a/src/tests/baseservices/typeequivalence/contracts/Types.cs
+++ b/src/tests/baseservices/typeequivalence/contracts/Types.cs
@@ -61,6 +61,12 @@ public interface ISparseType
         int MultiplyBy20(int a);
     }
 
+    [Guid("BD752276-52DF-4CD1-8C62-49D202F15C8D")]
+    public struct TestValueType
+    {
+        public int Field;
+    }
+
     //
     // Below types are used in type punning tests and shouldn't be used anywhere else.
     //
diff --git a/src/tests/baseservices/typeequivalence/impl/Impls.cs b/src/tests/baseservices/typeequivalence/impl/Impls.cs
index dd0ce12eec9baa..55117a68236175 100644
--- a/src/tests/baseservices/typeequivalence/impl/Impls.cs
+++ b/src/tests/baseservices/typeequivalence/impl/Impls.cs
@@ -130,3 +130,15 @@ public static int GetField_3(OnlyLoadOnce_3 s)
         return s.Field;
     }
 }
+
+public static class MethodCall
+{
+    // Include a generic type in the method signature before the type using type equivalence to ensure that
+    // processing of the generic type does not affect subsequent type processing during signature comparison.
+    public static System.Collections.Generic.List<int> InterfaceAfterGeneric(IEmptyType t) => null;
+    public static System.Collections.Generic.List<int> ValueTypeAfterGeneric(TestValueType t) => null;
+
+    // Generic type after the type using type equivalence should also not affect processing.
+    public static void InterfaceBeforeGeneric(IEmptyType t, System.Collections.Generic.List<int> l) { }
+    public static void ValueTypeBeforeGeneric(TestValueType t, System.Collections.Generic.List<int> l) { }
+}
diff --git a/src/tests/baseservices/typeequivalence/simple/Simple.cs b/src/tests/baseservices/typeequivalence/simple/Simple.cs
index 7595199a120e16..24e1c9684c70d4 100644
--- a/src/tests/baseservices/typeequivalence/simple/Simple.cs
+++ b/src/tests/baseservices/typeequivalence/simple/Simple.cs
@@ -17,6 +17,7 @@ public struct EquivalentValueType
     public int A;
 }
 
+[PlatformSpecific(TestPlatforms.Windows)]
 public class Simple
 {
     private class EmptyType2 : IEmptyType
@@ -30,7 +31,8 @@ public static object Create()
         }
     }
 
-    private static void InterfaceTypesFromDifferentAssembliesAreEquivalent()
+    [Fact]
+    public static void InterfaceTypesFromDifferentAssembliesAreEquivalent()
     {
         Console.WriteLine($"{nameof(InterfaceTypesFromDifferentAssembliesAreEquivalent)}");
         var inAsm = EmptyType.Create();
@@ -44,9 +46,10 @@ void AreNotSameObject(IEmptyType a, IEmptyType b)
         }
     }
 
-    private static void ValidateTypeInstanceEquality()
+    [Fact]
+    public static void TypeInstanceEquality()
     {
-        Console.WriteLine($"{nameof(ValidateTypeInstanceEquality)}");
+        Console.WriteLine($"{nameof(TypeInstanceEquality)}");
         var inAsm = EmptyType.Create();
         var otherAsm = EmptyType2.Create();
 
@@ -110,7 +113,8 @@ public override string ScaleString(string s)
         }
     }
 
-    private static void InterfaceTypesMethodOperations()
+    [Fact]
+    public static void InterfaceTypesMethodOperations()
     {
         Console.WriteLine($"{nameof(InterfaceTypesMethodOperations)}");
 
@@ -141,7 +145,8 @@ private static void InterfaceTypesMethodOperations()
         }
     }
 
-    private static void CallSparseInterface()
+    [Fact]
+    public static void CallSparseInterface()
     {
         Console.WriteLine($"{nameof(CallSparseInterface)}");
 
@@ -156,9 +161,10 @@ private static void CallSparseInterface()
         Assert.Equal(input * 18, sparseType.MultiplyBy18(input));
     }
 
-    private static void TestArrayEquivalence()
+    [Fact]
+    public static void ArrayEquivalence()
     {
-        Console.WriteLine($"{nameof(TestArrayEquivalence)}");
+        Console.WriteLine($"{nameof(ArrayEquivalence)}");
         var inAsm = EmptyType.Create();
         var otherAsm = EmptyType2.Create();
 
@@ -173,9 +179,10 @@ private static void TestArrayEquivalence()
         Assert.False(inAsmInterfaceType.MakeArrayType(1).IsEquivalentTo(otherAsmInterfaceType.MakeArrayType(2)));
     }
 
-    private static void TestByRefEquivalence()
+    [Fact]
+    public static void ByRefEquivalence()
     {
-        Console.WriteLine($"{nameof(TestByRefEquivalence)}");
+        Console.WriteLine($"{nameof(ByRefEquivalence)}");
         var inAsm = EmptyType.Create();
         var otherAsm = EmptyType2.Create();
 
@@ -197,9 +204,10 @@ public void Method(V input)
         }
     }
 
-    private static void TestGenericClassNonEquivalence()
+    [Fact]
+    public static void GenericClassNonEquivalence()
     {
-        Console.WriteLine($"{nameof(TestGenericClassNonEquivalence)}");
+        Console.WriteLine($"{nameof(GenericClassNonEquivalence)}");
         var inAsm = EmptyType.Create();
         var otherAsm = EmptyType2.Create();
 
@@ -209,9 +217,10 @@ private static void TestGenericClassNonEquivalence()
         Assert.False(typeof(Generic<>).MakeGenericType(inAsmInterfaceType).IsEquivalentTo(typeof(Generic<>).MakeGenericType(otherAsmInterfaceType)));
     }
 
-    private static void TestGenericInterfaceEquivalence()
+    [Fact]
+    public static void GenericInterfaceEquivalence()
     {
-        Console.WriteLine($"{nameof(TestGenericInterfaceEquivalence)}");
+        Console.WriteLine($"{nameof(GenericInterfaceEquivalence)}");
         var inAsm = EmptyType.Create();
         var otherAsm = EmptyType2.Create();
 
@@ -221,9 +230,10 @@ private static void TestGenericInterfaceEquivalence()
         Assert.True(typeof(IGeneric<>).MakeGenericType(inAsmInterfaceType).IsEquivalentTo(typeof(IGeneric<>).MakeGenericType(otherAsmInterfaceType)));
     }
 
-    private static unsafe void TestTypeEquivalenceWithTypePunning()
+    [Fact]
+    public static unsafe void TypeEquivalenceWithTypePunning()
     {
-        Console.WriteLine($"{nameof(TestTypeEquivalenceWithTypePunning)}");
+        Console.WriteLine($"{nameof(TypeEquivalenceWithTypePunning)}");
 
         {
             Console.WriteLine($"-- GetFunctionPointer()");
@@ -260,10 +270,11 @@ private static unsafe void TestTypeEquivalenceWithTypePunning()
         }
     }
 
+    [Fact]
     [MethodImpl (MethodImplOptions.NoInlining)]
-    private static void TestLoadingValueTypesWithMethod() 
+    public static void LoadValueTypesWithMethod()
     {
-        Console.WriteLine($"{nameof(TestLoadingValueTypesWithMethod)}");
+        Console.WriteLine($"{nameof(LoadValueTypesWithMethod)}");
         Console.WriteLine($"-- {typeof(ValueTypeWithStaticMethod).Name}");
         Assert.Throws<TypeLoadException>(() => LoadInvalidType());
     }
@@ -274,7 +285,8 @@ private static void LoadInvalidType()
         Console.WriteLine($"-- {typeof(ValueTypeWithInstanceMethod).Name}");
     }
 
-    private static void TestCastsOptimizations()
+    [Fact]
+    public static void CastsOptimizations()
     {
         string otherTypeName = $"{typeof(EquivalentValueType).FullName},{typeof(EmptyType).Assembly.GetName().Name}";
         Type otherEquivalentValueType = Type.GetType(otherTypeName);
@@ -285,32 +297,21 @@ private static void TestCastsOptimizations()
         EquivalentValueType inst = (EquivalentValueType)otherEquivalentValueTypeInstance;
     }
 
-    public static int Main()
+    [Fact]
+    public static void MethodCallSignature()
     {
-        if (!OperatingSystem.IsWindows())
-        {
-            return 100;
-        }
-        try
-        {
-            InterfaceTypesFromDifferentAssembliesAreEquivalent();
-            ValidateTypeInstanceEquality();
-            InterfaceTypesMethodOperations();
-            CallSparseInterface();
-            TestByRefEquivalence();
-            TestArrayEquivalence();
-            TestGenericClassNonEquivalence();
-            TestGenericInterfaceEquivalence();
-            TestTypeEquivalenceWithTypePunning();
-            TestLoadingValueTypesWithMethod();
-            TestCastsOptimizations();
-        }
-        catch (Exception e)
-        {
-            Console.WriteLine($"Test Failure: {e}");
-            return 101;
-        }
+        Console.WriteLine($"{nameof(MethodCallSignature)}");
+
+        Console.WriteLine($"-- {nameof(MethodCall.InterfaceAfterGeneric)}");
+        MethodCall.InterfaceAfterGeneric((IEmptyType)EmptyType2.Create());
+
+        Console.WriteLine($"-- {nameof(MethodCall.ValueTypeAfterGeneric)}");
+        MethodCall.ValueTypeAfterGeneric(new TestValueType());
+
+        Console.WriteLine($"-- {nameof(MethodCall.InterfaceBeforeGeneric)}");
+        MethodCall.InterfaceBeforeGeneric((IEmptyType)EmptyType2.Create(), null);
 
-        return 100;
+        Console.WriteLine($"-- {nameof(MethodCall.ValueTypeBeforeGeneric)}");
+        MethodCall.ValueTypeBeforeGeneric(new TestValueType(), null);
     }
 }

From 95988727574bd17962fa2d7e54525446835a9ebb Mon Sep 17 00:00:00 2001
From: "dotnet-maestro[bot]"
 <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Date: Mon, 12 Feb 2024 09:57:32 -0800
Subject: [PATCH 31/36] [release/8.0-staging] Update dependencies from
 dotnet/emsdk (#97405)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Update dependencies from https://github.com/dotnet/emsdk build 20240123.1

Microsoft.SourceBuild.Intermediate.emsdk , Microsoft.NET.Workload.Emscripten.Current.Manifest-8.0.100
 From Version 8.0.2-servicing.24062.1 -> To Version 8.0.2-servicing.24073.1

* Update dependencies from https://github.com/dotnet/emsdk build 20240208.3

Microsoft.SourceBuild.Intermediate.emsdk , Microsoft.NET.Workload.Emscripten.Current.Manifest-8.0.100
 From Version 8.0.2-servicing.24062.1 -> To Version 8.0.3-servicing.24108.3

---------

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com>
---
 NuGet.config            | 5 +----
 eng/Version.Details.xml | 8 ++++----
 eng/Versions.props      | 2 +-
 3 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/NuGet.config b/NuGet.config
index 12fa8c8879cdb6..a681bc250bc9ed 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -9,10 +9,7 @@
     <clear />
     <!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
     <!--  Begin: Package sources from dotnet-emsdk -->
-    <add key="darc-pub-dotnet-emsdk-2fc2ffd" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-2fc2ffd9/nuget/v3/index.json" />
-    <add key="darc-pub-dotnet-emsdk-2fc2ffd-3" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-2fc2ffd9-3/nuget/v3/index.json" />
-    <add key="darc-pub-dotnet-emsdk-2fc2ffd-2" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-2fc2ffd9-2/nuget/v3/index.json" />
-    <add key="darc-pub-dotnet-emsdk-2fc2ffd-1" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-2fc2ffd9-1/nuget/v3/index.json" />
+    <add key="darc-pub-dotnet-emsdk-9a29abd" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-9a29abdd/nuget/v3/index.json" />
     <!--  End: Package sources from dotnet-emsdk -->
     <!--  Begin: Package sources from dotnet-sdk -->
     <!--  End: Package sources from dotnet-sdk -->
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 04a7792f12c29a..4e522812e23bc7 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -90,13 +90,13 @@
       <Sha>45dd3a73dd5b64b010c4251303b3664bb30df029</Sha>
       <SourceBuild RepoName="cecil" ManagedOnly="true" />
     </Dependency>
-    <Dependency Name="Microsoft.NET.Workload.Emscripten.Current.Manifest-8.0.100" Version="8.0.2">
+    <Dependency Name="Microsoft.NET.Workload.Emscripten.Current.Manifest-8.0.100" Version="8.0.3">
       <Uri>https://github.com/dotnet/emsdk</Uri>
-      <Sha>2fc2ffd960930318f33fcaa690cbdbc55d72f52d</Sha>
+      <Sha>9a29abdd764a4de0f253ed368871877a47725247</Sha>
     </Dependency>
-    <Dependency Name="Microsoft.SourceBuild.Intermediate.emsdk" Version="8.0.2-servicing.24062.1">
+    <Dependency Name="Microsoft.SourceBuild.Intermediate.emsdk" Version="8.0.3-servicing.24108.3">
       <Uri>https://github.com/dotnet/emsdk</Uri>
-      <Sha>2fc2ffd960930318f33fcaa690cbdbc55d72f52d</Sha>
+      <Sha>9a29abdd764a4de0f253ed368871877a47725247</Sha>
       <SourceBuild RepoName="emsdk" ManagedOnly="true" />
     </Dependency>
     <Dependency Name="Microsoft.SourceBuild.Intermediate.source-build-reference-packages" Version="8.0.0-alpha.1.24061.1">
diff --git a/eng/Versions.props b/eng/Versions.props
index 05d877f78822fa..8b755c5895c9db 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -240,7 +240,7 @@
          Note: when the name is updated, make sure to update dependency name in eng/pipelines/common/xplat-setup.yml
                like - DarcDependenciesChanged.Microsoft_NET_Workload_Emscripten_Current_Manifest-8_0_100_Transport
     -->
-    <MicrosoftNETWorkloadEmscriptenCurrentManifest80100Version>8.0.2</MicrosoftNETWorkloadEmscriptenCurrentManifest80100Version>
+    <MicrosoftNETWorkloadEmscriptenCurrentManifest80100Version>8.0.3</MicrosoftNETWorkloadEmscriptenCurrentManifest80100Version>
     <MicrosoftNETRuntimeEmscriptenVersion>$(MicrosoftNETWorkloadEmscriptenCurrentManifest80100Version)</MicrosoftNETRuntimeEmscriptenVersion>
     <!-- workloads -->
     <SwixPackageVersion>1.1.87-gba258badda</SwixPackageVersion>

From 11ae42ba5af1bec15e7ab7c11529d5e006f253a2 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 12 Feb 2024 13:33:17 -0500
Subject: [PATCH 32/36] [release/8.0-staging] Fix regex lazy loop handling of
 backtracking state at max iteration limit (#97927)

* Fix regex lazy loop handling of backtracking state at max iteration limit

Upon entering a lazy loop, state is pushed onto the backtracking stack if the lazy loop might be backtracked into.  That state is then dutifully popped off when unwinding the loop due to failure to match. However, if the loop successfully matches its maximum number of times but still fails because of a failure after the lazy loop, the state still needs to be popped off the stack, but isn't. This fixes that.

* Add a few more test variations

---------

Co-authored-by: Stephen Toub <stoub@microsoft.com>
---
 .../gen/RegexGenerator.Emitter.cs             | 12 +++++++++
 .../Text/RegularExpressions/RegexCompiler.cs  | 26 +++++++++++++++++--
 .../FunctionalTests/Regex.Match.Tests.cs      |  5 ++++
 3 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs
index 19488703f07f7e..efe4f0e40b4390 100644
--- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs
+++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs
@@ -3770,6 +3770,17 @@ void EmitLazy(RegexNode node)
 
                         using (clause)
                         {
+                            // We're backtracking, which could either be to something prior to the lazy loop or to something
+                            // inside of the lazy loop.  If it's to something inside of the lazy loop, then either the loop
+                            // will eventually succeed or we'll eventually end up unwinding back through the iterations all
+                            // the way back to the loop not matching at all, in which case the state we first pushed on at the
+                            // beginning of the !isAtomic section will get popped off. But if here we're instead going to jump
+                            // to something prior to the lazy loop, then we need to pop off that state here.
+                            if (doneLabel == originalDoneLabel)
+                            {
+                                EmitAdd(writer, "stackpos", -entriesPerIteration);
+                            }
+
                             if (iterationMayBeEmpty)
                             {
                                 // If we saw empty, it must have been in the most recent iteration, as we wouldn't have
@@ -3777,6 +3788,7 @@ void EmitLazy(RegexNode node)
                                 // false prior to backtracking / undoing that iteration.
                                 writer.WriteLine($"{sawEmpty} = 0; // false");
                             }
+
                             Goto(doneLabel);
                         }
                     }
diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs
index 20ccc3afefcca6..fb710b26788732 100644
--- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs
+++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs
@@ -4075,6 +4075,8 @@ void EmitLazy(RegexNode node)
                     // Determine where to branch, either back to the lazy loop body to add an additional iteration,
                     // or to the last backtracking label.
 
+                    Label jumpToDone = DefineLabel();
+
                     if (iterationMayBeEmpty)
                     {
                         // if (sawEmpty != 0)
@@ -4093,7 +4095,7 @@ void EmitLazy(RegexNode node)
                         Ldc(0);
                         Stloc(sawEmpty!);
 
-                        BrFar(doneLabel);
+                        Br(jumpToDone);
                         MarkLabel(sawEmptyZero);
                     }
 
@@ -4102,12 +4104,32 @@ void EmitLazy(RegexNode node)
                         // if (iterationCount >= maxIterations) goto doneLabel;
                         Ldloc(iterationCount);
                         Ldc(maxIterations);
-                        BgeFar(doneLabel);
+                        Bge(jumpToDone);
                     }
 
                     // goto body;
                     BrFar(body);
 
+                    MarkLabel(jumpToDone);
+
+                    // We're backtracking, which could either be to something prior to the lazy loop or to something
+                    // inside of the lazy loop.  If it's to something inside of the lazy loop, then either the loop
+                    // will eventually succeed or we'll eventually end up unwinding back through the iterations all
+                    // the way back to the loop not matching at all, in which case the state we first pushed on at the
+                    // beginning of the !isAtomic section will get popped off. But if here we're instead going to jump
+                    // to something prior to the lazy loop, then we need to pop off that state here.
+                    if (doneLabel == originalDoneLabel)
+                    {
+                        // stackpos -= entriesPerIteration;
+                        Ldloc(stackpos);
+                        Ldc(entriesPerIteration);
+                        Sub();
+                        Stloc(stackpos);
+                    }
+
+                    // goto done;
+                    BrFar(doneLabel);
+
                     doneLabel = backtrack;
                     MarkLabel(skipBacktrack);
                 }
diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs
index 43bd39f8f36779..d09f45ac2064c4 100644
--- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs
+++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs
@@ -2374,6 +2374,11 @@ public static IEnumerable<object[]> AllMatches_TestData()
                 yield return new object[] { engine, "^(?:aaa|aa){1,5}?$", RegexOptions.None, "aaaaaaaa", new (int, int, string)[] { (0, 8, "aaaaaaaa") } };
                 yield return new object[] { engine, "^(?:aaa|aa){4}$", RegexOptions.None, "aaaaaaaa", new (int, int, string)[] { (0, 8, "aaaaaaaa") } };
                 yield return new object[] { engine, "^(?:aaa|aa){4}?$", RegexOptions.None, "aaaaaaaa", new (int, int, string)[] { (0, 8, "aaaaaaaa") } };
+                yield return new object[] { engine, "^((?:(xx?,xx?)|xx?,xx?>xx?,xx?)-?(x)??){1,2}$", RegexOptions.None, "xx,xx>xx,xx", new (int, int, string)[] { (0, 11, "xx,xx>xx,xx") } };
+                yield return new object[] { engine, "^((?:(xx?,xx?)|xx?,xx?>xx?,xx?)-?(x*)??){1,2}$", RegexOptions.None, "xx,xx>xx,xx", new (int, int, string)[] { (0, 11, "xx,xx>xx,xx") } };
+                yield return new object[] { engine, "^((?:(xx?,xx?)|xx?,xx?>xx?,xx?)-?(x+)??){1,2}$", RegexOptions.None, "xx,xx>xx,xx", new (int, int, string)[] { (0, 11, "xx,xx>xx,xx") } };
+                yield return new object[] { engine, "^((?:(x(x?),x(x?))|xx?,(x(x?)>x(x?)),(x((x))?))-?(x+?)??){1,2}$", RegexOptions.None, "xx,xx>xx,xx", new (int, int, string)[] { (0, 11, "xx,xx>xx,xx") } };
+                yield return new object[] { engine, "^(?:x|(x)??){2}$", RegexOptions.None, "x>", null };
 
                 // Mostly empty matches using unusual regexes consisting mostly of anchors only
                 yield return new object[] { engine, "^", RegexOptions.None, "", new (int, int, string)[] { (0, 0, "") } };

From b7fda9f36c2cd2a8cde7afdd4dd9670a6e9397d6 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 12 Feb 2024 12:16:33 -0800
Subject: [PATCH 33/36] Add ca-certificates to Mariner 2.0 deps (#98267)

Co-authored-by: Nikola Milosavljevic <nikolam@microsoft.com>
---
 .../dotnet-runtime-deps/dotnet-runtime-deps-cm.2.proj           | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/installer/pkg/sfx/installers/dotnet-runtime-deps/dotnet-runtime-deps-cm.2.proj b/src/installer/pkg/sfx/installers/dotnet-runtime-deps/dotnet-runtime-deps-cm.2.proj
index 52b410239d3be7..76315c4255ec16 100644
--- a/src/installer/pkg/sfx/installers/dotnet-runtime-deps/dotnet-runtime-deps-cm.2.proj
+++ b/src/installer/pkg/sfx/installers/dotnet-runtime-deps/dotnet-runtime-deps-cm.2.proj
@@ -5,6 +5,6 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <LinuxPackageDependency Include="openssl-libs;icu;krb5" />
+    <LinuxPackageDependency Include="openssl-libs;icu;krb5;ca-certificates" />
   </ItemGroup>
 </Project>

From 00c95a673bdc72cc8e903df4e0acb450f7ad1a9d Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 12 Feb 2024 13:03:15 -0800
Subject: [PATCH 34/36] [release/8.0-staging] Ensure that Vector512 uses the
 same patterns as Vector64/128/256 (#98115)

* Ensure that Vector512 uses the same patterns as Vector64/128/256

* Update src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs

Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>

---------

Co-authored-by: Tanner Gooding <tagoo@outlook.com>
Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>
---
 .../src/System/Runtime/Intrinsics/Vector512.cs   | 15 +++++----------
 .../tests/Vectors/Vector128Tests.cs              | 16 ++++++++++++++++
 .../tests/Vectors/Vector256Tests.cs              | 16 ++++++++++++++++
 .../tests/Vectors/Vector512Tests.cs              | 16 ++++++++++++++++
 .../tests/Vectors/Vector64Tests.cs               | 16 ++++++++++++++++
 5 files changed, 69 insertions(+), 10 deletions(-)

diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs
index 824440a5bf2a7b..9847a9fe0da476 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512.cs
@@ -483,8 +483,7 @@ public static void CopyTo<T>(this Vector512<T> vector, Span<T> destination)
                 ThrowHelper.ThrowArgumentException_DestinationTooShort();
             }
 
-            ref byte address = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(destination));
-            Unsafe.WriteUnaligned(ref address, vector);
+            Unsafe.WriteUnaligned(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(destination)), vector);
         }
 
         /// <summary>Creates a new <see cref="Vector512{T}" /> instance with all elements initialized to the specified value.</summary>
@@ -615,8 +614,7 @@ public static Vector512<T> Create<T>(T[] values)
                 ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException();
             }
 
-            ref byte address = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetArrayDataReference(values));
-            return Unsafe.ReadUnaligned<Vector512<T>>(ref address);
+            return Unsafe.ReadUnaligned<Vector512<T>>(ref Unsafe.As<T, byte>(ref values[0]));
         }
 
         /// <summary>Creates a new <see cref="Vector512{T}" /> from a given array.</summary>
@@ -636,8 +634,7 @@ public static Vector512<T> Create<T>(T[] values, int index)
                 ThrowHelper.ThrowArgumentOutOfRange_IndexMustBeLessOrEqualException();
             }
 
-            ref byte address = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetArrayDataReference(values));
-            return Unsafe.ReadUnaligned<Vector512<T>>(ref Unsafe.Add(ref address, index));
+            return Unsafe.ReadUnaligned<Vector512<T>>(ref Unsafe.As<T, byte>(ref values[index]));
         }
 
         /// <summary>Creates a new <see cref="Vector512{T}" /> from a given readonly span.</summary>
@@ -654,8 +651,7 @@ public static Vector512<T> Create<T>(ReadOnlySpan<T> values)
                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.values);
             }
 
-            ref byte address = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values));
-            return Unsafe.ReadUnaligned<Vector512<T>>(ref address);
+            return Unsafe.ReadUnaligned<Vector512<T>>(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)));
         }
 
         /// <summary>Creates a new <see cref="Vector512{Byte}" /> instance with each element initialized to the corresponding specified value.</summary>
@@ -2739,8 +2735,7 @@ public static bool TryCopyTo<T>(this Vector512<T> vector, Span<T> destination)
                 return false;
             }
 
-            ref byte address = ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(destination));
-            Unsafe.WriteUnaligned(ref address, vector);
+            Unsafe.WriteUnaligned(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(destination)), vector);
             return true;
         }
 
diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs
index cf1f6cec9be38d..0288e9b6b5408e 100644
--- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs
+++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector128Tests.cs
@@ -4517,6 +4517,22 @@ public void Vector128SingleEqualsNonCanonicalNaNTest()
             }
         }
 
+        [Fact]
+        public void Vector128SingleCreateFromArrayTest()
+        {
+            float[] array = [1.0f, 2.0f, 3.0f, 4.0f, 5.0f];
+            Vector128<float> vector = Vector128.Create(array);
+            Assert.Equal(Vector128.Create(1.0f, 2.0f, 3.0f, 4.0f), vector);
+        }
+
+        [Fact]
+        public void Vector128SingleCreateFromArrayOffsetTest()
+        {
+            float[] array = [1.0f, 2.0f, 3.0f, 4.0f, 5.0f];
+            Vector128<float> vector = Vector128.Create(array, 1);
+            Assert.Equal(Vector128.Create(2.0f, 3.0f, 4.0f, 5.0f), vector);
+        }
+
         [Fact]
         public void Vector128SingleCopyToTest()
         {
diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs
index 95c05c50310fe3..109e58da096688 100644
--- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs
+++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector256Tests.cs
@@ -5539,6 +5539,22 @@ public void Vector256SingleEqualsNonCanonicalNaNTest()
             }
         }
 
+        [Fact]
+        public void Vector256SingleCreateFromArrayTest()
+        {
+            float[] array = [1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f];
+            Vector256<float> vector = Vector256.Create(array);
+            Assert.Equal(Vector256.Create(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f), vector);
+        }
+
+        [Fact]
+        public void Vector256SingleCreateFromArrayOffsetTest()
+        {
+            float[] array = [1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f];
+            Vector256<float> vector = Vector256.Create(array, 1);
+            Assert.Equal(Vector256.Create(2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f), vector);
+        }
+
         [Fact]
         public void Vector256SingleCopyToTest()
         {
diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs
index 2b97f49d914981..0bc2b15c2aadc2 100644
--- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs
+++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector512Tests.cs
@@ -5016,6 +5016,22 @@ public void Vector512SingleEqualsNonCanonicalNaNTest()
             }
         }
 
+        [Fact]
+        public void Vector512SingleCreateFromArrayTest()
+        {
+            float[] array = [1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f];
+            Vector512<float> vector = Vector512.Create(array);
+            Assert.Equal(Vector512.Create(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f), vector);
+        }
+
+        [Fact]
+        public void Vector512SingleCreateFromArrayOffsetTest()
+        {
+            float[] array = [1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f];
+            Vector512<float> vector = Vector512.Create(array, 1);
+            Assert.Equal(Vector512.Create(2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f, 17.0f), vector);
+        }
+
         [Fact]
         public void Vector512SingleCopyToTest()
         {
diff --git a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs
index 46aed6abbb06a8..72293b224282b8 100644
--- a/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs
+++ b/src/libraries/System.Runtime.Intrinsics/tests/Vectors/Vector64Tests.cs
@@ -3937,6 +3937,22 @@ public void Vector64SingleEqualsNonCanonicalNaNTest()
             }
         }
 
+        [Fact]
+        public void Vector64SingleCreateFromArrayTest()
+        {
+            float[] array = [1.0f, 2.0f, 3.0f];
+            Vector64<float> vector = Vector64.Create(array);
+            Assert.Equal(Vector64.Create(1.0f, 2.0f), vector);
+        }
+
+        [Fact]
+        public void Vector64SingleCreateFromArrayOffsetTest()
+        {
+            float[] array = [1.0f, 2.0f, 3.0f];
+            Vector64<float> vector = Vector64.Create(array, 1);
+            Assert.Equal(Vector64.Create(2.0f, 3.0f), vector);
+        }
+
         [Fact]
         public void Vector64SingleCopyToTest()
         {

From c192fbadef5a315a796b5918b29baebd06157b74 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 12 Feb 2024 14:19:42 -0800
Subject: [PATCH 35/36] [release/8.0-staging] Implement faster RSA key check

Co-authored-by: Kevin Jones <kevin@vcsjones.com>
---
 .../apibridge.c                               |  23 ++
 .../apibridge.h                               |   4 +
 .../openssl_1_0_structs.h                     |  11 +-
 .../opensslshim.h                             |  35 +++
 .../osslcompat_111.h                          |   7 +
 .../pal_evp_pkey.c                            | 249 +++++++++++++++++-
 6 files changed, 317 insertions(+), 12 deletions(-)

diff --git a/src/native/libs/System.Security.Cryptography.Native/apibridge.c b/src/native/libs/System.Security.Cryptography.Native/apibridge.c
index bad65ee2b50211..5c8d05d17c74d4 100644
--- a/src/native/libs/System.Security.Cryptography.Native/apibridge.c
+++ b/src/native/libs/System.Security.Cryptography.Native/apibridge.c
@@ -442,6 +442,14 @@ void local_RSA_get0_crt_params(const RSA* rsa, const BIGNUM** dmp1, const BIGNUM
     }
 }
 
+int local_RSA_get_multi_prime_extra_count(const RSA* rsa)
+{
+    (void)rsa;
+    // OpenSSL before 1.1 does not support multi-prime RSA, so it implicitly
+    // has zero extra primes.
+    return 0;
+}
+
 int32_t local_RSA_set0_key(RSA* rsa, BIGNUM* n, BIGNUM* e, BIGNUM* d)
 {
     if (rsa == NULL)
@@ -909,4 +917,19 @@ int local_BN_is_zero(const BIGNUM* a)
     return a->top == 0;
 }
 
+int local_BN_is_one(const BIGNUM* a)
+{
+    return BN_abs_is_word(a, 1) && !a->neg;
+}
+
+int local_BN_abs_is_word(const BIGNUM *a, const BN_ULONG w)
+{
+    return ((a->top == 1) && (a->d[0] == w)) || ((w == 0) && (a->top == 0));
+}
+
+int local_BN_is_odd(const BIGNUM* a)
+{
+    return (a->top > 0) && (a->d[0] & 1);
+}
+
 #endif
diff --git a/src/native/libs/System.Security.Cryptography.Native/apibridge.h b/src/native/libs/System.Security.Cryptography.Native/apibridge.h
index 93cff0d2fd11ed..06bfa4c2fe8fb9 100644
--- a/src/native/libs/System.Security.Cryptography.Native/apibridge.h
+++ b/src/native/libs/System.Security.Cryptography.Native/apibridge.h
@@ -7,7 +7,10 @@
 #include "pal_types.h"
 
 int local_ASN1_TIME_to_tm(const ASN1_TIME* s, struct tm* tm);
+int local_BN_abs_is_word(const BIGNUM *a, const BN_ULONG w);
 int local_BN_is_zero(const BIGNUM* a);
+int local_BN_is_odd(const BIGNUM* a);
+int local_BN_is_one(const BIGNUM* a);
 int local_BIO_up_ref(BIO *a);
 const BIGNUM* local_DSA_get0_key(const DSA* dsa, const BIGNUM** pubKey, const BIGNUM** privKey);
 void local_DSA_get0_pqg(const DSA* dsa, const BIGNUM** p, const BIGNUM** q, const BIGNUM** g);
@@ -27,6 +30,7 @@ long local_OpenSSL_version_num(void);
 void local_RSA_get0_crt_params(const RSA* rsa, const BIGNUM** dmp1, const BIGNUM** dmq1, const BIGNUM** iqmp);
 void local_RSA_get0_factors(const RSA* rsa, const BIGNUM** p, const BIGNUM** q);
 void local_RSA_get0_key(const RSA* rsa, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d);
+int local_RSA_get_multi_prime_extra_count(const RSA* r);
 int32_t local_RSA_meth_get_flags(const RSA_METHOD* meth);
 int32_t local_RSA_set0_crt_params(RSA* rsa, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp);
 int32_t local_RSA_set0_factors(RSA* rsa, BIGNUM* p, BIGNUM* q);
diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl_1_0_structs.h b/src/native/libs/System.Security.Cryptography.Native/openssl_1_0_structs.h
index 486dbb902de3b3..f13fa7ba79d00c 100644
--- a/src/native/libs/System.Security.Cryptography.Native/openssl_1_0_structs.h
+++ b/src/native/libs/System.Security.Cryptography.Native/openssl_1_0_structs.h
@@ -185,10 +185,11 @@ struct bio_st
     int references;
 };
 
-struct bignum_st {
-    const void* _ignored1;
+struct bignum_st
+{
+    BN_ULONG *d;
     int top;
-    int _ignored2;
-    int _ignored3;
-    int _ignored4;
+    int dmax;
+    int neg;
+    int flags;
 };
diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h
index 0748e305d5ce0c..1f1b1851f098aa 100644
--- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h
+++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h
@@ -55,6 +55,9 @@
 #if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM
 
 // Remove problematic #defines
+#undef BN_abs_is_word
+#undef BN_is_odd
+#undef BN_is_one
 #undef BN_is_zero
 #undef SSL_get_state
 #undef SSL_is_init_finished
@@ -200,15 +203,28 @@ int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len);
     FALLBACK_FUNCTION(BIO_up_ref) \
     REQUIRED_FUNCTION(BIO_s_mem) \
     REQUIRED_FUNCTION(BIO_write) \
+    FALLBACK_FUNCTION(BN_abs_is_word) \
     REQUIRED_FUNCTION(BN_bin2bn) \
     REQUIRED_FUNCTION(BN_bn2bin) \
     REQUIRED_FUNCTION(BN_clear_free) \
+    REQUIRED_FUNCTION(BN_cmp) \
+    REQUIRED_FUNCTION(BN_div) \
     REQUIRED_FUNCTION(BN_dup) \
     REQUIRED_FUNCTION(BN_free) \
+    REQUIRED_FUNCTION(BN_gcd) \
+    FALLBACK_FUNCTION(BN_is_odd) \
+    FALLBACK_FUNCTION(BN_is_one) \
     FALLBACK_FUNCTION(BN_is_zero) \
+    REQUIRED_FUNCTION(BN_mod_inverse) \
+    REQUIRED_FUNCTION(BN_mod_mul) \
+    REQUIRED_FUNCTION(BN_mul) \
     REQUIRED_FUNCTION(BN_new) \
     REQUIRED_FUNCTION(BN_num_bits) \
     REQUIRED_FUNCTION(BN_set_word) \
+    REQUIRED_FUNCTION(BN_sub) \
+    REQUIRED_FUNCTION(BN_value_one) \
+    REQUIRED_FUNCTION(BN_CTX_new) \
+    REQUIRED_FUNCTION(BN_CTX_free) \
     LEGACY_FUNCTION(CRYPTO_add_lock) \
     REQUIRED_FUNCTION(CRYPTO_free) \
     REQUIRED_FUNCTION(CRYPTO_get_ex_new_index) \
@@ -474,6 +490,7 @@ int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len);
     REQUIRED_FUNCTION(RSA_free) \
     REQUIRED_FUNCTION(RSA_generate_key_ex) \
     REQUIRED_FUNCTION(RSA_get_method) \
+    FALLBACK_FUNCTION(RSA_get_multi_prime_extra_count) \
     FALLBACK_FUNCTION(RSA_get0_crt_params) \
     FALLBACK_FUNCTION(RSA_get0_factors) \
     FALLBACK_FUNCTION(RSA_get0_key) \
@@ -700,15 +717,28 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define BIO_up_ref BIO_up_ref_ptr
 #define BIO_s_mem BIO_s_mem_ptr
 #define BIO_write BIO_write_ptr
+#define BN_abs_is_word BN_abs_is_word_ptr
 #define BN_bin2bn BN_bin2bn_ptr
 #define BN_bn2bin BN_bn2bin_ptr
 #define BN_clear_free BN_clear_free_ptr
+#define BN_cmp BN_cmp_ptr
+#define BN_div BN_div_ptr
 #define BN_dup BN_dup_ptr
 #define BN_free BN_free_ptr
+#define BN_gcd BN_gcd_ptr
+#define BN_is_odd BN_is_odd_ptr
+#define BN_is_one BN_is_one_ptr
 #define BN_is_zero BN_is_zero_ptr
+#define BN_mod_inverse BN_mod_inverse_ptr
+#define BN_mod_mul BN_mod_mul_ptr
+#define BN_mul BN_mul_ptr
 #define BN_new BN_new_ptr
 #define BN_num_bits BN_num_bits_ptr
 #define BN_set_word BN_set_word_ptr
+#define BN_sub BN_sub_ptr
+#define BN_value_one BN_value_one_ptr
+#define BN_CTX_free BN_CTX_free_ptr
+#define BN_CTX_new BN_CTX_new_ptr
 #define CRYPTO_add_lock CRYPTO_add_lock_ptr
 #define CRYPTO_free CRYPTO_free_ptr
 #define CRYPTO_get_ex_new_index CRYPTO_get_ex_new_index_ptr
@@ -977,6 +1007,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define RSA_get0_factors RSA_get0_factors_ptr
 #define RSA_get0_key RSA_get0_key_ptr
 #define RSA_get_method RSA_get_method_ptr
+#define RSA_get_multi_prime_extra_count RSA_get_multi_prime_extra_count_ptr
 #define RSA_meth_get_flags RSA_meth_get_flags_ptr
 #define RSA_new RSA_new_ptr
 #define RSA_pkey_ctx_ctrl RSA_pkey_ctx_ctrl_ptr
@@ -1236,6 +1267,9 @@ FOR_ALL_OPENSSL_FUNCTIONS
 
 // Alias "future" API to the local_ version.
 #define ASN1_TIME_to_tm local_ASN1_TIME_to_tm
+#define BN_abs_is_word local_BN_abs_is_word
+#define BN_is_odd local_BN_is_odd
+#define BN_is_one local_BN_is_one
 #define BN_is_zero local_BN_is_zero
 #define BIO_up_ref local_BIO_up_ref
 #define DSA_get0_key local_DSA_get0_key
@@ -1253,6 +1287,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
 #define HMAC_CTX_free local_HMAC_CTX_free
 #define HMAC_CTX_new local_HMAC_CTX_new
 #define OpenSSL_version_num local_OpenSSL_version_num
+#define RSA_get_multi_prime_extra_count local_RSA_get_multi_prime_extra_count
 #define RSA_get0_crt_params local_RSA_get0_crt_params
 #define RSA_get0_factors local_RSA_get0_factors
 #define RSA_get0_key local_RSA_get0_key
diff --git a/src/native/libs/System.Security.Cryptography.Native/osslcompat_111.h b/src/native/libs/System.Security.Cryptography.Native/osslcompat_111.h
index 2581e7f8150682..a56becf4f85578 100644
--- a/src/native/libs/System.Security.Cryptography.Native/osslcompat_111.h
+++ b/src/native/libs/System.Security.Cryptography.Native/osslcompat_111.h
@@ -6,6 +6,9 @@
 #pragma once
 #include "pal_types.h"
 
+#undef BN_abs_is_word
+#undef BN_is_odd
+#undef BN_is_one
 #undef BN_is_zero
 #undef SSL_CTX_set_options
 #undef SSL_set_options
@@ -21,6 +24,9 @@ typedef struct stack_st OPENSSL_STACK;
 #define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L
 
 int ASN1_TIME_to_tm(const ASN1_TIME* s, struct tm* tm);
+int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w);
+int BN_is_odd(const BIGNUM* a);
+int BN_is_one(const BIGNUM* a);
 int BN_is_zero(const BIGNUM* a);
 int BIO_up_ref(BIO* a);
 const BIGNUM* DSA_get0_key(const DSA* dsa, const BIGNUM** pubKey, const BIGNUM** privKey);
@@ -52,6 +58,7 @@ const RSA_METHOD* RSA_PKCS1_OpenSSL(void);
 void RSA_get0_crt_params(const RSA* rsa, const BIGNUM** dmp1, const BIGNUM** dmq1, const BIGNUM** iqmp);
 void RSA_get0_factors(const RSA* rsa, const BIGNUM** p, const BIGNUM** q);
 void RSA_get0_key(const RSA* rsa, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d);
+int RSA_get_multi_prime_extra_count(const RSA* r);
 int32_t RSA_meth_get_flags(const RSA_METHOD* meth);
 int32_t RSA_pkey_ctx_ctrl(EVP_PKEY_CTX* ctx, int32_t optype, int32_t cmd, int32_t p1, void* p2);
 int32_t RSA_set0_crt_params(RSA* rsa, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp);
diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c
index 6cf59b97d057e8..80183b97a77c90 100644
--- a/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c
+++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c
@@ -89,7 +89,231 @@ int32_t CryptoNative_UpRefEvpPkey(EVP_PKEY* pkey)
     return EVP_PKEY_up_ref(pkey);
 }
 
-static bool CheckKey(EVP_PKEY* key, int32_t algId, int32_t (*check_func)(EVP_PKEY_CTX*))
+static bool Lcm(const BIGNUM* num1, const BIGNUM* num2, BN_CTX* ctx, BIGNUM* result)
+{
+    assert(result);
+
+    // lcm(num1, num2) = (num1 * num2) / gcd(num1, num2)
+    BIGNUM* mul = NULL;
+    BIGNUM* gcd = NULL;
+    bool ret = false;
+
+    if ((mul = BN_new()) == NULL ||
+        (gcd = BN_new()) == NULL ||
+        !BN_mul(mul, num1, num2, ctx) ||
+        !BN_gcd(gcd, num1, num2, ctx) ||
+        !BN_div(result, NULL, mul, gcd, ctx))
+    {
+        goto done;
+    }
+
+    ret = true;
+done:
+    BN_clear_free(mul);
+    BN_clear_free(gcd);
+    return ret;
+}
+
+static int32_t QuickRsaCheck(const RSA* rsa, bool isPublic)
+{
+    // This method does some lightweight key consistency checks on an RSA key to make sure all supplied values are
+    // sensible. This is not intended to be a strict key check that verifies a key conforms to any particular set
+    // of criteria or standards.
+
+    const BIGNUM* n = NULL;
+    const BIGNUM* e = NULL;
+    const BIGNUM* d = NULL;
+    const BIGNUM* p = NULL;
+    const BIGNUM* q = NULL;
+    const BIGNUM* dp = NULL;
+    const BIGNUM* dq = NULL;
+    const BIGNUM* inverseQ = NULL;
+    BN_CTX* ctx = NULL;
+
+    // x and y are scratch integers that receive the result of some operations.
+    BIGNUM* x = NULL;
+    BIGNUM* y = NULL;
+
+    // pM1 and qM1 are to hold p-1 and q-1, respectively. We need these values a couple of times, so don't waste time
+    // recomputing them in scratch integers.
+    BIGNUM* pM1 = NULL;
+    BIGNUM* qM1 = NULL;
+    int ret = 0;
+
+    RSA_get0_key(rsa, &n, &e, &d);
+
+    // Always need public parameters.
+    if (!n || !e)
+    {
+        ERR_PUT_error(ERR_LIB_RSA, 0, RSA_R_VALUE_MISSING, __FILE__, __LINE__);
+        goto done;
+    }
+
+    // Compatibility: We put this error for OpenSSL 1.0.2 and 1.1.x when the modulus is zero because OpenSSL did not
+    // handle this correctly. Continue to use the same error if the modulus is zero.
+    if (BN_is_zero(n))
+    {
+        ERR_put_error(ERR_LIB_EVP, 0, EVP_R_DECODE_ERROR, __FILE__, __LINE__);
+        goto done;
+    }
+
+    // OpenSSL has kept this value at 16,384 for all versions.
+    if (BN_num_bits(n) > OPENSSL_RSA_MAX_MODULUS_BITS)
+    {
+        ERR_PUT_error(ERR_LIB_RSA, 0, RSA_R_MODULUS_TOO_LARGE, __FILE__, __LINE__);
+        goto done;
+    }
+
+    // Exponent cannot be 1 and must be odd
+    if (BN_is_one(e) || !BN_is_odd(e))
+    {
+        ERR_PUT_error(ERR_LIB_RSA, 0, RSA_R_BAD_E_VALUE, __FILE__, __LINE__);
+        goto done;
+    }
+
+    // At this point everything that is public has been checked. Mark as successful and clean up.
+    if (isPublic)
+    {
+        ret = 1;
+        goto done;
+    }
+
+    // We do not support validating multi-prime RSA. Multi-prime RSA is not common. For these, we fall back to the
+    // OpenSSL key check.
+    if (RSA_get_multi_prime_extra_count(rsa) != 0)
+    {
+        ret = -1;
+        goto done;
+    }
+
+    // Get the private components now that we've moved on to checking the private parameters.
+    RSA_get0_factors(rsa, &p, &q);
+
+    // Need all the private parameters now. If we cannot get them, fall back to the OpenSSL key check so the provider
+    // or engine routine can be used.
+    if (!d || !p || !q)
+    {
+        ret = -1;
+        goto done;
+    }
+
+    // Check that d is less than n.
+    if (BN_cmp(d, n) >= 0)
+    {
+        ERR_put_error(ERR_LIB_EVP, 0, EVP_R_DECODE_ERROR, __FILE__, __LINE__);
+        goto done;
+    }
+
+    // Set up the scratch integers
+    if ((ctx = BN_CTX_new()) == NULL ||
+        (x = BN_new()) == NULL ||
+        (y = BN_new()) == NULL ||
+        (pM1 = BN_new()) == NULL ||
+        (qM1 = BN_new()) == NULL)
+    {
+        goto done;
+    }
+
+    // multiply p and q and put the result in x.
+    if (!BN_mul(x, p, q, ctx))
+    {
+        goto done;
+    }
+
+    // p * q == n
+    if (BN_cmp(x, n) != 0)
+    {
+        ERR_PUT_error(ERR_LIB_RSA, 0, RSA_R_N_DOES_NOT_EQUAL_P_Q, __FILE__, __LINE__);
+        goto done;
+    }
+
+    // Checking congruence of private parameters.
+    // de = 1 % lambda(n)
+    // lambda(n) = lcm(p-1, q-1)
+    // lambda(n) is known to be lambda(pq) already.
+    // pM1 = p-1
+    // qM1 = q-1
+    // x = lcm(pM1, qM1)
+    // Note that we are checking that these values have a valid relationship, not that the parameters
+    // are canonically correct. The d parameter (and subsequent derived parameters) may have more than
+    // one working value, but we do not check the the value is the "best" possible value.
+    if (!BN_sub(pM1, p, BN_value_one()) || !BN_sub(qM1, q, BN_value_one()) || !Lcm(pM1, qM1, ctx, x))
+    {
+        goto done;
+    }
+
+    // de % lambda(n)
+    // put the result in y
+    if (!BN_mod_mul(y, d, e, x, ctx))
+    {
+        goto done;
+    }
+
+    // Given de = 1 % lambda(n), de % lambda(n) should be one.
+    if (!BN_is_one(y))
+    {
+        ERR_PUT_error(ERR_LIB_RSA, 0, RSA_R_D_E_NOT_CONGRUENT_TO_1, __FILE__, __LINE__);
+        goto done;
+    }
+
+    // Move on to checking the CRT parameters. In compatibility with what OpenSSL does,
+    // these are optional and only check them if all are present.
+    RSA_get0_crt_params(rsa, &dp, &dq, &inverseQ);
+
+    if (dp && dq && inverseQ)
+    {
+        // Check dp = d % (p-1)
+        // compute d % (p-1) and put in x
+        if (!BN_div(NULL, x, d, pM1, ctx))
+        {
+            goto done;
+        }
+
+        if (BN_cmp(x, dp) != 0)
+        {
+            ERR_PUT_error(ERR_LIB_RSA, 0, RSA_R_DMP1_NOT_CONGRUENT_TO_D, __FILE__, __LINE__);
+            goto done;
+        }
+
+        // Check dq = d % (q-1)
+        // compute d % (q-1) and put in x
+        if (!BN_div(NULL, x, d, qM1, ctx))
+        {
+            goto done;
+        }
+
+        if (BN_cmp(x, dq) != 0)
+        {
+            ERR_PUT_error(ERR_LIB_RSA, 0, RSA_R_DMQ1_NOT_CONGRUENT_TO_D, __FILE__, __LINE__);
+            goto done;
+        }
+
+        // Check inverseQ = q^-1 % p
+        // Use mod_inverse and put the result in x.
+        if (!BN_mod_inverse(x, q, p, ctx))
+        {
+            goto done;
+        }
+
+        if (BN_cmp(x, inverseQ) != 0)
+        {
+            ERR_PUT_error(ERR_LIB_RSA, 0, RSA_R_IQMP_NOT_INVERSE_OF_Q, __FILE__, __LINE__);
+            goto done;
+        }
+    }
+
+    // If we made it to the end, everything looks good.
+    ret = 1;
+done:
+    if (x) BN_clear_free(x);
+    if (y) BN_clear_free(y);
+    if (pM1) BN_clear_free(pM1);
+    if (qM1) BN_clear_free(qM1);
+    if (ctx) BN_CTX_free(ctx);
+    return ret;
+}
+
+static bool CheckKey(EVP_PKEY* key, int32_t algId, bool isPublic, int32_t (*check_func)(EVP_PKEY_CTX*))
 {
     if (algId != NID_undef && EVP_PKEY_get_base_id(key) != algId)
     {
@@ -104,16 +328,27 @@ static bool CheckKey(EVP_PKEY* key, int32_t algId, int32_t (*check_func)(EVP_PKE
     {
         const RSA* rsa = EVP_PKEY_get0_RSA(key);
 
+        // If we can get the RSA object, use that for a faster path to validating the key that skips primality tests.
         if (rsa != NULL)
         {
-            const BIGNUM* modulus = NULL;
-            RSA_get0_key(rsa, &modulus, NULL, NULL);
+            //  0 = key check failed
+            //  1 = key check passed
+            // -1 = could not assess private key.
+            int32_t result = QuickRsaCheck(rsa, isPublic);
 
-            if (modulus != NULL && BN_is_zero(modulus))
+            if (result == 0)
             {
-                ERR_put_error(ERR_LIB_EVP, 0, EVP_R_DECODE_ERROR, __FILE__, __LINE__);
                 return false;
             }
+            if (result == 1)
+            {
+                return true;
+            }
+
+            // -1 falls though.
+            // If the fast check was indeterminate, fall though and use the OpenSSL routine.
+            // Clear out any errors we may have accumulated in our check.
+            ERR_clear_error();
         }
     }
 
@@ -149,7 +384,7 @@ EVP_PKEY* CryptoNative_DecodeSubjectPublicKeyInfo(const uint8_t* buf, int32_t le
 
     EVP_PKEY* key = d2i_PUBKEY(NULL, &buf, len);
 
-    if (key != NULL && !CheckKey(key, algId, EVP_PKEY_public_check))
+    if (key != NULL && !CheckKey(key, algId, true, EVP_PKEY_public_check))
     {
         EVP_PKEY_free(key);
         key = NULL;
@@ -175,7 +410,7 @@ EVP_PKEY* CryptoNative_DecodePkcs8PrivateKey(const uint8_t* buf, int32_t len, in
     EVP_PKEY* key = EVP_PKCS82PKEY(p8info);
     PKCS8_PRIV_KEY_INFO_free(p8info);
 
-    if (key != NULL && !CheckKey(key, algId, EVP_PKEY_check))
+    if (key != NULL && !CheckKey(key, algId, false, EVP_PKEY_check))
     {
         EVP_PKEY_free(key);
         key = NULL;

From 11a4ff1a98fc7607d0f4c2d1d04a43661f3caf64 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 12 Feb 2024 14:24:35 -0800
Subject: [PATCH 36/36] [release/8.0-staging] ServiceKey comparisons use Equals
 for matching (#96847)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* RemoveAllKeyed use Equals for matching

This brings RemoveAllKeyed in line with service resolution (ServiceProvider.GetRequiredKeyedService)

* Use equals for TryAdd and Replace

* Add packaging info to csproj

---------

Co-authored-by: Tommy Sørbråten <tommysor@gmail.com>
Co-authored-by: Steve Harter <steveharter@users.noreply.github.com>
---
 ...iceCollectionDescriptorExtensions.Keyed.cs |  2 +-
 .../ServiceCollectionDescriptorExtensions.cs  |  6 +-
 ...ns.DependencyInjection.Abstractions.csproj |  2 +
 ...iceCollectionKeyedServiceExtensionsTest.cs | 91 +++++++++++++++++++
 4 files changed, 97 insertions(+), 4 deletions(-)

diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs
index aad0b4ff2fe414..436f108e5eb5f2 100644
--- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs
+++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.Keyed.cs
@@ -401,7 +401,7 @@ public static IServiceCollection RemoveAllKeyed(this IServiceCollection collecti
             for (int i = collection.Count - 1; i >= 0; i--)
             {
                 ServiceDescriptor? descriptor = collection[i];
-                if (descriptor.ServiceType == serviceType && descriptor.ServiceKey == serviceKey)
+                if (descriptor.ServiceType == serviceType && object.Equals(descriptor.ServiceKey, serviceKey))
                 {
                     collection.RemoveAt(i);
                 }
diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs
index f2435dca6cfcee..2d000f17105832 100644
--- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs
+++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Extensions/ServiceCollectionDescriptorExtensions.cs
@@ -67,7 +67,7 @@ public static void TryAdd(
             for (int i = 0; i < count; i++)
             {
                 if (collection[i].ServiceType == descriptor.ServiceType
-                    && collection[i].ServiceKey == descriptor.ServiceKey)
+                    && object.Equals(collection[i].ServiceKey, descriptor.ServiceKey))
                 {
                     // Already added
                     return;
@@ -474,7 +474,7 @@ public static void TryAddEnumerable(
                 ServiceDescriptor service = services[i];
                 if (service.ServiceType == descriptor.ServiceType &&
                     service.GetImplementationType() == implementationType &&
-                    service.ServiceKey == descriptor.ServiceKey)
+                    object.Equals(service.ServiceKey, descriptor.ServiceKey))
                 {
                     // Already added
                     return;
@@ -532,7 +532,7 @@ public static IServiceCollection Replace(
             int count = collection.Count;
             for (int i = 0; i < count; i++)
             {
-                if (collection[i].ServiceType == descriptor.ServiceType && collection[i].ServiceKey == descriptor.ServiceKey)
+                if (collection[i].ServiceType == descriptor.ServiceType && object.Equals(collection[i].ServiceKey, descriptor.ServiceKey))
                 {
                     collection.RemoveAt(i);
                     break;
diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj
index 422c5bef17065a..134bae2b58535f 100644
--- a/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj
+++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj
@@ -4,6 +4,8 @@
     <TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.1;netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
     <EnableDefaultItems>true</EnableDefaultItems>
     <IsPackable>true</IsPackable>
+    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
+    <ServicingVersion>1</ServicingVersion>
     <PackageDescription>Abstractions for dependency injection.
 
 Commonly Used Types:
diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs
index 25b61065ef0ba3..6be7e22cce2c35 100644
--- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs
+++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/ServiceCollectionKeyedServiceExtensionsTest.cs
@@ -170,6 +170,7 @@ public static TheoryData TryAddImplementationTypeData
                     { collection => collection.TryAddKeyedTransient<IFakeService, FakeService>("key-2"), serviceType, "key-2", implementationType, ServiceLifetime.Transient },
                     { collection => collection.TryAddKeyedTransient<IFakeService>("key-3"), serviceType, "key-3", serviceType, ServiceLifetime.Transient },
                     { collection => collection.TryAddKeyedTransient(implementationType, "key-4"), implementationType, "key-4", implementationType, ServiceLifetime.Transient },
+                    { collection => collection.TryAddKeyedTransient(implementationType, 9), implementationType, 9, implementationType, ServiceLifetime.Transient },
 
                     { collection => collection.TryAddKeyedScoped(serviceType, "key-1", implementationType), serviceType, "key-1", implementationType, ServiceLifetime.Scoped },
                     { collection => collection.TryAddKeyedScoped<IFakeService, FakeService>("key-2"), serviceType, "key-2", implementationType, ServiceLifetime.Scoped },
@@ -325,6 +326,40 @@ public void TryAddEnumerable_DoesNotAddDuplicate(
             Assert.Equal(expectedLifetime, d.Lifetime);
         }
 
+        [Fact]
+        public void TryAddEnumerable_DoesNotAddDuplicateWhenKeyIsInt()
+        {
+            // Arrange
+            var collection = new ServiceCollection();
+            var descriptor1 = ServiceDescriptor.KeyedTransient<IFakeService, FakeService>(1);
+            collection.TryAddEnumerable(descriptor1);
+            var descriptor2 = ServiceDescriptor.KeyedTransient<IFakeService, FakeService>(1);
+
+            // Act
+            collection.TryAddEnumerable(descriptor2);
+
+            // Assert
+            var d = Assert.Single(collection);
+            Assert.Same(descriptor1, d);
+        }
+
+        [Fact]
+        public void TryAddEnumerable_DoesNotAddDuplicateWhenKeyIsString()
+        {
+            // Arrange
+            var collection = new ServiceCollection();
+            var descriptor1 = ServiceDescriptor.KeyedTransient<IFakeService, FakeService>("service1");
+            collection.TryAddEnumerable(descriptor1);
+            var descriptor2 = ServiceDescriptor.KeyedTransient<IFakeService, FakeService>("service1");
+
+            // Act
+            collection.TryAddEnumerable(descriptor2);
+
+            // Assert
+            var d = Assert.Single(collection);
+            Assert.Same(descriptor1, d);
+        }
+
         public static TheoryData TryAddEnumerableInvalidImplementationTypeData
         {
             get
@@ -412,6 +447,24 @@ public void Replace_ReplacesFirstServiceWithMatchingServiceType()
             Assert.Equal(new[] { descriptor2, descriptor3 }, collection);
         }
 
+        [Fact]
+        public void Replace_ReplacesFirstServiceWithMatchingServiceTypeWhenKeyIsInt()
+        {
+            // Arrange
+            var collection = new ServiceCollection();
+            var descriptor1 = new ServiceDescriptor(typeof(IFakeService), 1, typeof(FakeService), ServiceLifetime.Transient);
+            var descriptor2 = new ServiceDescriptor(typeof(IFakeService), 1, typeof(FakeService), ServiceLifetime.Transient);
+            collection.Add(descriptor1);
+            collection.Add(descriptor2);
+            var descriptor3 = new ServiceDescriptor(typeof(IFakeService), 1, typeof(FakeService), ServiceLifetime.Singleton);
+
+            // Act
+            collection.Replace(descriptor3);
+
+            // Assert
+            Assert.Equal(new[] { descriptor2, descriptor3 }, collection);
+        }
+
         [Fact]
         public void RemoveAll_RemovesAllServicesWithMatchingServiceType()
         {
@@ -431,6 +484,44 @@ public void RemoveAll_RemovesAllServicesWithMatchingServiceType()
             Assert.Equal(new[] { descriptor }, collection);
         }
 
+        private enum ServiceKeyEnum { First, Second }
+
+        [Fact]
+        public void RemoveAll_RemovesAllMatchingServicesWhenKeyIsEnum()
+        {
+            var descriptor = new ServiceDescriptor(typeof(IFakeService), ServiceKeyEnum.First, typeof(FakeService), ServiceLifetime.Transient);
+            var collection = new ServiceCollection
+            {
+                descriptor,
+                new ServiceDescriptor(typeof(IFakeService), ServiceKeyEnum.Second, typeof(FakeService), ServiceLifetime.Transient),
+                new ServiceDescriptor(typeof(IFakeService), ServiceKeyEnum.Second, typeof(FakeService), ServiceLifetime.Transient),
+            };
+
+            // Act
+            collection.RemoveAllKeyed<IFakeService>(ServiceKeyEnum.Second);
+
+            // Assert
+            Assert.Equal(new[] { descriptor }, collection);
+        }
+
+        [Fact]
+        public void RemoveAll_RemovesAllMatchingServicesWhenKeyIsInt()
+        {
+            var descriptor = new ServiceDescriptor(typeof(IFakeService), 1, typeof(FakeService), ServiceLifetime.Transient);
+            var collection = new ServiceCollection
+            {
+                descriptor,
+                new ServiceDescriptor(typeof(IFakeService), 2, typeof(FakeService), ServiceLifetime.Transient),
+                new ServiceDescriptor(typeof(IFakeService), 2, typeof(FakeService), ServiceLifetime.Transient),
+            };
+
+            // Act
+            collection.RemoveAllKeyed<IFakeService>(2);
+
+            // Assert
+            Assert.Equal(new[] { descriptor }, collection);
+        }
+
         public static TheoryData NullServiceKeyData
         {
             get
