diff --git a/Directory.Build.props b/Directory.Build.props
index d957a798303ad..541ad0417e40d 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -10,13 +10,15 @@
- OSX
- FreeBSD
- NetBSD
- illumos
- Solaris
- Linux
- windows
+ <_hostOS>Linux
+ <_hostOS Condition="$([MSBuild]::IsOSPlatform('OSX'))">OSX
+ <_hostOS Condition="$([MSBuild]::IsOSPlatform('FREEBSD'))">FreeBSD
+ <_hostOS Condition="$([MSBuild]::IsOSPlatform('NETBSD'))">NetBSD
+ <_hostOS Condition="$([MSBuild]::IsOSPlatform('ILLUMOS'))">illumos
+ <_hostOS Condition="$([MSBuild]::IsOSPlatform('SOLARIS'))">Solaris
+ <_hostOS Condition="$([MSBuild]::IsOSPlatform('WINDOWS'))">windows
+ <_hostOS Condition="'$(TargetOS)' == 'Browser'">Browser
+ $(_hostOS)
true
@@ -115,16 +117,13 @@
the build system to use browser/ios/android as the _runtimeOS for produced package RIDs. -->
<_runtimeOS Condition="'$(TargetsMobile)' == 'true'">$(TargetOS.ToLowerInvariant())
- <_runtimeOSVersionIndex>$(_runtimeOS.IndexOfAny(".-0123456789"))
- <_runtimeOSFamily Condition="'$(_runtimeOSVersionIndex)' != '-1'">$(_runtimeOS.SubString(0, $(_runtimeOSVersionIndex)))
-
<_portableOS>linux
<_portableOS Condition="'$(_runtimeOS)' == 'linux-musl'">linux-musl
- <_portableOS Condition="$([MSBuild]::IsOSPlatform('OSX'))">osx
- <_portableOS Condition="'$(_runtimeOSFamily)' == 'win' or '$(_runtimeOS)' == 'win' or '$(TargetOS)' == 'windows'">win
- <_portableOS Condition="'$(_runtimeOSFamily)' == 'FreeBSD'">freebsd
- <_portableOS Condition="'$(_runtimeOSFamily)' == 'illumos'">illumos
- <_portableOS Condition="'$(_runtimeOSFamily)' == 'Solaris'">solaris
+ <_portableOS Condition="'$(_hostOS)' == 'OSX'">osx
+ <_portableOS Condition="'$(_runtimeOS)' == 'win' or '$(TargetOS)' == 'windows'">win
+ <_portableOS Condition="'$(_runtimeOS)' == 'FreeBSD' or '$(TargetOS)' == 'FreeBSD'">freebsd
+ <_portableOS Condition="'$(_runtimeOS)' == 'illumos' or '$(TargetOS)' == 'illumos'">illumos
+ <_portableOS Condition="'$(_runtimeOS)' == 'Solaris' or '$(TargetOS)' == 'Solaris'">solaris
<_portableOS Condition="'$(_runtimeOS)' == 'Browser'">browser
<_portableOS Condition="'$(_runtimeOS)' == 'maccatalyst'">maccatalyst
<_portableOS Condition="'$(_runtimeOS)' == 'ios'">ios
@@ -135,16 +134,12 @@
<_runtimeOS Condition="$(_runtimeOS.StartsWith('tizen'))">linux
<_runtimeOS Condition="'$(PortableBuild)' == 'true'">$(_portableOS)
-
-
- <_portableOS Condition="'$(TargetOS)' == 'Unix' and '$(_runtimeOSFamily)' != 'osx' and '$(_runtimeOSFamily)' != 'FreeBSD' and '$(_runtimeOS)' != 'linux-musl' and '$(_runtimeOSFamily)' != 'illumos' and '$(_runtimeOSFamily)' != 'Solaris'">linux
+ <_toolRuntimeRID Condition="'$(CrossBuild)' == 'true'">$(_hostOS.ToLowerInvariant)-$(_hostArch)
<_toolRuntimeRID Condition="'$(BuildingInsideVisualStudio)' == 'true'">$(_runtimeOS)-x64
<_toolRuntimeRID Condition="'$(_toolRuntimeRID)' == ''">$(_runtimeOS)-$(_hostArch)
-
- <_toolRuntimeRID Condition="'$(_runtimeOS)' == 'linux-musl' and $(TargetArchitecture.StartsWith('arm')) and !$(_hostArch.StartsWith('arm'))">linux-x64
<_toolRuntimeRID Condition="'$(_runtimeOS)' == 'browser'">linux-x64
@@ -164,26 +159,12 @@
$(_toolRuntimeRID)
<_packageRID Condition="'$(PortableBuild)' == 'true'">$(_portableOS)-$(TargetArchitecture)
+ <_packageRID Condition="'$(CrossBuild)' == 'true'">$(_hostOS.ToLowerInvariant)-$(TargetArchitecture)
$(_packageRID)
$(_runtimeOS)-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'windows'">win-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'OSX'">osx-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'Linux'">linux-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'FreeBSD'">freebsd-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'NetBSD'">netbsd-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'illumos'">illumos-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'Solaris'">solaris-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'MacCatalyst'">maccatalyst-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'iOS'">ios-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'iOSSimulator'">iossimulator-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'tvOS'">tvos-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'tvOSSimulator'">tvossimulator-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'Android'">android-$(TargetArchitecture)
- <_outputRID Condition="'$(TargetOS)' == 'Browser'">browser-$(TargetArchitecture)
-
$(PackageRID)
- $(_outputRID)
+ $(_portableOS)-$(TargetArchitecture)
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 0460647e6de5d..e390cc3dda320 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -54,7 +54,9 @@
$(RuntimePackageDisclaimer)
$(PackageDescription)
+
$(BeforePack);AddNETStandardCompatErrorFileForPackaging
+ AddNETStandardCompatErrorFileForPackaging;$(GenerateNuspecDependsOn)
@@ -76,8 +78,7 @@
+ Outputs="unused">
<_NETStandardCompatErrorFilePath>$(BaseIntermediateOutputPath)netstandardcompaterrors\%(NETStandardCompatError.Identity)\$(PackageId).targets
<_NETStandardCompatErrorFileTarget>NETStandardCompatError_$(PackageId.Replace('.', '_'))_$([System.String]::new('%(NETStandardCompatError.Supported)').Replace('.', '_'))
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 00d781b1461fe..8301d951525f2 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -8,7 +8,7 @@
https://github.com/dotnet/msquic
d7db669b70f4dd67ec001c192f9809c218cab88b
-
+
https://github.com/dotnet/emsdk
f5349765b7af1970c5b25cce4ed278544907cbe0
diff --git a/eng/Versions.props b/eng/Versions.props
index cdb313d0a0654..5240e72cbb270 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -180,7 +180,7 @@
11.1.0-alpha.1.21328.1
11.1.0-alpha.1.21328.1
- 6.0.0-preview.7.21330.1
- $(MicrosoftNETRuntimeEmscripten2023Nodewinx64Version)
+ 6.0.0-preview.7.21330.1
+ $(MicrosoftNETWorkloadEmscriptenManifest60100)
diff --git a/eng/pipelines/coreclr/perf.yml b/eng/pipelines/coreclr/perf.yml
index 0db890a8e572d..6fc0b85de73dd 100644
--- a/eng/pipelines/coreclr/perf.yml
+++ b/eng/pipelines/coreclr/perf.yml
@@ -237,6 +237,22 @@ jobs:
logicalmachine: 'perfpixel4a'
iosLlvmBuild: False
+ - template: /eng/pipelines/common/platform-matrix.yml
+ parameters:
+ jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml
+ buildConfig: release
+ runtimeFlavor: mono
+ platforms:
+ - Windows_x64
+ jobParameters:
+ testGroup: perf
+ runtimeType: iOSMono
+ projectFile: ios_scenarios.proj
+ runKind: ios_scenarios
+ runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml
+ logicalmachine: 'perfpixel4a'
+ iosLlvmBuild: True
+
# run mono microbenchmarks perf job
- template: /eng/pipelines/common/platform-matrix.yml
parameters:
diff --git a/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml b/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml
index 6bfd8637bfac5..65b6226093a10 100644
--- a/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml
+++ b/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml
@@ -44,6 +44,29 @@ steps:
archiveExtension: '.tar.gz'
archiveType: tar
tarCompression: gz
+ - script: rm -r -f $(Build.SourcesDirectory)/src/mono/sample/iOS/bin
+ workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS
+ displayName: Clean bindir
+ - script: make build-appbundle TARGET=iOS MONO_ARCH=arm64 MONO_CONFIG=Release AOT=True USE_LLVM=True
+ env:
+ DevTeamProvisioning: '-'
+ workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS
+ displayName: Build HelloiOS AOT sample app LLVM=True
+ - task: PublishBuildArtifacts@1
+ condition: succeededOrFailed()
+ displayName: 'Publish binlog'
+ inputs:
+ pathtoPublish: $(Build.SourcesDirectory)/src/mono/sample/iOS/msbuild.binlog
+ artifactName: ${{ parameters.artifactName }}
+ - template: /eng/pipelines/common/upload-artifact-step.yml
+ parameters:
+ rootFolder: $(Build.SourcesDirectory)/src/mono/sample/iOS/bin/ios-arm64/publish/app/HelloiOS/Release-iphoneos/HelloiOS.app
+ includeRootFolder: true
+ displayName: iOS Sample App LLVM
+ artifactName: iOSSampleAppLLVM
+ archiveExtension: '.tar.gz'
+ archiveType: tar
+ tarCompression: gz
- template: /eng/pipelines/common/upload-artifact-step.yml
parameters:
diff --git a/eng/pipelines/coreclr/templates/perf-job.yml b/eng/pipelines/coreclr/templates/perf-job.yml
index 3dee80bb370d2..59b7843925e04 100644
--- a/eng/pipelines/coreclr/templates/perf-job.yml
+++ b/eng/pipelines/coreclr/templates/perf-job.yml
@@ -165,7 +165,13 @@ jobs:
artifactFileName: 'iOSSampleAppNoLLVM.tar.gz'
artifactName: 'iOSSampleAppNoLLVM'
displayName: 'iOS Sample App NoLLVM'
-
+ - template: /eng/pipelines/common/download-artifact-step.yml
+ parameters:
+ unpackFolder: $(Build.SourcesDirectory)/iosHelloWorld/llvm
+ cleanUnpackFolder: false
+ artifactFileName: 'iOSSampleAppLLVM.tar.gz'
+ artifactName: 'iOSSampleAppLLVM'
+ displayName: 'iOS Sample App LLVM'
# Create Core_Root
- script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) $(buildConfig) $(archType) generatelayoutonly $(librariesOverrideArg)
diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml
index e031d0fa1ce16..de523bb2d99e6 100644
--- a/eng/pipelines/coreclr/templates/run-performance-job.yml
+++ b/eng/pipelines/coreclr/templates/run-performance-job.yml
@@ -23,7 +23,6 @@ parameters:
runKind: '' # required -- test category
logicalMachine: '' # required -- Used to specify a which pool of machines the test should run against
javascriptEngine: 'NoJS'
- iosLlvmBuild: 'False'
jobs:
- template: xplat-pipeline-job.yml
@@ -143,6 +142,6 @@ jobs:
displayName: Publish Logs
inputs:
targetPath: $(Build.SourcesDirectory)/artifacts/log
- artifactName: 'Performance_Run_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.runtimeType }}_${{ parameters.codeGenType }}_${{ parameters.runKind }}_${{ parameters.logicalMachine }}_${{ parameters.javascriptEngine }}_${{ parameters.pgoRunType }}_${{ parameters.iosLlvmBuild }}'
+ artifactName: 'Performance_Run_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.runtimeType }}_${{ parameters.codeGenType }}_${{ parameters.runKind }}_${{ parameters.logicalMachine }}_${{ parameters.javascriptEngine }}_${{ parameters.pgoRunType }}'
continueOnError: true
condition: always()
diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml
index 075807453ec3d..2fa6822205aa0 100644
--- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml
+++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml
@@ -157,6 +157,6 @@ jobs:
displayName: Publish Logs
inputs:
targetPath: $(Build.SourcesDirectory)/artifacts/log
- artifactName: 'Performance_Run_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.runtimeType }}_${{ parameters.codeGenType }}_${{ parameters.runKind }}'
+ artifactName: 'Performance_Run_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.runtimeType }}_${{ parameters.codeGenType }}_${{ parameters.runKind }}_$(iOSLlvmBuild)'
continueOnError: true
condition: always()
diff --git a/eng/testing/performance/performance-setup.ps1 b/eng/testing/performance/performance-setup.ps1
index 03aff42d25f78..078cad080a4b9 100644
--- a/eng/testing/performance/performance-setup.ps1
+++ b/eng/testing/performance/performance-setup.ps1
@@ -152,7 +152,12 @@ if ($iOSMono) {
{
mkdir $WorkItemDirectory
}
- Copy-Item -path "$SourceDirectory\iosHelloWorld\nollvm" $PayloadDirectory\iosHelloWorld\nollvm -Recurse
+ if($iOSLlvmBuild) {
+ Copy-Item -path "$SourceDirectory\iosHelloWorld\nollvm" $PayloadDirectory\iosHelloWorld\llvm -Recurse
+ } else {
+ Copy-Item -path "$SourceDirectory\iosHelloWorld\llvm" $PayloadDirectory\iosHelloWorld\nollvm -Recurse
+ }
+
$SetupArguments = $SetupArguments -replace $Architecture, 'arm64'
}
diff --git a/src/coreclr/.nuget/Directory.Build.props b/src/coreclr/.nuget/Directory.Build.props
index c8c468ebc609c..cff00f49e0e56 100644
--- a/src/coreclr/.nuget/Directory.Build.props
+++ b/src/coreclr/.nuget/Directory.Build.props
@@ -119,8 +119,8 @@
-
-
+
amd64
$(TargetArchitecture)
diff --git a/src/coreclr/.nuget/builds.targets b/src/coreclr/.nuget/builds.targets
index afab9019e11dc..4dd4d825baeb9 100644
--- a/src/coreclr/.nuget/builds.targets
+++ b/src/coreclr/.nuget/builds.targets
@@ -7,11 +7,11 @@
-
+
- <_projectsToBuild Include="@(Project)" Condition="'%(Project.PackageTargetRuntime)' == '$(PackageRID)'" />
+ <_projectsToBuild Include="@(Project)" Condition="'%(Project.PackageTargetRuntime)' == '$(OutputRid)'" />
@@ -22,4 +22,4 @@
-
\ No newline at end of file
+
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs
index 86dd19a5a7560..47b1bd454d80e 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Threading/ThreadPool.CoreCLR.cs
@@ -450,6 +450,7 @@ internal static bool PerformRuntimeSpecificGateActivities(int cpuUtilization)
private static extern unsafe bool PostQueuedCompletionStatus(NativeOverlapped* overlapped);
[CLSCompliant(false)]
+ [SupportedOSPlatform("windows")]
public static unsafe bool UnsafeQueueNativeOverlapped(NativeOverlapped* overlapped) =>
PostQueuedCompletionStatus(overlapped);
@@ -547,6 +548,7 @@ RegisteredWaitHandle registeredWaitHandle
);
[Obsolete("ThreadPool.BindHandle(IntPtr) has been deprecated. Please use ThreadPool.BindHandle(SafeHandle) instead.", false)]
+ [SupportedOSPlatform("windows")]
public static bool BindHandle(IntPtr osHandle)
{
return BindIOCompletionCallbackNative(osHandle);
diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp
index 955a7bba1e9a9..35b01ad27ec43 100644
--- a/src/coreclr/jit/gentree.cpp
+++ b/src/coreclr/jit/gentree.cpp
@@ -14458,46 +14458,26 @@ GenTree* Compiler::gtFoldExprConst(GenTree* tree)
break;
case GT_CAST:
+ f1 = forceCastToFloat(d1);
- if (tree->gtOverflow() &&
- ((op1->TypeIs(TYP_DOUBLE) && CheckedOps::CastFromDoubleOverflows(d1, tree->CastToType())) ||
- (op1->TypeIs(TYP_FLOAT) &&
- CheckedOps::CastFromFloatOverflows(forceCastToFloat(d1), tree->CastToType()))))
+ if ((op1->TypeIs(TYP_DOUBLE) && CheckedOps::CastFromDoubleOverflows(d1, tree->CastToType())) ||
+ (op1->TypeIs(TYP_FLOAT) && CheckedOps::CastFromFloatOverflows(f1, tree->CastToType())))
{
- return tree;
- }
+ // The conversion overflows. The ECMA spec says, in III 3.27, that
+ // "...if overflow occurs converting a floating point type to an integer, ...,
+ // the value returned is unspecified." However, it would at least be
+ // desirable to have the same value returned for casting an overflowing
+ // constant to an int as would be obtained by passing that constant as
+ // a parameter and then casting that parameter to an int type.
- assert(tree->TypeIs(genActualType(tree->CastToType())));
+ // Don't fold overflowing converions, as the value returned by
+ // JIT's codegen doesn't always match with the C compiler's cast result.
+ // We want the behavior to be the same with or without folding.
- if ((op1->TypeIs(TYP_FLOAT) && !_finite(forceCastToFloat(d1))) ||
- (op1->TypeIs(TYP_DOUBLE) && !_finite(d1)))
- {
- // The floating point constant is not finite. The ECMA spec says, in
- // III 3.27, that "...if overflow occurs converting a floating point type
- // to an integer, ..., the value returned is unspecified." However, it would
- // at least be desirable to have the same value returned for casting an overflowing
- // constant to an int as would obtained by passing that constant as a parameter
- // then casting that parameter to an int type. We will assume that the C compiler's
- // cast logic will yield the desired result (and trust testing to tell otherwise).
- // Cross-compilation is an issue here; if that becomes an important scenario, we should
- // capture the target-specific values of overflow casts to the various integral types as
- // constants in a target-specific function.
- CLANG_FORMAT_COMMENT_ANCHOR;
-
- // Don't fold conversions of +inf/-inf to integral value on all platforms
- // as the value returned by JIT helper doesn't match with the C compiler's cast result.
- // We want the behavior to be same with or without folding.
return tree;
}
- if (d1 <= -1.0 && varTypeIsUnsigned(tree->CastToType()))
- {
- // Don't fold conversions of these cases becasue the result is unspecified per ECMA spec
- // and the native math doing the fold doesn't match the run-time computation on all
- // platforms.
- // We want the behavior to be same with or without folding.
- return tree;
- }
+ assert(tree->TypeIs(genActualType(tree->CastToType())));
switch (tree->CastToType())
{
diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp
index e49ba55eca816..110730f15e6c5 100644
--- a/src/coreclr/jit/valuenum.cpp
+++ b/src/coreclr/jit/valuenum.cpp
@@ -3012,7 +3012,7 @@ ValueNum ValueNumStore::EvalCastForConstantArgs(var_types typ, VNFunc func, Valu
case TYP_FLOAT:
{
float arg0Val = GetConstantSingle(arg0VN);
- assert(!checkedCast || !CheckedOps::CastFromFloatOverflows(arg0Val, castToType));
+ assert(!CheckedOps::CastFromFloatOverflows(arg0Val, castToType));
switch (castToType)
{
@@ -3054,7 +3054,7 @@ ValueNum ValueNumStore::EvalCastForConstantArgs(var_types typ, VNFunc func, Valu
case TYP_DOUBLE:
{
double arg0Val = GetConstantDouble(arg0VN);
- assert(!checkedCast || !CheckedOps::CastFromDoubleOverflows(arg0Val, castToType));
+ assert(!CheckedOps::CastFromDoubleOverflows(arg0Val, castToType));
switch (castToType)
{
@@ -3322,26 +3322,32 @@ bool ValueNumStore::VNEvalShouldFold(var_types typ, VNFunc func, ValueNum arg0VN
}
}
- // Is this a checked cast that will always throw an exception?
- if (func == VNF_CastOvf)
+ // Is this a checked cast that will always throw an exception or one with an implementation-defined result?
+ if (VNFuncIsNumericCast(func))
{
- var_types castToType;
- bool fromUnsigned;
- GetCastOperFromVN(arg1VN, &castToType, &fromUnsigned);
var_types castFromType = TypeOfVN(arg0VN);
- switch (castFromType)
+ // By policy, we do not fold conversions from floating-point types that result in
+ // overflow, as the value the C++ compiler gives us does not always match our own codegen.
+ if ((func == VNF_CastOvf) || varTypeIsFloating(castFromType))
{
- case TYP_INT:
- return !CheckedOps::CastFromIntOverflows(GetConstantInt32(arg0VN), castToType, fromUnsigned);
- case TYP_LONG:
- return !CheckedOps::CastFromLongOverflows(GetConstantInt64(arg0VN), castToType, fromUnsigned);
- case TYP_FLOAT:
- return !CheckedOps::CastFromFloatOverflows(GetConstantSingle(arg0VN), castToType);
- case TYP_DOUBLE:
- return !CheckedOps::CastFromDoubleOverflows(GetConstantDouble(arg0VN), castToType);
- default:
- return false;
+ var_types castToType;
+ bool fromUnsigned;
+ GetCastOperFromVN(arg1VN, &castToType, &fromUnsigned);
+
+ switch (castFromType)
+ {
+ case TYP_INT:
+ return !CheckedOps::CastFromIntOverflows(GetConstantInt32(arg0VN), castToType, fromUnsigned);
+ case TYP_LONG:
+ return !CheckedOps::CastFromLongOverflows(GetConstantInt64(arg0VN), castToType, fromUnsigned);
+ case TYP_FLOAT:
+ return !CheckedOps::CastFromFloatOverflows(GetConstantSingle(arg0VN), castToType);
+ case TYP_DOUBLE:
+ return !CheckedOps::CastFromDoubleOverflows(GetConstantDouble(arg0VN), castToType);
+ default:
+ return false;
+ }
}
}
diff --git a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx
index c031f303e44e0..56fbb93adb924 100644
--- a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx
+++ b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx
@@ -169,7 +169,7 @@
Instruction set(s) to use for compilation
- Instruction set must not be '{0}' for this architecture and operating system
+ Instruction set '{0}' is not valid for this architecture and operating system
Instruction set(s) specified without also specifying input-bubble
diff --git a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj
index be3bd23767f70..4b1fc1af49908 100644
--- a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj
+++ b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj
@@ -7,7 +7,7 @@
$(TargetArchitecture)
arm
- $(_runtimeOS)-$(TargetArchitectureAppHost)
+ $(PackageRID)
diff --git a/src/coreclr/vm/eventtrace.cpp b/src/coreclr/vm/eventtrace.cpp
index 14bd22538d2b5..ac7be2a94398f 100644
--- a/src/coreclr/vm/eventtrace.cpp
+++ b/src/coreclr/vm/eventtrace.cpp
@@ -5045,7 +5045,7 @@ VOID ETW::InfoLog::RuntimeInformation(INT32 type)
{
PCWSTR szDtraceOutput1=W(""),szDtraceOutput2=W("");
UINT8 startupMode = 0;
- UINT startupFlags = 0;
+ UINT startupFlags = CorHost2::GetStartupFlags();
PathString dllPath;
UINT8 Sku = ETW::InfoLog::InfoStructs::CoreCLR;
diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Composite.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Composite.sfxproj
index 0cd26443fc557..a3f364815d63c 100644
--- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Composite.sfxproj
+++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Composite.sfxproj
@@ -32,6 +32,9 @@
+
+
+
diff --git a/src/installer/tests/HostActivation.Tests/MultiArchInstallLocation.cs b/src/installer/tests/HostActivation.Tests/MultiArchInstallLocation.cs
index c1b00cafd4e6a..3206cd74d1559 100644
--- a/src/installer/tests/HostActivation.Tests/MultiArchInstallLocation.cs
+++ b/src/installer/tests/HostActivation.Tests/MultiArchInstallLocation.cs
@@ -71,6 +71,56 @@ public void EnvironmentVariable_ArchSpecificDotnetRootIsUsedOverDotnetRoot()
.And.NotHaveStdErrContaining("Using environment variable DOTNET_ROOT=");
}
+ [Fact]
+ public void EnvironmentVariable_DotnetRootPathDoesNotExist()
+ {
+ var fixture = sharedTestState.PortableAppFixture
+ .Copy();
+
+ var appExe = fixture.TestProject.AppExe;
+ using (TestOnlyProductBehavior.Enable(appExe))
+ {
+ Command.Create(appExe)
+ .EnableTracingAndCaptureOutputs()
+ .DotNetRoot("non_existent_path")
+ .MultilevelLookup(false)
+ .EnvironmentVariable(
+ Constants.TestOnlyEnvironmentVariables.GloballyRegisteredPath,
+ sharedTestState.InstallLocation)
+ .Execute()
+ .Should().Pass()
+ .And.HaveStdErrContaining("Did not find [DOTNET_ROOT] directory [non_existent_path]")
+ // If DOTNET_ROOT points to a folder that does not exist, we fall back to the global install path.
+ .And.HaveUsedGlobalInstallLocation(sharedTestState.InstallLocation)
+ .And.HaveStdOutContaining("Hello World");
+ }
+ }
+
+ [Fact]
+ public void EnvironmentVariable_DotnetRootPathExistsButHasNoHost()
+ {
+ var fixture = sharedTestState.PortableAppFixture
+ .Copy();
+
+ var appExe = fixture.TestProject.AppExe;
+ var projDir = fixture.TestProject.ProjectDirectory;
+ using (TestOnlyProductBehavior.Enable(appExe))
+ {
+ Command.Create(appExe)
+ .EnableTracingAndCaptureOutputs()
+ .DotNetRoot(projDir)
+ .MultilevelLookup(false)
+ .EnvironmentVariable(
+ Constants.TestOnlyEnvironmentVariables.GloballyRegisteredPath,
+ sharedTestState.InstallLocation)
+ .Execute()
+ .Should().Fail()
+ .And.HaveUsedDotNetRootInstallLocation(projDir, fixture.CurrentRid)
+ // If DOTNET_ROOT points to a folder that exists we assume that there's a dotnet installation in it
+ .And.HaveStdErrContaining($"A fatal error occurred. The required library {RuntimeInformationExtensions.GetSharedLibraryFileNameForCurrentPlatform ("hostfxr")} could not be found.");
+ }
+ }
+
[Fact]
[SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")]
public void InstallLocationFile_ArchSpecificLocationIsPickedFirst()
@@ -173,6 +223,7 @@ public SharedTestState()
PortableAppFixture = fixture;
BaseDirectory = Path.GetDirectoryName(PortableAppFixture.SdkDotnet.GreatestVersionHostFxrFilePath);
+ InstallLocation = fixture.BuiltDotnet.BinPath;
}
public void Dispose()
diff --git a/src/libraries/Common/src/Interop/Windows/Ole32/Interop.IStream.COMWrappers.cs b/src/libraries/Common/src/Interop/Windows/Ole32/Interop.IStream.COMWrappers.cs
new file mode 100644
index 0000000000000..a3ff4e14fb7a7
--- /dev/null
+++ b/src/libraries/Common/src/Interop/Windows/Ole32/Interop.IStream.COMWrappers.cs
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+
+internal static partial class Interop
+{
+ internal static partial class Ole32
+ {
+ ///
+ /// IStream interface.
+ ///
+ ///
+ /// This interface explicitly doesn't use the built-in COM support, but instead is only used with ComWrappers.
+ ///
+ internal interface IStream
+ {
+ // pcbRead is optional
+ unsafe void Read(byte* pv, uint cb, uint* pcbRead);
+
+ // pcbWritten is optional
+ unsafe void Write(byte* pv, uint cb, uint* pcbWritten);
+
+ // SeekOrgin matches the native values, plibNewPosition is optional
+ unsafe void Seek(long dlibMove, SeekOrigin dwOrigin, ulong* plibNewPosition);
+
+ void SetSize(ulong libNewSize);
+
+ // pcbRead and pcbWritten are optional
+ unsafe HRESULT CopyTo(
+ IntPtr pstm,
+ ulong cb,
+ ulong* pcbRead,
+ ulong* pcbWritten);
+
+ void Commit(uint grfCommitFlags);
+
+ void Revert();
+
+ HRESULT LockRegion(
+ ulong libOffset,
+ ulong cb,
+ uint dwLockType);
+
+ HRESULT UnlockRegion(
+ ulong libOffset,
+ ulong cb,
+ uint dwLockType);
+
+ unsafe void Stat(
+ STATSTG* pstatstg,
+ STATFLAG grfStatFlag);
+
+ unsafe HRESULT Clone(IntPtr* ppstm);
+ }
+ }
+}
diff --git a/src/libraries/Common/src/Interop/Windows/Ole32/Interop.IStream.cs b/src/libraries/Common/src/Interop/Windows/Ole32/Interop.IStream.NoCOMWrappers.cs
similarity index 97%
rename from src/libraries/Common/src/Interop/Windows/Ole32/Interop.IStream.cs
rename to src/libraries/Common/src/Interop/Windows/Ole32/Interop.IStream.NoCOMWrappers.cs
index 6fdf6718f050a..b8907e5a33a9f 100644
--- a/src/libraries/Common/src/Interop/Windows/Ole32/Interop.IStream.cs
+++ b/src/libraries/Common/src/Interop/Windows/Ole32/Interop.IStream.NoCOMWrappers.cs
@@ -9,7 +9,7 @@ internal static partial class Interop
internal static partial class Ole32
{
///
- /// COM IStream interface.
+ /// COM IStream interface.
///
///
/// The definition in does not lend
diff --git a/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs
index ecff49e72016a..f41e4f48df578 100644
--- a/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs
+++ b/src/libraries/Common/tests/System/Net/Http/GenericLoopbackServer.cs
@@ -11,6 +11,7 @@
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Threading;
+using System.Diagnostics;
namespace System.Net.Test.Common
{
@@ -20,7 +21,7 @@ namespace System.Net.Test.Common
public abstract class LoopbackServerFactory
{
public abstract GenericLoopbackServer CreateServer(GenericLoopbackOptions options = null);
- public abstract Task CreateServerAsync(Func funcAsync, int millisecondsTimeout = 60_000, GenericLoopbackOptions options = null);
+ public abstract Task CreateServerAsync(Func funcAsync, int millisecondsTimeout = 60_000, GenericLoopbackOptions options = null, List<(int, long)> times = null, Stopwatch s = null);
public abstract Task CreateConnectionAsync(SocketWrapper socket, Stream stream, GenericLoopbackOptions options = null);
@@ -28,15 +29,52 @@ public abstract class LoopbackServerFactory
// Common helper methods
- public Task CreateClientAndServerAsync(Func clientFunc, Func serverFunc, int millisecondsTimeout = 60_000, GenericLoopbackOptions options = null)
+ public Task CreateClientAndServerAsync(Func clientFunc, Func serverFunc, int millisecondsTimeout = 60_000, GenericLoopbackOptions options = null, List<(int, long)> times = null, Stopwatch s = null)
{
- return CreateServerAsync(async (server, uri) =>
+ times?.Add((100, s.ElapsedMilliseconds));
+ var server = CreateServerAsync(async (server, uri) =>
{
- Task clientTask = clientFunc(uri);
- Task serverTask = serverFunc(server);
+ times?.Add((101, s.ElapsedMilliseconds));
+ Task clientTask = Task.Run(async () =>
+ {
+ times?.Add((300, s.ElapsedMilliseconds));
+ try
+ {
+ times?.Add((301, s.ElapsedMilliseconds));
+ await clientFunc(uri);
+ times?.Add((302, s.ElapsedMilliseconds));
+ }
+ catch
+ {
+ times?.Add((303, s.ElapsedMilliseconds));
+ throw;
+ }
+ times?.Add((304, s.ElapsedMilliseconds));
+ });
+ times?.Add((102, s.ElapsedMilliseconds));
+ Task serverTask = Task.Run(async () =>
+ {
+ times?.Add((400, s.ElapsedMilliseconds));
+ try
+ {
+ times?.Add((401, s.ElapsedMilliseconds));
+ await serverFunc(server);
+ times?.Add((402, s.ElapsedMilliseconds));
+ }
+ catch
+ {
+ times?.Add((403, s.ElapsedMilliseconds));
+ throw;
+ }
+ times?.Add((404, s.ElapsedMilliseconds));
+ });
+ times?.Add((103, s.ElapsedMilliseconds));
await new Task[] { clientTask, serverTask }.WhenAllOrAnyFailed().ConfigureAwait(false);
- }, options: options).WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout));
+ times?.Add((104, s.ElapsedMilliseconds));
+ }, options: options, times: times, s: s).WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout + 50000));
+ times?.Add((200, s.ElapsedMilliseconds));
+ return server;
}
}
diff --git a/src/libraries/Common/tests/System/Net/Http/Http2LoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/Http2LoopbackServer.cs
index 45df14c0380ea..1ed7f134d4d8b 100644
--- a/src/libraries/Common/tests/System/Net/Http/Http2LoopbackServer.cs
+++ b/src/libraries/Common/tests/System/Net/Http/Http2LoopbackServer.cs
@@ -2,6 +2,7 @@
// 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.Security;
using System.Net.Sockets;
@@ -220,12 +221,30 @@ private static Http2Options CreateOptions(GenericLoopbackOptions options)
return http2Options;
}
- public override async Task CreateServerAsync(Func funcAsync, int millisecondsTimeout = 60_000, GenericLoopbackOptions options = null)
+ public override async Task CreateServerAsync(Func funcAsync, int millisecondsTimeout = 60_000, GenericLoopbackOptions options = null, List<(int, long)> times = null, Stopwatch s = null)
{
- using (var server = CreateServer(options))
+ times?.Add((500, s.ElapsedMilliseconds));
+ var server = CreateServer(options);
+ times?.Add((501, s.ElapsedMilliseconds));
+ try
{
- await funcAsync(server, server.Address).WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout));
+ times?.Add((502, s.ElapsedMilliseconds));
+ await funcAsync(server, server.Address)
+ .WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout + 10000));
+ times?.Add((503, s.ElapsedMilliseconds));
+ }
+ catch
+ {
+ times?.Add((504, s.ElapsedMilliseconds));
+ throw;
+ }
+ finally
+ {
+ times?.Add((505, s.ElapsedMilliseconds));
+ server.Dispose();
+ times?.Add((506, s.ElapsedMilliseconds));
}
+ times?.Add((507, s.ElapsedMilliseconds));
}
public override Version Version => HttpVersion20.Value;
diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs
index 6e511915f047b..f3a8f7b482434 100644
--- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs
+++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs
@@ -94,7 +94,7 @@ public override GenericLoopbackServer CreateServer(GenericLoopbackOptions option
return new Http3LoopbackServer(_quicImplementationProvider, CreateOptions(options));
}
- public override async Task CreateServerAsync(Func funcAsync, int millisecondsTimeout = 60000, GenericLoopbackOptions options = null)
+ public override async Task CreateServerAsync(Func funcAsync, int millisecondsTimeout = 60000, GenericLoopbackOptions options = null, List<(int, long)> times = null, Stopwatch s = null)
{
using GenericLoopbackServer server = CreateServer(options);
await funcAsync(server, server.Address).WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout));
diff --git a/src/libraries/Common/tests/System/Net/Http/HttpAgnosticLoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/HttpAgnosticLoopbackServer.cs
index 88a8071153e6c..37b9cbf8af234 100644
--- a/src/libraries/Common/tests/System/Net/Http/HttpAgnosticLoopbackServer.cs
+++ b/src/libraries/Common/tests/System/Net/Http/HttpAgnosticLoopbackServer.cs
@@ -2,6 +2,7 @@
// 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.Security;
using System.Net.Sockets;
@@ -206,7 +207,7 @@ private static HttpAgnosticOptions CreateOptions(GenericLoopbackOptions options)
return httpOptions;
}
- public override async Task CreateServerAsync(Func funcAsync, int millisecondsTimeout = 60_000, GenericLoopbackOptions options = null)
+ public override async Task CreateServerAsync(Func funcAsync, int millisecondsTimeout = 60_000, GenericLoopbackOptions options = null, List<(int, long)> times = null, Stopwatch s = null)
{
using (var server = CreateServer(options))
{
diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs
index dbb1382c9aaf5..ab0b0a406eda4 100644
--- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs
+++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cookies.cs
@@ -151,34 +151,72 @@ await LoopbackServerFactory.CreateClientAndServerAsync(
[Fact]
public async Task GetAsync_AddMultipleCookieHeaders_CookiesSent()
{
- await LoopbackServerFactory.CreateClientAndServerAsync(
- async uri =>
- {
- using (HttpClient client = CreateHttpClient())
+ List<(int, long)> times = new List<(int, long)>();
+ Stopwatch s = Stopwatch.StartNew();
+
+ try
+ {
+ times.Add((0, s.ElapsedMilliseconds));
+
+ await LoopbackServerFactory.CreateClientAndServerAsync(
+ async uri =>
{
- var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri) { Version = UseVersion };
- requestMessage.Headers.Add("Cookie", "A=1");
- requestMessage.Headers.Add("Cookie", "B=2");
- requestMessage.Headers.Add("Cookie", "C=3");
+ times.Add((10, s.ElapsedMilliseconds));
+ HttpClient client = CreateHttpClient();
+ times.Add((11, s.ElapsedMilliseconds));
+ try
+ {
+ var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri) { Version = UseVersion };
+ requestMessage.Headers.Add("Cookie", "A=1");
+ requestMessage.Headers.Add("Cookie", "B=2");
+ requestMessage.Headers.Add("Cookie", "C=3");
+ times.Add((12, s.ElapsedMilliseconds));
- await client.SendAsync(TestAsync, requestMessage);
- }
- },
- async server =>
- {
- HttpRequestData requestData = await server.HandleRequestAsync();
+ await client.SendAsync(TestAsync, requestMessage)
+ .WaitAsync(TimeSpan.FromSeconds(10));
+
+ times.Add((13, s.ElapsedMilliseconds));
+ }
+ catch
+ {
+ times.Add((14, s.ElapsedMilliseconds));
+ throw;
+ }
+ finally
+ {
+ times.Add((15, s.ElapsedMilliseconds));
+ client.Dispose();
+ }
+ },
+ async server =>
+ {
+ times.Add((20, s.ElapsedMilliseconds));
+
+ HttpRequestData requestData = await server.HandleRequestAsync()
+ .WaitAsync(TimeSpan.FromSeconds(15));
+
+ times.Add((21, s.ElapsedMilliseconds));
// Multiple Cookie header values are treated as any other header values and are
// concatenated using ", " as the separator.
string cookieHeaderValue = requestData.GetSingleHeaderValue("Cookie");
- var cookieValues = cookieHeaderValue.Split(new string[] { ", " }, StringSplitOptions.None);
- Assert.Contains("A=1", cookieValues);
- Assert.Contains("B=2", cookieValues);
- Assert.Contains("C=3", cookieValues);
- Assert.Equal(3, cookieValues.Count());
- });
+ var cookieValues = cookieHeaderValue.Split(new string[] { ", " }, StringSplitOptions.None);
+ Assert.Contains("A=1", cookieValues);
+ Assert.Contains("B=2", cookieValues);
+ Assert.Contains("C=3", cookieValues);
+ Assert.Equal(3, cookieValues.Count());
+
+ times.Add((22, s.ElapsedMilliseconds));
+ },
+ millisecondsTimeout: 300_000);
+ }
+ catch (Exception ex)
+ {
+ times.Add((1, s.ElapsedMilliseconds));
+ throw new Exception(string.Join('\n', times.Select(t => $"{t.Item1,2} {t.Item2}")), ex);
+ }
}
private string GetCookieValue(HttpRequestData request)
diff --git a/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs
index 7594b4908010f..ae3a65e02b1a5 100644
--- a/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs
+++ b/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs
@@ -13,6 +13,7 @@
using System.Threading.Tasks;
using System.Net.WebSockets;
using Xunit;
+using System.Diagnostics;
namespace System.Net.Test.Common
{
@@ -1086,7 +1087,7 @@ public override GenericLoopbackServer CreateServer(GenericLoopbackOptions option
return loopbackServer;
}
- public override Task CreateServerAsync(Func funcAsync, int millisecondsTimeout = 60_000, GenericLoopbackOptions options = null)
+ public override Task CreateServerAsync(Func funcAsync, int millisecondsTimeout = 60_000, GenericLoopbackOptions options = null, List<(int, long)> times = null, Stopwatch s = null)
{
return LoopbackServer.CreateServerAsync((server, uri) => funcAsync(server, uri), options: CreateOptions(options));
}
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs
index 908efaf6afe32..16c16f482aadd 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs
@@ -370,7 +370,7 @@ private void GenLogMethod(LoggerMethod lm, string nestedIndentation)
GenDefineTypes(lm, brackets: true);
- _builder.Append(@$"({level}, new global::Microsoft.Extensions.Logging.EventId({lm.EventId}, {eventName}), ""{ConvertEndOfLineAndQuotationCharactersToEscapeForm(lm.Message)}"", true);
+ _builder.Append(@$"({level}, new global::Microsoft.Extensions.Logging.EventId({lm.EventId}, {eventName}), ""{ConvertEndOfLineAndQuotationCharactersToEscapeForm(lm.Message)}"", new global::Microsoft.Extensions.Logging.LogDefineOptions() {{ SkipEnabledCheck = true }});
");
}
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs
index ef9d46564ec61..1404880a97288 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs
@@ -48,6 +48,11 @@ public partial interface ISupportExternalScope
{
void SetScopeProvider(Microsoft.Extensions.Logging.IExternalScopeProvider scopeProvider);
}
+ public partial class LogDefineOptions
+ {
+ public LogDefineOptions() { }
+ public bool SkipEnabledCheck { get { throw null; } set { } }
+ }
public static partial class LoggerExtensions
{
public static System.IDisposable BeginScope(this Microsoft.Extensions.Logging.ILogger logger, string messageFormat, params object?[] args) { throw null; }
@@ -94,7 +99,7 @@ public static partial class LoggerFactoryExtensions
public static partial class LoggerMessage
{
public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString) { throw null; }
- public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, bool skipEnabledCheck) { throw null; }
+ public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, Microsoft.Extensions.Logging.LogDefineOptions? options) { throw null; }
public static System.Func DefineScope(string formatString) { throw null; }
public static System.Func DefineScope(string formatString) { throw null; }
public static System.Func DefineScope(string formatString) { throw null; }
@@ -103,17 +108,17 @@ public static partial class LoggerMessage
public static System.Func DefineScope(string formatString) { throw null; }
public static System.Func DefineScope(string formatString) { throw null; }
public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString) { throw null; }
- public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, bool skipEnabledCheck) { throw null; }
+ public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, Microsoft.Extensions.Logging.LogDefineOptions? options) { throw null; }
public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString) { throw null; }
- public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, bool skipEnabledCheck) { throw null; }
+ public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, Microsoft.Extensions.Logging.LogDefineOptions? options) { throw null; }
public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString) { throw null; }
- public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, bool skipEnabledCheck) { throw null; }
+ public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, Microsoft.Extensions.Logging.LogDefineOptions? options) { throw null; }
public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString) { throw null; }
- public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, bool skipEnabledCheck) { throw null; }
+ public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, Microsoft.Extensions.Logging.LogDefineOptions? options) { throw null; }
public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString) { throw null; }
- public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, bool skipEnabledCheck) { throw null; }
+ public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, Microsoft.Extensions.Logging.LogDefineOptions? options) { throw null; }
public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString) { throw null; }
- public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, bool skipEnabledCheck) { throw null; }
+ public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString, Microsoft.Extensions.Logging.LogDefineOptions? options) { throw null; }
}
[System.AttributeUsageAttribute(System.AttributeTargets.Method)]
public sealed partial class LoggerMessageAttribute : System.Attribute
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogDefineOptions.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogDefineOptions.cs
new file mode 100644
index 0000000000000..48016fcd2b781
--- /dev/null
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LogDefineOptions.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+namespace Microsoft.Extensions.Logging
+{
+ ///
+ /// Options for and its overloads
+ ///
+ public class LogDefineOptions
+ {
+ ///
+ /// Gets or sets the flag to skip IsEnabled check for the logging method.
+ ///
+ public bool SkipEnabledCheck { get; set; }
+ }
+}
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LoggerMessage.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LoggerMessage.cs
index ee40fc116bc38..db1ffdfd1d89f 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LoggerMessage.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/LoggerMessage.cs
@@ -128,7 +128,7 @@ public static Func DefineScopeThe named format string
/// A delegate which when invoked creates a log message.
public static Action Define(LogLevel logLevel, EventId eventId, string formatString)
- => Define(logLevel, eventId, formatString, skipEnabledCheck: false);
+ => Define(logLevel, eventId, formatString, options: null);
///
/// Creates a delegate which can be invoked for logging a message.
@@ -136,9 +136,9 @@ public static Func DefineScopeThe
/// The event id
/// The named format string
- /// Skips the check if the logging category is enabled.
+ /// The
/// A delegate which when invoked creates a log message.
- public static Action Define(LogLevel logLevel, EventId eventId, string formatString, bool skipEnabledCheck)
+ public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
{
LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, expectedNamedParameterCount: 0);
@@ -147,7 +147,7 @@ void Log(ILogger logger, Exception? exception)
logger.Log(logLevel, eventId, new LogValues(formatter), exception, LogValues.Callback);
}
- if (skipEnabledCheck)
+ if (options != null && options.SkipEnabledCheck)
{
return Log;
}
@@ -170,7 +170,7 @@ void Log(ILogger logger, Exception? exception)
/// The named format string
/// A delegate which when invoked creates a log message.
public static Action Define(LogLevel logLevel, EventId eventId, string formatString)
- => Define(logLevel, eventId, formatString, skipEnabledCheck: false);
+ => Define(logLevel, eventId, formatString, options: null);
///
/// Creates a delegate which can be invoked for logging a message.
@@ -179,9 +179,9 @@ void Log(ILogger logger, Exception? exception)
/// The
/// The event id
/// The named format string
- /// Skips the check if the logging category is enabled.
+ /// The
/// A delegate which when invoked creates a log message.
- public static Action Define(LogLevel logLevel, EventId eventId, string formatString, bool skipEnabledCheck)
+ public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
{
LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, expectedNamedParameterCount: 1);
@@ -190,7 +190,7 @@ void Log(ILogger logger, T1 arg1, Exception? exception)
logger.Log(logLevel, eventId, new LogValues(formatter, arg1), exception, LogValues.Callback);
}
- if (skipEnabledCheck)
+ if (options != null && options.SkipEnabledCheck)
{
return Log;
}
@@ -214,7 +214,7 @@ void Log(ILogger logger, T1 arg1, Exception? exception)
/// The named format string
/// A delegate which when invoked creates a log message.
public static Action Define(LogLevel logLevel, EventId eventId, string formatString)
- => Define(logLevel, eventId, formatString, skipEnabledCheck: false);
+ => Define(logLevel, eventId, formatString, options: null);
///
/// Creates a delegate which can be invoked for logging a message.
@@ -224,9 +224,9 @@ void Log(ILogger logger, T1 arg1, Exception? exception)
/// The
/// The event id
/// The named format string
- /// Skips the check if the logging category is enabled.
+ /// The
/// A delegate which when invoked creates a log message.
- public static Action Define(LogLevel logLevel, EventId eventId, string formatString, bool skipEnabledCheck)
+ public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
{
LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, expectedNamedParameterCount: 2);
@@ -235,7 +235,7 @@ void Log(ILogger logger, T1 arg1, T2 arg2, Exception? exception)
logger.Log(logLevel, eventId, new LogValues(formatter, arg1, arg2), exception, LogValues.Callback);
}
- if (skipEnabledCheck)
+ if (options != null && options.SkipEnabledCheck)
{
return Log;
}
@@ -260,7 +260,7 @@ void Log(ILogger logger, T1 arg1, T2 arg2, Exception? exception)
/// The named format string
/// A delegate which when invoked creates a log message.
public static Action Define(LogLevel logLevel, EventId eventId, string formatString)
- => Define(logLevel, eventId, formatString, skipEnabledCheck: false);
+ => Define(logLevel, eventId, formatString, options: null);
///
/// Creates a delegate which can be invoked for logging a message.
@@ -271,9 +271,9 @@ void Log(ILogger logger, T1 arg1, T2 arg2, Exception? exception)
/// The
/// The event id
/// The named format string
- /// Skips the check if the logging category is enabled.
+ /// The
/// A delegate which when invoked creates a log message.
- public static Action Define(LogLevel logLevel, EventId eventId, string formatString, bool skipEnabledCheck)
+ public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
{
LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, expectedNamedParameterCount: 3);
@@ -282,7 +282,7 @@ void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, Exception? exception)
logger.Log(logLevel, eventId, new LogValues(formatter, arg1, arg2, arg3), exception, LogValues.Callback);
}
- if (skipEnabledCheck)
+ if (options != null && options.SkipEnabledCheck)
{
return Log;
}
@@ -308,7 +308,7 @@ void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, Exception? exception)
/// The named format string
/// A delegate which when invoked creates a log message.
public static Action Define(LogLevel logLevel, EventId eventId, string formatString)
- => Define(logLevel, eventId, formatString, skipEnabledCheck: false);
+ => Define(logLevel, eventId, formatString, options: null);
///
/// Creates a delegate which can be invoked for logging a message.
@@ -320,9 +320,9 @@ void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, Exception? exception)
/// The
/// The event id
/// The named format string
- /// Skips the check if the logging category is enabled.
+ /// The
/// A delegate which when invoked creates a log message.
- public static Action Define(LogLevel logLevel, EventId eventId, string formatString, bool skipEnabledCheck)
+ public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
{
LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, expectedNamedParameterCount: 4);
@@ -331,7 +331,7 @@ void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, Exception? exceptio
logger.Log(logLevel, eventId, new LogValues(formatter, arg1, arg2, arg3, arg4), exception, LogValues.Callback);
}
- if (skipEnabledCheck)
+ if (options != null && options.SkipEnabledCheck)
{
return Log;
}
@@ -358,7 +358,7 @@ void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, Exception? exceptio
/// The named format string
/// A delegate which when invoked creates a log message.
public static Action Define(LogLevel logLevel, EventId eventId, string formatString)
- => Define(logLevel, eventId, formatString, skipEnabledCheck: false);
+ => Define(logLevel, eventId, formatString, options: null);
///
/// Creates a delegate which can be invoked for logging a message.
@@ -371,9 +371,9 @@ void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, Exception? exceptio
/// The
/// The event id
/// The named format string
- /// Skips the check if the logging category is enabled.
+ /// The
/// A delegate which when invoked creates a log message.
- public static Action Define(LogLevel logLevel, EventId eventId, string formatString, bool skipEnabledCheck)
+ public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
{
LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, expectedNamedParameterCount: 5);
@@ -382,7 +382,7 @@ void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, Exception?
logger.Log(logLevel, eventId, new LogValues(formatter, arg1, arg2, arg3, arg4, arg5), exception, LogValues.Callback);
}
- if (skipEnabledCheck)
+ if (options != null && options.SkipEnabledCheck)
{
return Log;
}
@@ -410,7 +410,7 @@ void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, Exception?
/// The named format string
/// A delegate which when invoked creates a log message.
public static Action Define(LogLevel logLevel, EventId eventId, string formatString)
- => Define(logLevel, eventId, formatString, skipEnabledCheck: false);
+ => Define(logLevel, eventId, formatString, options: null);
///
/// Creates a delegate which can be invoked for logging a message.
@@ -424,9 +424,9 @@ void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, Exception?
/// The
/// The event id
/// The named format string
- /// Skips the check if the logging category is enabled.
+ /// The
/// A delegate which when invoked creates a log message.
- public static Action Define(LogLevel logLevel, EventId eventId, string formatString, bool skipEnabledCheck)
+ public static Action Define(LogLevel logLevel, EventId eventId, string formatString, LogDefineOptions? options)
{
LogValuesFormatter formatter = CreateLogValuesFormatter(formatString, expectedNamedParameterCount: 6);
@@ -435,7 +435,7 @@ void Log(ILogger logger, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, E
logger.Log(logLevel, eventId, new LogValues(formatter, arg1, arg2, arg3, arg4, arg5, arg6), exception, LogValues.Callback);
}
- if (skipEnabledCheck)
+ if (options != null && options.SkipEnabledCheck)
{
return Log;
}
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClass.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClass.generated.txt
index 024e0464c715f..e10a678aef24c 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClass.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClass.generated.txt
@@ -17,7 +17,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses.NestedNamesp
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")]
private static readonly global::System.Action __M9Callback =
- global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(9, nameof(M9)), "M9", true);
+ global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(9, nameof(M9)), "M9", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")]
public static partial void M9(global::Microsoft.Extensions.Logging.ILogger logger)
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithSkipEnabledCheck.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithSkipEnabledCheck.generated.txt
index c4b242a0a9e17..6576bb4b394f1 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithSkipEnabledCheck.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithSkipEnabledCheck.generated.txt
@@ -7,7 +7,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")]
private static readonly global::System.Action __M0Callback =
- global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Information, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "Message: When using SkipEnabledCheck, the generated code skips logger.IsEnabled(logLevel) check before calling log. To be used when consumer has already guarded logger method in an IsEnabled check.", true);
+ global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Information, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "Message: When using SkipEnabledCheck, the generated code skips logger.IsEnabled(logLevel) check before calling log. To be used when consumer has already guarded logger method in an IsEnabled check.", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")]
public static partial void M0(global::Microsoft.Extensions.Logging.ILogger logger)
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithTwoParams.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithTwoParams.generated.txt
index ae5b89b74a4d4..5daee3ddd43a1 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithTwoParams.generated.txt
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithTwoParams.generated.txt
@@ -7,7 +7,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")]
private static readonly global::System.Action, global::System.Exception?> __M0Callback =
- global::Microsoft.Extensions.Logging.LoggerMessage.Define>(global::Microsoft.Extensions.Logging.LogLevel.Error, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0 {a1} {a2}", true);
+ global::Microsoft.Extensions.Logging.LoggerMessage.Define>(global::Microsoft.Extensions.Logging.LogLevel.Error, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0 {a1} {a2}", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true });
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")]
public static partial void M0(global::Microsoft.Extensions.Logging.ILogger logger, global::System.Int32 a1, global::System.Collections.Generic.IEnumerable a2)
diff --git a/src/libraries/Microsoft.Extensions.Logging/tests/Common/LoggerMessageTest.cs b/src/libraries/Microsoft.Extensions.Logging/tests/Common/LoggerMessageTest.cs
index 6422a7a188b86..a47ccc154fc6c 100644
--- a/src/libraries/Microsoft.Extensions.Logging/tests/Common/LoggerMessageTest.cs
+++ b/src/libraries/Microsoft.Extensions.Logging/tests/Common/LoggerMessageTest.cs
@@ -430,13 +430,13 @@ public void DefineAndDefineScope_ThrowsException_WhenFormatString_IsNull(Delegat
public static IEnumerable
- internal unsafe class DrawingComWrappers : ComWrappers
+ internal unsafe partial class DrawingCom : ComWrappers
{
private const int S_OK = (int)Interop.HRESULT.S_OK;
private static readonly Guid IID_IStream = new Guid(0x0000000C, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
private static readonly ComInterfaceEntry* s_wrapperEntry = InitializeComInterfaceEntry();
- internal static DrawingComWrappers Instance { get; } = new DrawingComWrappers();
+ internal static DrawingCom Instance { get; } = new DrawingCom();
- private DrawingComWrappers() { }
+ private DrawingCom() { }
private static ComInterfaceEntry* InitializeComInterfaceEntry()
{
@@ -31,7 +31,7 @@ private DrawingComWrappers() { }
IntPtr iStreamVtbl = IStreamVtbl.Create(fpQueryInterface, fpAddRef, fpRelease);
- ComInterfaceEntry* wrapperEntry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(DrawingComWrappers), sizeof(ComInterfaceEntry));
+ ComInterfaceEntry* wrapperEntry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(DrawingCom), sizeof(ComInterfaceEntry));
wrapperEntry->IID = IID_IStream;
wrapperEntry->Vtable = iStreamVtbl;
return wrapperEntry;
@@ -66,6 +66,27 @@ protected override void ReleaseObjects(IEnumerable objects)
throw new NotImplementedException();
}
+ internal static IStreamWrapper GetComWrapper(Interop.Ole32.IStream stream)
+ {
+ IntPtr streamWrapperPtr = Instance.GetOrCreateComInterfaceForObject(stream, CreateComInterfaceFlags.None);
+
+ Guid streamIID = IID_IStream;
+ int result = Marshal.QueryInterface(streamWrapperPtr, ref streamIID, out IntPtr streamPtr);
+
+ Marshal.Release(streamWrapperPtr);
+
+ ThrowExceptionForHR(result);
+
+ return new IStreamWrapper(streamPtr);
+ }
+
+ internal static void ThrowExceptionForHR(int errorCode)
+ {
+ // Pass -1 for errorInfo to indicate that Windows' GetErrorInfo shouldn't be called, and only
+ // throw the Exception corresponding to the specified errorCode.
+ Marshal.ThrowExceptionForHR(errorCode, errorInfo: new IntPtr(-1));
+ }
+
internal static class IStreamVtbl
{
public static IntPtr Create(IntPtr fpQueryInterface, IntPtr fpAddRef, IntPtr fpRelease)
@@ -159,16 +180,13 @@ private static int CopyTo(IntPtr thisPtr, IntPtr pstm, ulong cb, ulong* pcbRead,
try
{
Interop.Ole32.IStream inst = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr);
- Interop.Ole32.IStream pstmStream = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)pstm);
- inst.CopyTo(pstmStream, cb, pcbRead, pcbWritten);
+ return (int)inst.CopyTo(pstm, cb, pcbRead, pcbWritten);
}
catch (Exception e)
{
return e.HResult;
}
-
- return S_OK;
}
[UnmanagedCallersOnly]
@@ -250,23 +268,16 @@ private static int Stat(IntPtr thisPtr, Interop.Ole32.STATSTG* pstatstg, Interop
[UnmanagedCallersOnly]
private static int Clone(IntPtr thisPtr, IntPtr* ppstm)
{
- if (ppstm == null)
- {
- return (int)Interop.HRESULT.STG_E_INVALIDPOINTER;
- }
-
try
{
Interop.Ole32.IStream inst = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr);
- *ppstm = Instance.GetOrCreateComInterfaceForObject(inst.Clone(), CreateComInterfaceFlags.None);
+ return (int)inst.Clone(ppstm);
}
catch (Exception e)
{
return e.HResult;
}
-
- return S_OK;
}
}
@@ -297,7 +308,7 @@ public unsafe int SaveAsFile(IntPtr pstm, int fSaveMemCopy, int* pcbSize)
{
// Get the IStream implementation, since the ComWrappers runtime returns a pointer to the IUnknown interface implementation
Guid streamIID = IID_IStream;
- Marshal.ThrowExceptionForHR(Marshal.QueryInterface(pstm, ref streamIID, out IntPtr pstmImpl));
+ ThrowExceptionForHR(Marshal.QueryInterface(pstm, ref streamIID, out IntPtr pstmImpl));
try
{
diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/DrawingCom.NoCOMWrappers.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/DrawingCom.NoCOMWrappers.cs
new file mode 100644
index 0000000000000..d3fdd2115bffb
--- /dev/null
+++ b/src/libraries/System.Drawing.Common/src/System/Drawing/DrawingCom.NoCOMWrappers.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Drawing.Internal;
+using System.Runtime.InteropServices;
+
+namespace System.Drawing
+{
+ internal static partial class DrawingCom
+ {
+ internal static IStreamWrapper GetComWrapper(GPStream stream)
+ {
+ return new IStreamWrapper(Marshal.GetComInterfaceForObject(stream));
+ }
+ }
+}
diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/DrawingCom.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/DrawingCom.cs
new file mode 100644
index 0000000000000..a5b53e65ff589
--- /dev/null
+++ b/src/libraries/System.Drawing.Common/src/System/Drawing/DrawingCom.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.InteropServices;
+
+namespace System.Drawing
+{
+ internal partial class DrawingCom
+ {
+ internal readonly struct IStreamWrapper : IDisposable
+ {
+ public readonly IntPtr Ptr;
+
+ public IStreamWrapper(IntPtr ptr)
+ {
+ Ptr = ptr;
+ }
+
+ public void Dispose()
+ {
+ Marshal.Release(Ptr);
+ }
+ }
+ }
+}
diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Windows.cs
index 47aeb4f9397c3..3edf4a0e7b67e 100644
--- a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Windows.cs
+++ b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Windows.cs
@@ -210,10 +210,10 @@ private static void PlatformInitialize()
internal static extern int GdipDeleteBrush(HandleRef brush);
[DllImport(LibraryName, ExactSpelling = true)]
- internal static extern int GdipLoadImageFromStream(Interop.Ole32.IStream stream, out IntPtr image);
+ internal static extern int GdipLoadImageFromStream(IntPtr stream, IntPtr* image);
[DllImport(LibraryName, ExactSpelling = true)]
- internal static extern int GdipLoadImageFromStreamICM(Interop.Ole32.IStream stream, out IntPtr image);
+ internal static extern int GdipLoadImageFromStreamICM(IntPtr stream, IntPtr* image);
[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipCloneImage(HandleRef image, out IntPtr cloneimage);
@@ -222,7 +222,7 @@ private static void PlatformInitialize()
internal static extern int GdipSaveImageToFile(HandleRef image, string filename, ref Guid classId, HandleRef encoderParams);
[DllImport(LibraryName, ExactSpelling = true)]
- internal static extern int GdipSaveImageToStream(HandleRef image, Interop.Ole32.IStream stream, ref Guid classId, HandleRef encoderParams);
+ internal static extern int GdipSaveImageToStream(HandleRef image, IntPtr stream, Guid* classId, HandleRef encoderParams);
[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipSaveAdd(HandleRef image, HandleRef encoderParams);
@@ -327,7 +327,7 @@ private static void PlatformInitialize()
internal static extern int GdipGetMetafileHeaderFromFile(string filename, IntPtr header);
[DllImport(LibraryName, ExactSpelling = true)]
- internal static extern int GdipGetMetafileHeaderFromStream(Interop.Ole32.IStream stream, IntPtr header);
+ internal static extern int GdipGetMetafileHeaderFromStream(IntPtr stream, IntPtr header);
[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipGetMetafileHeaderFromMetafile(HandleRef metafile, IntPtr header);
@@ -336,16 +336,16 @@ private static void PlatformInitialize()
internal static extern int GdipGetHemfFromMetafile(HandleRef metafile, out IntPtr hEnhMetafile);
[DllImport(LibraryName, ExactSpelling = true)]
- internal static extern int GdipCreateMetafileFromStream(Interop.Ole32.IStream stream, out IntPtr metafile);
+ internal static extern int GdipCreateMetafileFromStream(IntPtr stream, IntPtr* metafile);
[DllImport(LibraryName, ExactSpelling = true, CharSet = CharSet.Unicode)]
- internal static extern int GdipRecordMetafileStream(Interop.Ole32.IStream stream, IntPtr referenceHdc, EmfType emfType, ref RectangleF frameRect, MetafileFrameUnit frameUnit, string? description, out IntPtr metafile);
+ internal static extern int GdipRecordMetafileStream(IntPtr stream, IntPtr referenceHdc, EmfType emfType, RectangleF* frameRect, MetafileFrameUnit frameUnit, string? description, IntPtr* metafile);
[DllImport(LibraryName, ExactSpelling = true, CharSet = CharSet.Unicode)]
- internal static extern int GdipRecordMetafileStream(Interop.Ole32.IStream stream, IntPtr referenceHdc, EmfType emfType, IntPtr pframeRect, MetafileFrameUnit frameUnit, string? description, out IntPtr metafile);
+ internal static extern int GdipRecordMetafileStream(IntPtr stream, IntPtr referenceHdc, EmfType emfType, IntPtr pframeRect, MetafileFrameUnit frameUnit, string? description, IntPtr* metafile);
[DllImport(LibraryName, ExactSpelling = true, CharSet = CharSet.Unicode)]
- internal static extern int GdipRecordMetafileStreamI(Interop.Ole32.IStream stream, IntPtr referenceHdc, EmfType emfType, ref Rectangle frameRect, MetafileFrameUnit frameUnit, string? description, out IntPtr metafile);
+ internal static extern int GdipRecordMetafileStreamI(IntPtr stream, IntPtr referenceHdc, EmfType emfType, Rectangle* frameRect, MetafileFrameUnit frameUnit, string? description, IntPtr* metafile);
[DllImport(LibraryName, ExactSpelling = true)]
internal static extern int GdipComment(HandleRef graphics, int sizeData, byte[] data);
@@ -354,10 +354,10 @@ private static void PlatformInitialize()
internal static extern int GdipCreateFontFromLogfontW(IntPtr hdc, ref Interop.User32.LOGFONT lf, out IntPtr font);
[DllImport(LibraryName, ExactSpelling = true)]
- internal static extern int GdipCreateBitmapFromStream(Interop.Ole32.IStream stream, out IntPtr bitmap);
+ internal static extern int GdipCreateBitmapFromStream(IntPtr stream, IntPtr* bitmap);
[DllImport(LibraryName, ExactSpelling = true)]
- internal static extern int GdipCreateBitmapFromStreamICM(Interop.Ole32.IStream stream, out IntPtr bitmap);
+ internal static extern int GdipCreateBitmapFromStreamICM(IntPtr stream, IntPtr* bitmap);
}
}
}
diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.COMWrappers.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.COMWrappers.cs
index a03ad5ed133bb..3d9ad1a356676 100644
--- a/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.COMWrappers.cs
+++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Icon.Windows.COMWrappers.cs
@@ -28,7 +28,7 @@ public unsafe void Save(Stream outputStream)
// But, in the interest of simplicity, we just call to
// OLE to do it for us.
PICTDESC pictdesc = PICTDESC.CreateIconPICTDESC(Handle);
- Guid iid = DrawingComWrappers.IPicture.IID;
+ Guid iid = DrawingCom.IPicture.IID;
IntPtr lpPicture;
Marshal.ThrowExceptionForHR(OleCreatePictureIndirect(&pictdesc, &iid, fOwn: 0, &lpPicture));
@@ -36,13 +36,13 @@ public unsafe void Save(Stream outputStream)
try
{
// Use UniqueInstance here because we never want to cache the wrapper. It only gets used once and then disposed.
- using DrawingComWrappers.IPicture picture = (DrawingComWrappers.IPicture)DrawingComWrappers.Instance
+ using DrawingCom.IPicture picture = (DrawingCom.IPicture)DrawingCom.Instance
.GetOrCreateObjectForComInstance(lpPicture, CreateObjectFlags.UniqueInstance);
var gpStream = new GPStream(outputStream, makeSeekable: false);
- streamPtr = DrawingComWrappers.Instance.GetOrCreateComInterfaceForObject(gpStream, CreateComInterfaceFlags.None);
+ streamPtr = DrawingCom.Instance.GetOrCreateComInterfaceForObject(gpStream, CreateComInterfaceFlags.None);
- CheckSaveAsFileResult(picture.SaveAsFile(streamPtr, -1, null));
+ DrawingCom.ThrowExceptionForHR(picture.SaveAsFile(streamPtr, -1, null));
}
finally
{
@@ -61,13 +61,6 @@ public unsafe void Save(Stream outputStream)
}
}
- private static void CheckSaveAsFileResult(int errorCode)
- {
- // Pass -1 for errorInfo to indicate that Windows' GetErrorInfo shouldn't be called, and only
- // throw the Exception corresponding to the specified errorCode.
- Marshal.ThrowExceptionForHR(errorCode, errorInfo: new IntPtr(-1));
- }
-
[DllImport(Interop.Libraries.Oleaut32)]
private static unsafe extern int OleCreatePictureIndirect(PICTDESC* pictdesc, Guid* refiid, int fOwn, IntPtr* lplpvObj);
diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Windows.cs
index a6dd53744a974..ccea5ff42d52e 100644
--- a/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Windows.cs
+++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Image.Windows.cs
@@ -23,16 +23,7 @@ public static Image FromStream(Stream stream, bool useEmbeddedColorManagement, b
if (stream == null)
throw new ArgumentNullException(nameof(stream));
- IntPtr image = IntPtr.Zero;
-
- if (useEmbeddedColorManagement)
- {
- Gdip.CheckStatus(Gdip.GdipLoadImageFromStreamICM(new GPStream(stream), out image));
- }
- else
- {
- Gdip.CheckStatus(Gdip.GdipLoadImageFromStream(new GPStream(stream), out image));
- }
+ IntPtr image = LoadGdipImageFromStream(new GPStream(stream), useEmbeddedColorManagement);
if (validateImageData)
ValidateImage(image);
@@ -45,9 +36,7 @@ public static Image FromStream(Stream stream, bool useEmbeddedColorManagement, b
// Used for serialization
private IntPtr InitializeFromStream(Stream stream)
{
- IntPtr image = IntPtr.Zero;
-
- Gdip.CheckStatus(Gdip.GdipLoadImageFromStream(new GPStream(stream), out image));
+ IntPtr image = LoadGdipImageFromStream(new GPStream(stream), useEmbeddedColorManagement: false);
ValidateImage(image);
nativeImage = image;
@@ -59,6 +48,22 @@ private IntPtr InitializeFromStream(Stream stream)
return image;
}
+ private static unsafe IntPtr LoadGdipImageFromStream(GPStream stream, bool useEmbeddedColorManagement)
+ {
+ using DrawingCom.IStreamWrapper streamWrapper = DrawingCom.GetComWrapper(stream);
+
+ IntPtr image = IntPtr.Zero;
+ if (useEmbeddedColorManagement)
+ {
+ Gdip.CheckStatus(Gdip.GdipLoadImageFromStreamICM(streamWrapper.Ptr, &image));
+ }
+ else
+ {
+ Gdip.CheckStatus(Gdip.GdipLoadImageFromStream(streamWrapper.Ptr, &image));
+ }
+ return image;
+ }
+
internal Image(IntPtr nativeImage) => SetNativeImage(nativeImage);
///
@@ -240,11 +245,15 @@ public void Save(Stream stream, ImageCodecInfo encoder, EncoderParameters? encod
if (!saved)
{
- Gdip.CheckStatus(Gdip.GdipSaveImageToStream(
- new HandleRef(this, nativeImage),
- new GPStream(stream, makeSeekable: false),
- ref g,
- new HandleRef(encoderParams, encoderParamsMemory)));
+ using DrawingCom.IStreamWrapper streamWrapper = DrawingCom.GetComWrapper(new GPStream(stream, makeSeekable: false));
+ unsafe
+ {
+ Gdip.CheckStatus(Gdip.GdipSaveImageToStream(
+ new HandleRef(this, nativeImage),
+ streamWrapper.Ptr,
+ &g,
+ new HandleRef(encoderParams, encoderParamsMemory)));
+ }
}
}
finally
diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Windows.cs
index 447799333febf..4d8dccb01e71f 100644
--- a/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Windows.cs
+++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Windows.cs
@@ -1,11 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Runtime.InteropServices;
-using System.IO;
using System.Drawing.Internal;
+using System.IO;
+using System.Runtime.InteropServices;
using Gdip = System.Drawing.SafeNativeMethods.Gdip;
-using System.Runtime.Serialization;
namespace System.Drawing.Imaging
{
@@ -27,14 +26,18 @@ public Metafile(IntPtr hmetafile, WmfPlaceableFileHeader wmfHeader) :
///
/// Initializes a new instance of the class from the specified stream.
///
- public Metafile(Stream stream)
+ public unsafe Metafile(Stream stream)
{
if (stream == null)
{
throw new ArgumentNullException(nameof(stream));
}
- Gdip.CheckStatus(Gdip.GdipCreateMetafileFromStream(new GPStream(stream), out IntPtr metafile));
+ using DrawingCom.IStreamWrapper streamWrapper = DrawingCom.GetComWrapper(new GPStream(stream));
+
+ IntPtr metafile = IntPtr.Zero;
+ Gdip.CheckStatus(Gdip.GdipCreateMetafileFromStream(streamWrapper.Ptr, &metafile));
+
SetNativeImage(metafile);
}
@@ -145,16 +148,19 @@ public Metafile(string fileName, IntPtr referenceHdc, Rectangle frameRect, Metaf
///
/// Initializes a new instance of the class from the specified data stream.
///
- public Metafile(Stream stream, IntPtr referenceHdc, EmfType type, string? description)
+ public unsafe Metafile(Stream stream, IntPtr referenceHdc, EmfType type, string? description)
{
+ using DrawingCom.IStreamWrapper streamWrapper = DrawingCom.GetComWrapper(new GPStream(stream));
+
+ IntPtr metafile = IntPtr.Zero;
Gdip.CheckStatus(Gdip.GdipRecordMetafileStream(
- new GPStream(stream),
+ streamWrapper.Ptr,
referenceHdc,
type,
IntPtr.Zero,
MetafileFrameUnit.GdiCompatible,
description,
- out IntPtr metafile));
+ &metafile));
SetNativeImage(metafile);
}
@@ -162,16 +168,19 @@ public Metafile(Stream stream, IntPtr referenceHdc, EmfType type, string? descri
///
/// Initializes a new instance of the class with the specified filename.
///
- public Metafile(Stream stream, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit, EmfType type, string? description)
+ public unsafe Metafile(Stream stream, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit, EmfType type, string? description)
{
+ using DrawingCom.IStreamWrapper streamWrapper = DrawingCom.GetComWrapper(new GPStream(stream));
+
+ IntPtr metafile = IntPtr.Zero;
Gdip.CheckStatus(Gdip.GdipRecordMetafileStream(
- new GPStream(stream),
+ streamWrapper.Ptr,
referenceHdc,
type,
- ref frameRect,
+ &frameRect,
frameUnit,
description,
- out IntPtr metafile));
+ &metafile));
SetNativeImage(metafile);
}
@@ -179,31 +188,32 @@ public Metafile(Stream stream, IntPtr referenceHdc, RectangleF frameRect, Metafi
///
/// Initializes a new instance of the class with the specified filename.
///
- public Metafile(Stream stream, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit, EmfType type, string? description)
+ public unsafe Metafile(Stream stream, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit, EmfType type, string? description)
{
- IntPtr metafile = IntPtr.Zero;
+ using DrawingCom.IStreamWrapper streamWrapper = DrawingCom.GetComWrapper(new GPStream(stream));
+ IntPtr metafile = IntPtr.Zero;
if (frameRect.IsEmpty)
{
Gdip.CheckStatus(Gdip.GdipRecordMetafileStream(
- new GPStream(stream),
+ streamWrapper.Ptr,
referenceHdc,
type,
IntPtr.Zero,
frameUnit,
description,
- out metafile));
+ &metafile));
}
else
{
Gdip.CheckStatus(Gdip.GdipRecordMetafileStreamI(
- new GPStream(stream),
+ streamWrapper.Ptr,
referenceHdc,
type,
- ref frameRect,
+ &frameRect,
frameUnit,
description,
- out metafile));
+ &metafile));
}
SetNativeImage(metafile);
@@ -292,7 +302,8 @@ public static MetafileHeader GetMetafileHeader(Stream stream)
try
{
- Gdip.CheckStatus(Gdip.GdipGetMetafileHeaderFromStream(new GPStream(stream), memory));
+ using DrawingCom.IStreamWrapper streamWrapper = DrawingCom.GetComWrapper(new GPStream(stream));
+ Gdip.CheckStatus(Gdip.GdipGetMetafileHeaderFromStream(streamWrapper.Ptr, memory));
int[] type = new int[] { 0 };
diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Internal/GPStream.COMWrappers.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Internal/GPStream.COMWrappers.cs
new file mode 100644
index 0000000000000..65079d5698a4b
--- /dev/null
+++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Internal/GPStream.COMWrappers.cs
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Buffers;
+using System.Runtime.InteropServices;
+
+namespace System.Drawing.Internal
+{
+ internal sealed partial class GPStream : Interop.Ole32.IStream
+ {
+ public unsafe Interop.HRESULT Clone(IntPtr* ppstm)
+ {
+ if (ppstm == null)
+ {
+ return Interop.HRESULT.STG_E_INVALIDPOINTER;
+ }
+
+ // The cloned object should have the same current "position"
+ var clone = new GPStream(_dataStream)
+ {
+ _virtualPosition = _virtualPosition
+ };
+
+ *ppstm = DrawingCom.Instance.GetOrCreateComInterfaceForObject(clone, CreateComInterfaceFlags.None);
+
+ return Interop.HRESULT.S_OK;
+ }
+
+ public unsafe Interop.HRESULT CopyTo(IntPtr pstm, ulong cb, ulong* pcbRead, ulong* pcbWritten)
+ {
+ byte[] buffer = ArrayPool.Shared.Rent(4096);
+
+ ulong remaining = cb;
+ ulong totalWritten = 0;
+ ulong totalRead = 0;
+
+ fixed (byte* b = buffer)
+ {
+ while (remaining > 0)
+ {
+ uint read = remaining < (ulong)buffer.Length ? (uint)remaining : (uint)buffer.Length;
+ Read(b, read, &read);
+ remaining -= read;
+ totalRead += read;
+
+ if (read == 0)
+ {
+ break;
+ }
+
+ uint written;
+ Interop.HRESULT hr = (Interop.HRESULT)WriteToStream(pstm, b, read, &written);
+ if (hr != Interop.HRESULT.S_OK)
+ {
+ return hr;
+ }
+ totalWritten += written;
+ }
+ }
+
+ ArrayPool.Shared.Return(buffer);
+
+ if (pcbRead != null)
+ {
+ *pcbRead = totalRead;
+ }
+
+ if (pcbWritten != null)
+ {
+ *pcbWritten = totalWritten;
+ }
+
+ return Interop.HRESULT.S_OK;
+ }
+
+ private static unsafe int WriteToStream(IntPtr pstm, byte* pv, uint cb, uint* pcbWritten)
+ {
+ return ((delegate* unmanaged)(*(*(void***)pstm + 4 /* IStream.Write slot */)))
+ (pstm, pv, cb, pcbWritten);
+ }
+ }
+}
diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Internal/GPStream.NoCOMWrappers.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Internal/GPStream.NoCOMWrappers.cs
new file mode 100644
index 0000000000000..0c4e56ef8d685
--- /dev/null
+++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Internal/GPStream.NoCOMWrappers.cs
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Buffers;
+
+namespace System.Drawing.Internal
+{
+ internal sealed partial class GPStream : Interop.Ole32.IStream
+ {
+ public Interop.Ole32.IStream Clone()
+ {
+ // The cloned object should have the same current "position"
+ return new GPStream(_dataStream)
+ {
+ _virtualPosition = _virtualPosition
+ };
+ }
+
+ public unsafe void CopyTo(Interop.Ole32.IStream pstm, ulong cb, ulong* pcbRead, ulong* pcbWritten)
+ {
+ byte[] buffer = ArrayPool.Shared.Rent(4096);
+
+ ulong remaining = cb;
+ ulong totalWritten = 0;
+ ulong totalRead = 0;
+
+ fixed (byte* b = buffer)
+ {
+ while (remaining > 0)
+ {
+ uint read = remaining < (ulong)buffer.Length ? (uint)remaining : (uint)buffer.Length;
+ Read(b, read, &read);
+ remaining -= read;
+ totalRead += read;
+
+ if (read == 0)
+ {
+ break;
+ }
+
+ uint written;
+ pstm.Write(b, read, &written);
+ totalWritten += written;
+ }
+ }
+
+ ArrayPool.Shared.Return(buffer);
+
+ if (pcbRead != null)
+ *pcbRead = totalRead;
+
+ if (pcbWritten != null)
+ *pcbWritten = totalWritten;
+ }
+ }
+}
diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Internal/GPStream.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Internal/GPStream.cs
index dd6a8a16350ff..524be173b52cf 100644
--- a/src/libraries/System.Drawing.Common/src/System/Drawing/Internal/GPStream.cs
+++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Internal/GPStream.cs
@@ -1,12 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Buffers;
using System.IO;
namespace System.Drawing.Internal
{
- internal sealed class GPStream : Interop.Ole32.IStream
+ internal sealed partial class GPStream : Interop.Ole32.IStream
{
private readonly Stream _dataStream;
@@ -41,15 +40,6 @@ private void ActualizeVirtualPosition()
_virtualPosition = -1;
}
- public Interop.Ole32.IStream Clone()
- {
- // The cloned object should have the same current "position"
- return new GPStream(_dataStream)
- {
- _virtualPosition = _virtualPosition
- };
- }
-
public void Commit(uint grfCommitFlags)
{
_dataStream.Flush();
@@ -58,43 +48,6 @@ public void Commit(uint grfCommitFlags)
ActualizeVirtualPosition();
}
- public unsafe void CopyTo(Interop.Ole32.IStream pstm, ulong cb, ulong* pcbRead, ulong* pcbWritten)
- {
- byte[] buffer = ArrayPool.Shared.Rent(4096);
-
- ulong remaining = cb;
- ulong totalWritten = 0;
- ulong totalRead = 0;
-
- fixed (byte* b = buffer)
- {
- while (remaining > 0)
- {
- uint read = remaining < (ulong)buffer.Length ? (uint)remaining : (uint)buffer.Length;
- Read(b, read, &read);
- remaining -= read;
- totalRead += read;
-
- if (read == 0)
- {
- break;
- }
-
- uint written;
- pstm.Write(b, read, &written);
- totalWritten += written;
- }
- }
-
- ArrayPool.Shared.Return(buffer);
-
- if (pcbRead != null)
- *pcbRead = totalRead;
-
- if (pcbWritten != null)
- *pcbWritten = totalWritten;
- }
-
public unsafe void Read(byte* pv, uint cb, uint* pcbRead)
{
ActualizeVirtualPosition();
diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs
index 26207c1ccf733..ca3800ccfa50e 100644
--- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs
+++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs
@@ -240,6 +240,20 @@ public static IEnumerable
+
+
+
+
diff --git a/src/libraries/System.Memory.Data/src/System/BinaryData.cs b/src/libraries/System.Memory.Data/src/System/BinaryData.cs
index b0e56d1e7bae3..2e5dfbfacfb68 100644
--- a/src/libraries/System.Memory.Data/src/System/BinaryData.cs
+++ b/src/libraries/System.Memory.Data/src/System/BinaryData.cs
@@ -4,7 +4,6 @@
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
-using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Threading;
@@ -17,6 +16,8 @@ namespace System
///
public class BinaryData
{
+ private const string JsonSerializerRequiresUnreferencedCode = "JSON serialization and deserialization might require types that cannot be statically analyzed.";
+
///
/// The backing store for the instance.
///
@@ -41,12 +42,12 @@ public BinaryData(byte[] data)
/// Creates a instance by serializing the provided object to JSON
/// using .
///
- ///
/// The object that will be serialized to JSON using
/// .
/// The options to use when serializing to JSON.
/// The type to use when serializing the data. If not specified, will
/// be used to determine the type.
+ [RequiresUnreferencedCode(JsonSerializerRequiresUnreferencedCode)]
public BinaryData(object? jsonSerializable, JsonSerializerOptions? options = default, Type? type = default)
{
type ??= jsonSerializable?.GetType() ?? typeof(object);
@@ -177,12 +178,11 @@ private static async Task FromStreamAsync(Stream stream, bool async,
/// Creates a instance by serializing the provided object using
/// the .
///
- ///
/// The type to use when serializing the data.
/// The data to use.
/// The options to use when serializing to JSON.
- ///
/// A value representing the UTF-8 encoding of the JSON representation of .
+ [RequiresUnreferencedCode(JsonSerializerRequiresUnreferencedCode)]
public static BinaryData FromObjectAsJson(T jsonSerializable, JsonSerializerOptions? options = default)
{
byte[] buffer = JsonSerializer.SerializeToUtf8Bytes(jsonSerializable, typeof(T), options);
@@ -230,6 +230,7 @@ public override unsafe string ToString()
/// converted to.
/// The to use when serializing to JSON.
/// The data converted to the specified type.
+ [RequiresUnreferencedCode(JsonSerializerRequiresUnreferencedCode)]
public T? ToObjectFromJson(JsonSerializerOptions? options = default)
{
return JsonSerializer.Deserialize(_bytes.Span, options);
diff --git a/src/libraries/System.Net.Http/src/ILLink/ILLink.Substitutions.xml b/src/libraries/System.Net.Http/src/ILLink/ILLink.Substitutions.xml
index 314469c96d777..d6aea3dbf37e4 100644
--- a/src/libraries/System.Net.Http/src/ILLink/ILLink.Substitutions.xml
+++ b/src/libraries/System.Net.Http/src/ILLink/ILLink.Substitutions.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj
index 0fee14684e2ea..1423025f7c169 100644
--- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj
+++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj
@@ -1,4 +1,4 @@
-
+
win
true
@@ -494,7 +494,6 @@
-
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs
index 4e4d730c4c188..14c1464e77a70 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandler.cs
@@ -15,103 +15,121 @@ namespace System.Net.Http
///
internal sealed class DiagnosticsHandler : DelegatingHandler
{
- ///
- /// DiagnosticHandler constructor
- ///
- /// Inner handler: Windows or Unix implementation of HttpMessageHandler.
- /// Note that DiagnosticHandler is the latest in the pipeline
- public DiagnosticsHandler(HttpMessageHandler innerHandler) : base(innerHandler)
- {
- }
+ private const string Namespace = "System.Net.Http";
+ private const string RequestWriteNameDeprecated = Namespace + ".Request";
+ private const string ResponseWriteNameDeprecated = Namespace + ".Response";
+ private const string ExceptionEventName = Namespace + ".Exception";
+ private const string ActivityName = Namespace + ".HttpRequestOut";
+ private const string ActivityStartName = ActivityName + ".Start";
+ private const string ActivityStopName = ActivityName + ".Stop";
- internal static bool IsEnabled()
- {
- // check if there is a parent Activity (and propagation is not suppressed)
- // or if someone listens to HttpHandlerDiagnosticListener
- return IsGloballyEnabled() && (Activity.Current != null || Settings.s_diagnosticListener.IsEnabled());
- }
+ private static readonly DiagnosticListener s_diagnosticListener = new("HttpHandlerDiagnosticListener");
+ private static readonly ActivitySource s_activitySource = new(Namespace);
+
+ public static bool IsGloballyEnabled { get; } = GetEnableActivityPropagationValue();
- internal static bool IsGloballyEnabled()
+ private static bool GetEnableActivityPropagationValue()
{
- return Settings.s_activityPropagationEnabled;
- }
+ // First check for the AppContext switch, giving it priority over the environment variable.
+ if (AppContext.TryGetSwitch(Namespace + ".EnableActivityPropagation", out bool enableActivityPropagation))
+ {
+ return enableActivityPropagation;
+ }
- // SendAsyncCore returns already completed ValueTask for when async: false is passed.
- // Internally, it calls the synchronous Send method of the base class.
- protected internal override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) =>
- SendAsyncCore(request, async: false, cancellationToken).AsTask().GetAwaiter().GetResult();
+ // AppContext switch wasn't used. Check the environment variable to determine which handler should be used.
+ string? envVar = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_NET_HTTP_ENABLEACTIVITYPROPAGATION");
+ if (envVar != null && (envVar.Equals("false", StringComparison.OrdinalIgnoreCase) || envVar.Equals("0")))
+ {
+ // Suppress Activity propagation.
+ return false;
+ }
- protected internal override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) =>
- SendAsyncCore(request, async: true, cancellationToken).AsTask();
+ // Defaults to enabling Activity propagation.
+ return true;
+ }
- private async ValueTask SendAsyncCore(HttpRequestMessage request, bool async,
- CancellationToken cancellationToken)
+ public DiagnosticsHandler(HttpMessageHandler innerHandler) : base(innerHandler)
{
- // HttpClientHandler is responsible to call static DiagnosticsHandler.IsEnabled() before forwarding request here.
- // It will check if propagation is on (because parent Activity exists or there is a listener) or off (forcibly disabled)
- // This code won't be called unless consumer unsubscribes from DiagnosticListener right after the check.
- // So some requests happening right after subscription starts might not be instrumented. Similarly,
- // when consumer unsubscribes, extra requests might be instrumented
+ Debug.Assert(IsGloballyEnabled);
+ }
- if (request == null)
+ private static bool ShouldLogDiagnostics(HttpRequestMessage request, out Activity? activity)
+ {
+ if (request is null)
{
throw new ArgumentNullException(nameof(request), SR.net_http_handler_norequest);
}
- Activity? activity = null;
- DiagnosticListener diagnosticListener = Settings.s_diagnosticListener;
+ activity = null;
+
+ if (s_activitySource.HasListeners())
+ {
+ activity = s_activitySource.CreateActivity(ActivityName, ActivityKind.Client);
+ }
- // if there is no listener, but propagation is enabled (with previous IsEnabled() check)
- // do not write any events just start/stop Activity and propagate Ids
- if (!diagnosticListener.IsEnabled())
+ if (activity is null)
{
- activity = new Activity(DiagnosticsHandlerLoggingStrings.ActivityName);
- activity.Start();
- InjectHeaders(activity, request);
+ bool diagnosticListenerEnabled = s_diagnosticListener.IsEnabled();
- try
+ if (Activity.Current is not null || (diagnosticListenerEnabled && s_diagnosticListener.IsEnabled(ActivityName, request)))
{
- return async ?
- await base.SendAsync(request, cancellationToken).ConfigureAwait(false) :
- base.Send(request, cancellationToken);
+ // If a diagnostics listener is enabled for the Activity, always create one
+ activity = new Activity(ActivityName);
}
- finally
+ else
{
- activity.Stop();
+ // There is no Activity, but we may still want to use the instrumented SendAsyncCore if diagnostic listeners are interested in other events
+ return diagnosticListenerEnabled;
}
}
- Guid loggingRequestId = Guid.Empty;
+ activity.Start();
- // There is a listener. Check if listener wants to be notified about HttpClient Activities
- if (diagnosticListener.IsEnabled(DiagnosticsHandlerLoggingStrings.ActivityName, request))
+ if (s_diagnosticListener.IsEnabled(ActivityStartName))
{
- activity = new Activity(DiagnosticsHandlerLoggingStrings.ActivityName);
+ Write(ActivityStartName, new ActivityStartData(request));
+ }
- // Only send start event to users who subscribed for it, but start activity anyway
- if (diagnosticListener.IsEnabled(DiagnosticsHandlerLoggingStrings.ActivityStartName))
- {
- StartActivity(diagnosticListener, activity, new ActivityStartData(request));
- }
- else
- {
- activity.Start();
- }
+ InjectHeaders(activity, request);
+
+ return true;
+ }
+
+ protected internal override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken)
+ {
+ if (ShouldLogDiagnostics(request, out Activity? activity))
+ {
+ ValueTask sendTask = SendAsyncCore(request, activity, async: false, cancellationToken);
+ return sendTask.IsCompleted ?
+ sendTask.Result :
+ sendTask.AsTask().GetAwaiter().GetResult();
}
- // try to write System.Net.Http.Request event (deprecated)
- if (diagnosticListener.IsEnabled(DiagnosticsHandlerLoggingStrings.RequestWriteNameDeprecated))
+ else
{
- long timestamp = Stopwatch.GetTimestamp();
- loggingRequestId = Guid.NewGuid();
- Write(diagnosticListener, DiagnosticsHandlerLoggingStrings.RequestWriteNameDeprecated,
- new RequestData(request, loggingRequestId, timestamp));
+ return base.Send(request, cancellationToken);
}
+ }
- // If we are on at all, we propagate current activity information
- Activity? currentActivity = Activity.Current;
- if (currentActivity != null)
+ protected internal override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+ {
+ if (ShouldLogDiagnostics(request, out Activity? activity))
+ {
+ return SendAsyncCore(request, activity, async: true, cancellationToken).AsTask();
+ }
+ else
{
- InjectHeaders(currentActivity, request);
+ return base.SendAsync(request, cancellationToken);
+ }
+ }
+
+ private async ValueTask SendAsyncCore(HttpRequestMessage request, Activity? activity, bool async, CancellationToken cancellationToken)
+ {
+ Guid loggingRequestId = default;
+
+ if (s_diagnosticListener.IsEnabled(RequestWriteNameDeprecated))
+ {
+ loggingRequestId = Guid.NewGuid();
+ Write(RequestWriteNameDeprecated, new RequestData(request, loggingRequestId, Stopwatch.GetTimestamp()));
}
HttpResponseMessage? response = null;
@@ -126,52 +144,39 @@ await base.SendAsync(request, cancellationToken).ConfigureAwait(false) :
catch (OperationCanceledException)
{
taskStatus = TaskStatus.Canceled;
-
- // we'll report task status in HttpRequestOut.Stop
throw;
}
catch (Exception ex)
{
- taskStatus = TaskStatus.Faulted;
-
- if (diagnosticListener.IsEnabled(DiagnosticsHandlerLoggingStrings.ExceptionEventName))
+ if (s_diagnosticListener.IsEnabled(ExceptionEventName))
{
- // If request was initially instrumented, Activity.Current has all necessary context for logging
- // Request is passed to provide some context if instrumentation was disabled and to avoid
- // extensive Activity.Tags usage to tunnel request properties
- Write(diagnosticListener, DiagnosticsHandlerLoggingStrings.ExceptionEventName, new ExceptionData(ex, request));
+ Write(ExceptionEventName, new ExceptionData(ex, request));
}
+
+ taskStatus = TaskStatus.Faulted;
throw;
}
finally
{
- // always stop activity if it was started
- if (activity != null)
+ if (activity is not null)
{
- StopActivity(diagnosticListener, activity, new ActivityStopData(
- response,
- // If request is failed or cancelled, there is no response, therefore no information about request;
- // pass the request in the payload, so consumers can have it in Stop for failed/canceled requests
- // and not retain all requests in Start
- request,
- taskStatus));
+ activity.SetEndTime(DateTime.UtcNow);
+
+ if (s_diagnosticListener.IsEnabled(ActivityStopName))
+ {
+ Write(ActivityStopName, new ActivityStopData(response, request, taskStatus));
+ }
+
+ activity.Stop();
}
- // Try to write System.Net.Http.Response event (deprecated)
- if (diagnosticListener.IsEnabled(DiagnosticsHandlerLoggingStrings.ResponseWriteNameDeprecated))
+
+ if (s_diagnosticListener.IsEnabled(ResponseWriteNameDeprecated))
{
- long timestamp = Stopwatch.GetTimestamp();
- Write(diagnosticListener, DiagnosticsHandlerLoggingStrings.ResponseWriteNameDeprecated,
- new ResponseData(
- response,
- loggingRequestId,
- timestamp,
- taskStatus));
+ Write(ResponseWriteNameDeprecated, new ResponseData(response, loggingRequestId, Stopwatch.GetTimestamp(), taskStatus));
}
}
}
- #region private
-
private sealed class ActivityStartData
{
// matches the properties selected in https://github.com/dotnet/diagnostics/blob/ffd0254da3bcc47847b1183fa5453c0877020abd/src/Microsoft.Diagnostics.Monitoring.EventPipe/Configuration/HttpRequestSourceConfiguration.cs#L36-L40
@@ -269,55 +274,29 @@ internal ResponseData(HttpResponseMessage? response, Guid loggingRequestId, long
public override string ToString() => $"{{ {nameof(Response)} = {Response}, {nameof(LoggingRequestId)} = {LoggingRequestId}, {nameof(Timestamp)} = {Timestamp}, {nameof(RequestTaskStatus)} = {RequestTaskStatus} }}";
}
- private static class Settings
- {
- private const string EnableActivityPropagationEnvironmentVariableSettingName = "DOTNET_SYSTEM_NET_HTTP_ENABLEACTIVITYPROPAGATION";
- private const string EnableActivityPropagationAppCtxSettingName = "System.Net.Http.EnableActivityPropagation";
-
- public static readonly bool s_activityPropagationEnabled = GetEnableActivityPropagationValue();
-
- private static bool GetEnableActivityPropagationValue()
- {
- // First check for the AppContext switch, giving it priority over the environment variable.
- if (AppContext.TryGetSwitch(EnableActivityPropagationAppCtxSettingName, out bool enableActivityPropagation))
- {
- return enableActivityPropagation;
- }
-
- // AppContext switch wasn't used. Check the environment variable to determine which handler should be used.
- string? envVar = Environment.GetEnvironmentVariable(EnableActivityPropagationEnvironmentVariableSettingName);
- if (envVar != null && (envVar.Equals("false", StringComparison.OrdinalIgnoreCase) || envVar.Equals("0")))
- {
- // Suppress Activity propagation.
- return false;
- }
-
- // Defaults to enabling Activity propagation.
- return true;
- }
-
- public static readonly DiagnosticListener s_diagnosticListener =
- new DiagnosticListener(DiagnosticsHandlerLoggingStrings.DiagnosticListenerName);
- }
-
private static void InjectHeaders(Activity currentActivity, HttpRequestMessage request)
{
+ const string TraceParentHeaderName = "traceparent";
+ const string TraceStateHeaderName = "tracestate";
+ const string RequestIdHeaderName = "Request-Id";
+ const string CorrelationContextHeaderName = "Correlation-Context";
+
if (currentActivity.IdFormat == ActivityIdFormat.W3C)
{
- if (!request.Headers.Contains(DiagnosticsHandlerLoggingStrings.TraceParentHeaderName))
+ if (!request.Headers.Contains(TraceParentHeaderName))
{
- request.Headers.TryAddWithoutValidation(DiagnosticsHandlerLoggingStrings.TraceParentHeaderName, currentActivity.Id);
+ request.Headers.TryAddWithoutValidation(TraceParentHeaderName, currentActivity.Id);
if (currentActivity.TraceStateString != null)
{
- request.Headers.TryAddWithoutValidation(DiagnosticsHandlerLoggingStrings.TraceStateHeaderName, currentActivity.TraceStateString);
+ request.Headers.TryAddWithoutValidation(TraceStateHeaderName, currentActivity.TraceStateString);
}
}
}
else
{
- if (!request.Headers.Contains(DiagnosticsHandlerLoggingStrings.RequestIdHeaderName))
+ if (!request.Headers.Contains(RequestIdHeaderName))
{
- request.Headers.TryAddWithoutValidation(DiagnosticsHandlerLoggingStrings.RequestIdHeaderName, currentActivity.Id);
+ request.Headers.TryAddWithoutValidation(RequestIdHeaderName, currentActivity.Id);
}
}
@@ -333,41 +312,16 @@ private static void InjectHeaders(Activity currentActivity, HttpRequestMessage r
baggage.Add(new NameValueHeaderValue(WebUtility.UrlEncode(item.Key), WebUtility.UrlEncode(item.Value)).ToString());
}
while (e.MoveNext());
- request.Headers.TryAddWithoutValidation(DiagnosticsHandlerLoggingStrings.CorrelationContextHeaderName, baggage);
+ request.Headers.TryAddWithoutValidation(CorrelationContextHeaderName, baggage);
}
}
}
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern",
Justification = "The values being passed into Write have the commonly used properties being preserved with DynamicDependency.")]
- private static void Write<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(
- DiagnosticSource diagnosticSource,
- string name,
- T value)
- {
- diagnosticSource.Write(name, value);
- }
-
- [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern",
- Justification = "The args being passed into StartActivity have the commonly used properties being preserved with DynamicDependency.")]
- private static Activity StartActivity<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(
- DiagnosticSource diagnosticSource,
- Activity activity,
- T? args)
+ private static void Write<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(string name, T value)
{
- return diagnosticSource.StartActivity(activity, args);
+ s_diagnosticListener.Write(name, value);
}
-
- [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern",
- Justification = "The args being passed into StopActivity have the commonly used properties being preserved with DynamicDependency.")]
- private static void StopActivity<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(
- DiagnosticSource diagnosticSource,
- Activity activity,
- T? args)
- {
- diagnosticSource.StopActivity(activity, args);
- }
-
- #endregion
}
}
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandlerLoggingStrings.cs b/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandlerLoggingStrings.cs
deleted file mode 100644
index 0fa57394c1cc3..0000000000000
--- a/src/libraries/System.Net.Http/src/System/Net/Http/DiagnosticsHandlerLoggingStrings.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace System.Net.Http
-{
- ///
- /// Defines names of DiagnosticListener and Write events for DiagnosticHandler
- ///
- internal static class DiagnosticsHandlerLoggingStrings
- {
- public const string DiagnosticListenerName = "HttpHandlerDiagnosticListener";
- public const string RequestWriteNameDeprecated = "System.Net.Http.Request";
- public const string ResponseWriteNameDeprecated = "System.Net.Http.Response";
-
- public const string ExceptionEventName = "System.Net.Http.Exception";
- public const string ActivityName = "System.Net.Http.HttpRequestOut";
- public const string ActivityStartName = "System.Net.Http.HttpRequestOut.Start";
-
- public const string RequestIdHeaderName = "Request-Id";
- public const string CorrelationContextHeaderName = "Correlation-Context";
-
- public const string TraceParentHeaderName = "traceparent";
- public const string TraceStateHeaderName = "tracestate";
- }
-}
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs
index 2e3289643cfbe..bfb8f6cae7834 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs
@@ -20,17 +20,17 @@ namespace System.Net.Http
public partial class HttpClientHandler : HttpMessageHandler
{
private readonly HttpHandlerType _underlyingHandler;
- private readonly DiagnosticsHandler? _diagnosticsHandler;
+ private readonly HttpMessageHandler _handler;
private ClientCertificateOption _clientCertificateOptions;
private volatile bool _disposed;
public HttpClientHandler()
{
- _underlyingHandler = new HttpHandlerType();
- if (DiagnosticsHandler.IsGloballyEnabled())
+ _handler = _underlyingHandler = new HttpHandlerType();
+ if (DiagnosticsHandler.IsGloballyEnabled)
{
- _diagnosticsHandler = new DiagnosticsHandler(_underlyingHandler);
+ _handler = new DiagnosticsHandler(_handler);
}
ClientCertificateOptions = ClientCertificateOption.Manual;
}
@@ -288,21 +288,11 @@ public SslProtocols SslProtocols
public IDictionary Properties => _underlyingHandler.Properties;
[UnsupportedOSPlatform("browser")]
- protected internal override HttpResponseMessage Send(HttpRequestMessage request,
- CancellationToken cancellationToken)
- {
- return DiagnosticsHandler.IsEnabled() && _diagnosticsHandler != null ?
- _diagnosticsHandler.Send(request, cancellationToken) :
- _underlyingHandler.Send(request, cancellationToken);
- }
+ protected internal override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationToken) =>
+ _handler.Send(request, cancellationToken);
- protected internal override Task SendAsync(HttpRequestMessage request,
- CancellationToken cancellationToken)
- {
- return DiagnosticsHandler.IsEnabled() && _diagnosticsHandler != null ?
- _diagnosticsHandler.SendAsync(request, cancellationToken) :
- _underlyingHandler.SendAsync(request, cancellationToken);
- }
+ protected internal override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) =>
+ _handler.SendAsync(request, cancellationToken);
// lazy-load the validator func so it can be trimmed by the ILLinker if it isn't used.
private static Func? s_dangerousAcceptAnyServerCertificateValidator;
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs
index 4b00bb31f652a..63427bb96b535 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs
@@ -173,7 +173,7 @@ public async Task SendAsync(CancellationToken cancellationT
// See Http2Connection.SendAsync for a full comment on this logic -- it is identical behavior.
if (sendContentTask.IsCompleted ||
_request.Content?.AllowDuplex != true ||
- sendContentTask == await Task.WhenAny(sendContentTask, readResponseTask).ConfigureAwait(false) ||
+ await Task.WhenAny(sendContentTask, readResponseTask).ConfigureAwait(false) == sendContentTask ||
sendContentTask.IsCompleted)
{
try
diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/DiagnosticsTests.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/DiagnosticsTests.cs
index 1fb6fd925fd33..66b60e800b8a7 100644
--- a/src/libraries/System.Net.Http/tests/FunctionalTests/DiagnosticsTests.cs
+++ b/src/libraries/System.Net.Http/tests/FunctionalTests/DiagnosticsTests.cs
@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Tracing;
+using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Net.Test.Common;
@@ -256,7 +257,7 @@ public void SendAsync_ExpectedDiagnosticCancelledLogging()
GetProperty(kvp.Value, "Request");
TaskStatus status = GetProperty(kvp.Value, "RequestTaskStatus");
Assert.Equal(TaskStatus.Canceled, status);
- activityStopTcs.SetResult();;
+ activityStopTcs.SetResult();
}
});
@@ -344,7 +345,7 @@ public void SendAsync_ExpectedDiagnosticSourceActivityLogging(ActivityIdFormat i
activityStopResponseLogged = GetProperty(kvp.Value, "Response");
TaskStatus requestStatus = GetProperty(kvp.Value, "RequestTaskStatus");
Assert.Equal(TaskStatus.RanToCompletion, requestStatus);
- activityStopTcs.SetResult();;
+ activityStopTcs.SetResult();
}
});
@@ -409,7 +410,7 @@ public void SendAsync_ExpectedDiagnosticSourceActivityLogging_InvalidBaggage()
Assert.Contains("goodkey=bad%2Fvalue", correlationContext);
TaskStatus requestStatus = GetProperty(kvp.Value, "RequestTaskStatus");
Assert.Equal(TaskStatus.RanToCompletion, requestStatus);
- activityStopTcs.SetResult();;
+ activityStopTcs.SetResult();
}
else if (kvp.Key.Equals("System.Net.Http.Exception"))
{
@@ -467,7 +468,7 @@ public void SendAsync_ExpectedDiagnosticSourceActivityLoggingDoesNotOverwriteHea
Assert.False(request.Headers.TryGetValues("traceparent", out var _));
Assert.False(request.Headers.TryGetValues("tracestate", out var _));
- activityStopTcs.SetResult();;
+ activityStopTcs.SetResult();
}
});
@@ -519,7 +520,7 @@ public void SendAsync_ExpectedDiagnosticSourceActivityLoggingDoesNotOverwriteW3C
}
else if (kvp.Key.Equals("System.Net.Http.HttpRequestOut.Stop"))
{
- activityStopTcs.SetResult();;
+ activityStopTcs.SetResult();
}
});
@@ -608,7 +609,7 @@ public void SendAsync_ExpectedDiagnosticExceptionActivityLogging()
GetProperty(kvp.Value, "Request");
TaskStatus requestStatus = GetProperty(kvp.Value, "RequestTaskStatus");
Assert.Equal(TaskStatus.Faulted, requestStatus);
- activityStopTcs.SetResult();;
+ activityStopTcs.SetResult();
}
else if (kvp.Key.Equals("System.Net.Http.Exception"))
{
@@ -647,7 +648,7 @@ public void SendAsync_ExpectedDiagnosticSynchronousExceptionActivityLogging()
GetProperty(kvp.Value, "Request");
TaskStatus requestStatus = GetProperty(kvp.Value, "RequestTaskStatus");
Assert.Equal(TaskStatus.Faulted, requestStatus);
- activityStopTcs.SetResult();;
+ activityStopTcs.SetResult();
}
else if (kvp.Key.Equals("System.Net.Http.Exception"))
{
@@ -796,44 +797,6 @@ public void SendAsync_ExpectedDiagnosticExceptionOnlyActivityLogging()
}, UseVersion.ToString(), TestAsync.ToString()).Dispose();
}
- [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
- public void SendAsync_ExpectedActivityPropagationWithoutListener()
- {
- RemoteExecutor.Invoke(async (useVersion, testAsync) =>
- {
- Activity parent = new Activity("parent").Start();
-
- await GetFactoryForVersion(useVersion).CreateClientAndServerAsync(
- async uri =>
- {
- await GetAsync(useVersion, testAsync, uri);
- },
- async server =>
- {
- HttpRequestData requestData = await server.AcceptConnectionSendResponseAndCloseAsync();
- AssertHeadersAreInjected(requestData, parent);
- });
- }, UseVersion.ToString(), TestAsync.ToString()).Dispose();
- }
-
- [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
- public void SendAsync_ExpectedActivityPropagationWithoutListenerOrParentActivity()
- {
- RemoteExecutor.Invoke(async (useVersion, testAsync) =>
- {
- await GetFactoryForVersion(useVersion).CreateClientAndServerAsync(
- async uri =>
- {
- await GetAsync(useVersion, testAsync, uri);
- },
- async server =>
- {
- HttpRequestData requestData = await server.AcceptConnectionSendResponseAndCloseAsync();
- AssertNoHeadersAreInjected(requestData);
- });
- }, UseVersion.ToString(), TestAsync.ToString()).Dispose();
- }
-
[ConditionalTheory(nameof(EnableActivityPropagationEnvironmentVariableIsNotSetAndRemoteExecutorSupported))]
[InlineData("true")]
[InlineData("1")]
@@ -899,6 +862,111 @@ await GetFactoryForVersion(useVersion).CreateClientAndServerAsync(
}, UseVersion.ToString(), TestAsync.ToString(), switchValue.ToString()).Dispose();
}
+ [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+ [InlineData(true, true, true)] // Activity was set and ActivitySource created an Activity
+ [InlineData(true, false, true)] // Activity was set and ActivitySource created an Activity
+ [InlineData(true, null, true)] // Activity was set and ActivitySource created an Activity
+ [InlineData(true, true, false)] // Activity was set, ActivitySource chose not to create an Activity, so one was manually created
+ [InlineData(true, false, false)] // Activity was set, ActivitySource chose not to create an Activity, so one was manually created
+ [InlineData(true, null, false)] // Activity was set, ActivitySource chose not to create an Activity, so one was manually created
+ [InlineData(true, true, null)] // Activity was set, ActivitySource had no listeners, so an Activity was manually created
+ [InlineData(true, false, null)] // Activity was set, ActivitySource had no listeners, so an Activity was manually created
+ [InlineData(true, null, null)] // Activity was set, ActivitySource had no listeners, so an Activity was manually created
+ [InlineData(false, true, true)] // DiagnosticListener requested an Activity and ActivitySource created an Activity
+ [InlineData(false, true, false)] // DiagnosticListener requested an Activity, ActivitySource chose not to create an Activity, so one was manually created
+ [InlineData(false, true, null)] // DiagnosticListener requested an Activity, ActivitySource had no listeners, so an Activity was manually created
+ [InlineData(false, false, true)] // No Activity is set, DiagnosticListener does not want one, but ActivitySource created an Activity
+ [InlineData(false, false, false)] // No Activity is set, DiagnosticListener does not want one and ActivitySource chose not to create an Activity
+ [InlineData(false, false, null)] // No Activity is set, DiagnosticListener does not want one and ActivitySource has no listeners
+ [InlineData(false, null, true)] // No Activity is set, there is no DiagnosticListener, but ActivitySource created an Activity
+ [InlineData(false, null, false)] // No Activity is set, there is no DiagnosticListener and ActivitySource chose not to create an Activity
+ [InlineData(false, null, null)] // No Activity is set, there is no DiagnosticListener and ActivitySource has no listeners
+ public void SendAsync_ActivityIsCreatedIfRequested(bool currentActivitySet, bool? diagnosticListenerActivityEnabled, bool? activitySourceCreatesActivity)
+ {
+ string parameters = $"{currentActivitySet},{diagnosticListenerActivityEnabled},{activitySourceCreatesActivity}";
+
+ RemoteExecutor.Invoke(async (useVersion, testAsync, parametersString) =>
+ {
+ bool?[] parameters = parametersString.Split(',').Select(p => p.Length == 0 ? (bool?)null : bool.Parse(p)).ToArray();
+ bool currentActivitySet = parameters[0].Value;
+ bool? diagnosticListenerActivityEnabled = parameters[1];
+ bool? activitySourceCreatesActivity = parameters[2];
+
+ bool madeASamplingDecision = false;
+ if (activitySourceCreatesActivity.HasValue)
+ {
+ ActivitySource.AddActivityListener(new ActivityListener
+ {
+ ShouldListenTo = _ => true,
+ Sample = (ref ActivityCreationOptions _) =>
+ {
+ madeASamplingDecision = true;
+ return activitySourceCreatesActivity.Value ? ActivitySamplingResult.AllData : ActivitySamplingResult.None;
+ }
+ });
+ }
+
+ bool listenerCallbackWasCalled = false;
+ IDisposable listenerSubscription = new MemoryStream(); // Dummy disposable
+ if (diagnosticListenerActivityEnabled.HasValue)
+ {
+ var diagnosticListenerObserver = new FakeDiagnosticListenerObserver(_ => listenerCallbackWasCalled = true);
+
+ diagnosticListenerObserver.Enable(name => !name.Contains("HttpRequestOut") || diagnosticListenerActivityEnabled.Value);
+
+ listenerSubscription = DiagnosticListener.AllListeners.Subscribe(diagnosticListenerObserver);
+ }
+
+ Activity activity = currentActivitySet ? new Activity("parent").Start() : null;
+
+ if (!currentActivitySet)
+ {
+ // Listen to new activity creations if an Activity was created without a parent
+ // (when a DiagnosticListener forced one to be created)
+ ActivitySource.AddActivityListener(new ActivityListener
+ {
+ ShouldListenTo = _ => true,
+ ActivityStarted = created =>
+ {
+ Assert.Null(activity);
+ activity = created;
+ }
+ });
+ }
+
+ using (listenerSubscription)
+ {
+ await GetFactoryForVersion(useVersion).CreateClientAndServerAsync(
+ async uri =>
+ {
+ await GetAsync(useVersion, testAsync, uri);
+ },
+ async server =>
+ {
+ HttpRequestData requestData = await server.AcceptConnectionSendResponseAndCloseAsync();
+
+ if (currentActivitySet || diagnosticListenerActivityEnabled == true || activitySourceCreatesActivity == true)
+ {
+ Assert.NotNull(activity);
+ AssertHeadersAreInjected(requestData, activity);
+ }
+ else
+ {
+ AssertNoHeadersAreInjected(requestData);
+
+ if (!currentActivitySet)
+ {
+ Assert.Null(activity);
+ }
+ }
+ });
+ }
+
+ Assert.Equal(activitySourceCreatesActivity.HasValue, madeASamplingDecision);
+ Assert.Equal(diagnosticListenerActivityEnabled.HasValue, listenerCallbackWasCalled);
+ }, UseVersion.ToString(), TestAsync.ToString(), parameters).Dispose();
+ }
+
private static T GetProperty(object obj, string propertyName)
{
Type t = obj.GetType();
diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs
index 9902e490ce5fb..d5c429466ae3c 100644
--- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs
+++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs
@@ -2876,14 +2876,18 @@ await LoopbackServerFactory.CreateClientAndServerAsync(
using HttpClient client = CreateHttpClient(handler);
- HttpRequestException hre = await Assert.ThrowsAnyAsync(async () => await client.SendAsync(requestMessage));
+ HttpRequestException hre =
+ await Assert.ThrowsAnyAsync(async () => await client.SendAsync(requestMessage))
+ .WaitAsync(TimeSpan.FromSeconds(10));
+
Assert.Equal(e, hre.InnerException);
},
async server =>
{
try
{
- await server.AcceptConnectionSendResponseAndCloseAsync(content: "foo");
+ await server.AcceptConnectionSendResponseAndCloseAsync(content: "foo")
+ .WaitAsync(TimeSpan.FromSeconds(15));
}
catch { }
}, options: options);
diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocksProxyTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocksProxyTest.cs
index 821794e9f82d5..24b8ce369e0fa 100644
--- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocksProxyTest.cs
+++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocksProxyTest.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Test.Common;
@@ -35,35 +36,119 @@ public async Task TestLoopbackAsync(string scheme, bool useSsl, bool useAuth, st
return;
}
- await LoopbackServerFactory.CreateClientAndServerAsync(
- async uri =>
- {
- using LoopbackSocksServer proxy = useAuth ? LoopbackSocksServer.Create("DOTNET", "424242") : LoopbackSocksServer.Create();
- using HttpClientHandler handler = CreateHttpClientHandler();
- using HttpClient client = CreateHttpClient(handler);
+ List<(int, long)> times = new List<(int, long)>();
+ Stopwatch s = Stopwatch.StartNew();
- handler.Proxy = new WebProxy($"{scheme}://127.0.0.1:{proxy.Port}");
- handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
-
- if (useAuth)
+ try
+ {
+ times.Add((0, s.ElapsedMilliseconds));
+ await LoopbackServerFactory.CreateClientAndServerAsync(
+ async uri =>
+ {
+ times.Add((10, s.ElapsedMilliseconds));
+ LoopbackSocksServer proxy = useAuth ? LoopbackSocksServer.Create("DOTNET", "424242") : LoopbackSocksServer.Create();
+ try
+ {
+ times.Add((11, s.ElapsedMilliseconds));
+ HttpClientHandler handler = CreateHttpClientHandler();
+ try
+ {
+ times.Add((12, s.ElapsedMilliseconds));
+ HttpClient client = CreateHttpClient(handler);
+ try
+ {
+ times.Add((13, s.ElapsedMilliseconds));
+
+ handler.Proxy = new WebProxy($"{scheme}://127.0.0.1:{proxy.Port}");
+ handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
+
+ if (useAuth)
+ {
+ handler.Proxy.Credentials = new NetworkCredential("DOTNET", "424242");
+ }
+
+ uri = new UriBuilder(uri) { Host = host }.Uri;
+
+ HttpRequestMessage request = CreateRequest(HttpMethod.Get, uri, UseVersion, exactVersion: true);
+
+ times.Add((14, s.ElapsedMilliseconds));
+
+ HttpResponseMessage response = await client.SendAsync(TestAsync, request);
+ try
+ {
+ times.Add((15, s.ElapsedMilliseconds));
+ string responseString = await response.Content.ReadAsStringAsync();
+ times.Add((16, s.ElapsedMilliseconds));
+ Assert.Equal("Echo", responseString);
+ times.Add((17, s.ElapsedMilliseconds));
+ }
+ catch
+ {
+ times.Add((43, s.ElapsedMilliseconds));
+ throw;
+ }
+ finally
+ {
+ times.Add((36, s.ElapsedMilliseconds));
+ response.Dispose();
+ times.Add((37, s.ElapsedMilliseconds));
+ }
+ }
+ catch
+ {
+ times.Add((42, s.ElapsedMilliseconds));
+ throw;
+ }
+ finally
+ {
+ times.Add((34, s.ElapsedMilliseconds));
+ client.Dispose();
+ times.Add((35, s.ElapsedMilliseconds));
+ }
+ }
+ catch
+ {
+ times.Add((41, s.ElapsedMilliseconds));
+ throw;
+ }
+ finally
+ {
+ times.Add((32, s.ElapsedMilliseconds));
+ //handler.Dispose();
+ times.Add((33, s.ElapsedMilliseconds));
+ }
+ }
+ catch
+ {
+ times.Add((40, s.ElapsedMilliseconds));
+ throw;
+ }
+ finally
+ {
+ times.Add((30, s.ElapsedMilliseconds));
+ proxy.Dispose();
+ times.Add((31, s.ElapsedMilliseconds));
+ }
+ },
+ async server =>
+ {
+ times.Add((20, s.ElapsedMilliseconds));
+ await server.HandleRequestAsync(content: "Echo");
+ times.Add((21, s.ElapsedMilliseconds));
+ },
+ options: new GenericLoopbackOptions
{
- handler.Proxy.Credentials = new NetworkCredential("DOTNET", "424242");
- }
-
- uri = new UriBuilder(uri) { Host = host }.Uri;
-
- HttpRequestMessage request = CreateRequest(HttpMethod.Get, uri, UseVersion, exactVersion: true);
-
- using HttpResponseMessage response = await client.SendAsync(TestAsync, request);
- string responseString = await response.Content.ReadAsStringAsync();
- Assert.Equal("Echo", responseString);
- },
- async server => await server.HandleRequestAsync(content: "Echo"),
- options: new GenericLoopbackOptions
- {
- UseSsl = useSsl,
- Address = host == "::1" ? IPAddress.IPv6Loopback : IPAddress.Loopback
- });
+ UseSsl = useSsl,
+ Address = host == "::1" ? IPAddress.IPv6Loopback : IPAddress.Loopback
+ },
+ times: times,
+ s: s);
+ }
+ catch (Exception ex)
+ {
+ times.Add((1, s.ElapsedMilliseconds));
+ throw new Exception(string.Join('\n', times.Select(t => $"{t.Item1,2} {t.Item2}")), ex);
+ }
}
public static IEnumerable
- runtimes/$(PackageRID)/native
+ runtimes/$(OutputRid)/native
diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt
index 038be0cbcf7cc..52a82116bc424 100644
--- a/src/mono/CMakeLists.txt
+++ b/src/mono/CMakeLists.txt
@@ -62,29 +62,6 @@ if(ENABLE_MINIMAL)
process_enable_minimal()
endif()
-#
-# This is the version of the corlib-runtime interface. When
-# making changes to this interface (by changing the layout
-# of classes the runtime knows about, changing icall signature or
-# semantics etc), change this variable.
-#
-# This must be unique relative to corlib interface and semantics.
-#
-# If you change corlib such that a runtime change is required, or
-# vice versa, change this string. Examples include removing icalls,
-# adding icalls, changing icall signatures, and changing type layouts
-# that both sides know.
-#
-# It is an arbitrary string and should be parsed as such.
-# A guid works and is encouraged.
-#
-# There is no ordering of corlib versions, no old or new,
-# an exact match is required between corlib and runtime.
-#
-# This line is parsed by other tools, it should remain in the format they expect.
-#
-set(MONO_CORLIB_VERSION 1A5E0066-58DC-428A-B21C-0AD6CDAE2789)
-
set(DISABLE_MDB 1)
set(DISABLE_COM 1)
set(DISABLE_PERFCOUNTERS 1)
@@ -726,6 +703,10 @@ else()
# FIXME:
set(NAME_DEV_RANDOM "\"/dev/random\"")
endif()
+
+if(HOST_LINUX AND HAVE_SYS_MMAN_H AND HAVE_ELF_H AND HAVE_SYS_SYSCALL_H)
+ set(ENABLE_JIT_DUMP 1)
+endif()
### End of other checks
######################################
diff --git a/src/mono/System.Private.CoreLib/GenerateMonoCoreLibVersionFile.targets b/src/mono/System.Private.CoreLib/GenerateMonoCoreLibVersionFile.targets
deleted file mode 100644
index b9bfab7bd6a4b..0000000000000
--- a/src/mono/System.Private.CoreLib/GenerateMonoCoreLibVersionFile.targets
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
- GenerateMonoCoreLibVersionFile;$(CompileDependsOn)
- $(IntermediateOutputPath)\Environment.MonoCoreLibVersion.cs
-
-
-
-
- <_MonoCoreLibVersionNumber>$([System.Text.RegularExpressions.Regex]::Match($([System.IO.File]::ReadAllText('$(MonoProjectRoot)\CMakeLists.txt')), 'MONO_CORLIB_VERSION ([a-fA-F0-9\-]+)').Groups[1].Value)
- <_MonoCoreLibVersionFileLines>
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-// This is a generated file. Do not edit.
-
-#pragma warning disable CA1823 // unused field
-namespace System
-{
- public partial class Environment
- {
- private const string mono_corlib_version = "$(_MonoCoreLibVersionNumber)"%3B
- }
-}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
index fd93f62380088..5290a6bc8c57f 100644
--- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -1,7 +1,4 @@

-
-
-
false
true
diff --git a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml
index f332a9d01cb80..eac1bad9a0b2a 100644
--- a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml
+++ b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml
@@ -129,8 +129,6 @@
-
-
diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs
index 5fb9e07417464..21ac12509e6be 100644
--- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs
+++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs
@@ -253,9 +253,7 @@ private static void AddPublicNestedTypes(Type type, List types, Listdomain) : NULL;
if (debug_info) {
offset_entries = debug_info->num_line_numbers;
- size_t needed_size = (offset_entries * sizeof (uint32_t) * 2);
- if (!events_data->buffer || needed_size > events_data->buffer_size) {
- g_free (events_data->buffer);
- events_data->buffer_size = (size_t)(needed_size * 1.5);
- events_data->buffer = g_new (uint8_t, events_data->buffer_size);
- }
+ if (offset_entries != 0) {
+ size_t needed_size = (offset_entries * sizeof (uint32_t) * 2);
+ if (!events_data->buffer || needed_size > events_data->buffer_size) {
+ g_free (events_data->buffer);
+ events_data->buffer_size = (size_t)(needed_size * 1.5);
+ events_data->buffer = g_new (uint8_t, events_data->buffer_size);
+ }
- if (events_data->buffer) {
- il_offsets = (uint32_t*)events_data->buffer;
- native_offsets = il_offsets + offset_entries;
+ if (events_data->buffer) {
+ il_offsets = (uint32_t*)events_data->buffer;
+ native_offsets = il_offsets + offset_entries;
- for (int offset_count = 0; offset_count < offset_entries; ++offset_count) {
- il_offsets [offset_count] = debug_info->line_numbers [offset_count].il_offset;
- native_offsets [offset_count] = debug_info->line_numbers [offset_count].native_offset;
+ for (int offset_count = 0; offset_count < offset_entries; ++offset_count) {
+ il_offsets [offset_count] = debug_info->line_numbers [offset_count].il_offset;
+ native_offsets [offset_count] = debug_info->line_numbers [offset_count].native_offset;
+ }
}
}
@@ -794,6 +824,21 @@ eventpipe_fire_method_events (
g_free (method_signature);
}
+static
+inline
+bool
+include_method (MonoMethod *method)
+{
+ if (!method) {
+ return false;
+ } else if (!m_method_is_wrapper (method)) {
+ return true;
+ } else {
+ WrapperInfo *wrapper = mono_marshal_get_wrapper_info (method);
+ return (wrapper && wrapper->subtype == WRAPPER_SUBTYPE_PINVOKE) ? true : false;
+ }
+}
+
static
void
eventpipe_fire_method_events_func (
@@ -805,7 +850,7 @@ eventpipe_fire_method_events_func (
if (ji && !ji->is_trampoline && !ji->async) {
MonoMethod *method = jinfo_get_method (ji);
- if (method && !m_method_is_wrapper (method))
+ if (include_method (method))
eventpipe_fire_method_events (ji, method, events_data);
}
}
@@ -899,15 +944,28 @@ eventpipe_execute_rundown (
if (root_domain) {
uint64_t domain_id = (uint64_t)root_domain;
- // Iterate all functions in use (JIT, AOT and Interpreter).
+ // Emit all functions in use (JIT, AOT and Interpreter).
EventPipeFireMethodEventsData events_data;
events_data.domain = root_domain;
events_data.buffer_size = 1024 * sizeof(uint32_t);
events_data.buffer = g_new (uint8_t, events_data.buffer_size);
events_data.method_events_func = method_events_func;
+
+ // All called JIT/AOT methods should be included in jit info table.
mono_jit_info_table_foreach_internal (eventpipe_fire_method_events_func, &events_data);
+
+ // All called interpreted methods should be included in interpreter jit info table.
if (mono_get_runtime_callbacks ()->is_interpreter_enabled())
mono_get_runtime_callbacks ()->interp_jit_info_foreach (eventpipe_fire_method_events_func, &events_data);
+
+ // Phantom methods injected in callstacks representing runtime functions.
+ if (_ep_rt_mono_runtime_helper_compile_method_jitinfo && _ep_rt_mono_runtime_helper_compile_method)
+ eventpipe_fire_method_events (_ep_rt_mono_runtime_helper_compile_method_jitinfo, _ep_rt_mono_runtime_helper_compile_method, &events_data);
+ if (_ep_rt_mono_monitor_enter_method_jitinfo && _ep_rt_mono_monitor_enter_method)
+ eventpipe_fire_method_events (_ep_rt_mono_monitor_enter_method_jitinfo, _ep_rt_mono_monitor_enter_method, &events_data);
+ if (_ep_rt_mono_monitor_enter_v4_method_jitinfo && _ep_rt_mono_monitor_enter_v4_method)
+ eventpipe_fire_method_events (_ep_rt_mono_monitor_enter_v4_method_jitinfo, _ep_rt_mono_monitor_enter_v4_method, &events_data);
+
g_free (events_data.buffer);
// Iterate all assemblies in domain.
@@ -936,17 +994,78 @@ eventpipe_execute_rundown (
return TRUE;
}
+inline
+static
+bool
+in_safe_point_frame (EventPipeStackContents *stack_content, WrapperInfo *wrapper)
+{
+ EP_ASSERT (stack_content != NULL);
+
+ // If top of stack is a managed->native icall wrapper for one of the below subtypes, we are at a safe point frame.
+ if (wrapper && ep_stack_contents_get_length (stack_content) == 0 && wrapper->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER &&
+ (wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_state_poll ||
+ wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_enter_gc_safe_region_unbalanced ||
+ wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_exit_gc_safe_region_unbalanced ||
+ wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_enter_gc_unsafe_region_unbalanced ||
+ wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_exit_gc_unsafe_region_unbalanced))
+ return true;
+
+ return false;
+}
+
+inline
+static
+bool
+in_runtime_invoke_frame (EventPipeStackContents *stack_content, WrapperInfo *wrapper)
+{
+ EP_ASSERT (stack_content != NULL);
+
+ // If top of stack is a managed->native runtime invoke wrapper, we are at a managed frame.
+ if (wrapper && ep_stack_contents_get_length (stack_content) == 0 &&
+ (wrapper->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL ||
+ wrapper->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT ||
+ wrapper->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DYNAMIC ||
+ wrapper->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL))
+ return true;
+
+ return false;
+}
+
+inline
+static
+bool
+in_monitor_enter_frame (WrapperInfo *wrapper)
+{
+ if (wrapper && wrapper->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER &&
+ (wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_monitor_enter_fast ||
+ wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_monitor_enter_internal))
+ return true;
+
+ return false;
+}
+
+inline
+static
+bool
+in_monitor_enter_v4_frame (WrapperInfo *wrapper)
+{
+ if (wrapper && wrapper->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER &&
+ (wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_monitor_enter_v4_fast ||
+ wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_monitor_enter_v4_internal))
+ return true;
+
+ return false;
+}
+
static
gboolean
eventpipe_walk_managed_stack_for_thread (
MonoStackFrameInfo *frame,
MonoContext *ctx,
- void *data,
- bool *async_frame,
- bool *safe_point_frame)
+ EventPipeStackWalkData *stack_walk_data)
{
EP_ASSERT (frame != NULL);
- EP_ASSERT (data != NULL);
+ EP_ASSERT (stack_walk_data != NULL);
switch (frame->type) {
case FRAME_TYPE_DEBUGGER_INVOKE:
@@ -955,23 +1074,41 @@ eventpipe_walk_managed_stack_for_thread (
case FRAME_TYPE_INTERP_TO_MANAGED:
case FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX:
case FRAME_TYPE_INTERP_ENTRY:
+ stack_walk_data->top_frame = false;
+ return FALSE;
+ case FRAME_TYPE_JIT_ENTRY:
+ // Frame in JIT compiler at top of callstack, add phantom frame representing call into JIT compiler.
+ // Makes it possible to detect stacks waiting on JIT compiler.
+ if (_ep_rt_mono_runtime_helper_compile_method && stack_walk_data->top_frame)
+ ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)_ep_rt_mono_runtime_helper_compile_method), _ep_rt_mono_runtime_helper_compile_method);
+ stack_walk_data->top_frame = false;
return FALSE;
case FRAME_TYPE_MANAGED:
case FRAME_TYPE_INTERP:
- if (!frame->ji)
- return FALSE;
- *async_frame |= frame->ji->async;
- MonoMethod *method = frame->ji->async ? NULL : frame->actual_method;
- if (method && m_method_is_wrapper (method)) {
- WrapperInfo *wrapper = mono_marshal_get_wrapper_info(method);
- if (wrapper && wrapper->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER && wrapper->d.icall.jit_icall_id == MONO_JIT_ICALL_mono_threads_state_poll)
- *safe_point_frame = true;
- } else if (method && !m_method_is_wrapper (method)) {
- ep_stack_contents_append ((EventPipeStackContents *)data, (uintptr_t)((uint8_t*)frame->ji->code_start + frame->native_offset), method);
- } else if (!method && frame->ji->async && !frame->ji->is_trampoline) {
- ep_stack_contents_append ((EventPipeStackContents *)data, (uintptr_t)((uint8_t*)frame->ji->code_start), method);
+ if (frame->ji) {
+ stack_walk_data->async_frame |= frame->ji->async;
+ MonoMethod *method = frame->ji->async ? NULL : frame->actual_method;
+ if (method && m_method_is_wrapper (method)) {
+ WrapperInfo *wrapper = mono_marshal_get_wrapper_info (method);
+ if (in_safe_point_frame (stack_walk_data->stack_contents, wrapper)) {
+ stack_walk_data->safe_point_frame = true;
+ }else if (in_runtime_invoke_frame (stack_walk_data->stack_contents, wrapper)) {
+ stack_walk_data->runtime_invoke_frame = true;
+ } else if (_ep_rt_mono_monitor_enter_method && in_monitor_enter_frame (wrapper)) {
+ ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)_ep_rt_mono_monitor_enter_method), _ep_rt_mono_monitor_enter_method);
+ } else if (_ep_rt_mono_monitor_enter_v4_method && in_monitor_enter_v4_frame (wrapper)) {
+ ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)_ep_rt_mono_monitor_enter_v4_method), _ep_rt_mono_monitor_enter_v4_method);
+ } else if (wrapper && wrapper->subtype == WRAPPER_SUBTYPE_PINVOKE) {
+ ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)frame->ji->code_start + frame->native_offset), method);
+ }
+ } else if (method && !m_method_is_wrapper (method)) {
+ ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)frame->ji->code_start + frame->native_offset), method);
+ } else if (!method && frame->ji->async && !frame->ji->is_trampoline) {
+ ep_stack_contents_append (stack_walk_data->stack_contents, (uintptr_t)((uint8_t*)frame->ji->code_start), method);
+ }
}
- return ep_stack_contents_get_length ((EventPipeStackContents *)data) >= EP_MAX_STACK_DEPTH;
+ stack_walk_data->top_frame = false;
+ return ep_stack_contents_get_length (stack_walk_data->stack_contents) >= EP_MAX_STACK_DEPTH;
default:
EP_UNREACHABLE ("eventpipe_walk_managed_stack_for_thread");
return FALSE;
@@ -985,9 +1122,7 @@ eventpipe_walk_managed_stack_for_thread_func (
MonoContext *ctx,
void *data)
{
- bool async_frame = false;
- bool safe_point_frame = false;
- return eventpipe_walk_managed_stack_for_thread (frame, ctx, data, &async_frame, &safe_point_frame);
+ return eventpipe_walk_managed_stack_for_thread (frame, ctx, (EventPipeStackWalkData *)data);
}
static
@@ -1000,7 +1135,7 @@ eventpipe_sample_profiler_walk_managed_stack_for_thread_func (
EP_ASSERT (frame != NULL);
EP_ASSERT (data != NULL);
- EventPipeSampleProfileData *sample_data = (EventPipeSampleProfileData *)data;
+ EventPipeSampleProfileStackWalkData *sample_data = (EventPipeSampleProfileStackWalkData *)data;
if (sample_data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR) {
switch (frame->type) {
@@ -1011,11 +1146,11 @@ eventpipe_sample_profiler_walk_managed_stack_for_thread_func (
case FRAME_TYPE_TRAMPOLINE:
sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
break;
+ case FRAME_TYPE_JIT_ENTRY:
+ sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
+ break;
case FRAME_TYPE_INTERP:
- if (frame->managed)
- sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
- else
- sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
+ sample_data->payload_data = frame->managed ? EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED : EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
break;
case FRAME_TYPE_INTERP_TO_MANAGED:
case FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX:
@@ -1025,7 +1160,7 @@ eventpipe_sample_profiler_walk_managed_stack_for_thread_func (
}
}
- return eventpipe_walk_managed_stack_for_thread (frame, ctx, &sample_data->stack_contents, &sample_data->async_frame, &sample_data->safe_point_frame);
+ return eventpipe_walk_managed_stack_for_thread (frame, ctx, &sample_data->stack_walk_data);
}
static
@@ -1051,6 +1186,65 @@ ep_rt_mono_init (void)
_ep_rt_mono_profiler = mono_profiler_create (NULL);
mono_profiler_set_thread_stopped_callback (_ep_rt_mono_profiler, profiler_eventpipe_thread_exited);
+
+ MonoMethodSignature *method_signature = mono_metadata_signature_alloc (mono_get_corlib (), 1);
+ if (method_signature) {
+ method_signature->params[0] = m_class_get_byval_arg (mono_get_object_class());
+ method_signature->ret = m_class_get_byval_arg (mono_get_void_class());
+
+ ERROR_DECL (error);
+ MonoClass *runtime_helpers = mono_class_from_name_checked (mono_get_corlib (), "System.Runtime.CompilerServices", "RuntimeHelpers", error);
+ if (is_ok (error) && runtime_helpers) {
+ MonoMethodBuilder *method_builder = mono_mb_new (runtime_helpers, "CompileMethod", MONO_WRAPPER_RUNTIME_INVOKE);
+ if (method_builder) {
+ _ep_rt_mono_runtime_helper_compile_method = mono_mb_create_method (method_builder, method_signature, 1);
+ mono_mb_free (method_builder);
+ }
+ }
+ mono_error_cleanup (error);
+ mono_metadata_free_method_signature (method_signature);
+
+ _ep_rt_mono_runtime_helper_compile_method_jitinfo = (MonoJitInfo *)g_new0 (MonoJitInfo, 1);
+ if (_ep_rt_mono_runtime_helper_compile_method) {
+ _ep_rt_mono_runtime_helper_compile_method_jitinfo->code_start = MINI_FTNPTR_TO_ADDR (_ep_rt_mono_runtime_helper_compile_method);
+ _ep_rt_mono_runtime_helper_compile_method_jitinfo->code_size = 20;
+ _ep_rt_mono_runtime_helper_compile_method_jitinfo->d.method = _ep_rt_mono_runtime_helper_compile_method;
+ }
+ }
+
+ {
+ ERROR_DECL (error);
+ MonoMethodDesc *desc = NULL;
+ MonoClass *monitor = mono_class_from_name_checked (mono_get_corlib (), "System.Threading", "Monitor", error);
+ if (is_ok (error) && monitor) {
+ desc = mono_method_desc_new ("Monitor:Enter(object,bool&)", FALSE);
+ if (desc) {
+ _ep_rt_mono_monitor_enter_v4_method = mono_method_desc_search_in_class (desc, monitor);
+ mono_method_desc_free (desc);
+
+ _ep_rt_mono_monitor_enter_v4_method_jitinfo = (MonoJitInfo *)g_new0 (MonoJitInfo, 1);
+ if (_ep_rt_mono_monitor_enter_v4_method_jitinfo) {
+ _ep_rt_mono_monitor_enter_v4_method_jitinfo->code_start = MINI_FTNPTR_TO_ADDR (_ep_rt_mono_monitor_enter_v4_method);
+ _ep_rt_mono_monitor_enter_v4_method_jitinfo->code_size = 20;
+ _ep_rt_mono_monitor_enter_v4_method_jitinfo->d.method = _ep_rt_mono_monitor_enter_v4_method;
+ }
+ }
+
+ desc = mono_method_desc_new ("Monitor:Enter(object)", FALSE);
+ if (desc) {
+ _ep_rt_mono_monitor_enter_method = mono_method_desc_search_in_class (desc, monitor);
+ mono_method_desc_free (desc);
+
+ _ep_rt_mono_monitor_enter_method_jitinfo = (MonoJitInfo *)g_new0 (MonoJitInfo, 1);
+ if (_ep_rt_mono_monitor_enter_method_jitinfo) {
+ _ep_rt_mono_monitor_enter_method_jitinfo->code_start = MINI_FTNPTR_TO_ADDR (_ep_rt_mono_monitor_enter_method);
+ _ep_rt_mono_monitor_enter_method_jitinfo->code_size = 20;
+ _ep_rt_mono_monitor_enter_method_jitinfo->d.method = _ep_rt_mono_monitor_enter_method;
+ }
+ }
+ }
+ mono_error_cleanup (error);
+ }
}
void
@@ -1082,6 +1276,20 @@ ep_rt_mono_fini (void)
if (_ep_rt_mono_initialized)
mono_rand_close (_ep_rt_mono_rand_provider);
+ g_free (_ep_rt_mono_runtime_helper_compile_method_jitinfo);
+ _ep_rt_mono_runtime_helper_compile_method_jitinfo = NULL;
+
+ mono_free_method (_ep_rt_mono_runtime_helper_compile_method);
+ _ep_rt_mono_runtime_helper_compile_method = NULL;
+
+ g_free (_ep_rt_mono_monitor_enter_method_jitinfo);
+ _ep_rt_mono_monitor_enter_method_jitinfo = NULL;
+ _ep_rt_mono_monitor_enter_method = NULL;
+
+ g_free (_ep_rt_mono_monitor_enter_v4_method_jitinfo);
+ _ep_rt_mono_monitor_enter_v4_method_jitinfo = NULL;
+ _ep_rt_mono_monitor_enter_v4_method = NULL;
+
_ep_rt_mono_sampled_thread_callstacks = NULL;
_ep_rt_mono_rand_provider = NULL;
_ep_rt_mono_initialized = FALSE;
@@ -1126,6 +1334,41 @@ ep_rt_mono_thread_attach (bool background_thread)
return thread;
}
+void *
+ep_rt_mono_thread_attach_2 (bool background_thread, EventPipeThreadType thread_type)
+{
+ void *result = ep_rt_mono_thread_attach (background_thread);
+ if (result && thread_type == EP_THREAD_TYPE_SAMPLING) {
+ // Increase sampling thread priority, accepting failures.
+#ifdef HOST_WIN32
+ SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
+#elif _POSIX_PRIORITY_SCHEDULING
+ int policy;
+ int priority;
+ struct sched_param param;
+ int schedparam_result = pthread_getschedparam (pthread_self (), &policy, ¶m);
+ if (schedparam_result == 0) {
+ // Attempt to switch the thread to real time scheduling. This will not
+ // necessarily work on all OSs; for example, most Linux systems will give
+ // us EPERM here unless configured to allow this.
+ priority = param.sched_priority;
+ param.sched_priority = sched_get_priority_max (SCHED_RR);
+ if (param.sched_priority != -1) {
+ schedparam_result = pthread_setschedparam (pthread_self (), SCHED_RR, ¶m);
+ if (schedparam_result != 0) {
+ // Fallback, attempt to increase to max priority using current policy.
+ param.sched_priority = sched_get_priority_max (policy);
+ if (param.sched_priority != -1 && param.sched_priority != priority)
+ pthread_setschedparam (pthread_self (), policy, ¶m);
+ }
+ }
+ }
+#endif
+ }
+
+ return result;
+}
+
void
ep_rt_mono_thread_detach (void)
{
@@ -1446,10 +1689,17 @@ ep_rt_mono_walk_managed_stack_for_thread (
{
EP_ASSERT (thread != NULL && stack_contents != NULL);
+ EventPipeStackWalkData stack_walk_data;
+ stack_walk_data.stack_contents = stack_contents;
+ stack_walk_data.top_frame = true;
+ stack_walk_data.async_frame = false;
+ stack_walk_data.safe_point_frame = false;
+ stack_walk_data.runtime_invoke_frame = false;
+
if (thread == ep_rt_thread_get_handle () && mono_get_eh_callbacks ()->mono_walk_stack_with_ctx)
- mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (eventpipe_walk_managed_stack_for_thread_func, NULL, MONO_UNWIND_SIGNAL_SAFE, stack_contents);
+ mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (eventpipe_walk_managed_stack_for_thread_func, NULL, MONO_UNWIND_SIGNAL_SAFE, &stack_walk_data);
else if (mono_get_eh_callbacks ()->mono_walk_stack_with_state)
- mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_walk_managed_stack_for_thread_func, mono_thread_info_get_suspend_state (thread), MONO_UNWIND_SIGNAL_SAFE, stack_contents);
+ mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_walk_managed_stack_for_thread_func, mono_thread_info_get_suspend_state (thread), MONO_UNWIND_SIGNAL_SAFE, &stack_walk_data);
return true;
}
@@ -1503,7 +1753,7 @@ ep_rt_mono_sample_profiler_write_sampling_event_for_threads (
// Sample profiler only runs on one thread, no need to synchorinize.
if (!_ep_rt_mono_sampled_thread_callstacks)
- _ep_rt_mono_sampled_thread_callstacks = g_array_sized_new (FALSE, FALSE, sizeof (EventPipeSampleProfileData), _ep_rt_mono_max_sampled_thread_count);
+ _ep_rt_mono_sampled_thread_callstacks = g_array_sized_new (FALSE, FALSE, sizeof (EventPipeSampleProfileStackWalkData), _ep_rt_mono_max_sampled_thread_count);
// Make sure there is room based on previous max number of sampled threads.
// NOTE, there is a chance there are more threads than max, if that's the case we will
@@ -1524,16 +1774,22 @@ ep_rt_mono_sample_profiler_write_sampling_event_for_threads (
MonoThreadUnwindState *thread_state = mono_thread_info_get_suspend_state (thread_info);
if (thread_state->valid) {
if (sampled_thread_count < _ep_rt_mono_max_sampled_thread_count) {
- EventPipeSampleProfileData *data = &g_array_index (_ep_rt_mono_sampled_thread_callstacks, EventPipeSampleProfileData, sampled_thread_count);
+ EventPipeSampleProfileStackWalkData *data = &g_array_index (_ep_rt_mono_sampled_thread_callstacks, EventPipeSampleProfileStackWalkData, sampled_thread_count);
data->thread_id = ep_rt_thread_id_t_to_uint64_t (mono_thread_info_get_tid (thread_info));
data->thread_ip = (uintptr_t)MONO_CONTEXT_GET_IP (&thread_state->ctx);
data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR;
- data->async_frame = FALSE;
- data->safe_point_frame = FALSE;
+ data->stack_walk_data.stack_contents = &data->stack_contents;
+ data->stack_walk_data.top_frame = true;
+ data->stack_walk_data.async_frame = false;
+ data->stack_walk_data.safe_point_frame = false;
+ data->stack_walk_data.runtime_invoke_frame = false;
ep_stack_contents_reset (&data->stack_contents);
- mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_sample_profiler_walk_managed_stack_for_thread_func, thread_state, MONO_UNWIND_SIGNAL_SAFE, data);
- if (data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL && data->safe_point_frame)
+ mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_sample_profiler_walk_managed_stack_for_thread_func, thread_state, MONO_UNWIND_SIGNAL_SAFE, data);
+ if (data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL && (data->stack_walk_data.safe_point_frame || data->stack_walk_data.runtime_invoke_frame)) {
+ // If classified as external code (managed->native frame on top of stack), but have a safe point or runtime invoke frame
+ // as second, re-classify current callstack to be executing managed code.
data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
+ }
sampled_thread_count++;
}
@@ -1550,12 +1806,12 @@ ep_rt_mono_sample_profiler_write_sampling_event_for_threads (
// adapter instance and only set recorded tid as parameter inside adapter.
THREAD_INFO_TYPE adapter = { { 0 } };
for (uint32_t i = 0; i < sampled_thread_count; ++i) {
- EventPipeSampleProfileData *data = &g_array_index (_ep_rt_mono_sampled_thread_callstacks, EventPipeSampleProfileData, i);
+ EventPipeSampleProfileStackWalkData *data = &g_array_index (_ep_rt_mono_sampled_thread_callstacks, EventPipeSampleProfileStackWalkData, i);
if (data->payload_data != EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR && ep_stack_contents_get_length(&data->stack_contents) > 0) {
// Check if we have an async frame, if so we will need to make sure all frames are registered in regular jit info table.
// TODO: An async frame can contain wrapper methods (no way to check during stackwalk), we could skip writing profile event
// for this specific stackwalk or we could cleanup stack_frames before writing profile event.
- if (data->async_frame) {
+ if (data->stack_walk_data.async_frame) {
for (int i = 0; i < data->stack_contents.next_available_frame; ++i)
mono_jit_info_table_find_internal ((gpointer)data->stack_contents.stack_frames [i], TRUE, FALSE);
}
@@ -1720,19 +1976,21 @@ ep_rt_mono_write_event_method_il_to_native_map (
MonoDebugMethodJitInfo *debug_info = method ? mono_debug_find_method (method, root_domain) : NULL;
if (debug_info) {
- offset_entries = debug_info->num_line_numbers;
- size_t needed_size = (offset_entries * sizeof (uint32_t) * 2);
- if (needed_size > sizeof (fixed_buffer)) {
- buffer = g_new (uint8_t, needed_size);
- il_offsets = (uint32_t*)buffer;
- } else {
- il_offsets = fixed_buffer;
- }
- if (il_offsets) {
- native_offsets = il_offsets + offset_entries;
- for (int offset_count = 0; offset_count < offset_entries; ++offset_count) {
- il_offsets [offset_count] = debug_info->line_numbers [offset_count].il_offset;
- native_offsets [offset_count] = debug_info->line_numbers [offset_count].native_offset;
+ if (offset_entries != 0) {
+ offset_entries = debug_info->num_line_numbers;
+ size_t needed_size = (offset_entries * sizeof (uint32_t) * 2);
+ if (needed_size > sizeof (fixed_buffer)) {
+ buffer = g_new (uint8_t, needed_size);
+ il_offsets = (uint32_t*)buffer;
+ } else {
+ il_offsets = fixed_buffer;
+ }
+ if (il_offsets) {
+ native_offsets = il_offsets + offset_entries;
+ for (int offset_count = 0; offset_count < offset_entries; ++offset_count) {
+ il_offsets [offset_count] = debug_info->line_numbers [offset_count].il_offset;
+ native_offsets [offset_count] = debug_info->line_numbers [offset_count].native_offset;
+ }
}
}
diff --git a/src/mono/mono/eventpipe/ep-rt-mono.h b/src/mono/mono/eventpipe/ep-rt-mono.h
index 22bdccdcd7df2..2c3a5f7e36d70 100644
--- a/src/mono/mono/eventpipe/ep-rt-mono.h
+++ b/src/mono/mono/eventpipe/ep-rt-mono.h
@@ -527,6 +527,15 @@ ep_rt_mono_thread_setup (bool background_thread)
ep_rt_mono_thread_attach (background_thread);
}
+static
+inline
+void
+ep_rt_mono_thread_setup_2 (bool background_thread, EventPipeThreadType thread_type)
+{
+ extern void * ep_rt_mono_thread_attach_2 (bool background_thread, EventPipeThreadType thread_type);
+ ep_rt_mono_thread_attach_2 (background_thread, thread_type);
+}
+
static
inline
void
@@ -1233,7 +1242,7 @@ EP_RT_DEFINE_THREAD_FUNC (ep_rt_thread_mono_start_func)
{
rt_mono_thread_params_internal_t *thread_params = (rt_mono_thread_params_internal_t *)data;
- ep_rt_mono_thread_setup (thread_params->background_thread);
+ ep_rt_mono_thread_setup_2 (thread_params->background_thread, thread_params->thread_params.thread_type);
thread_params->thread_params.thread = ep_rt_thread_get_handle ();
mono_thread_start_return_t result = thread_params->thread_params.thread_func (thread_params);
diff --git a/src/mono/mono/metadata/appdomain.c b/src/mono/mono/metadata/appdomain.c
index 1e9b3d213839d..09d8c4527e3e1 100644
--- a/src/mono/mono/metadata/appdomain.c
+++ b/src/mono/mono/metadata/appdomain.c
@@ -309,37 +309,6 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT
HANDLE_FUNCTION_RETURN ();
}
-static char*
-mono_get_corlib_version (void)
-{
- ERROR_DECL (error);
-
- MonoClass *klass;
- MonoClassField *field;
-
- klass = mono_class_load_from_name (mono_defaults.corlib, "System", "Environment");
- mono_class_init_internal (klass);
- field = mono_class_get_field_from_name_full (klass, "mono_corlib_version", NULL);
- if (!field)
- return NULL;
-
- if (! (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_LITERAL)))
- return NULL;
-
- char *value;
- MonoTypeEnum field_type;
- const char *data = mono_class_get_field_default_value (field, &field_type);
- if (field_type != MONO_TYPE_STRING)
- return NULL;
- mono_metadata_read_constant_value (data, field_type, &value, error);
- mono_error_assert_ok (error);
-
- char *res = mono_string_from_blob (value, error);
- mono_error_assert_ok (error);
-
- return res;
-}
-
/**
* mono_check_corlib_version:
* Checks that the corlib that is loaded matches the version of this runtime.
@@ -364,18 +333,6 @@ mono_check_corlib_version_internal (void)
return NULL;
#else
char *result = NULL;
- char *version = mono_get_corlib_version ();
- if (!version) {
- result = g_strdup_printf ("expected corlib string (%s) but not found or not string", MONO_CORLIB_VERSION);
- goto exit;
- }
- if (strcmp (version, MONO_CORLIB_VERSION) != 0) {
- result = g_strdup_printf ("The runtime did not find the mscorlib.dll it expected. "
- "Expected interface version %s but found %s. Check that "
- "your runtime and class libraries are matching.",
- MONO_CORLIB_VERSION, version);
- goto exit;
- }
/* Check that the managed and unmanaged layout of MonoInternalThread matches */
guint32 native_offset;
@@ -384,8 +341,6 @@ mono_check_corlib_version_internal (void)
managed_offset = mono_field_get_offset (mono_class_get_field_from_name_full (mono_defaults.internal_thread_class, "last", NULL));
if (native_offset != managed_offset)
result = g_strdup_printf ("expected InternalThread.last field offset %u, found %u. See InternalThread.last comment", native_offset, managed_offset);
-exit:
- g_free (version);
return result;
#endif
}
diff --git a/src/mono/mono/metadata/components.c b/src/mono/mono/metadata/components.c
index d0a2c1257f23d..242580434fd37 100644
--- a/src/mono/mono/metadata/components.c
+++ b/src/mono/mono/metadata/components.c
@@ -16,17 +16,23 @@
#include "mono/utils/mono-logger-internals.h"
#include "mono/utils/mono-path.h"
#include "mono/utils/mono-time.h"
+#include "mono/utils/refcount.h"
static gint64 event_pipe_100ns_ticks;
typedef MonoComponent * (*MonoComponentInitFn) (void);
+typedef struct _MonoComponentLibrary {
+ MonoRefCount ref;
+ MonoDl *lib;
+} MonoComponentLibrary;
+
typedef struct _MonoComponentEntry {
const char *lib_name;
const char *name;
MonoComponentInitFn init;
MonoComponent **component;
- MonoDl *lib;
+ MonoComponentLibrary *lib;
} MonoComponentEntry;
#define COMPONENT_INIT_FUNC(name) (MonoComponentInitFn) mono_component_ ## name ## _init
@@ -58,8 +64,10 @@ MonoComponentEntry components[] = {
};
#ifndef STATIC_COMPONENTS
+static GHashTable *component_library_load_history = NULL;
+
static MonoComponent*
-get_component (const MonoComponentEntry *component, MonoDl **component_lib);
+get_component (const MonoComponentEntry *component, MonoComponentLibrary **component_lib);
#endif
void
@@ -82,12 +90,14 @@ mono_components_init (void)
for (int i = 0; i < G_N_ELEMENTS (components); ++i)
*components [i].component = components [i].init ();
#else
+ component_library_load_history = g_hash_table_new (g_str_hash, g_str_equal);
+
/* call get_component for each component and init it or its stubs and add it to loaded_components */
- MonoDl *lib = NULL;
+ MonoComponentLibrary *component_lib = NULL;
for (int i = 0; i < G_N_ELEMENTS (components); ++i) {
- *components [i].component = get_component (&components [i], &lib);
- components [i].lib = lib;
+ *components [i].component = get_component (&components [i], &component_lib);
+ components [i].lib = component_lib;
if (!*components [i].component)
*components [i].component = components [i].init ();
}
@@ -106,11 +116,11 @@ component_init_name (const MonoComponentEntry *component)
}
static gpointer
-load_component_entrypoint (MonoDl *lib, const MonoComponentEntry *component)
+load_component_entrypoint (MonoComponentLibrary *component_lib, const MonoComponentEntry *component)
{
char *component_init = component_init_name (component);
gpointer sym = NULL;
- char *error_msg = mono_dl_symbol (lib, component_init, &sym);
+ char *error_msg = mono_dl_symbol (component_lib->lib, component_init, &sym);
if (error_msg) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Component %s library does not have symbol %s: %s", component->name, component_init, error_msg);
g_free (error_msg);
@@ -150,59 +160,76 @@ try_load (const char* dir, const MonoComponentEntry *component, const char* comp
char *path = NULL;
void *iter = NULL;
- while ((path = mono_dl_build_path (dir, component_base_lib, &iter))) {
+ while (lib == NULL && (path = mono_dl_build_platform_path (dir, component_base_lib, &iter))) {
char *error_msg = NULL;
lib = mono_dl_open (path, MONO_DL_EAGER | MONO_DL_LOCAL, &error_msg);
- if (lib)
- break;
if (!lib) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Component %s not found: %s", component->name, error_msg);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Component library %s not found at %s: %s", component_base_lib, path, error_msg);
+ g_free (error_msg);
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Component library %s found at %s", component_base_lib, path);
}
- g_free (error_msg);
g_free (path);
}
- if (lib)
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Component %s found at %s", component->name, path);
- g_free (path);
+
return lib;
}
+
+
static MonoComponentInitFn
-load_component (const MonoComponentEntry *component, MonoDl **lib_out)
+load_component (const MonoComponentEntry *component, MonoComponentLibrary **component_lib_out)
{
// If init method has been static linked not using stub library, use that instead of dynamic component.
if (component->init() && component->init()->available ()) {
- *lib_out = NULL;
+ *component_lib_out = NULL;
return component->init;
}
char *component_base_lib = component_library_base_name (component);
MonoComponentInitFn result = NULL;
+ MonoComponentLibrary *component_lib = NULL;
- /* FIXME: just copy what mono_profiler_load does, assuming it works */
+ // Check history of component library loads to reduce try_load attempts (optimization for libraries hosting multiple components).
+ if (!g_hash_table_lookup_extended (component_library_load_history, component_base_lib, NULL, (gpointer *)&component_lib)) {
+ MonoDl *lib = NULL;
+#if !defined(HOST_IOS) && !defined(HOST_TVOS) && !defined(HOST_WATCHOS) && !defined(HOST_MACCAT) && !defined(HOST_ANDROID)
+ lib = try_load (components_dir (), component, component_base_lib);
+#endif
+ if (!lib)
+ lib = try_load (NULL, component, component_base_lib);
- /* FIXME: do I need to provide a path? */
- MonoDl *lib = NULL;
- lib = try_load (components_dir (), component, component_base_lib);
- if (!lib)
- lib = try_load (NULL, component, component_base_lib);
+ component_lib = g_new0 (MonoComponentLibrary, 1);
+ if (component_lib) {
+ mono_refcount_init (component_lib, NULL);
+ component_lib->lib = lib;
+ }
- g_free (component_base_lib);
- if (!lib)
+ g_hash_table_insert (component_library_load_history, g_strdup (component_base_lib), (gpointer)component_lib);
+ }
+
+ if (!component_lib || !component_lib->lib) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Component %s not found", component->name);
goto done;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Component %s found in %s", component->name, component_base_lib);
- gpointer sym = load_component_entrypoint (lib, component);
+ gpointer sym = load_component_entrypoint (component_lib, component);
result = (MonoComponentInitFn)sym;
- *lib_out = lib;
+
+ mono_refcount_inc (component_lib);
+ *component_lib_out = component_lib;
done:
+ g_free (component_base_lib);
return result;
}
MonoComponent*
-get_component (const MonoComponentEntry *component, MonoDl **lib_out)
+get_component (const MonoComponentEntry *component, MonoComponentLibrary **component_lib_out)
{
- MonoComponentInitFn initfn = load_component (component, lib_out);
+ MonoComponentInitFn initfn = load_component (component, component_lib_out);
if (!initfn)
return NULL;
return initfn();
diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c
index 84fc4df27c1b2..d725b1c3b5fd1 100644
--- a/src/mono/mono/metadata/icall.c
+++ b/src/mono/mono/metadata/icall.c
@@ -4462,12 +4462,18 @@ MonoStringHandle
ves_icall_System_Reflection_RuntimeAssembly_get_code_base (MonoReflectionAssemblyHandle assembly, MonoError *error)
{
MonoAssembly *mass = MONO_HANDLE_GETVAL (assembly, assembly);
- gchar *absolute;
- if (g_path_is_absolute (mass->image->name)) {
- absolute = g_strdup (mass->image->name);
+ /* return NULL for bundled assemblies in single-file scenarios */
+ const char* filename = m_image_get_filename (mass->image);
+
+ if (!filename)
+ return NULL_HANDLE_STRING;
+
+ gchar *absolute;
+ if (g_path_is_absolute (filename)) {
+ absolute = g_strdup (filename);
} else {
- absolute = g_build_filename (mass->basedir, mass->image->name, (const char*)NULL);
+ absolute = g_build_filename (mass->basedir, filename, (const char*)NULL);
}
mono_icall_make_platform_path (absolute);
diff --git a/src/mono/mono/metadata/loader.c b/src/mono/mono/metadata/loader.c
index f16c8c36f8147..fc64623fad652 100644
--- a/src/mono/mono/metadata/loader.c
+++ b/src/mono/mono/metadata/loader.c
@@ -1657,6 +1657,7 @@ stack_walk_adapter (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data)
case FRAME_TYPE_INTERP_TO_MANAGED:
case FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX:
case FRAME_TYPE_INTERP_ENTRY:
+ case FRAME_TYPE_JIT_ENTRY:
return FALSE;
case FRAME_TYPE_MANAGED:
case FRAME_TYPE_INTERP:
diff --git a/src/mono/mono/metadata/method-builder.h b/src/mono/mono/metadata/method-builder.h
index d746fd3806c29..fd3903c866445 100644
--- a/src/mono/mono/metadata/method-builder.h
+++ b/src/mono/mono/metadata/method-builder.h
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
typedef struct _MonoMethodBuilder MonoMethodBuilder;
@@ -30,16 +31,16 @@ typedef struct {
MonoMethod* (*create_method) (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack);
} MonoMethodBuilderCallbacks;
-MonoMethodBuilder *
+MONO_COMPONENT_API MonoMethodBuilder *
mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type);
MonoMethodBuilder *
mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType type);
-void
+MONO_COMPONENT_API void
mono_mb_free (MonoMethodBuilder *mb);
-MonoMethod *
+MONO_COMPONENT_API MonoMethod *
mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack);
guint32
diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c
index 10808d2144b13..6867a07379cd8 100644
--- a/src/mono/mono/metadata/native-library.c
+++ b/src/mono/mono/metadata/native-library.c
@@ -493,12 +493,11 @@ static MonoDl *
netcore_probe_for_module_variations (const char *mdirname, const char *file_name, int raw_flags)
{
void *iter = NULL;
- char *full_name;
+ char *full_name = NULL;
MonoDl *module = NULL;
- // FIXME: this appears to search *.dylib twice for some reason
- while ((full_name = mono_dl_build_path (mdirname, file_name, &iter)) && module == NULL) {
- char *error_msg;
+ while (module == NULL && (full_name = mono_dl_build_path (mdirname, file_name, &iter))) {
+ char *error_msg = NULL;
module = mono_dl_open_full (full_name, MONO_DL_LAZY, raw_flags, &error_msg);
if (!module) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "DllImport error loading library '%s': '%s'.", full_name, error_msg);
@@ -506,7 +505,6 @@ netcore_probe_for_module_variations (const char *mdirname, const char *file_name
}
g_free (full_name);
}
- g_free (full_name);
return module;
}
diff --git a/src/mono/mono/mini/mini-exceptions.c b/src/mono/mono/mini/mini-exceptions.c
index d6df5b150120d..eea17726ba2e0 100644
--- a/src/mono/mono/mini/mini-exceptions.c
+++ b/src/mono/mono/mini/mini-exceptions.c
@@ -450,6 +450,8 @@ arch_unwind_frame (MonoJitTlsData *jit_tls,
frame->type = FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX;
memcpy (new_ctx, &ext->ctx, sizeof (MonoContext));
}
+ } else if (ext->kind == MONO_LMFEXT_JIT_ENTRY) {
+ frame->type = FRAME_TYPE_JIT_ENTRY;
} else {
g_assert_not_reached ();
}
@@ -1873,6 +1875,7 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
case FRAME_TYPE_INTERP_TO_MANAGED:
case FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX:
case FRAME_TYPE_INTERP_ENTRY:
+ case FRAME_TYPE_JIT_ENTRY:
continue;
case FRAME_TYPE_INTERP:
case FRAME_TYPE_MANAGED:
@@ -2278,6 +2281,7 @@ handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filt
case FRAME_TYPE_TRAMPOLINE:
case FRAME_TYPE_INTERP_TO_MANAGED:
case FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX:
+ case FRAME_TYPE_JIT_ENTRY:
*ctx = new_ctx;
continue;
case FRAME_TYPE_INTERP_ENTRY:
@@ -2722,6 +2726,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
case FRAME_TYPE_TRAMPOLINE:
case FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX:
case FRAME_TYPE_INTERP_ENTRY:
+ case FRAME_TYPE_JIT_ENTRY:
*ctx = new_ctx;
continue;
case FRAME_TYPE_INTERP_TO_MANAGED:
diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c
index 87f2070d38982..7ba23bd560f92 100644
--- a/src/mono/mono/mini/mini-runtime.c
+++ b/src/mono/mono/mini/mini-runtime.c
@@ -87,6 +87,7 @@
#include "mini-gc.h"
#include "mini-llvm.h"
+#include "llvm-runtime.h"
#include "lldb.h"
#include "mini-runtime.h"
#include "interp/interp.h"
@@ -2664,13 +2665,54 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, gboolean jit_
return p;
}
+typedef struct {
+ MonoMethod *method;
+ guint32 opt;
+ gboolean jit_only;
+ MonoError *error;
+ gpointer code;
+} JitCompileMethodWithOptCallbackData;
+
+static void
+jit_compile_method_with_opt_cb (gpointer arg)
+{
+ JitCompileMethodWithOptCallbackData *params = (JitCompileMethodWithOptCallbackData *)arg;
+ params->code = mono_jit_compile_method_with_opt (params->method, params->opt, params->jit_only, params->error);
+}
+
+static gpointer
+jit_compile_method_with_opt (JitCompileMethodWithOptCallbackData *params)
+{
+ MonoLMFExt ext;
+
+ memset (&ext, 0, sizeof (MonoLMFExt));
+ ext.kind = MONO_LMFEXT_JIT_ENTRY;
+ mono_push_lmf (&ext);
+
+ gboolean thrown = FALSE;
+#if defined(ENABLE_LLVM_RUNTIME) || defined(ENABLE_LLVM)
+ mono_llvm_cpp_catch_exception (jit_compile_method_with_opt_cb, params, &thrown);
+#else
+ jit_compile_method_with_opt_cb (params);
+#endif
+
+ mono_pop_lmf (&ext.lmf);
+
+ return !thrown ? params->code : NULL;
+}
+
gpointer
mono_jit_compile_method (MonoMethod *method, MonoError *error)
{
- gpointer code;
+ JitCompileMethodWithOptCallbackData params;
- code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), FALSE, error);
- return code;
+ params.method = method;
+ params.opt = mono_get_optimizations_for_method (method, default_opt);
+ params.jit_only = FALSE;
+ params.error = error;
+ params.code = NULL;
+
+ return jit_compile_method_with_opt (¶ms);
}
/*
@@ -2681,10 +2723,15 @@ mono_jit_compile_method (MonoMethod *method, MonoError *error)
gpointer
mono_jit_compile_method_jit_only (MonoMethod *method, MonoError *error)
{
- gpointer code;
+ JitCompileMethodWithOptCallbackData params;
- code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), TRUE, error);
- return code;
+ params.method = method;
+ params.opt = mono_get_optimizations_for_method (method, default_opt);
+ params.jit_only = TRUE;
+ params.error = error;
+ params.code = NULL;
+
+ return jit_compile_method_with_opt (¶ms);
}
/*
diff --git a/src/mono/mono/mini/mini-runtime.h b/src/mono/mono/mini/mini-runtime.h
index 57fb1b2982466..2e349a35ed031 100644
--- a/src/mono/mono/mini/mini-runtime.h
+++ b/src/mono/mono/mini/mini-runtime.h
@@ -197,6 +197,7 @@ struct MonoJitTlsData {
#define MONO_LMFEXT_DEBUGGER_INVOKE 1
#define MONO_LMFEXT_INTERP_EXIT 2
#define MONO_LMFEXT_INTERP_EXIT_WITH_CTX 3
+#define MONO_LMFEXT_JIT_ENTRY 4
/*
* The MonoLMF structure is arch specific, it includes at least these fields.
diff --git a/src/mono/mono/sgen/gc-internal-agnostic.h b/src/mono/mono/sgen/gc-internal-agnostic.h
index 73d431d54d8c7..581cdb4896e1b 100644
--- a/src/mono/mono/sgen/gc-internal-agnostic.h
+++ b/src/mono/mono/sgen/gc-internal-agnostic.h
@@ -110,7 +110,7 @@ word aligned or size is not a multiple of word size.
*/
void mono_gc_bzero_atomic (void *dest, size_t size);
void mono_gc_bzero_aligned (void *dest, size_t size);
-void mono_gc_memmove_atomic (void *dest, const void *src, size_t size);
+MONO_COMPONENT_API void mono_gc_memmove_atomic (void *dest, const void *src, size_t size);
void mono_gc_memmove_aligned (void *dest, const void *src, size_t size);
FILE *mono_gc_get_logfile (void);
diff --git a/src/mono/mono/utils/mono-dl.c b/src/mono/mono/utils/mono-dl.c
index eec013399de3a..166cd5d602a8f 100644
--- a/src/mono/mono/utils/mono-dl.c
+++ b/src/mono/mono/utils/mono-dl.c
@@ -390,35 +390,12 @@ mono_dl_close (MonoDl *module)
g_free (module);
}
-/**
- * mono_dl_build_path:
- * \param directory optional directory
- * \param name base name of the library
- * \param iter iterator token
- * Given a directory name and the base name of a library, iterate
- * over the possible file names of the library, taking into account
- * the possible different suffixes and prefixes on the host platform.
- *
- * The returned file name must be freed by the caller.
- * \p iter must point to a NULL pointer the first time the function is called
- * and then passed unchanged to the following calls.
- * \returns the filename or NULL at the end of the iteration
- */
-char*
-mono_dl_build_path (const char *directory, const char *name, void **iter)
-{
- int idx;
- const char *prefix;
- const char *suffix;
- gboolean need_prefix = TRUE, need_suffix = TRUE;
- int prlen;
- int suffixlen;
- char *res;
- int iteration;
-
- if (!iter)
- return NULL;
+typedef gboolean (*dl_library_name_formatting_func)(int idx, gboolean *need_prefix, gboolean *need_suffix, const char **suffix);
+static
+gboolean
+dl_default_library_name_formatting (int idx, gboolean *need_prefix, gboolean *need_suffix, const char **suffix)
+{
/*
The first time we are called, idx = 0 (as *iter is initialized to NULL). This is our
"bootstrap" phase in which we check the passed name verbatim and only if we fail to find
@@ -428,26 +405,79 @@ mono_dl_build_path (const char *directory, const char *name, void **iter)
libsomething.so.1.1 or libsomething.so - testing it algorithmically would be an overkill
here.
*/
- iteration = GPOINTER_TO_UINT (*iter);
- idx = iteration;
if (idx == 0) {
/* Name */
- need_prefix = FALSE;
- need_suffix = FALSE;
- suffix = "";
+ *need_prefix = FALSE;
+ *need_suffix = FALSE;
+ *suffix = "";
} else if (idx == 1) {
/* netcore system libs have a suffix but no prefix */
- need_prefix = FALSE;
- need_suffix = TRUE;
- suffix = mono_dl_get_so_suffixes () [0];
- suffixlen = strlen (suffix);
+ *need_prefix = FALSE;
+ *need_suffix = TRUE;
+ *suffix = mono_dl_get_so_suffixes () [0];
} else {
/* Prefix.Name.suffix */
- suffix = mono_dl_get_so_suffixes () [idx - 2];
- if (suffix [0] == '\0')
- return NULL;
+ *need_prefix = TRUE;
+ *need_suffix = TRUE;
+ *suffix = mono_dl_get_so_suffixes () [idx - 2];
+ if ((*suffix) [0] == '\0')
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static
+gboolean
+dl_reverse_library_name_formatting (int idx, gboolean *need_prefix, gboolean *need_suffix, const char **suffix)
+{
+ const char ** suffixes = mono_dl_get_so_suffixes ();
+ int suffix_count = 0;
+
+ while (suffixes [suffix_count][0] != '\0')
+ suffix_count++;
+
+ if (idx < suffix_count) {
+ /* Prefix.Name.suffix */
+ *need_prefix = TRUE;
+ *need_suffix = TRUE;
+ *suffix = suffixes [idx];
+ } else if (idx == suffix_count) {
+ /* netcore system libs have a suffix but no prefix */
+ *need_prefix = FALSE;
+ *need_suffix = TRUE;
+ *suffix = suffixes [0];
+ } else if (idx == suffix_count + 1) {
+ /* Name */
+ *need_prefix = FALSE;
+ *need_suffix = FALSE;
+ *suffix = "";
+ } else {
+ return FALSE;
}
+ return TRUE;
+}
+
+static char*
+dl_build_path (const char *directory, const char *name, void **iter, dl_library_name_formatting_func func)
+{
+ const char *prefix;
+ const char *suffix;
+ gboolean need_prefix = TRUE, need_suffix = TRUE;
+ int prlen;
+ int suffixlen;
+ char *res;
+ int iteration;
+
+ if (!iter)
+ return NULL;
+
+
+ iteration = GPOINTER_TO_UINT (*iter);
+ if (!func (iteration, &need_prefix, &need_suffix, &suffix))
+ return NULL;
+
if (need_prefix) {
prlen = strlen (mono_dl_get_so_prefix ());
if (prlen && strncmp (name, mono_dl_get_so_prefix (), prlen) != 0)
@@ -471,6 +501,64 @@ mono_dl_build_path (const char *directory, const char *name, void **iter)
return res;
}
+/**
+ * mono_dl_build_path:
+ * \param directory optional directory
+ * \param name base name of the library
+ * \param iter iterator token
+ * Given a directory name and the base name of a library, iterate
+ * over the possible file names of the library, taking into account
+ * the possible different suffixes and prefixes on the host platform.
+ *
+ * The returned file name must be freed by the caller.
+ * \p iter must point to a NULL pointer the first time the function is called
+ * and then passed unchanged to the following calls.
+ * \returns the filename or NULL at the end of the iteration
+ */
+char*
+mono_dl_build_path (const char *directory, const char *name, void **iter)
+{
+#ifdef HOST_ANDROID
+ return dl_build_path (directory, name, iter, dl_reverse_library_name_formatting);
+#else
+ return dl_build_path (directory, name, iter, dl_default_library_name_formatting);
+#endif
+}
+
+static
+gboolean
+dl_prefix_suffix_library_name_formatting (int idx, gboolean *need_prefix, gboolean *need_suffix, const char **suffix)
+{
+ /* Prefix.Name.suffix */
+ *need_prefix = TRUE;
+ *need_suffix = TRUE;
+ *suffix = mono_dl_get_so_suffixes () [idx];
+ if ((*suffix) [0] == '\0')
+ return FALSE;
+
+ return TRUE;
+}
+
+/**
+ * mono_dl_build_platform_path:
+ * \param directory optional directory
+ * \param name base name of the library
+ * \param iter iterator token
+ * Given a directory name and the base name of a library, iterate
+ * over platform prefix and suffixes generating a library name
+ * suitable for the platform. Function won't try additional fallbacks.
+ *
+ * The returned file name must be freed by the caller.
+ * \p iter must point to a NULL pointer the first time the function is called
+ * and then passed unchanged to the following calls.
+ * \returns the filename or NULL at the end of the iteration
+ */
+char*
+mono_dl_build_platform_path (const char *directory, const char *name, void **iter)
+{
+ return dl_build_path (directory, name, iter, dl_prefix_suffix_library_name_formatting);
+}
+
MonoDlFallbackHandler *
mono_dl_fallback_register (MonoDlFallbackLoad load_func, MonoDlFallbackSymbol symbol_func, MonoDlFallbackClose close_func, void *user_data)
{
diff --git a/src/mono/mono/utils/mono-dl.h b/src/mono/mono/utils/mono-dl.h
index 44e7e9e34e186..5a810f8c295da 100644
--- a/src/mono/mono/utils/mono-dl.h
+++ b/src/mono/mono/utils/mono-dl.h
@@ -36,6 +36,7 @@ MONO_EXTERN_C
void mono_dl_close (MonoDl *module);
char* mono_dl_build_path (const char *directory, const char *name, void **iter);
+char* mono_dl_build_platform_path (const char *directory, const char *name, void **iter);
MonoDl* mono_dl_open_runtime_lib (const char *lib_name, int flags, char **error_msg);
diff --git a/src/mono/mono/utils/mono-stack-unwinding.h b/src/mono/mono/utils/mono-stack-unwinding.h
index 15335fc961926..f27b2cbb00a6a 100644
--- a/src/mono/mono/utils/mono-stack-unwinding.h
+++ b/src/mono/mono/utils/mono-stack-unwinding.h
@@ -30,7 +30,9 @@ typedef enum {
FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX = 6,
/* Frame for transitioning to interpreted code */
FRAME_TYPE_INTERP_ENTRY = 7,
- FRAME_TYPE_NUM = 8
+ /* Frame marking transition to native JIT compiler */
+ FRAME_TYPE_JIT_ENTRY = 8,
+ FRAME_TYPE_NUM = 9
} MonoStackFrameType;
typedef enum {
diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.json.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.json.in
index 4c50a08f007c8..059efeed70cea 100644
--- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.json.in
+++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.json.in
@@ -1,5 +1,8 @@
{
"version": "${WorkloadVersion}",
+ "depends-on": {
+ "Microsoft.NET.Workload.Emscripten": "${EmscriptenVersion}"
+ },
"workloads": {
"microsoft-net-sdk-blazorwebassembly-aot": {
"description": "Browser Runtime native performance tools",
@@ -11,7 +14,7 @@
"Microsoft.NET.Runtime.Emscripten.Python",
"Microsoft.NET.Runtime.Emscripten.Sdk"
],
- "extends": [ "microsoft-net-runtime-mono-tooling" ],
+ "extends": [ "microsoft-net-runtime-mono-tooling", "microsoft-net-sdk-emscripten" ],
"platforms": [ "win-x64", "linux-x64", "osx-x64", "osx-arm64" ]
},
"microsoft-net-runtime-android": {
@@ -266,34 +269,5 @@
"kind": "framework",
"version": "${PackageVersion}"
},
- "Microsoft.NET.Runtime.Emscripten.Node" : {
- "kind": "Sdk",
- "version": "${EmscriptenVersion}",
- "alias-to": {
- "win-x64": "Microsoft.NET.Runtime.Emscripten.2.0.23.Node.win-x64",
- "linux-x64": "Microsoft.NET.Runtime.Emscripten.2.0.23.Node.linux-x64",
- "osx-x64": "Microsoft.NET.Runtime.Emscripten.2.0.23.Node.osx-x64",
- "osx-arm64": "Microsoft.NET.Runtime.Emscripten.2.0.23.Node.osx-x64"
- }
- },
- "Microsoft.NET.Runtime.Emscripten.Python" : {
- "kind": "Sdk",
- "version": "${EmscriptenVersion}",
- "alias-to": {
- "win-x64": "Microsoft.NET.Runtime.Emscripten.2.0.23.Python.win-x64",
- "osx-x64": "Microsoft.NET.Runtime.Emscripten.2.0.23.Python.osx-x64",
- "osx-arm64": "Microsoft.NET.Runtime.Emscripten.2.0.23.Python.osx-x64"
- }
- },
- "Microsoft.NET.Runtime.Emscripten.Sdk" : {
- "kind": "Sdk",
- "version": "${EmscriptenVersion}",
- "alias-to": {
- "win-x64": "Microsoft.NET.Runtime.Emscripten.2.0.23.Sdk.win-x64",
- "linux-x64": "Microsoft.NET.Runtime.Emscripten.2.0.23.Sdk.linux-x64",
- "osx-x64": "Microsoft.NET.Runtime.Emscripten.2.0.23.Sdk.osx-x64",
- "osx-arm64": "Microsoft.NET.Runtime.Emscripten.2.0.23.Sdk.osx-x64"
- }
- }
}
}
\ No newline at end of file
diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets
index ab039e9a71678..4176041469bc1 100644
--- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets
+++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets
@@ -44,9 +44,6 @@
-
-
-
diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile
index 64d7b9d658f94..8455ce69a39d8 100644
--- a/src/mono/wasm/Makefile
+++ b/src/mono/wasm/Makefile
@@ -71,7 +71,7 @@ MONO_LIBS = \
$(ICU_LIBDIR)/libicuuc.a \
$(ICU_LIBDIR)/libicui18n.a
-EMCC_DEBUG_FLAGS =-g -Os -s ASSERTIONS=1 -DDEBUG=1
+EMCC_DEBUG_FLAGS =-g -Os -s -DDEBUG=1
EMCC_RELEASE_FLAGS=-Oz
ifeq ($(NOSTRIP),)
diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets
index e1de26e4a4cde..50e491ac060f7 100644
--- a/src/mono/wasm/build/WasmApp.Native.targets
+++ b/src/mono/wasm/build/WasmApp.Native.targets
@@ -160,13 +160,14 @@
<_WasmRuntimeICallTablePath>$(_WasmIntermediateOutputPath)runtime-icall-table.h
<_WasmPInvokeTablePath>$(_WasmIntermediateOutputPath)pinvoke-table.h
- <_EmccOptimizationFlagDefault Condition="'$(_WasmDevel)' == 'true'">-O0
+ <_EmccAssertionLevelDefault>0
+ <_EmccOptimizationFlagDefault Condition="'$(_WasmDevel)' == 'true'">-O0 -s ASSERTIONS=$(_EmccAssertionLevelDefault)
<_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == '' and '$(OS)' != 'Windows_NT' and '$(Configuration)' == 'Debug'">-Os
<_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == '' and '$(Configuration)' != 'Debug'">-Oz
<_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == ''">-Oz
$(_EmccOptimizationFlagDefault)
- -O0
+ -O0 -s ASSERTIONS=$(_EmccAssertionLevelDefault)
diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj
index c8186ff30d3b6..45640378ac3cc 100644
--- a/src/mono/wasm/wasm.proj
+++ b/src/mono/wasm/wasm.proj
@@ -178,7 +178,7 @@
DependsOnTargets="GenerateEmccPropsAndRspFiles;BuildPInvokeTable;BundleTimezones">
- -g -Os -s ASSERTIONS=1 -DENABLE_NETCORE=1 -DDEBUG=1
+ -g -Os -s -DENABLE_NETCORE=1 -DDEBUG=1
-Oz -DENABLE_NETCORE=1
"$(EMSDK_PATH)/upstream/bin/wasm-opt" --strip-dwarf "$(NativeBinDir)dotnet.wasm" -o "$(NativeBinDir)dotnet.wasm"
$(ArtifactsObjDir)wasm
diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.props b/src/tasks/AotCompilerTask/MonoAOTCompiler.props
index 159c01ff3f27b..c6b2f2ad28e94 100644
--- a/src/tasks/AotCompilerTask/MonoAOTCompiler.props
+++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.props
@@ -5,7 +5,6 @@
-
@@ -13,6 +12,9 @@
+
+
+
diff --git a/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2.cs b/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2.cs
index dfd292b755bec..acff1809714c4 100644
--- a/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2.cs
+++ b/src/tests/JIT/Methodical/Overflow/FloatOvfToInt2.cs
@@ -6,6 +6,9 @@
internal class FloatOvfToInt
{
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static bool BreakUpFlow() => false;
+
[MethodImpl(MethodImplOptions.NoInlining)]
public static long FloatToLong(float f)
{
@@ -228,6 +231,64 @@ public static int TestValuesFloatLong()
return 100;
}
+ public static int TestValuesFloatLongVN()
+ {
+ float bigf = 100000000000000000000000000000.0f;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (FloatToLong(bigf) != FloatToLongInline(bigf)) return 401;
+ if (FloatToUlong(bigf) != FloatToUlongInline(bigf)) return 402;
+ if (FloatToLong(-bigf) != FloatToLongInline(-bigf)) return 403;
+ if (FloatToUlong(-bigf) != FloatToUlongInline(-bigf)) return 404;
+
+ bigf = 987654321001234567899876543210.0f;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (FloatToLong(bigf) != FloatToLongInline(bigf)) return 401;
+ if (FloatToUlong(bigf) != FloatToUlongInline(bigf)) return 402;
+ if (FloatToLong(-bigf) != FloatToLongInline(-bigf)) return 403;
+ if (FloatToUlong(-bigf) != FloatToUlongInline(-bigf)) return 404;
+
+ bigf = 254783961024896571038054632179.0f;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (FloatToLong(bigf) != FloatToLongInline(bigf)) return 401;
+ if (FloatToUlong(bigf) != FloatToUlongInline(bigf)) return 402;
+ if (FloatToLong(-bigf) != FloatToLongInline(-bigf)) return 403;
+ if (FloatToUlong(-bigf) != FloatToUlongInline(-bigf)) return 404;
+
+ return 100;
+ }
+
+ public static int TestValuesFloatLongImport()
+ {
+ float bigf = 100000000000000000000000000000.0f;
+ if (FloatToLong(bigf) != FloatToLongInline(100000000000000000000000000000.0f)) return 501;
+ if (FloatToUlong(bigf) != FloatToUlongInline(100000000000000000000000000000.0f)) return 502;
+ if (FloatToLong(-bigf) != FloatToLongInline(-100000000000000000000000000000.0f)) return 503;
+ if (FloatToUlong(-bigf) != FloatToUlongInline(-100000000000000000000000000000.0f)) return 504;
+
+ bigf = 987654321001234567899876543210.0f;
+ if (FloatToLong(bigf) != FloatToLongInline(987654321001234567899876543210.0f)) return 501;
+ if (FloatToUlong(bigf) != FloatToUlongInline(987654321001234567899876543210.0f)) return 502;
+ if (FloatToLong(-bigf) != FloatToLongInline(-987654321001234567899876543210.0f)) return 503;
+ if (FloatToUlong(-bigf) != FloatToUlongInline(-987654321001234567899876543210.0f)) return 504;
+
+ bigf = 254783961024896571038054632179.0f;
+ if (FloatToLong(bigf) != FloatToLongInline(254783961024896571038054632179.0f)) return 501;
+ if (FloatToUlong(bigf) != FloatToUlongInline(254783961024896571038054632179.0f)) return 502;
+ if (FloatToLong(-bigf) != FloatToLongInline(-254783961024896571038054632179.0f)) return 503;
+ if (FloatToUlong(-bigf) != FloatToUlongInline(-254783961024896571038054632179.0f)) return 504;
+
+ return 100;
+ }
+
public static int TestValuesFloatInt()
{
float bigf = 100000000000000000000000000000.0f;
@@ -251,6 +312,64 @@ public static int TestValuesFloatInt()
return 100;
}
+ public static int TestValuesFloatIntVN()
+ {
+ float bigf = 100000000000000000000000000000.0f;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (FloatToInt(bigf) != FloatToIntInline(bigf)) return 411;
+ if (FloatToUint(bigf) != FloatToUintInline(bigf)) return 412;
+ if (FloatToInt(-bigf) != FloatToIntInline(-bigf)) return 413;
+ if (FloatToUint(-bigf) != FloatToUintInline(-bigf)) return 414;
+
+ bigf = 987654321001234567899876543210.0f;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (FloatToInt(bigf) != FloatToIntInline(bigf)) return 411;
+ if (FloatToUint(bigf) != FloatToUintInline(bigf)) return 412;
+ if (FloatToInt(-bigf) != FloatToIntInline(-bigf)) return 413;
+ if (FloatToUint(-bigf) != FloatToUintInline(-bigf)) return 414;
+
+ bigf = 254783961024896571038054632179.0f;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (FloatToInt(bigf) != FloatToIntInline(bigf)) return 411;
+ if (FloatToUint(bigf) != FloatToUintInline(bigf)) return 412;
+ if (FloatToInt(-bigf) != FloatToIntInline(-bigf)) return 413;
+ if (FloatToUint(-bigf) != FloatToUintInline(-bigf)) return 414;
+
+ return 100;
+ }
+
+ public static int TestValuesFloatIntImport()
+ {
+ float bigf = 100000000000000000000000000000.0f;
+ if (FloatToInt(bigf) != FloatToIntInline(100000000000000000000000000000.0f)) return 511;
+ if (FloatToUint(bigf) != FloatToUintInline(100000000000000000000000000000.0f)) return 512;
+ if (FloatToInt(-bigf) != FloatToIntInline(-100000000000000000000000000000.0f)) return 513;
+ if (FloatToUint(-bigf) != FloatToUintInline(-100000000000000000000000000000.0f)) return 514;
+
+ bigf = 987654321001234567899876543210.0f;
+ if (FloatToInt(bigf) != FloatToIntInline(987654321001234567899876543210.0f)) return 511;
+ if (FloatToUint(bigf) != FloatToUintInline(987654321001234567899876543210.0f)) return 512;
+ if (FloatToInt(-bigf) != FloatToIntInline(-987654321001234567899876543210.0f)) return 513;
+ if (FloatToUint(-bigf) != FloatToUintInline(-987654321001234567899876543210.0f)) return 514;
+
+ bigf = 254783961024896571038054632179.0f;
+ if (FloatToInt(bigf) != FloatToIntInline(254783961024896571038054632179.0f)) return 511;
+ if (FloatToUint(bigf) != FloatToUintInline(254783961024896571038054632179.0f)) return 512;
+ if (FloatToInt(-bigf) != FloatToIntInline(-254783961024896571038054632179.0f)) return 513;
+ if (FloatToUint(-bigf) != FloatToUintInline(-254783961024896571038054632179.0f)) return 514;
+
+ return 100;
+ }
+
public static int TestValuesFloatShort()
{
float bigf = 100000000000000000000000000000.0f;
@@ -274,6 +393,64 @@ public static int TestValuesFloatShort()
return 100;
}
+ public static int TestValuesFloatShortVN()
+ {
+ float bigf = 100000000000000000000000000000.0f;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (FloatToShort(bigf) != FloatToShortInline(bigf)) return 421;
+ if (FloatToUshort(bigf) != FloatToUshortInline(bigf)) return 422;
+ if (FloatToShort(-bigf) != FloatToShortInline(-bigf)) return 423;
+ if (FloatToUshort(-bigf) != FloatToUshortInline(-bigf)) return 424;
+
+ bigf = 987654321001234567899876543210.0f;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (FloatToShort(bigf) != FloatToShortInline(bigf)) return 421;
+ if (FloatToUshort(bigf) != FloatToUshortInline(bigf)) return 422;
+ if (FloatToShort(-bigf) != FloatToShortInline(-bigf)) return 423;
+ if (FloatToUshort(-bigf) != FloatToUshortInline(-bigf)) return 424;
+
+ bigf = 254783961024896571038054632179.0f;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (FloatToShort(bigf) != FloatToShortInline(bigf)) return 421;
+ if (FloatToUshort(bigf) != FloatToUshortInline(bigf)) return 422;
+ if (FloatToShort(-bigf) != FloatToShortInline(-bigf)) return 423;
+ if (FloatToUshort(-bigf) != FloatToUshortInline(-bigf)) return 424;
+
+ return 100;
+ }
+
+ public static int TestValuesFloatShortImport()
+ {
+ float bigf = 100000000000000000000000000000.0f;
+ if (FloatToShort(bigf) != FloatToShortInline(100000000000000000000000000000.0f)) return 521;
+ if (FloatToUshort(bigf) != FloatToUshortInline(100000000000000000000000000000.0f)) return 522;
+ if (FloatToShort(-bigf) != FloatToShortInline(-100000000000000000000000000000.0f)) return 523;
+ if (FloatToUshort(-bigf) != FloatToUshortInline(-100000000000000000000000000000.0f)) return 524;
+
+ bigf = 987654321001234567899876543210.0f;
+ if (FloatToShort(bigf) != FloatToShortInline(987654321001234567899876543210.0f)) return 521;
+ if (FloatToUshort(bigf) != FloatToUshortInline(987654321001234567899876543210.0f)) return 522;
+ if (FloatToShort(-bigf) != FloatToShortInline(-987654321001234567899876543210.0f)) return 523;
+ if (FloatToUshort(-bigf) != FloatToUshortInline(-987654321001234567899876543210.0f)) return 524;
+
+ bigf = 254783961024896571038054632179.0f;
+ if (FloatToShort(bigf) != FloatToShortInline(254783961024896571038054632179.0f)) return 521;
+ if (FloatToUshort(bigf) != FloatToUshortInline(254783961024896571038054632179.0f)) return 522;
+ if (FloatToShort(-bigf) != FloatToShortInline(-254783961024896571038054632179.0f)) return 523;
+ if (FloatToUshort(-bigf) != FloatToUshortInline(-254783961024896571038054632179.0f)) return 524;
+
+ return 100;
+ }
+
public static int TestValuesFloatByte()
{
float bigf = 100000000000000000000000000000.0f;
@@ -297,21 +474,91 @@ public static int TestValuesFloatByte()
return 100;
}
+ public static int TestValuesFloatByteVN()
+ {
+ float bigf = 100000000000000000000000000000.0f;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (FloatToSbyte(bigf) != FloatToSbyteInline(bigf)) return 441;
+ if (FloatToByte(bigf) != FloatToByteInline(bigf)) return 442;
+ if (FloatToSbyte(-bigf) != FloatToSbyteInline(-bigf)) return 443;
+ if (FloatToByte(-bigf) != FloatToByteInline(-bigf)) return 444;
+
+ bigf = 987654321001234567899876543210.0f;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (FloatToSbyte(bigf) != FloatToSbyteInline(bigf)) return 441;
+ if (FloatToByte(bigf) != FloatToByteInline(bigf)) return 442;
+ if (FloatToSbyte(-bigf) != FloatToSbyteInline(-bigf)) return 443;
+ if (FloatToByte(-bigf) != FloatToByteInline(-bigf)) return 444;
+
+ bigf = 254783961024896571038054632179.0f;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (FloatToSbyte(bigf) != FloatToSbyteInline(bigf)) return 441;
+ if (FloatToByte(bigf) != FloatToByteInline(bigf)) return 442;
+ if (FloatToSbyte(-bigf) != FloatToSbyteInline(-bigf)) return 443;
+ if (FloatToByte(-bigf) != FloatToByteInline(-bigf)) return 444;
+
+ return 100;
+ }
+
+ public static int TestValuesFloatByteImport()
+ {
+ float bigf = 100000000000000000000000000000.0f;
+ if (FloatToSbyte(bigf) != FloatToSbyteInline(100000000000000000000000000000.0f)) return 541;
+ if (FloatToByte(bigf) != FloatToByteInline(100000000000000000000000000000.0f)) return 542;
+ if (FloatToSbyte(-bigf) != FloatToSbyteInline(-100000000000000000000000000000.0f)) return 543;
+ if (FloatToByte(-bigf) != FloatToByteInline(-100000000000000000000000000000.0f)) return 544;
+
+ bigf = 987654321001234567899876543210.0f;
+ if (FloatToSbyte(bigf) != FloatToSbyteInline(987654321001234567899876543210.0f)) return 541;
+ if (FloatToByte(bigf) != FloatToByteInline(987654321001234567899876543210.0f)) return 542;
+ if (FloatToSbyte(-bigf) != FloatToSbyteInline(-987654321001234567899876543210.0f)) return 543;
+ if (FloatToByte(-bigf) != FloatToByteInline(-987654321001234567899876543210.0f)) return 544;
+
+ bigf = 254783961024896571038054632179.0f;
+ if (FloatToSbyte(bigf) != FloatToSbyteInline(254783961024896571038054632179.0f)) return 541;
+ if (FloatToByte(bigf) != FloatToByteInline(254783961024896571038054632179.0f)) return 542;
+ if (FloatToSbyte(-bigf) != FloatToSbyteInline(-254783961024896571038054632179.0f)) return 543;
+ if (FloatToByte(-bigf) != FloatToByteInline(-254783961024896571038054632179.0f)) return 544;
+
+ return 100;
+ }
+
public static int TestValuesDoubleLong()
{
double bigd = 100000000000000000000000000000.0;
+
+ if (BreakUpFlow())
+ return 1000;
+
if (DoubleToLong(bigd) != DoubleToLongInline(bigd)) return 201;
if (DoubleToUlong(bigd) != DoubleToUlongInline(bigd)) return 202;
if (DoubleToLong(-bigd) != DoubleToLongInline(-bigd)) return 203;
if (DoubleToUlong(-bigd) != DoubleToUlongInline(-bigd)) return 204;
bigd = 987654321001234567899876543210.0;
+
+ if (BreakUpFlow())
+ return 1000;
+
if (DoubleToLong(bigd) != DoubleToLongInline(bigd)) return 201;
if (DoubleToUlong(bigd) != DoubleToUlongInline(bigd)) return 202;
if (DoubleToLong(-bigd) != DoubleToLongInline(-bigd)) return 203;
if (DoubleToUlong(-bigd) != DoubleToUlongInline(-bigd)) return 204;
bigd = 254783961024896571038054632179.0;
+
+ if (BreakUpFlow())
+ return 1000;
+
if (DoubleToLong(bigd) != DoubleToLongInline(bigd)) return 201;
if (DoubleToUlong(bigd) != DoubleToUlongInline(bigd)) return 202;
if (DoubleToLong(-bigd) != DoubleToLongInline(-bigd)) return 203;
@@ -320,6 +567,52 @@ public static int TestValuesDoubleLong()
return 100;
}
+ public static int TestValuesDoubleLongVN()
+ {
+ double bigd = 100000000000000000000000000000.0;
+ if (DoubleToLong(bigd) != DoubleToLongInline(bigd)) return 301;
+ if (DoubleToUlong(bigd) != DoubleToUlongInline(bigd)) return 302;
+ if (DoubleToLong(-bigd) != DoubleToLongInline(-bigd)) return 303;
+ if (DoubleToUlong(-bigd) != DoubleToUlongInline(-bigd)) return 304;
+
+ bigd = 987654321001234567899876543210.0;
+ if (DoubleToLong(bigd) != DoubleToLongInline(bigd)) return 301;
+ if (DoubleToUlong(bigd) != DoubleToUlongInline(bigd)) return 302;
+ if (DoubleToLong(-bigd) != DoubleToLongInline(-bigd)) return 303;
+ if (DoubleToUlong(-bigd) != DoubleToUlongInline(-bigd)) return 304;
+
+ bigd = 254783961024896571038054632179.0;
+ if (DoubleToLong(bigd) != DoubleToLongInline(bigd)) return 301;
+ if (DoubleToUlong(bigd) != DoubleToUlongInline(bigd)) return 302;
+ if (DoubleToLong(-bigd) != DoubleToLongInline(-bigd)) return 303;
+ if (DoubleToUlong(-bigd) != DoubleToUlongInline(-bigd)) return 304;
+
+ return 100;
+ }
+
+ public static int TestValuesDoubleLongImport()
+ {
+ double bigd = 100000000000000000000000000000.0;
+ if (DoubleToLong(bigd) != DoubleToLongInline(100000000000000000000000000000.0)) return 601;
+ if (DoubleToUlong(bigd) != DoubleToUlongInline(100000000000000000000000000000.0)) return 602;
+ if (DoubleToLong(-bigd) != DoubleToLongInline(-100000000000000000000000000000.0)) return 603;
+ if (DoubleToUlong(-bigd) != DoubleToUlongInline(-100000000000000000000000000000.0)) return 604;
+
+ bigd = 987654321001234567899876543210.0;
+ if (DoubleToLong(bigd) != DoubleToLongInline(987654321001234567899876543210.0)) return 601;
+ if (DoubleToUlong(bigd) != DoubleToUlongInline(987654321001234567899876543210.0)) return 602;
+ if (DoubleToLong(-bigd) != DoubleToLongInline(-987654321001234567899876543210.0)) return 603;
+ if (DoubleToUlong(-bigd) != DoubleToUlongInline(-987654321001234567899876543210.0)) return 604;
+
+ bigd = 254783961024896571038054632179.0;
+ if (DoubleToLong(bigd) != DoubleToLongInline(254783961024896571038054632179.0)) return 601;
+ if (DoubleToUlong(bigd) != DoubleToUlongInline(254783961024896571038054632179.0)) return 602;
+ if (DoubleToLong(-bigd) != DoubleToLongInline(-254783961024896571038054632179.0)) return 603;
+ if (DoubleToUlong(-bigd) != DoubleToUlongInline(-254783961024896571038054632179.0)) return 604;
+
+ return 100;
+ }
+
public static int TestValuesDoubleInt()
{
double bigd = 100000000000000000000000000000.0;
@@ -343,6 +636,64 @@ public static int TestValuesDoubleInt()
return 100;
}
+ public static int TestValuesDoubleIntVN()
+ {
+ double bigd = 100000000000000000000000000000.0;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (DoubleToInt(bigd) != DoubleToIntInline(bigd)) return 311;
+ if (DoubleToUint(bigd) != DoubleToUintInline(bigd)) return 312;
+ if (DoubleToInt(-bigd) != DoubleToIntInline(-bigd)) return 313;
+ if (DoubleToUint(-bigd) != DoubleToUintInline(-bigd)) return 314;
+
+ bigd = 987654321001234567899876543210.0;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (DoubleToInt(bigd) != DoubleToIntInline(bigd)) return 311;
+ if (DoubleToUint(bigd) != DoubleToUintInline(bigd)) return 312;
+ if (DoubleToInt(-bigd) != DoubleToIntInline(-bigd)) return 313;
+ if (DoubleToUint(-bigd) != DoubleToUintInline(-bigd)) return 314;
+
+ bigd = 254783961024896571038054632179.0;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (DoubleToInt(bigd) != DoubleToIntInline(bigd)) return 311;
+ if (DoubleToUint(bigd) != DoubleToUintInline(bigd)) return 312;
+ if (DoubleToInt(-bigd) != DoubleToIntInline(-bigd)) return 313;
+ if (DoubleToUint(-bigd) != DoubleToUintInline(-bigd)) return 314;
+
+ return 100;
+ }
+
+ public static int TestValuesDoubleIntImport()
+ {
+ double bigd = 100000000000000000000000000000.0;
+ if (DoubleToInt(bigd) != DoubleToIntInline(100000000000000000000000000000.0)) return 611;
+ if (DoubleToUint(bigd) != DoubleToUintInline(100000000000000000000000000000.0)) return 612;
+ if (DoubleToInt(-bigd) != DoubleToIntInline(-100000000000000000000000000000.0)) return 613;
+ if (DoubleToUint(-bigd) != DoubleToUintInline(-100000000000000000000000000000.0)) return 614;
+
+ bigd = 987654321001234567899876543210.0;
+ if (DoubleToInt(bigd) != DoubleToIntInline(987654321001234567899876543210.0)) return 611;
+ if (DoubleToUint(bigd) != DoubleToUintInline(987654321001234567899876543210.0)) return 612;
+ if (DoubleToInt(-bigd) != DoubleToIntInline(-987654321001234567899876543210.0)) return 613;
+ if (DoubleToUint(-bigd) != DoubleToUintInline(-987654321001234567899876543210.0)) return 614;
+
+ bigd = 254783961024896571038054632179.0;
+ if (DoubleToInt(bigd) != DoubleToIntInline(254783961024896571038054632179.0)) return 611;
+ if (DoubleToUint(bigd) != DoubleToUintInline(254783961024896571038054632179.0)) return 612;
+ if (DoubleToInt(-bigd) != DoubleToIntInline(-254783961024896571038054632179.0)) return 613;
+ if (DoubleToUint(-bigd) != DoubleToUintInline(-254783961024896571038054632179.0)) return 614;
+
+ return 100;
+ }
+
public static int TestValuesDoubleShort()
{
double bigd = 100000000000000000000000000000.0;
@@ -366,6 +717,64 @@ public static int TestValuesDoubleShort()
return 100;
}
+ public static int TestValuesDoubleShortVN()
+ {
+ double bigd = 100000000000000000000000000000.0;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (DoubleToShort(bigd) != DoubleToShortInline(bigd)) return 321;
+ if (DoubleToUshort(bigd) != DoubleToUshortInline(bigd)) return 322;
+ if (DoubleToShort(-bigd) != DoubleToShortInline(-bigd)) return 323;
+ if (DoubleToUshort(-bigd) != DoubleToUshortInline(-bigd)) return 324;
+
+ bigd = 987654321001234567899876543210.0;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (DoubleToShort(bigd) != DoubleToShortInline(bigd)) return 321;
+ if (DoubleToUshort(bigd) != DoubleToUshortInline(bigd)) return 322;
+ if (DoubleToShort(-bigd) != DoubleToShortInline(-bigd)) return 323;
+ if (DoubleToUshort(-bigd) != DoubleToUshortInline(-bigd)) return 324;
+
+ bigd = 254783961024896571038054632179.0;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (DoubleToShort(bigd) != DoubleToShortInline(bigd)) return 321;
+ if (DoubleToUshort(bigd) != DoubleToUshortInline(bigd)) return 322;
+ if (DoubleToShort(-bigd) != DoubleToShortInline(-bigd)) return 323;
+ if (DoubleToUshort(-bigd) != DoubleToUshortInline(-bigd)) return 324;
+
+ return 100;
+ }
+
+ public static int TestValuesDoubleShortImport()
+ {
+ double bigd = 100000000000000000000000000000.0;
+ if (DoubleToShort(bigd) != DoubleToShortInline(100000000000000000000000000000.0)) return 621;
+ if (DoubleToUshort(bigd) != DoubleToUshortInline(100000000000000000000000000000.0)) return 622;
+ if (DoubleToShort(-bigd) != DoubleToShortInline(-100000000000000000000000000000.0)) return 623;
+ if (DoubleToUshort(-bigd) != DoubleToUshortInline(-bigd)) return 624;
+
+ bigd = 987654321001234567899876543210.0;
+ if (DoubleToShort(bigd) != DoubleToShortInline(987654321001234567899876543210.0)) return 621;
+ if (DoubleToUshort(bigd) != DoubleToUshortInline(987654321001234567899876543210.0)) return 622;
+ if (DoubleToShort(-bigd) != DoubleToShortInline(-987654321001234567899876543210.0)) return 623;
+ if (DoubleToUshort(-bigd) != DoubleToUshortInline(-987654321001234567899876543210.0)) return 624;
+
+ bigd = 254783961024896571038054632179.0;
+ if (DoubleToShort(bigd) != DoubleToShortInline(254783961024896571038054632179.0)) return 621;
+ if (DoubleToUshort(bigd) != DoubleToUshortInline(254783961024896571038054632179.0)) return 622;
+ if (DoubleToShort(-bigd) != DoubleToShortInline(-254783961024896571038054632179.0)) return 623;
+ if (DoubleToUshort(-bigd) != DoubleToUshortInline(-254783961024896571038054632179.0)) return 624;
+
+ return 100;
+ }
+
public static int TestValuesDoubleByte()
{
double bigd = 100000000000000000000000000000.0;
@@ -389,17 +798,91 @@ public static int TestValuesDoubleByte()
return 100;
}
+ public static int TestValuesDoubleByteVN()
+ {
+ double bigd = 100000000000000000000000000000.0;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (DoubleToSbyte(bigd) != DoubleToSbyteInline(bigd)) return 341;
+ if (DoubleToByte(bigd) != DoubleToByteInline(bigd)) return 342;
+ if (DoubleToSbyte(-bigd) != DoubleToSbyteInline(-bigd)) return 343;
+ if (DoubleToByte(-bigd) != DoubleToByteInline(-bigd)) return 344;
+
+ bigd = 987654321001234567899876543210.0;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (DoubleToSbyte(bigd) != DoubleToSbyteInline(bigd)) return 341;
+ if (DoubleToByte(bigd) != DoubleToByteInline(bigd)) return 342;
+ if (DoubleToSbyte(-bigd) != DoubleToSbyteInline(-bigd)) return 343;
+ if (DoubleToByte(-bigd) != DoubleToByteInline(-bigd)) return 344;
+
+ bigd = 254783961024896571038054632179.0;
+
+ if (BreakUpFlow())
+ return 1000;
+
+ if (DoubleToSbyte(bigd) != DoubleToSbyteInline(bigd)) return 341;
+ if (DoubleToByte(bigd) != DoubleToByteInline(bigd)) return 342;
+ if (DoubleToSbyte(-bigd) != DoubleToSbyteInline(-bigd)) return 343;
+ if (DoubleToByte(-bigd) != DoubleToByteInline(-bigd)) return 344;
+
+ return 100;
+ }
+
+ public static int TestValuesDoubleByteImport()
+ {
+ double bigd = 100000000000000000000000000000.0;
+ if (DoubleToSbyte(bigd) != DoubleToSbyteInline(100000000000000000000000000000.0)) return 641;
+ if (DoubleToByte(bigd) != DoubleToByteInline(100000000000000000000000000000.0)) return 642;
+ if (DoubleToSbyte(-bigd) != DoubleToSbyteInline(-100000000000000000000000000000.0)) return 643;
+ if (DoubleToByte(-bigd) != DoubleToByteInline(-100000000000000000000000000000.0)) return 644;
+
+ bigd = 987654321001234567899876543210.0;
+ if (DoubleToSbyte(bigd) != DoubleToSbyteInline(987654321001234567899876543210.0)) return 641;
+ if (DoubleToByte(bigd) != DoubleToByteInline(987654321001234567899876543210.0)) return 642;
+ if (DoubleToSbyte(-bigd) != DoubleToSbyteInline(-987654321001234567899876543210.0)) return 643;
+ if (DoubleToByte(-bigd) != DoubleToByteInline(-987654321001234567899876543210.0)) return 644;
+
+ bigd = 254783961024896571038054632179.0;
+ if (DoubleToSbyte(bigd) != DoubleToSbyteInline(987654321001234567899876543210.0)) return 641;
+ if (DoubleToByte(bigd) != DoubleToByteInline(987654321001234567899876543210.0)) return 642;
+ if (DoubleToSbyte(-bigd) != DoubleToSbyteInline(-987654321001234567899876543210.0)) return 643;
+ if (DoubleToByte(-bigd) != DoubleToByteInline(-987654321001234567899876543210.0)) return 644;
+
+ return 100;
+ }
+
public static int TestValues()
{
int res = TestValuesFloatLong(); if (res != 100) return res;
+ res = TestValuesFloatLongVN(); if (res != 100) return res;
+ res = TestValuesFloatLongImport(); if (res != 100) return res;
res = TestValuesFloatInt(); if (res != 100) return res;
+ res = TestValuesFloatIntVN(); if (res != 100) return res;
+ res = TestValuesFloatIntImport(); if (res != 100) return res;
res = TestValuesFloatShort(); if (res != 100) return res;
+ res = TestValuesFloatShortImport(); if (res != 100) return res;
+ res = TestValuesFloatShortVN(); if (res != 100) return res;
res = TestValuesFloatByte(); if (res != 100) return res;
+ res = TestValuesFloatByteImport(); if (res != 100) return res;
+ res = TestValuesFloatByteVN(); if (res != 100) return res;
res = TestValuesDoubleLong(); if (res != 100) return res;
+ res = TestValuesDoubleLongVN(); if (res != 100) return res;
+ res = TestValuesDoubleLongImport(); if (res != 100) return res;
res = TestValuesDoubleInt(); if (res != 100) return res;
+ res = TestValuesDoubleIntVN(); if (res != 100) return res;
+ res = TestValuesDoubleIntImport(); if (res != 100) return res;
res = TestValuesDoubleShort(); if (res != 100) return res;
+ res = TestValuesDoubleShortVN(); if (res != 100) return res;
+ res = TestValuesDoubleShortImport(); if (res != 100) return res;
res = TestValuesDoubleByte(); if (res != 100) return res;
+ res = TestValuesDoubleByteVN(); if (res != 100) return res;
+ res = TestValuesDoubleByteImport(); if (res != 100) return res;
return res;
}
diff --git a/src/tests/Loader/binding/tracing/BinderTracingTest.targets b/src/tests/Loader/binding/tracing/BinderTracingTest.targets
index 426a5556093f1..67b0d2d3a20fa 100644
--- a/src/tests/Loader/binding/tracing/BinderTracingTest.targets
+++ b/src/tests/Loader/binding/tracing/BinderTracingTest.targets
@@ -38,15 +38,16 @@
fr-FR
+ $(OutDir)/DependentAssemblies
-
+
-
-
-
+
+
+
diff --git a/src/tests/build.proj b/src/tests/build.proj
index d1ce4ab95ba51..e06e245e96548 100644
--- a/src/tests/build.proj
+++ b/src/tests/build.proj
@@ -43,7 +43,7 @@
- <_ConfigurationProperties>/p:TargetOS=$(TargetOS) /p:TargetArchitecture=$(TargetArchitecture) /p:Configuration=$(Configuration)
+ <_ConfigurationProperties>/p:TargetOS=$(TargetOS) /p:TargetArchitecture=$(TargetArchitecture) /p:Configuration=$(Configuration) /p:CrossBuild=$(CrossBuild)
"$(DotNetTool)" restore $(RestoreProj) $(PackageVersionArg) /p:SetTFMForRestore=true $(_ConfigurationProperties)
"$(DotNetTool)" restore -r $(__DistroRid) $(RestoreProj) $(PackageVersionArg) /p:SetTFMForRestore=true $(_ConfigurationProperties)
diff --git a/src/tests/build.sh b/src/tests/build.sh
index da6fa03e1cfcf..e5575f69f98ff 100755
--- a/src/tests/build.sh
+++ b/src/tests/build.sh
@@ -573,6 +573,10 @@ if [[ "${__BuildArch}" != "${__HostArch}" ]]; then
__CrossBuild=1
fi
+if [[ "$__CrossBuild" == 1 ]]; then
+ __UnprocessedBuildArgs+=("/p:CrossBuild=true")
+fi
+
# Set dependent variables
__LogsDir="$__RootBinDir/log"
__MsbuildDebugLogsDir="$__LogsDir/MsbuildDebugLogs"
diff --git a/src/tests/issues.targets b/src/tests/issues.targets
index f94900a742146..9aa21e9c19cf2 100644
--- a/src/tests/issues.targets
+++ b/src/tests/issues.targets
@@ -1026,6 +1026,18 @@
Mono does not define out of range fp to int conversions
+
+ https://github.com/dotnet/runtime/issues/51323
+
+
+ https://github.com/dotnet/runtime/issues/51323
+
+
+ https://github.com/dotnet/runtime/issues/51323
+
+
+ https://github.com/dotnet/runtime/issues/51323
+
https://github.com/dotnet/runtime/issues/48190
@@ -2203,12 +2215,6 @@
https://github.com/dotnet/runtime/issues/54376
-
- https://github.com/dotnet/runtime/issues/54374e
-
-
- https://github.com/dotnet/runtime/issues/54374
-