diff --git a/NuGet.config b/NuGet.config
index 874a54ee27326c..a681bc250bc9ed 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -9,11 +9,7 @@
-
-
-
-
-
+
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 95c24b9f3675f5..b54cff26d4cff0 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -90,13 +90,13 @@
45dd3a73dd5b64b010c4251303b3664bb30df029
-
+
https://github.com/dotnet/emsdk
- 2fc2ffd960930318f33fcaa690cbdbc55d72f52d
+ 9a29abdd764a4de0f253ed368871877a47725247
-
+
https://github.com/dotnet/emsdk
- 2fc2ffd960930318f33fcaa690cbdbc55d72f52d
+ 9a29abdd764a4de0f253ed368871877a47725247
@@ -111,9 +111,9 @@
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
@@ -121,121 +121,121 @@
73f0850939d96131c28cf6ea6ee5aacb4da0083a
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
https://github.com/dotnet/llvm-project
@@ -334,9 +334,9 @@
https://github.com/dotnet/xharness
a417169d3ba558fd6daa522f04e686574bbce520
-
+
https://github.com/dotnet/arcade
- 61ae141d2bf3534619265c8f691fd55dc3e75147
+ da98edc4c3ea539f109ea320672136ceb32591a7
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
@@ -354,13 +354,13 @@
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
67613417f5e1af250e6ddfba79f8f2885d8e90fb
-
+
https://github.com/dotnet/hotreload-utils
- 3b7da338c73b31b943c5512dcf0e2f6dd75f601c
+ bc857c64c5c5f1fc73048261e8f471c3310224d2
-
+
https://github.com/dotnet/runtime-assets
- 3b165c269b12cc194f48fde6a1a7694bece8931b
+ ca6c46012f68934198ce0d303196c3ae179230f5
https://github.com/dotnet/roslyn
diff --git a/eng/Versions.props b/eng/Versions.props
index 55ce55ada067df..360490779f98a2 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -1,11 +1,11 @@
- 8.0.2
+ 8.0.3
8
0
- 2
+ 3
8.0.100
7.0.$([MSBuild]::Add($(PatchVersion),14))
6.0.$([MSBuild]::Add($([System.Version]::Parse('$(PackageVersionNet7)').Build),11))
@@ -87,21 +87,21 @@
8.0.100
- 8.0.0-beta.24059.4
- 8.0.0-beta.24059.4
- 8.0.0-beta.24059.4
- 8.0.0-beta.24059.4
- 8.0.0-beta.24059.4
- 2.5.1-beta.24059.4
- 8.0.0-beta.24059.4
- 8.0.0-beta.24059.4
- 8.0.0-beta.24059.4
- 8.0.0-beta.24059.4
- 8.0.0-beta.24059.4
- 8.0.0-beta.24059.4
- 8.0.0-beta.24059.4
- 8.0.0-beta.24059.4
- 8.0.0-beta.24059.4
+ 8.0.0-beta.24113.2
+ 8.0.0-beta.24113.2
+ 8.0.0-beta.24113.2
+ 8.0.0-beta.24113.2
+ 8.0.0-beta.24113.2
+ 2.5.1-beta.24113.2
+ 8.0.0-beta.24113.2
+ 8.0.0-beta.24113.2
+ 8.0.0-beta.24113.2
+ 8.0.0-beta.24113.2
+ 8.0.0-beta.24113.2
+ 8.0.0-beta.24113.2
+ 8.0.0-beta.24113.2
+ 8.0.0-beta.24113.2
+ 8.0.0-beta.24113.2
6.0.0-preview.1.102
@@ -126,7 +126,7 @@
4.5.1
7.0.0
5.0.0
- 4.8.5
+ 4.8.6
8.0.0
5.0.0
4.5.5
@@ -143,20 +143,20 @@
4.5.0
8.0.0-rc.1.23406.6
- 8.0.0-beta.24060.2
- 8.0.0-beta.24060.2
- 8.0.0-beta.24060.2
- 8.0.0-beta.24060.2
- 8.0.0-beta.24060.2
- 8.0.0-beta.24060.2
- 8.0.0-beta.24060.2
- 8.0.0-beta.24060.2
- 8.0.0-beta.24060.2
- 8.0.0-beta.24060.2
- 8.0.0-beta.24060.2
- 8.0.0-beta.24060.2
- 8.0.0-beta.24060.2
- 8.0.0-beta.24060.2
+ 8.0.0-beta.24108.4
+ 8.0.0-beta.24108.4
+ 8.0.0-beta.24108.4
+ 8.0.0-beta.24108.4
+ 8.0.0-beta.24108.4
+ 8.0.0-beta.24108.4
+ 8.0.0-beta.24108.4
+ 8.0.0-beta.24108.4
+ 8.0.0-beta.24108.4
+ 8.0.0-beta.24108.4
+ 8.0.0-beta.24108.4
+ 8.0.0-beta.24108.4
+ 8.0.0-beta.24108.4
+ 8.0.0-beta.24108.4
1.0.0-prerelease.23566.3
1.0.0-prerelease.23566.3
@@ -186,7 +186,7 @@
8.0.0-prerelease.24060.1
8.0.0-prerelease.24060.1
8.0.0-prerelease.24060.1
- 8.0.0-alpha.0.24060.1
+ 8.0.0-alpha.0.24072.2
2.4.2
1.0.0
2.4.5
@@ -219,7 +219,7 @@
8.0.0-rtm.23523.2
- 2.2.3
+ 2.2.5-ci.444313
8.0.0-alpha.1.23527.1
16.0.5-alpha.1.23566.1
@@ -240,11 +240,10 @@
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
-->
- 8.0.2
+ 8.0.3
$(MicrosoftNETWorkloadEmscriptenCurrentManifest80100Version)
1.1.87-gba258badda
- 1.0.0-v3.14.0.5722
16.0.5-alpha.1.23566.1
16.0.5-alpha.1.23566.1
diff --git a/eng/common/post-build/publish-using-darc.ps1 b/eng/common/post-build/publish-using-darc.ps1
index 1e779fec4dd1ea..5a3a32ea8d75b4 100644
--- a/eng/common/post-build/publish-using-darc.ps1
+++ b/eng/common/post-build/publish-using-darc.ps1
@@ -12,7 +12,7 @@ param(
try {
. $PSScriptRoot\post-build-utils.ps1
- $darc = Get-Darc
+ $darc = Get-Darc
$optionalParams = [System.Collections.ArrayList]::new()
@@ -46,7 +46,7 @@ try {
}
Write-Host 'done.'
-}
+}
catch {
Write-Host $_
Write-PipelineTelemetryError -Category 'PromoteBuild' -Message "There was an error while trying to publish build '$BuildId' to default channels."
diff --git a/eng/common/templates/job/publish-build-assets.yml b/eng/common/templates/job/publish-build-assets.yml
index fa5446c093dd11..8ec0151def21a8 100644
--- a/eng/common/templates/job/publish-build-assets.yml
+++ b/eng/common/templates/job/publish-build-assets.yml
@@ -58,7 +58,7 @@ jobs:
demands: Cmd
# If it's not devdiv, it's dnceng
${{ if ne(variables['System.TeamProject'], 'DevDiv') }}:
- name: $(DncEngInternalBuildPool)
+ name: NetCore1ESPool-Publishing-Internal
demands: ImageOverride -equals windows.vs2019.amd64
steps:
@@ -71,7 +71,7 @@ jobs:
checkDownloadedFiles: true
condition: ${{ parameters.condition }}
continueOnError: ${{ parameters.continueOnError }}
-
+
- task: NuGetAuthenticate@1
- task: PowerShell@2
@@ -86,7 +86,7 @@ jobs:
/p:OfficialBuildId=$(Build.BuildNumber)
condition: ${{ parameters.condition }}
continueOnError: ${{ parameters.continueOnError }}
-
+
- task: powershell@2
displayName: Create ReleaseConfigs Artifact
inputs:
@@ -95,7 +95,7 @@ jobs:
Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value $(BARBuildId)
Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value "$(DefaultChannels)"
Add-Content -Path "$(Build.StagingDirectory)/ReleaseConfigs.txt" -Value $(IsStableBuild)
-
+
- task: PublishBuildArtifacts@1
displayName: Publish ReleaseConfigs Artifact
inputs:
@@ -121,7 +121,7 @@ jobs:
- task: PublishBuildArtifacts@1
displayName: Publish SymbolPublishingExclusionsFile Artifact
- condition: eq(variables['SymbolExclusionFile'], 'true')
+ condition: eq(variables['SymbolExclusionFile'], 'true')
inputs:
PathtoPublish: '$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt'
PublishLocation: Container
@@ -137,7 +137,7 @@ jobs:
displayName: Publish Using Darc
inputs:
filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1
- arguments: -BuildId $(BARBuildId)
+ arguments: -BuildId $(BARBuildId)
-PublishingInfraVersion 3
-AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)'
-MaestroToken '$(MaestroApiAccessToken)'
@@ -148,4 +148,4 @@ jobs:
- ${{ if eq(parameters.enablePublishBuildArtifacts, 'true') }}:
- template: /eng/common/templates/steps/publish-logs.yml
parameters:
- JobLabel: 'Publish_Artifacts_Logs'
+ JobLabel: 'Publish_Artifacts_Logs'
diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml
index 3f74abf7ce0f8a..aba44a25a33878 100644
--- a/eng/common/templates/post-build/post-build.yml
+++ b/eng/common/templates/post-build/post-build.yml
@@ -39,7 +39,7 @@ parameters:
displayName: Enable NuGet validation
type: boolean
default: true
-
+
- name: publishInstallersAndChecksums
displayName: Publish installers and checksums
type: boolean
@@ -131,8 +131,8 @@ stages:
displayName: Validate
inputs:
filePath: $(Build.SourcesDirectory)/eng/common/post-build/nuget-validation.ps1
- arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/
- -ToolDestinationPath $(Agent.BuildDirectory)/Extract/
+ arguments: -PackagesPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/
+ -ToolDestinationPath $(Agent.BuildDirectory)/Extract/
- job:
displayName: Signing Validation
@@ -221,9 +221,9 @@ stages:
displayName: Validate
inputs:
filePath: $(Build.SourcesDirectory)/eng/common/post-build/sourcelink-validation.ps1
- arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/
- -ExtractPath $(Agent.BuildDirectory)/Extract/
- -GHRepoName $(Build.Repository.Name)
+ arguments: -InputPath $(Build.ArtifactStagingDirectory)/BlobArtifacts/
+ -ExtractPath $(Agent.BuildDirectory)/Extract/
+ -GHRepoName $(Build.Repository.Name)
-GHCommit $(Build.SourceVersion)
-SourcelinkCliVersion $(SourceLinkCLIVersion)
continueOnError: true
@@ -258,7 +258,7 @@ stages:
demands: Cmd
# If it's not devdiv, it's dnceng
${{ else }}:
- name: $(DncEngInternalBuildPool)
+ name: NetCore1ESPool-Publishing-Internal
demands: ImageOverride -equals windows.vs2019.amd64
steps:
- template: setup-maestro-vars.yml
@@ -272,7 +272,7 @@ stages:
displayName: Publish Using Darc
inputs:
filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1
- arguments: -BuildId $(BARBuildId)
+ arguments: -BuildId $(BARBuildId)
-PublishingInfraVersion ${{ parameters.publishingInfraVersion }}
-AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)'
-MaestroToken '$(MaestroApiAccessToken)'
diff --git a/eng/common/templates/variables/pool-providers.yml b/eng/common/templates/variables/pool-providers.yml
index 9cc5c550d3b36f..d236f9fdbb153b 100644
--- a/eng/common/templates/variables/pool-providers.yml
+++ b/eng/common/templates/variables/pool-providers.yml
@@ -1,15 +1,15 @@
-# Select a pool provider based off branch name. Anything with branch name containing 'release' must go into an -Svc pool,
+# Select a pool provider based off branch name. Anything with branch name containing 'release' must go into an -Svc pool,
# otherwise it should go into the "normal" pools. This separates out the queueing and billing of released branches.
-# Motivation:
+# Motivation:
# Once a given branch of a repository's output has been officially "shipped" once, it is then considered to be COGS
# (Cost of goods sold) and should be moved to a servicing pool provider. This allows both separation of queueing
# (allowing release builds and main PR builds to not intefere with each other) and billing (required for COGS.
-# Additionally, the pool provider name itself may be subject to change when the .NET Core Engineering Services
-# team needs to move resources around and create new and potentially differently-named pools. Using this template
+# Additionally, the pool provider name itself may be subject to change when the .NET Core Engineering Services
+# team needs to move resources around and create new and potentially differently-named pools. Using this template
# file from an Arcade-ified repo helps guard against both having to update one's release/* branches and renaming.
-# How to use:
+# How to use:
# This yaml assumes your shipped product branches use the naming convention "release/..." (which many do).
# If we find alternate naming conventions in broad usage it can be added to the condition below.
#
@@ -54,4 +54,4 @@ variables:
False,
'NetCore1ESPool-Internal'
)
- ]
\ No newline at end of file
+ ]
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/global.json b/global.json
index 13f92203054630..c987cd4bc00e7d 100644
--- a/global.json
+++ b/global.json
@@ -8,9 +8,9 @@
"dotnet": "8.0.101"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24059.4",
- "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.24059.4",
- "Microsoft.DotNet.SharedFramework.Sdk": "8.0.0-beta.24059.4",
+ "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24113.2",
+ "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.24113.2",
+ "Microsoft.DotNet.SharedFramework.Sdk": "8.0.0-beta.24113.2",
"Microsoft.Build.NoTargets": "3.7.0",
"Microsoft.Build.Traversal": "3.4.0",
"Microsoft.NET.Sdk.IL": "8.0.0-rc.1.23406.6"
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");
}
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/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/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/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
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(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(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(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..fa60633afbc233 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(shiftAmount));
+ }
+ else
+ {
+ arg1VN = VNForLongCon(static_cast(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(shiftAmount));
+ }
+ else
+ {
+ arg1VN = VNForLongCon(static_cast(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(shiftAmount));
+ }
+ else
+ {
+ arg1VN = VNForLongCon(static_cast(shiftAmount));
+ }
+ }
+#endif // TARGET_XARCH
+
return EvaluateBinarySimd(this, GT_RSZ, /* scalar */ false, type, baseType, arg0VN, arg1VN);
}
@@ -7734,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/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.
+
+
+
+
+
+
+ <_XcodeVersion>$([System.Text.RegularExpressions.Regex]::Match($(_XcodeVersionString), '[1-9]\d*'))
+
+
+
+
+
+
<_CommandProbe>command -v
<_CommandProbe Condition="$([MSBuild]::IsOSPlatform('Windows'))">where /Q
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 @@
+
+
+
+
+
+
+ <_XcodeVersion>$([System.Text.RegularExpressions.Regex]::Match($(_XcodeVersionString), '[1-9]\d*'))
+
+
+
+
+
+
$(_CC_LDFLAGS.SubString(0, $(_CC_LDFLAGS.IndexOf(';'))))
<_LDFLAGS>$(_CC_LDFLAGS.SubString($([MSBuild]::Add($(_CC_LDFLAGS.IndexOf(';')), 1))))
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
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/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/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 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 m_managedObjectComWrapperMap;
+ ManagedObjectComWrapperByIdMap* m_managedObjectComWrapperMap;
#endif // FEATURE_COMWRAPPERS
#ifdef FEATURE_OBJCMARSHAL
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 @@
+
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 @@
-
+
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 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/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 @@
$(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.1;netstandard2.0;$(NetFrameworkMinimum)
true
true
+ true
+ 1
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("key-2"), serviceType, "key-2", implementationType, ServiceLifetime.Transient },
{ collection => collection.TryAddKeyedTransient("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("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(1);
+ collection.TryAddEnumerable(descriptor1);
+ var descriptor2 = ServiceDescriptor.KeyedTransient(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("service1");
+ collection.TryAddEnumerable(descriptor1);
+ var descriptor2 = ServiceDescriptor.KeyedTransient("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(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(2);
+
+ // Assert
+ Assert.Equal(new[] { descriptor }, collection);
+ }
+
public static TheoryData NullServiceKeyData
{
get
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 @@
true
true
true
+ true
+ 1
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 @@
+//
+#nullable enable
+
+namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
+{
+ partial class GenericTypeWithAttribute
+ {
+ partial class Log
+ {
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")]
+ private static readonly global::System.Action __M0Callback =
+ global::Microsoft.Extensions.Logging.LoggerMessage.Define(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(A a, B b, C c, ILogger logger) => Log.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());
+ Assert.NotNull(type.GenericTypeParameters[1].GetCustomAttribute());
+ }
+
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 diagnostics = await RunGenerator(@"
+ partial class C
+ {
+ public partial class Nested
+ {
+ [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""M1"")]
+ static partial void M1(ILogger logger);
+ }
+ }
+ ");
+
+ Assert.Empty(diagnostics);
+ }
+
+ [Fact]
+ public async Task NestedTypeWithGenericParameterWithAttributeOK()
+ {
+ IReadOnlyList 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
+ {
+ 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 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(A a, B b, C c, ILogger logger) => Log.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
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs
index e9cce1c24d34d5..14c9685a4f511a 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs
@@ -1446,6 +1446,14 @@ private int WriteHeaderCollection(HttpRequestMessage request, HttpHeaders header
continue;
}
+ // Extended connect requests will use the response content stream for bidirectional communication.
+ // We will ignore any content set for such requests in Http2Stream.SendRequestBodyAsync, as it has no defined semantics.
+ // Drop the Content-Length header as well in the unlikely case it was set.
+ if (knownHeader == KnownHeaders.ContentLength && request.IsExtendedConnectRequest)
+ {
+ continue;
+ }
+
// For all other known headers, send them via their pre-encoded name and the associated value.
WriteBytes(knownHeader.Http2EncodedName, ref headerBuffer);
string? separator = null;
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs
index de66b7cfa103d2..d834679274b4a8 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs
@@ -105,7 +105,9 @@ public Http2Stream(HttpRequestMessage request, Http2Connection connection)
_headerBudgetRemaining = connection._pool.Settings.MaxResponseHeadersByteLength;
- if (_request.Content == null)
+ // Extended connect requests will use the response content stream for bidirectional communication.
+ // We will ignore any content set for such requests in SendRequestBodyAsync, as it has no defined semantics.
+ if (_request.Content == null || _request.IsExtendedConnectRequest)
{
_requestCompletionState = StreamCompletionState.Completed;
if (_request.IsExtendedConnectRequest)
@@ -173,7 +175,9 @@ public HttpResponseMessage GetAndClearResponse()
public async Task SendRequestBodyAsync(CancellationToken cancellationToken)
{
- if (_request.Content == null)
+ // Extended connect requests will use the response content stream for bidirectional communication.
+ // Ignore any content set for such requests, as it has no defined semantics.
+ if (_request.Content == null || _request.IsExtendedConnectRequest)
{
Debug.Assert(_requestCompletionState == StreamCompletionState.Completed);
return;
@@ -250,6 +254,7 @@ public async Task SendRequestBodyAsync(CancellationToken cancellationToken)
// and we also don't want to propagate any error to the caller, in particular for non-duplex scenarios.
Debug.Assert(_responseCompletionState == StreamCompletionState.Completed);
_requestCompletionState = StreamCompletionState.Completed;
+ Debug.Assert(!ConnectProtocolEstablished);
Complete();
return;
}
@@ -261,6 +266,7 @@ public async Task SendRequestBodyAsync(CancellationToken cancellationToken)
_requestCompletionState = StreamCompletionState.Failed;
SendReset();
+ Debug.Assert(!ConnectProtocolEstablished);
Complete();
}
@@ -313,6 +319,7 @@ public async Task SendRequestBodyAsync(CancellationToken cancellationToken)
if (complete)
{
+ Debug.Assert(!ConnectProtocolEstablished);
Complete();
}
}
@@ -420,7 +427,17 @@ private void Cancel()
if (sendReset)
{
SendReset();
- Complete();
+
+ // Extended CONNECT notes:
+ //
+ // To prevent from calling it *twice*, Extended CONNECT stream's Complete() is only
+ // called from CloseResponseBody(), as CloseResponseBody() is *always* called
+ // from Extended CONNECT stream's Dispose().
+
+ if (!ConnectProtocolEstablished)
+ {
+ Complete();
+ }
}
}
@@ -810,7 +827,20 @@ public void OnHeadersComplete(bool endStream)
Debug.Assert(_responseCompletionState == StreamCompletionState.InProgress, $"Response already completed with state={_responseCompletionState}");
_responseCompletionState = StreamCompletionState.Completed;
- if (_requestCompletionState == StreamCompletionState.Completed)
+
+ // Extended CONNECT notes:
+ //
+ // To prevent from calling it *prematurely*, Extended CONNECT stream's Complete() is only
+ // called from CloseResponseBody(), as CloseResponseBody() is *only* called
+ // from Extended CONNECT stream's Dispose().
+ //
+ // Due to bidirectional streaming nature of the Extended CONNECT request,
+ // the *write side* of the stream can only be completed by calling Dispose().
+ //
+ // The streaming in both ways happens over the single "response" stream instance, which makes
+ // _requestCompletionState *not indicative* of the actual state of the write side of the stream.
+
+ if (_requestCompletionState == StreamCompletionState.Completed && !ConnectProtocolEstablished)
{
Complete();
}
@@ -871,7 +901,20 @@ public void OnResponseData(ReadOnlySpan buffer, bool endStream)
Debug.Assert(_responseCompletionState == StreamCompletionState.InProgress, $"Response already completed with state={_responseCompletionState}");
_responseCompletionState = StreamCompletionState.Completed;
- if (_requestCompletionState == StreamCompletionState.Completed)
+
+ // Extended CONNECT notes:
+ //
+ // To prevent from calling it *prematurely*, Extended CONNECT stream's Complete() is only
+ // called from CloseResponseBody(), as CloseResponseBody() is *only* called
+ // from Extended CONNECT stream's Dispose().
+ //
+ // Due to bidirectional streaming nature of the Extended CONNECT request,
+ // the *write side* of the stream can only be completed by calling Dispose().
+ //
+ // The streaming in both ways happens over the single "response" stream instance, which makes
+ // _requestCompletionState *not indicative* of the actual state of the write side of the stream.
+
+ if (_requestCompletionState == StreamCompletionState.Completed && !ConnectProtocolEstablished)
{
Complete();
}
@@ -1036,17 +1079,17 @@ public async Task ReadResponseHeadersAsync(CancellationToken cancellationToken)
Debug.Assert(_response != null && _response.Content != null);
// Start to process the response body.
var responseContent = (HttpConnectionResponseContent)_response.Content;
- if (emptyResponse)
+ if (ConnectProtocolEstablished)
+ {
+ responseContent.SetStream(new Http2ReadWriteStream(this, closeResponseBodyOnDispose: true));
+ }
+ else if (emptyResponse)
{
// If there are any trailers, copy them over to the response. Normally this would be handled by
// the response stream hitting EOF, but if there is no response body, we do it here.
MoveTrailersToResponseMessage(_response);
responseContent.SetStream(EmptyReadStream.Instance);
}
- else if (ConnectProtocolEstablished)
- {
- responseContent.SetStream(new Http2ReadWriteStream(this));
- }
else
{
responseContent.SetStream(new Http2ReadStream(this));
@@ -1309,8 +1352,25 @@ private async ValueTask SendDataAsync(ReadOnlyMemory buffer, CancellationT
}
}
+ // This method should only be called from Http2ReadWriteStream.Dispose()
private void CloseResponseBody()
{
+ // Extended CONNECT notes:
+ //
+ // Due to bidirectional streaming nature of the Extended CONNECT request,
+ // the *write side* of the stream can only be completed by calling Dispose()
+ // (which, for Extended CONNECT case, will in turn call CloseResponseBody())
+ //
+ // Similarly to QuicStream, disposal *gracefully* closes the write side of the stream
+ // (unless we've received RST_STREAM before) and *abortively* closes the read side
+ // of the stream (unless we've received EOS before).
+
+ if (ConnectProtocolEstablished && _resetException is null)
+ {
+ // Gracefully close the write side of the Extended CONNECT stream
+ _connection.LogExceptions(_connection.SendEndStreamAsync(StreamId));
+ }
+
// Check if the response body has been fully consumed.
bool fullyConsumed = false;
Debug.Assert(!Monitor.IsEntered(SyncObject));
@@ -1323,6 +1383,7 @@ private void CloseResponseBody()
}
// If the response body isn't completed, cancel it now.
+ // This includes aborting the read side of the Extended CONNECT stream.
if (!fullyConsumed)
{
Cancel();
@@ -1337,6 +1398,12 @@ private void CloseResponseBody()
lock (SyncObject)
{
+ if (ConnectProtocolEstablished)
+ {
+ // This should be the only place where Extended Connect stream is completed
+ Complete();
+ }
+
_responseBuffer.Dispose();
}
}
@@ -1430,10 +1497,7 @@ private enum StreamCompletionState : byte
private sealed class Http2ReadStream : Http2ReadWriteStream
{
- public Http2ReadStream(Http2Stream http2Stream) : base(http2Stream)
- {
- base.CloseResponseBodyOnDispose = true;
- }
+ public Http2ReadStream(Http2Stream http2Stream) : base(http2Stream, closeResponseBodyOnDispose: true) { }
public override bool CanWrite => false;
@@ -1482,12 +1546,13 @@ public class Http2ReadWriteStream : HttpBaseStream
private Http2Stream? _http2Stream;
private readonly HttpResponseMessage _responseMessage;
- public Http2ReadWriteStream(Http2Stream http2Stream)
+ public Http2ReadWriteStream(Http2Stream http2Stream, bool closeResponseBodyOnDispose = false)
{
Debug.Assert(http2Stream != null);
Debug.Assert(http2Stream._response != null);
_http2Stream = http2Stream;
_responseMessage = _http2Stream._response;
+ CloseResponseBodyOnDispose = closeResponseBodyOnDispose;
}
~Http2ReadWriteStream()
@@ -1503,7 +1568,7 @@ public Http2ReadWriteStream(Http2Stream http2Stream)
}
}
- protected bool CloseResponseBodyOnDispose { get; set; }
+ protected bool CloseResponseBodyOnDispose { get; private init; }
protected override void Dispose(bool disposing)
{
diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2ExtendedConnect.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2ExtendedConnect.cs
index 0ea6ae9e13f60b..cb1a15df14e774 100644
--- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2ExtendedConnect.cs
+++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2ExtendedConnect.cs
@@ -2,8 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Net.Test.Common;
+using System.Threading;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
@@ -31,6 +33,7 @@ public static IEnumerable