diff --git a/.azure-ci.yml b/.azure-ci.yml
index fe836bdda2e0..de5c4e809703 100644
--- a/.azure-ci.yml
+++ b/.azure-ci.yml
@@ -69,7 +69,6 @@ jobs:
- WindowsNoTest
- AllConfigurations
- LinuxTest
- - LinuxNoTest
- MacOS
- RedHat6
# - FreeBSD
diff --git a/.gitignore b/.gitignore
index f680d2ef59fa..a6a208ee0737 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,9 +3,9 @@ syntax: glob
### VisualStudio ###
# Tool Runtime Dir
-/[Tt]ools/
.dotnet/
.packages/
+.tools/
# User-specific files
*.suo
diff --git a/Directory.Build.props b/Directory.Build.props
index 23ce8247235f..05f23e1bf042 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -31,19 +31,25 @@
-
+
Debug
Release
-
+
- OSX
- FreeBSD
- NetBSD
- Linux
+
+ OSX
+ FreeBSD
+ NetBSD
+ Linux
$(OS)
@@ -70,7 +76,6 @@
package
-
true
@@ -96,14 +101,14 @@
-
+
$(_excludeRestorePackageImports)
$([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'artifacts', 'bin'))
-
+
$([MSBuild]::NormalizePath('$(ArtifactsBinDir)', 'native', '$(BuildConfiguration)'))
@@ -150,8 +155,6 @@
https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json;
https://dotnetfeed.blob.core.windows.net/dotnet-coreclr/index.json;
- https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json;
- https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;
https://api.nuget.org/v3/index.json;
$(OverridePackageSource);
$(RestoreSources)
@@ -164,7 +167,7 @@
Library
Open
- true
+ true
$(RepositoryEngineeringDir)DefaultGenApiDocIds.txt
true
@@ -196,7 +199,7 @@
<_portableOS Condition="'$(OSGroup)' == 'Unix' AND '$(_runtimeOSFamily)' != 'osx' AND '$(_runtimeOSFamily)' != 'FreeBSD' AND '$(_runtimeOS)' != 'linux-musl'">linux
- <_packageRID/>
+ <_packageRID />
<_packageRID Condition="'$(PortableBuild)' == 'true'">$(_portableOS)-$(ArchGroup)
<_packageRID Condition="$(TargetGroup.StartsWith('uap'))">win10-$(ArchGroup)
<_packageRID Condition="$(TargetGroup.EndsWith('aot'))">$(_packageRID)-aot
@@ -215,8 +218,7 @@
- true
- true
+ true
true
true
true
@@ -236,7 +238,7 @@
-
+
$(CopyrightNetFoundation)
-
+
@@ -253,7 +255,7 @@
portable
-
+
false
@@ -262,10 +264,15 @@
false
-
+
-
- true
+
+ true
+
+ optimization.windows_nt-x64.IBC.CoreFx
+ $(optimizationwindows_ntx64IBCCoreFxPackageVersion)
+ optimization.linux-x64.IBC.CoreFx
+ $(optimizationwindows_ntx64IBCCoreFxPackageVersion)
@@ -317,11 +324,11 @@
true
-
+
false
true
true
-
+
$(NoWarn);BCL0020
@@ -353,7 +360,8 @@
$(RefRootPath)netstandard/
$(RefRootPath)netstandard2.1/
$(RefRootPath)netfx/
- $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'tools'))
+
+ $([MSBuild]::NormalizeDirectory('$(RepoRoot)', '.tools', 'globaltools'))
$([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'ibc'))
$([MSBuild]::NormalizeDirectory('$(ArtifactsToolsetDir)', 'ilasm'))
$([MSBuild]::NormalizeDirectory('$(ArtifactsToolsetDir)', 'ILLink'))
@@ -373,13 +381,11 @@
$(ArtifactsBinDir)pkg\netcoreapp\ref
$(ArtifactsBinDir)pkg\netcoreapp\lib
- $(ArtifactsBinDir)pkg\netcoreappaot\lib
$(ArtifactsBinDir)pkg\uap\ref
$(ArtifactsBinDir)pkg\uap\lib
$(ArtifactsBinDir)pkg\uapaot\lib
$(ArtifactsBinDir)pkg\netfx\ref
$(ArtifactsBinDir)pkg\netfx\lib
- $(ArtifactsBinDir)NetStandardTestSuite\
true
@@ -452,7 +458,7 @@
-
+
false
diff --git a/Directory.Build.targets b/Directory.Build.targets
index 42bcbb6ae9ff..8591539bf844 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -68,18 +68,13 @@
ILLinkTrimAssembly=true
-
- $(NETCoreAppAotPackageRuntimePath)
-
- ILLinkTrimAssembly=true
-
-
+
$(UAPPackageRefPath)
-
+
$(UAPPackageRuntimePath)
-
+
$(UAPAOTPackageRuntimePath)
@@ -88,25 +83,17 @@
$(NETCoreAppTestSharedFrameworkPath)
-
- $(ILCFXInputFolder)
-
-
+
$(ILCFXInputFolder)
-
+
$(UAPTestSharedFrameworkPath)
-
+
$(TestHostRootPath)
-
-
- $(NETStandardTestSuiteOutputPath)$(AssemblyName)/
-
-
$(RefRootPath)netstandard/
@@ -127,6 +114,10 @@
Include="@(_TargetGroupsWithIsAot->WithMetadataValue('IsAot', 'false'))">
$(RefRootPath)%(Identity)/
+
+
+ $(ArtifactsBinDir)runtime/%(Identity)-$(ConfigurationGroup)-$(ArchGroup)
+
diff --git a/Documentation/api-guidelines/nullability.md b/Documentation/api-guidelines/nullability.md
new file mode 100644
index 000000000000..f48dbd0a65b0
--- /dev/null
+++ b/Documentation/api-guidelines/nullability.md
@@ -0,0 +1,92 @@
+# Nullability annotations
+
+C# 8 provides an opt-in feature that allows for the compiler to track reference type nullability in order to catch potential null dereferences. We are starting to adopt that feature in both System.Private.CoreLib in coreclr and in the libraries in corefx, working up from the bottom of the stack. We're doing this for three primary reasons, in order of importance:
+
+- **To annotate the .NET Core surface area with appropriate nullability annotations.** While this could be done solely in the reference assemblies, we're doing it first in the implementation to help validate the selected annotations.
+- **To help validate the nullability feature itself.** With millions of lines of C# code, we have a very large and robust codebase with which to try out the feature and find areas in which it shines and areas in which we can improve it.
+- **To find null-related bugs in .NET Core itself.** We expect to find relatively few meaningful bugs, due to how relatively well-tested the codebases are and how long they've been around.
+
+## Breaking Change Guidance
+
+We are striving to get annotations correct the "first time" and are doing due-diligence in an attempt to do so. However, we acknowledge that we are likely to need to augment and change some annotations in the future:
+
+- **Mistakes.** Given the sheer number of APIs being reviewed and annotated, we are likely to make some errors, and we'd like to be able to fix them so that long-term customers get the greatest benefit.
+- **Breadth.** We are unlikely to have the time to annotate all of the enormous number of APIs in .NET for an initial release, and we'd like to be able to finish the task in subsequent updates.
+- **Feedback.** We may need to revisit some "gray area" decisions as to whether a parameter or return type should be nullable or non-nullable (more details later).
+
+Any such additions or changes to annotations can impact the warnings consuming code receives if that code has opted in to nullability analysis and warnings. Even so, for at least the foreseeable future we may still do so. We will be very thoughtful about when and how we do.
+
+## Annotation Guidance
+
+Nullability annotations are considered to represent intent: they represent the nullability contract for the member. Any deviation from that intent on the part of an implementation should be considered an implementation bug, and the compiler will help to minimize the chances of such bugs via its flow analysis and nullability warnings. At the same time, it's important to recognize that the validation performed by the compiler isn't perfect; it can have both false positive warnings (suggesting that something may be null even when it isn't) and false negatives (not warning when something that may be null is dereferenced). The compiler cannot guarantee that an API declared as returning a non-nullable reference never returns null, just as it can't validate that an implementation declared as accepting nulls always behaves correctly when given them. When deciding how to annotate APIs, it's important then to consider the desired contract rather than the current implementation; in other words, prefer to first annotate the API surface area the way that's desired, and only then work to address any warnings in the codebase, rather than driving the API surface area annotations based on where those warnings lead.
+
+- **DO** annotate all new APIs with the desired contract.
+- **CONSIDER** changing that contract if overwhelming use suggests a different de facto contract. This is particularly relevant to virtual/abstract/interface methods defined in a library where all implementations may not be under your control, and derived implementations may not have adhered to the original intent.
+- **DO** continue to validate all arguments as you would have prior to nullability warnings. In particular, if you would have checked an argument for null and thrown an ArgumentNullException if it was null, continue to do so, even if the parameter is defined as non-nullable.
+- **DO NOT** remove existing argument validation when annotating existing APIS.
+- **AVOID** making any changes while annotating that impact the generated IL for an implementation (e.g. `some.Method()` to `some?.Method()`). Any such changes should be thoroughly analyzed and reviewed as a bug fix.
+
+The majority of reference type usage in our APIs is fairly clear as to whether it should be nullable or not. For parameters, these general guidelines cover the majority of cases:
+
+- **DO** define a parameter as non-nullable if the method checks for null and throws an `Argument{Null}Exception` if `null` is passed in for that parameter (whether explicitly in that same method or implicitly as part of some method it calls), such that there's no way null could be passed in and have the method return successfully.
+- **DO** define a parameter as non-nullable if the method fails to check for `null` but instead will always end up dereferencing the `null` and throwing a `NullReferenceException`.
+- **DO** define a parameter as nullable if the parameter is explicitly documented to accept `null`.
+- **DO** define a parameter as nullable if method checks the parameter for `null` and does something other than throw. This may include normalizing the input, e.g. treating `null` as `string.Empty`.
+- **DO** define a parameter as nullable if the parameter is optional and has a default value of `null`.
+- **DO** prefer nullable over non-nullable if there's any disagreement between the previous guidelines. For example, if a method has documentation that suggests `null` isn't accepted but the implementation explicitly checks for, normalizes, and accepts a `null` input, the parameter should be defined nullable.
+
+However, there are some gray areas that require case-by-case analysis to determine intent. In particular, if a parameter isn't validated nor sanitized nor documented regarding null, but in some cases simply ignored such that a null doesn't currently cause any problems, several factors should be considered when determining whether to annotate it as null.
+- Is null ever passed in our own code bases? If yes, it likely should be nullable.
+- Is null ever passed in prominent 3rd-party code bases? If yes, it likely should be nullable.
+- Is null likely to be interpreted as a default / nop placeholder by callers? If yes, it likely should be nullable.
+- Is null accepted by other methods in a similar area or that have a similar purposes in the same code base? If yes, it likely should be nullable.
+- If the method is largely oblivious to null and just happens to still work if null is passed, and if the API's purpose wouldn't make sense if null were used, the parameter likely should be non-nullable.
+
+Things are generally easier when looking at return values (and out parameters), as those can largely be driven by what the API's implementation is capable of:
+
+- **DO** define a return value or out parameter as nullable if it may be assigned `null` under any circumstance.
+- **DO** define all other return values or out parameters as non-nullable.
+
+Annotating one of our return types as non-nullable is equivalent to documenting a guarantee that it will never return null. Violations of that guarantee are bugs to be fixed in the implementation. However, there is a huge gap here, in the form of overridable members…
+
+### Virtual/Abstract Methods and Interfaces
+
+For virtual members, annotating a return type as non-nullable places a requirement on all overrides to meet those same guarantees, just as any other documented behaviors of a virtuals apply to all overrides, whether those stated guarantees can be enforced by the compiler or not. An override that doesn't abide by these guarantees has a bug. For existing virtual APIs that have already documented a guarantee about a non-nullable return, it's expected that the return type will be annotated as non-nullable, and derived types must continue to respect that guarantee, albeit now with the compiler's assistance.
+
+However, for existing virtual APIs that do not have any such strong guarantee documented but where the intent was for the return value to be non-null, it is a grayer area. The most accurate return type would be T?, whereas the intent-based return type would be T. For T?, the pros are that it accurately reflects that nulls may emerge, but at the expense of consumers that know a null will never emerge having to use `!` or some other suppression when dereferencing. For T, the pros are that it accurately conveys the intent to overriders and allows consumers to avoid needing any form of suppression, but ironically at the expense of potential increases in occurrences of NullReferenceExceptions due to consumers then not validating the return type to be non-null and not being able to trust in the meaning of a method returning non-nullable. As such, there are several factors to then consider when deciding which return type to use for an existing virtual/abstract/interface method:
+1. How common is it that an existing override written before the guarantee was put in effect would return null?
+2. How widespread are overrides of the method in question? This contributes to (1).
+3. How common is it to invoke the method via the base vs via a derived type that may narrow the return type to `T` from `T?`?
+4. How common is it in the case of (3) for such invocations to then dereference the result rather than passing it off to something else that accepts a `T?`?
+
+Object.ToString is arguably the most extreme case. Answering the above questions:
+1. It is fairly easy in any reasonably-sized code base to find cases, intentional or otherwise, where ToString returns null in some cases (we've found examples in corefx, Roslyn, NuGet, ASP.NET, and so on). One of the most prevalent conditions for this are types that just return the value in a string field which may contain its default value of null, and in particular for structs where a ctor may not have even had a chance to run and validate an input. Guidance in the docs suggests that ToString shouldn't return null or string.Empty, but even the docs don't follow its own guidance.
+2. Thousands upon thousands of types we don't control override this method today.
+3. It's common for helper routines to invoke via the base object.ToString, but many ToString uses are actually on derived types. This is particularly true when working in a code base that both defines a type and consumes its ToString.
+4. Based on examination of several large code bases, we believe it to be relatively rare that the result of an Object.ToString call (made on the base) to be directly dereferenced. It's much more common to pass it to another method that accepts `string?`, such as `String.Concat`, `String.Format`, `Console.WriteLine`, logging utilities, and so on. And while we advocate that ToString results shouldn't be assumed to be in a particular machine-readable format and parsed, it's certainly the case that code bases do, such as using `Substring` on the result, but in such cases, the caller needs to understand the format of what's being rendered, which generally means they're working with a derived type rather than calling through the base Object.ToString.
+
+As such, for now, we will start with `Object.ToString` returning `string?`. We can re-evaluate this decision as we get more experience with consumers of the feature.
+
+In contrast, for `Exception.Message` which is also virtual, we plan to have it be non-nullable, even though technically a derived class could override it to return null, because doing so is so rare that we couldn't find any meaningful examples of doing so.
+
+## Code Review Guidance
+
+Code reviews for enabling the nullability warnings are particularly interesting in that they often differ significantly from general code reviews. Typically, a code reviewer focuses only on the code actually being modified (e.g. the lines highlighted by the code diffing tool); however, enabling the nullability feature has a much broader impact, in that it effectively inverts the meaning of every reference type use in the codebase (or, more specifically, in the scope at which the nullability warning context was applied). So, for example, if you turn on nullability for a whole file (`#enable nullable` at the top of the file) and then touch no other lines in the file, every method that accepts a `string` is now accepting a non-nullable `string`; whereas previously passing in `null` to that argument would be fine, now the compiler will warn about it, and to allow nulls, the argument must be changed to `string?`. This means that enabling nullability checking requires reviewing all exposed APIs in that context, regardless of whether they were modified or not, as the contract exposed by the API may have been implicitly modified.
+
+A code review for enabling nullability generally involves three passes:
+
+- **Review all implementation changes made in the code.** Except when explicitly fixing a bug (which should be rare), the annotations employed for nullability should have zero impact on the generated IL (other than potentially some added attributes in the metadata). The most common changes are:
+
+ - Adding `?` to reference type parameters and local symbols. These inform the compiler that nulls are allowed. For locals, they evaporate entirely at compile time. For parameters, they impact the [Nullable(...)] attributes emitted into the metadata by the compiler, but have no effect on the implementation IL.
+
+ - Adding `!` to reference type usage. These essentially suppress the null warning, telling the compiler to treat the expression as if it's non-null. These evaporate at compile-time.
+
+ - Adding `Debug.Assert(reference != null);` statements. These inform the compiler that the mentioned reference is non-null, which will cause the compiler to factor that in and have the effect of suppressing subsequent warnings on that reference (until the flow analysis suggests that could change). As with any Debug.Assert, these evaporate at compile-time in release builds (where DEBUG isn't defined).
+
+ - Most any other changes have the potential to change the IL, which should not be necessary for the feature. In particular, it's common for `?`s on dereferences to sneak in, e.g. changing `someVar.SomeMethod()` to `someVar?.SomeMethod()`; that is a change to the IL, and should only be employed when there's an actual known bug that's important to fix, as otherwise we're incurring unnecessary cost.
+
+ - Any `!`s added that should have been unnecessary and are required due to either a compiler issue or due to lack of expressibility about annotations should have a `// TODO-NULLABLE: http://link/to/relevant/issue` comment added on the same line. Issues due to lack of expressability should link to https://github.com/dotnet/roslyn/issues/26761. Issues due to lack of annotation support for never-returning methods should link to https://github.com/dotnet/csharplang/issues/538.
+
+- **Review the API changes explicitly made.** These are the ones that show up in the diff. They should be reviewed to validate that they make sense from a contract perspective. Do we expect/allow nulls everywhere a parameter reference type was augmented with `?`? Do we potentially return nulls everywhere a return type was augmented with `?`? Was anything else changed that could be an accidental breaking change (e.g. a value type parameter getting annotated to become a Nullable instead of a T)? Any APIs where the contract could be more constrained if more expressibility were present should have a `// TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761` comment.
+
+- **Review all other exported APIs (e.g. public and protected on public types) for all reference types in both return and parameter positions.** Anything that wasn't changed to be `?` is now defined as non-nullable. For parameters, that means consuming code will now get a harsh warning if it tries to pass null, and thus these should be changed if null actually is allowed / expected. For returns, it means the API will never return null; if it might return null in some circumstance, the API should be changed to return `?`. This is the most time consuming and tedious part of the review.
diff --git a/Documentation/building/windows-instructions.md b/Documentation/building/windows-instructions.md
index c367bede5511..d777addfcffc 100644
--- a/Documentation/building/windows-instructions.md
+++ b/Documentation/building/windows-instructions.md
@@ -4,7 +4,7 @@ Building CoreFX on Windows
## Required Software
1. **[Visual Studio 2017](https://www.visualstudio.com/downloads/)** or **[Visual Studio 2019](https://visualstudio.microsoft.com/vs/preview/)** (Community, Professional, Enterprise) with the latest update must be installed. The Community version is completely free.
-2. **[.NET Core SDK](https://www.microsoft.com/net/download/windows)** >= v2.1.401 must be installed which will add the `dotnet` toolchain to your path.
+2. **[.NET Core SDK](https://www.microsoft.com/net/download/windows)** >= v3.0.0-preview3 must be installed which will add the `dotnet` toolchain to your path.
3. **[CMake](https://cmake.org/)** must be installed from [the CMake download page](https://cmake.org/download/#latest) and added to your path. CMake 3.14 or later is required to build with VS 2019.
### Visual Studio 2019
diff --git a/Documentation/coding-guidelines/coding-style.md b/Documentation/coding-guidelines/coding-style.md
index 606b44ee3d93..06b67ffeb445 100644
--- a/Documentation/coding-guidelines/coding-style.md
+++ b/Documentation/coding-guidelines/coding-style.md
@@ -31,9 +31,7 @@ The general rule we follow is "use Visual Studio defaults".
15. When including non-ASCII characters in the source code use Unicode escape sequences (\uXXXX) instead of literal characters. Literal non-ASCII characters occasionally get garbled by a tool or editor.
16. When using labels (for goto), indent the label one less than the current indentation.
-We have provided a Visual Studio vssettings file (`corefx.vssettings`) at the root of the corefx repository, enabling C# auto-formatting conforming to the above guidelines. Note that rules 7 and 8 are not covered by the vssettings, since these are not rules currently supported by VS formatting.
-
-Additionally for auto-formatting in non-Visual Studio editors, an [EditorConfig](https://editorconfig.org "EditorConfig homepage") file (`.editorconfig`) has also been provided at the root of the corefx repository.
+An [EditorConfig](https://editorconfig.org "EditorConfig homepage") file (`.editorconfig`) has been provided at the root of the corefx repository, enabling C# auto-formatting conforming to the above guidelines.
We also use the [.NET Codeformatter Tool](https://github.com/dotnet/codeformatter) to ensure the code base maintains a consistent style over time, the tool automatically fixes the code base to conform to the guidelines outlined above.
diff --git a/Documentation/project-docs/issue-guide.md b/Documentation/project-docs/issue-guide.md
index 730f51b526a0..4c99053dfc07 100644
--- a/Documentation/project-docs/issue-guide.md
+++ b/Documentation/project-docs/issue-guide.md
@@ -70,11 +70,11 @@ Areas are tracked by labels area-* (e.g. area-System.Collections). Each area
| [System.Linq.Parallel](https://github.com/dotnet/corefx/labels/area-System.Linq.Parallel) | **[@tarekgh](https://github.com/tarekgh)**, [@kouvel](https://github.com/kouvel) | |
| [System.Management](https://github.com/dotnet/corefx/labels/area-System.Management) | [@Anipik](https://github.com/Anipik) | WMI |
| [System.Memory](https://github.com/dotnet/corefx/labels/area-System.Memory) | [@ahsonkhan](https://github.com/ahsonkhan) | |
-| [System.Net](https://github.com/dotnet/corefx/labels/area-System.Net) | [@davidsh](https://github.com/davidsh), [@wfurt](https://github.com/wfurt), [@caesar1995](https://github.com/caesar1995), [@rmkerr](https://github.com/rmkerr), [@karelz](https://github.com/karelz) | Included: |
-| [System.Net.Http](https://github.com/dotnet/corefx/labels/area-System.Net.Http) | [@davidsh](https://github.com/davidsh), [@wfurt](https://github.com/wfurt), [@caesar1995](https://github.com/caesar1995), [@rmkerr](https://github.com/rmkerr), [@karelz](https://github.com/karelz) | |
+| [System.Net](https://github.com/dotnet/corefx/labels/area-System.Net) | [@davidsh](https://github.com/davidsh), [@wfurt](https://github.com/wfurt), [@karelz](https://github.com/karelz) | Included:System.Uri - [@wtgodbe](https://github.com/wtgodbe) |
+| [System.Net.Http](https://github.com/dotnet/corefx/labels/area-System.Net.Http) | [@davidsh](https://github.com/davidsh), [@wfurt](https://github.com/wfurt), [@karelz](https://github.com/karelz) | |
| [System.Net.Http.SocketsHttpHandler](https://github.com/dotnet/corefx/labels/area-System.Net.Http.SocketsHttpHandler) | [@geoffkizer](https://github.com/geoffkizer), [@wfurt](https://github.com/wfurt), [@davidsh](https://github.com/davidsh), [@karelz](https://github.com/karelz) | |
-| [System.Net.Security](https://github.com/dotnet/corefx/labels/area-System.Net.Security) | [@davidsh](https://github.com/davidsh), [@wfurt](https://github.com/wfurt), [@caesar1995](https://github.com/caesar1995), [@rmkerr](https://github.com/rmkerr), [@karelz](https://github.com/karelz) | |
-| [System.Net.Sockets](https://github.com/dotnet/corefx/labels/area-System.Net.Sockets) | [@davidsh](https://github.com/davidsh), [@wfurt](https://github.com/wfurt), [@caesar1995](https://github.com/caesar1995), [@rmkerr](https://github.com/rmkerr), [@karelz](https://github.com/karelz) | |
+| [System.Net.Security](https://github.com/dotnet/corefx/labels/area-System.Net.Security) | [@davidsh](https://github.com/davidsh), [@wfurt](https://github.com/wfurt), [@karelz](https://github.com/karelz) | |
+| [System.Net.Sockets](https://github.com/dotnet/corefx/labels/area-System.Net.Sockets) | [@davidsh](https://github.com/davidsh), [@wfurt](https://github.com/wfurt), [@karelz](https://github.com/karelz) | |
| [System.Numerics](https://github.com/dotnet/corefx/labels/area-System.Numerics) | [@tannergooding](https://github.com/tannergooding), [@ViktorHofer](https://github.com/ViktorHofer) | |
| [System.Numerics.Tensors](https://github.com/dotnet/corefx/labels/area-System.Numerics.Tensors) | [@tannergooding](https://github.com/tannergooding) | |
| [System.Reflection](https://github.com/dotnet/corefx/labels/area-System.Reflection) | [@steveharter](https://github.com/steveharter), [@GrabYourPitchforks](https://github.com/GrabYourPitchforks) | |
diff --git a/THIRD-PARTY-NOTICES.TXT b/THIRD-PARTY-NOTICES.TXT
index db542ca24f27..b25636f506b8 100644
--- a/THIRD-PARTY-NOTICES.TXT
+++ b/THIRD-PARTY-NOTICES.TXT
@@ -307,3 +307,28 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+License notice for Json.NET
+-------------------------------
+
+https://github.com/JamesNK/Newtonsoft.Json/blob/master/LICENSE.md
+
+The MIT License (MIT)
+
+Copyright (c) 2007 James Newton-King
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/eng/InternalTools.props b/eng/InternalTools.props
index db0a13dcae15..b16d4b44460d 100644
--- a/eng/InternalTools.props
+++ b/eng/InternalTools.props
@@ -14,8 +14,8 @@
-
- https://devdiv.pkgs.visualstudio.com/_packaging/dotnet-core-internal-tooling/nuget/v3/index.json;
+
+ https://dnceng.pkgs.visualstudio.com/_packaging/dotnet-internal/nuget/v3/index.json;
$(RestoreSources);
diff --git a/eng/Tools.props b/eng/Tools.props
index 0285180199fa..6cd5fb9f7829 100644
--- a/eng/Tools.props
+++ b/eng/Tools.props
@@ -90,7 +90,8 @@
- $(ArtifactsDir)tools
+
+ $([MSBuild]::NormalizePath('$(RepoRoot)', '.tools', 'globaltools'))
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index edee493fcfed..392fa78eccba 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,100 +1,100 @@
-
+
https://github.com/dotnet/coreclr
- f1440bb696e2eee957a30f37c6c735f51696edad
+ 0c1f6b9e3282f04d48b756afc8dbe60334ffd9b1
-
+
https://github.com/dotnet/coreclr
- f1440bb696e2eee957a30f37c6c735f51696edad
+ 0c1f6b9e3282f04d48b756afc8dbe60334ffd9b1
-
+
https://github.com/dotnet/coreclr
- f1440bb696e2eee957a30f37c6c735f51696edad
+ 0c1f6b9e3282f04d48b756afc8dbe60334ffd9b1
-
+
https://github.com/dotnet/core-setup
- ccdc90de5f757c56e13bf5c095ee5d2aa8ca1aa4
+ 25abcf43fe1da7a8bdad3d5053ebc01dc80ea450
-
+
https://github.com/dotnet/core-setup
- ccdc90de5f757c56e13bf5c095ee5d2aa8ca1aa4
+ 25abcf43fe1da7a8bdad3d5053ebc01dc80ea450
-
+
https://github.com/dotnet/core-setup
- ccdc90de5f757c56e13bf5c095ee5d2aa8ca1aa4
+ 25abcf43fe1da7a8bdad3d5053ebc01dc80ea450
-
+
https://github.com/dotnet/corefx
- 35249a0072b41a89ce1542deacb2611c2393dec0
+ 1f9b84a0804e868c7e0f37a3c10fbaf7c735ae14
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/standard
- 31a38c14c8a4d06ea59c67706fe4399c1f14368f
+ 25538d60f7f4c2c79cf098f2b808907d87b516a7
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://github.com/dotnet/arcade
- 36bc9d99630b4b544c6f09065dc37c00b4ca90a9
+ 09e01af076175a6dbf19e442707722e751a7163b
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
4f9d0ecf2b8151859fd2bd0734af32ea59258a3d
diff --git a/eng/Versions.props b/eng/Versions.props
index 82a2bf74be74..90e5a35fcdea 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -23,31 +23,31 @@
- 1.0.0-beta.19202.3
- 1.0.0-beta.19202.3
- 1.0.0-beta.19202.3
- 1.0.0-beta.19202.3
- 1.0.0-beta.19177.11
- 2.4.0-beta.19202.3
- 2.5.1-beta.19202.3
- 1.0.0-beta.19202.3
- 1.0.0-beta.19202.3
- 1.0.0-beta.19202.3
- 1.0.0-beta.19202.3
- 2.2.0-beta.19202.3
- 1.0.0-beta.19202.3
+ 1.0.0-beta.19216.2
+ 1.0.0-beta.19216.2
+ 1.0.0-beta.19216.2
+ 1.0.0-beta.19216.2
+ 1.0.0-beta.19216.2
+ 2.4.0-beta.19216.2
+ 2.5.1-beta.19216.2
+ 1.0.0-beta.19216.2
+ 1.0.0-beta.19216.2
+ 1.0.0-beta.19216.2
+ 1.0.0-beta.19216.2
+ 2.2.0-beta.19216.2
+ 1.0.0-beta.19216.2
- 3.0.0-preview5-27606-01
- 3.0.0-preview5-27606-01
- 3.0.0-preview5-27606-01
+ 3.0.0-preview5-27618-02
+ 3.0.0-preview5-27618-02
+ 3.0.0-preview5-27618-02
- 3.0.0-preview4-27527-73
- 3.0.0-preview4-27527-73
+ 3.0.0-preview5-27617-73
+ 3.0.0-preview5-27617-73
- 3.0.0-preview5.19205.9
+ 3.0.0-preview5.19217.12
- 2.1.0-prerelease.19205.2
+ 2.1.0-prerelease.19217.2
- 99.99.99-master-20190308.5
+ 99.99.99-master-20190313.3
diff --git a/eng/codeOptimization.targets b/eng/codeOptimization.targets
index c52fec409f7f..b49f8e52bec5 100644
--- a/eng/codeOptimization.targets
+++ b/eng/codeOptimization.targets
@@ -9,6 +9,10 @@
+
+ $(IbcOptimizationDataDir)$(LinuxCoreFxOptimizationDataPackageId)\
+ $(IbcOptimizationDataDir)$(WindowsCoreFxOptimizationDataPackageId)\
+
<_optimizationDataAssembly Include="$(IbcOptimizationDataDir)**\$(TargetFileName)" />
@@ -17,4 +21,4 @@
-
\ No newline at end of file
+
diff --git a/eng/common/CheckSymbols.ps1 b/eng/common/CheckSymbols.ps1
new file mode 100644
index 000000000000..074b423245c8
--- /dev/null
+++ b/eng/common/CheckSymbols.ps1
@@ -0,0 +1,134 @@
+param(
+ [Parameter(Mandatory=$true)][string] $InputPath, # Full path to directory where NuGet packages to be checked are stored
+ [Parameter(Mandatory=$true)][string] $ExtractPath, # Full path to directory where the packages will be extracted during validation
+ [Parameter(Mandatory=$true)][string] $SymbolToolPath # Full path to directory where dotnet symbol-tool was installed
+)
+
+Add-Type -AssemblyName System.IO.Compression.FileSystem
+
+function FirstMatchingSymbolDescriptionOrDefault {
+ param(
+ [string] $FullPath, # Full path to the module that has to be checked
+ [string] $TargetServerParam # Parameter to pass to `Symbol Tool` indicating the server to lookup for symbols
+ )
+
+ $FileName = [System.IO.Path]::GetFileName($FullPath)
+ $Extension = [System.IO.Path]::GetExtension($FullPath)
+
+ # Those below are potential symbol files that the `dotnet symbol` might
+ # return. Which one will be returned depend on the type of file we are
+ # checking and which type of file was uploaded.
+
+ # The file itself is returned
+ $SymbolPath = $SymbolsPath + "\" + $FileName
+
+ # PDB file for the module
+ $PdbPath = $SymbolPath.Replace($Extension, ".pdb")
+
+ # PDB file for R2R module (created by crossgen)
+ $NGenPdb = $SymbolPath.Replace($Extension, ".ni.pdb")
+
+ # DBG file for a .so library
+ $SODbg = $SymbolPath.Replace($Extension, ".so.dbg")
+
+ # DWARF file for a .dylib
+ $DylibDwarf = $SymbolPath.Replace($Extension, ".dylib.dwarf")
+
+ .\dotnet-symbol.exe --symbols --modules $TargetServerParam $FullPath -o $SymbolsPath -d | Out-Null
+
+ if (Test-Path $PdbPath) {
+ return "PDB"
+ }
+ elseif (Test-Path $NGenPdb) {
+ return "NGen PDB"
+ }
+ elseif (Test-Path $SODbg) {
+ return "DBG for SO"
+ }
+ elseif (Test-Path $DylibDwarf) {
+ return "Dwarf for Dylib"
+ }
+ elseif (Test-Path $SymbolPath) {
+ return "Module"
+ }
+ else {
+ return $null
+ }
+}
+
+function CountMissingSymbols {
+ param(
+ [string] $PackagePath # Path to a NuGet package
+ )
+
+ # Ensure input file exist
+ if (!(Test-Path $PackagePath)) {
+ throw "Input file does not exist: $PackagePath"
+ }
+
+ # Extensions for which we'll look for symbols
+ $RelevantExtensions = @(".dll", ".exe", ".so", ".dylib")
+
+ # How many files are missing symbol information
+ $MissingSymbols = 0
+
+ $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath)
+ $ExtractPath = $ExtractPath + $PackageId;
+ $SymbolsPath = $ExtractPath + $PackageId + ".Symbols";
+
+ [System.IO.Compression.ZipFile]::ExtractToDirectory($PackagePath, $ExtractPath)
+
+ # Makes easier to reference `symbol tool`
+ Push-Location $SymbolToolPath
+
+ Get-ChildItem -Recurse $ExtractPath |
+ Where-Object {$RelevantExtensions -contains $_.Extension} |
+ ForEach-Object {
+ Write-Host -NoNewLine "`t Checking file" $_.FullName "... "
+
+ $SymbolsOnMSDL = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--microsoft-symbol-server"
+ $SymbolsOnSymWeb = FirstMatchingSymbolDescriptionOrDefault $_.FullName "--internal-server"
+
+ if ($SymbolsOnMSDL -ne $null -and $SymbolsOnSymWeb -ne $null) {
+ Write-Host "Symbols found on MSDL (" $SymbolsOnMSDL ") and SymWeb (" $SymbolsOnSymWeb ")"
+ }
+ else {
+ $MissingSymbols++
+
+ if ($SymbolsOnMSDL -eq $null -and $SymbolsOnSymWeb -eq $null) {
+ Write-Host "No symbols found on MSDL or SymWeb!"
+ }
+ else {
+ if ($SymbolsOnMSDL -eq $null) {
+ Write-Host "No symbols found on MSDL!"
+ }
+ else {
+ Write-Host "No symbols found on SymWeb!"
+ }
+ }
+ }
+ }
+
+ Pop-Location
+
+ return $MissingSymbols
+}
+
+function CheckSymbolsAvailable {
+ if (Test-Path $ExtractPath) {
+ Remove-Item -recurse $ExtractPath
+ }
+
+ Get-ChildItem "$InputPath\*.nupkg" |
+ ForEach-Object {
+ $FileName = $_.Name
+ Write-Host "Validating $FileName "
+ $Status = CountMissingSymbols "$InputPath\$FileName"
+
+ if ($Status -ne 0) {
+ Write-Error "Missing symbols for $Status modules in the package $FileName"
+ }
+ }
+}
+
+CheckSymbolsAvailable
diff --git a/eng/common/PublishToPackageFeed.proj b/eng/common/PublishToPackageFeed.proj
index ccb81e8c3550..e17f72644e3e 100644
--- a/eng/common/PublishToPackageFeed.proj
+++ b/eng/common/PublishToPackageFeed.proj
@@ -1,11 +1,13 @@
-
+
+
+
netcoreapp2.1
@@ -41,6 +43,16 @@
https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json
https://dotnetfeed.blob.core.windows.net/arcade-validation/index.json
+ https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore/index.json
+ https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore-tooling/index.json
+ https://dotnetfeed.blob.core.windows.net/aspnet-entityframeworkcore/index.json
+ https://dotnetfeed.blob.core.windows.net/aspnet-extensions/index.json
+ https://dotnetfeed.blob.core.windows.net/dotnet-coreclr/index.json
+ https://dotnetfeed.blob.core.windows.net/dotnet-sdk/index.json
+ https://dotnetfeed.blob.core.windows.net/dotnet-tools-internal/index.json
+ https://dotnetfeed.blob.core.windows.net/dotnet-toolset/index.json
+ https://dotnetfeed.blob.core.windows.net/dotnet-windowsdesktop/index.json
+ https://dotnetfeed.blob.core.windows.net/nuget-nugetclient/index.json
+
+
+
+
+ netcoreapp2.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3650
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/eng/common/SigningValidation.proj b/eng/common/SigningValidation.proj
index 17e40d128773..7045fb6fb9d4 100644
--- a/eng/common/SigningValidation.proj
+++ b/eng/common/SigningValidation.proj
@@ -1,18 +1,20 @@
-
+
+
-
+ - PackageBasePath : Directory containing all files that need to be validated.
+ - SignCheckVersion : Version of SignCheck package to be used.
+ - SignValidationExclusionList : ItemGroup containing exclusion list to be forwarded to SignCheck.
+ - EnableJarSigningCheck : Whether .jar files should be validated.
+ - EnableStrongNameCheck : Whether strong name check should be performed.
+ -->
+
netcoreapp2.1
diff --git a/eng/common/darc-init.ps1 b/eng/common/darc-init.ps1
index 29c443212b45..81ffd16779cb 100644
--- a/eng/common/darc-init.ps1
+++ b/eng/common/darc-init.ps1
@@ -19,7 +19,7 @@ function InstallDarcCli ($darcVersion) {
# Until we can anonymously query the BAR API for the latest arcade-services
# build applied to the PROD channel, this is hardcoded.
if (-not $darcVersion) {
- $darcVersion = '1.1.0-beta.19175.6'
+ $darcVersion = '1.1.0-beta.19205.4'
}
$arcadeServicesSource = 'https://dotnetfeed.blob.core.windows.net/dotnet-arcade/index.json'
diff --git a/eng/common/darc-init.sh b/eng/common/darc-init.sh
index cab6cd5bf9f3..bd7eb4639864 100755
--- a/eng/common/darc-init.sh
+++ b/eng/common/darc-init.sh
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
source="${BASH_SOURCE[0]}"
-darcVersion="1.1.0-beta.19175.6"
+darcVersion="1.1.0-beta.19205.4"
while [[ $# > 0 ]]; do
opt="$(echo "$1" | awk '{print tolower($0)}')"
diff --git a/eng/common/internal/Tools.csproj b/eng/common/internal/Tools.csproj
index 1a81ff906f6e..1a39a7ef3f67 100644
--- a/eng/common/internal/Tools.csproj
+++ b/eng/common/internal/Tools.csproj
@@ -12,8 +12,12 @@
-
- https://devdiv.pkgs.visualstudio.com/_packaging/8f470c7e-ac49-4afe-a6ee-cf784e438b93/nuget/v3/index.json;
+
+
+ https://devdiv.pkgs.visualstudio.com/_packaging/dotnet-core-internal-tooling/nuget/v3/index.json;
+
+
+ $(RestoreSources);
https://devdiv.pkgs.visualstudio.com/_packaging/VS/nuget/v3/index.json;
diff --git a/eng/common/templates/phases/publish-build-assets.yml b/eng/common/templates/phases/publish-build-assets.yml
index 211967debab5..a0a8074282aa 100644
--- a/eng/common/templates/phases/publish-build-assets.yml
+++ b/eng/common/templates/phases/publish-build-assets.yml
@@ -5,6 +5,7 @@ parameters:
condition: succeeded()
continueOnError: false
runAsPublic: false
+ publishUsingPipelines: false
phases:
- phase: Asset_Registry_Publish
displayName: Publish to Build Asset Registry
@@ -36,6 +37,7 @@ phases:
/p:ManifestsPath='$(Build.StagingDirectory)/Download/AssetManifests'
/p:BuildAssetRegistryToken=$(MaestroAccessToken)
/p:MaestroApiEndpoint=https://maestro-prod.westus2.cloudapp.azure.com
+ /p:PublishUsingPipelines=${{ parameters.publishUsingPipelines }}
/p:Configuration=$(_BuildConfig)
condition: ${{ parameters.condition }}
continueOnError: ${{ parameters.continueOnError }}
diff --git a/eng/configurations/targetgroups.props b/eng/configurations/targetgroups.props
index bc9482979dea..320103337fdb 100644
--- a/eng/configurations/targetgroups.props
+++ b/eng/configurations/targetgroups.props
@@ -166,20 +166,6 @@
netcoreapp3.0
netstandard
-
- 3.0
- netcoreapp3.0
- aot
- netcoreapp;netcoreapp2.1
- netstandard
-
-
- 3.0
- netcoreapp3.0
- aot
- netcoreapp;netcoreapp3.0aot
- netstandard
-
net45
Microsoft.TargetingPack.NETFramework.v4.5
diff --git a/eng/dependencies.props b/eng/dependencies.props
index b0531b4ac8f0..1a8151c6ee8b 100644
--- a/eng/dependencies.props
+++ b/eng/dependencies.props
@@ -9,8 +9,8 @@
These ref versions are pulled from https://github.com/dotnet/versions.
-->
- 1ec5055956dc17901d269b582a9af9fa82475387
- 1ec5055956dc17901d269b582a9af9fa82475387
+ c86a1e0c3659a3046d43dc278e9711cd23002d97
+ c86a1e0c3659a3046d43dc278e9711cd23002d97
8bd1ec5fac9f0eec34ff6b34b1d878b4359e02dd
@@ -22,9 +22,9 @@
- beta-27527-00
- beta-27527-00
- 1.0.0-beta-27527-00
+ beta-27612-00
+ beta-27612-00
+ 1.0.0-beta-27612-00
4.4.0
diff --git a/eng/internal/NuGet.config b/eng/internal/NuGet.config
new file mode 100644
index 000000000000..f3a94002b19a
--- /dev/null
+++ b/eng/internal/NuGet.config
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/eng/pipelines/corefx-base.yml b/eng/pipelines/corefx-base.yml
index ca9b656350f3..67a02a0391a3 100644
--- a/eng/pipelines/corefx-base.yml
+++ b/eng/pipelines/corefx-base.yml
@@ -74,11 +74,14 @@ jobs:
- _msbuildCommonParameters: ''
- _archiveTestsParameter: ''
+ - _finalFrameworkArg: -framework $(_framework)
+
+ - ${{ if ne(job._jobFramework, '')}}:
+ - _finalFrameworkArg: ${{ job._jobFramework }}
- ${{ if eq(parameters.isOfficialBuild, 'true') }}:
- _msbuildCommonParameters: /p:OfficialBuildId=$(Build.BuildNumber)
- _dotnetFeedUrl: https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json
- - group: DotNet-Internal-Tools-Feed
- group: DotNet-Blob-Feed
- ${{ if eq(job.submitToHelix, 'true') }}:
@@ -86,7 +89,7 @@ jobs:
- ${{ if eq(parameters.isOfficialBuild, 'true') }}:
- group: DotNet-HelixApi-Access
- - _args: -restore -build -configuration $(_BuildConfig) -ci -buildtests -arch $(_architecture) -framework $(_framework) $(_archiveTestsParameter)
+ - _args: -configuration $(_BuildConfig) -ci -arch $(_architecture) $(_finalFrameworkArg) $(_archiveTestsParameter) ${{ job.buildExtraArguments }}
- _commonArguments: $(_args)
# Windows variables
@@ -124,30 +127,30 @@ jobs:
- ${{ if ne(job.preBuildSteps[0], '') }}:
- ${{ job.preBuildSteps }}
+ - script: $(_buildScript) -restore $(_commonArguments)
+ displayName: Restore Build Tools
+
- ${{ if eq(parameters.isOfficialBuild, 'true') }}:
- - task: NuGetToolInstaller@0
- inputs:
- versionSpec: '4.9.2'
- condition: ne(variables['_skipRestoreInternalTools'], 'true')
- - task: NuGetCommand@2
+ - task: DotNetCoreCLI@2
displayName: Restore internal tools
+ condition: ne(variables['_skipRestoreInternalTools'], 'true')
inputs:
command: restore
feedsToUse: config
- restoreSolution: 'eng\common\internal\Tools.csproj'
- nugetConfigPath: 'NuGet.config'
+ projects: 'eng/common/internal/Tools.csproj'
+ nugetConfigPath: 'eng/internal/NuGet.config'
restoreDirectory: '$(Build.SourcesDirectory)\.packages'
+ verbosityRestore: 'normal'
+ externalFeedCredentials: 'dotnet-core-internal-tooling'
env:
- VSS_NUGET_EXTERNAL_FEED_ENDPOINTS: '{"endpointCredentials": [{"endpoint":"https://devdiv.pkgs.visualstudio.com/_packaging/8f470c7e-ac49-4afe-a6ee-cf784e438b93/nuget/v3/index.json","username":"dn-bot","password":"$(dn-bot-devdiv-nuget-feed-read)"},
- {"endpoint":"https://devdiv.pkgs.visualstudio.com/_packaging/97a41293-2972-4f48-8c0e-05493ae82010/nuget/v3/index.json","username":"dn-bot","password":"$(dn-bot-devdiv-nuget-feed-read)"},
- {"endpoint":"https://devdiv.pkgs.visualstudio.com/_packaging/VS/nuget/v3/index.json","username":"dn-bot","password":"$(dn-bot-devdiv-nuget-feed-read)"}]}'
TargetGroup: $(_framework)
- ${{ if eq(job.customBuildSteps[0], '') }}:
- script: $(_buildScript)
+ -build
+ -buildtests
$(_commonArguments)
/p:OuterLoop=$(_outerloop)
- ${{ job.buildExtraArguments }}
$(_msbuildCommonParameters)
displayName: Build Sources and Tests
diff --git a/eng/pipelines/linux.yml b/eng/pipelines/linux.yml
index 14938c4dcfa8..2b623afeb34c 100644
--- a/eng/pipelines/linux.yml
+++ b/eng/pipelines/linux.yml
@@ -86,6 +86,15 @@ jobs:
_buildScriptPrefix: 'ROOTFS_DIR=/crossrootfs/arm '
_buildExtraArguments: -warnAsError false
+ musl_arm64_Release:
+ _BuildConfig: Release
+ _architecture: arm64
+ _framework: netcoreapp
+ _helixQueues: $(alpineArm64Queues)
+ _dockerContainer: alpine_37_arm64_container
+ _buildScriptPrefix: 'ROOTFS_DIR=/crossrootfs/arm64 '
+ _buildExtraArguments: -warnAsError false /p:BuildNativeCompiler=--clang5.0 /p:RuntimeOS=linux-musl
+
pool:
name: Hosted Ubuntu 1604
@@ -104,28 +113,28 @@ jobs:
- linuxDefaultQueues: Centos.7.Amd64.Open+RedHat.7.Amd64.Open+Debian.8.Amd64.Open+Ubuntu.1604.Amd64.Open+Ubuntu.1804.Amd64.Open+OpenSuse.42.Amd64.Open+\(Fedora.28.Amd64\)ubuntu.1604.amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-28-helix-45b1fa2-20190402012449
- linuxArm64Queues: \(Ubuntu.1604.Arm64\)Ubuntu.1604.Arm64.Docker.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-helix-arm64v8-b049512-20190321153539
- alpineQueues: \(Alpine.38.Amd64\)ubuntu.1604.amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.8-helix-45b1fa2-20190327215821
-
+
- ${{ if eq(parameters.isOfficialBuild, 'true') }}:
- linuxDefaultQueues: Centos.7.Amd64+RedHat.7.Amd64+Debian.8.Amd64+Debian.9.Amd64+Ubuntu.1604.Amd64+Ubuntu.1804.Amd64+Ubuntu.1810.Amd64+OpenSuse.42.Amd64+SLES.12.Amd64+SLES.15.Amd64+\(Fedora.28.Amd64\)ubuntu.1604.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-28-helix-45b1fa2-20190402012449+\(Fedora.29.Amd64\)ubuntu.1604.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-29-helix-c6dc5e6-20190402012449
- linuxArm64Queues: \(Ubuntu.1604.Arm64\)Ubuntu.1604.Arm64.Docker@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-16.04-helix-arm64v8-b049512-20190321153539
- linuxArmQueues: \(Debian.9.Arm32\)Ubuntu.1604.Arm32@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-9-helix-arm32v7-b049512-20190321153542
- alpineQueues: \(Alpine.38.Amd64\)ubuntu.1604.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.8-helix-45b1fa2-20190327215821+\(Alpine.39.Amd64\)ubuntu.1604.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.9-helix-e4eaef4-20190228230637
+ - alpineArm64Queues: \(Alpine.38.Arm64\)Ubuntu.1604.Arm64.Docker@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.8-helix-arm64v8-46e69dd-20190327215724
# Legs without helix testing
- # There is no point of running legs without outerloop tests, when in an outerloop build.
- - ${{ if eq(parameters.isOuterloopBuild, 'false') }}:
+ # Only run this leg in PRs.
+ - ${{ if and(eq(parameters.isOfficialBuild, 'false'), eq(parameters.isOuterloopBuild, 'false')) }}:
- job: LinuxNoTest
displayName: Linux
strategy:
matrix:
- ${{ if eq(parameters.isOfficialBuild, 'false') }}:
- arm_Release:
- _BuildConfig: Release
- _architecture: arm
- _framework: netcoreapp
- _buildExtraArguments: /p:RuntimeOS=ubuntu.16.04 -warnAsError false
- _buildScriptPrefix: 'ROOTFS_DIR=/crossrootfs/arm '
- _dockerContainer: ubuntu_1604_arm_cross_container
+ arm_Release:
+ _BuildConfig: Release
+ _architecture: arm
+ _framework: netcoreapp
+ _buildExtraArguments: /p:RuntimeOS=ubuntu.16.04 -warnAsError false
+ _buildScriptPrefix: 'ROOTFS_DIR=/crossrootfs/arm '
+ _dockerContainer: ubuntu_1604_arm_cross_container
musl_arm64_Release:
_BuildConfig: Release
@@ -133,7 +142,7 @@ jobs:
_framework: netcoreapp
_dockerContainer: alpine_37_arm64_container
_buildScriptPrefix: 'ROOTFS_DIR=/crossrootfs/arm64 '
- _buildExtraArguments: -warnAsError false /p:BuildNativeClang=--clang5.0 /p:RuntimeOS=linux-musl
+ _buildExtraArguments: -warnAsError false /p:BuildNativeCompiler=--clang5.0 /p:RuntimeOS=linux-musl
pool:
name: Hosted Ubuntu 1604
diff --git a/eng/pipelines/outerloop.yml b/eng/pipelines/outerloop.yml
index 4a916f952fc6..e3222799f409 100644
--- a/eng/pipelines/outerloop.yml
+++ b/eng/pipelines/outerloop.yml
@@ -8,6 +8,9 @@ resources:
- container: ubuntu_1604_arm64_cross_container
image: microsoft/dotnet-buildtools-prereqs:ubuntu-16.04-cross-arm64-a3ae44b-20180315221921
+ - container: alpine_36_container
+ image: microsoft/dotnet-buildtools-prereqs:alpine-3.6-WithNode-f4d3fe3-20181213005010
+
jobs:
# Windows outerloop legs
- ${{ if endsWith(variables['Build.DefinitionName'], 'windows') }}:
diff --git a/eng/pipelines/publish.yml b/eng/pipelines/publish.yml
index fe505183bf0a..7813515ffac2 100644
--- a/eng/pipelines/publish.yml
+++ b/eng/pipelines/publish.yml
@@ -25,11 +25,9 @@ jobs:
variables:
- group: Publish-Build-Assets
- group: DotNet-Blob-Feed
- - group: DotNet-MyGet-Publish
- group: DotNet-Versions-Publish
- _dotnetFeedUrl: https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json
- _maestroApiEndpoint: https://maestro-prod.westus2.cloudapp.azure.com
- - _mygetFeedUrl: https://dotnet.myget.org/F/dotnet-core/api/v2/package
- _manifestsDir: ${{ parameters.artifactsDir }}/AssetManifests
- _TeamName: DotNetCore
- _SignType: real
@@ -96,13 +94,6 @@ jobs:
/p:Configuration=${{ parameters.buildConfiguration }}
displayName: Publish to Build Assets Registry
- # - script: powershell -ExecutionPolicy ByPass -NoProfile eng\common\msbuild.ps1 eng\publish.proj
- # -warnaserror:0 -ci
- # /t:NuGetPush
- # /p:NuGetSource=$(_mygetFeedUrl)
- # /p:NuGetApiKey=$(dotnet-myget-org-api-key)
- # displayName: Push to myget.org
-
- script: powershell -ExecutionPolicy ByPass -NoProfile eng\common\msbuild.ps1 build.proj
-warnaserror:0 -ci
/t:UpdatePublishedVersions
diff --git a/eng/pipelines/windows.yml b/eng/pipelines/windows.yml
index bd591873307c..b165a2ae837e 100644
--- a/eng/pipelines/windows.yml
+++ b/eng/pipelines/windows.yml
@@ -166,6 +166,7 @@ jobs:
name: Hosted VS2017
submitToHelix: true
+ buildExtraArguments: /p:RuntimeOS=win10
# azure pipelines reporter only supports xunit results based tests.
enableAzurePipelinesReporter: false
@@ -176,9 +177,9 @@ jobs:
- ${{ if eq(parameters.isOfficialBuild, 'true') }}:
- allConfigurationsQueues: Windows.10.Amd64.ClientRS5
+ _jobFramework: -allConfigurations
customBuildSteps:
- script: build.cmd
- -restore
-build
-configuration $(_BuildConfig)
-ci
@@ -187,19 +188,8 @@ jobs:
-arch $(_architecture)
/p:RuntimeOS=win10
/p:ArchiveTests=Packages
- $(_windowsOfficialBuildArguments)
$(_msbuildCommonParameters)
displayName: Build Packages and Tests
- - ${{ if eq(parameters.isOfficialBuild, 'false') }}:
- - script: build.cmd
- -restore
- -build
- -configuration $(_BuildConfig)
- -ci
- -buildtests
- -framework netstandard
- -arch $(_architecture)
- displayName: Build Netstandard Test Suite
# TODO: UAPAOT official builds should send to helix using continuation runner.
# Legs without HELIX testing
diff --git a/eng/referenceFromRuntime.targets b/eng/referenceFromRuntime.targets
index e739943c31e8..c81a64c967cb 100644
--- a/eng/referenceFromRuntime.targets
+++ b/eng/referenceFromRuntime.targets
@@ -48,7 +48,9 @@
<_filteredReferencePathFromRuntimeByFileName Include="@(_referencePathFromRuntimeByFileName)"
- Condition="'@(_referencePathFromRuntimeByFileName)' == '@(ReferenceFromRuntime)' AND '%(Identity)' != ''" />
+ Condition="'@(_referencePathFromRuntimeByFileName)' == '@(ReferenceFromRuntime)' AND '%(Identity)' != ''">
+ @(ReferenceFromRuntime->'%(Aliases)')
+
<_remainingReferenceFromRuntime Include="@(ReferenceFromRuntime)" Exclude="@(_filteredReferencePathFromRuntimeByFileName)" />
@@ -58,12 +60,16 @@
<_filteredReferencePathFromRuntimeByFileName Include="@(_referencePathFromRuntimeByFileName)"
- Condition="'@(_referencePathFromRuntimeByFileName)' == '@(_remainingReferenceFromRuntimeWithNI)' AND '%(Identity)' != ''" />
+ Condition="'@(_referencePathFromRuntimeByFileName)' == '@(_remainingReferenceFromRuntimeWithNI)' AND '%(Identity)' != ''">
+ @(_remainingReferenceFromRuntimeWithNI->'%(Aliases)')
+
<_missingReferenceFromRuntime Include="@(_remainingReferenceFromRuntimeWithNI)" Exclude="@(_filteredReferencePathFromRuntimeByFileName)" />
+
+
test/functional/ilc/
-
+
set DOTNET_CLI_TELEMETRY_OPTOUT=1;set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1;set DOTNET_MULTILEVEL_LOOKUP=0
%HELIX_CORRELATION_PAYLOAD%\tools\dotnet.exe msbuild %HELIX_CORRELATION_PAYLOAD%\test.msbuild
@@ -66,17 +66,24 @@
$(HelixCommand) /p:LocalPackagesPath="%HELIX_CORRELATION_PAYLOAD%\packages\
+
+
+ true
+
-
+
- call RunTests.cmd %HELIX_CORRELATION_PAYLOAD% %HELIX_CORRELATION_PAYLOAD% %HELIX_CORRELATION_PAYLOAD%\tools
- ./RunTests.sh $HELIX_CORRELATION_PAYLOAD $HELIX_CORRELATION_PAYLOAD $HELIX_CORRELATION_PAYLOAD/tools
+ call RunTests.cmd --runtime-path %HELIX_CORRELATION_PAYLOAD% --dotnet-root %HELIX_CORRELATION_PAYLOAD%
+ $(HelixCommand) --global-tools-dir "%HELIX_CORRELATION_PAYLOAD%\tools"
+
+
+
+ ./RunTests.sh --runtime-path "$HELIX_CORRELATION_PAYLOAD" --dotnet-root "$HELIX_CORRELATION_PAYLOAD"
+ $(HelixCommand) --global-tools-dir "$HELIX_CORRELATION_PAYLOAD/tools"
-
- true
-
-
diff --git a/external/optimizationData/optimizationData.depproj b/external/optimizationData/optimizationData.depproj
index 7a5efe42cccc..7bdc2518c2c3 100644
--- a/external/optimizationData/optimizationData.depproj
+++ b/external/optimizationData/optimizationData.depproj
@@ -3,14 +3,11 @@
$(IbcOptimizationDataDir)
false
-
- optimization.windows_nt-x64.IBC.CoreFx
- optimization.linux-x64.IBC.CoreFx
- $(optimizationwindows_ntx64IBCCoreFxPackageVersion)
-
+
+
diff --git a/external/runtime/Configurations.props b/external/runtime/Configurations.props
index a63f4d4d76df..dd6a33c689e3 100644
--- a/external/runtime/Configurations.props
+++ b/external/runtime/Configurations.props
@@ -2,8 +2,6 @@
netcoreapp-Windows_NT;
- netcoreappaot-Windows_NT;
- netcoreappaot-WebAssembly;
netcoreapp-Unix;
uap10.0.16299;
uap10.0.16299aot;
diff --git a/external/runtime/runtime.depproj b/external/runtime/runtime.depproj
index 83dad8708613..3a876a60aaf1 100644
--- a/external/runtime/runtime.depproj
+++ b/external/runtime/runtime.depproj
@@ -19,7 +19,7 @@
- 1.1.0-$(ProjectNTfsExpectedPrerelease)
+ 1.1.0-$(ProjectNTfsExpectedPrerelease)
1.1.0-rel-25728-00
diff --git a/external/test-runtime/Configurations.props b/external/test-runtime/Configurations.props
index d9c88a0605aa..9fc9521a1890 100644
--- a/external/test-runtime/Configurations.props
+++ b/external/test-runtime/Configurations.props
@@ -3,7 +3,6 @@
uap;
uapaot;
- netcoreappaot;
netstandard;
netfx;
netcoreapp;
diff --git a/external/test-runtime/XUnit.Runtime.depproj b/external/test-runtime/XUnit.Runtime.depproj
index c7faf26e0db6..e795c082bc1c 100644
--- a/external/test-runtime/XUnit.Runtime.depproj
+++ b/external/test-runtime/XUnit.Runtime.depproj
@@ -44,14 +44,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/external/tools/Configurations.props b/external/tools/Configurations.props
index 93d8aff55d97..2870dced4592 100644
--- a/external/tools/Configurations.props
+++ b/external/tools/Configurations.props
@@ -1,16 +1,7 @@

- netcoreapp-Windows_NT;
- netcoreappaot-Windows_NT;
- netcoreappaot-WebAssembly;
- netcoreapp-Unix;
- netfx;
- uap10.0.16299;
- uap10.0.16299aot;
- uap;
- uapaot;
- mono;
+ netstandard;
diff --git a/global.json b/global.json
index 3d75bc4ee04b..157d39d6d579 100644
--- a/global.json
+++ b/global.json
@@ -1,10 +1,10 @@
{
"tools": {
- "dotnet": "2.2.103"
+ "dotnet": "3.0.100-preview3-010431"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19202.3",
- "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19202.3",
- "Microsoft.NET.Sdk.IL": "3.0.0-preview4-27527-73"
+ "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19216.2",
+ "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19216.2",
+ "Microsoft.NET.Sdk.IL": "3.0.0-preview5-27617-73"
}
}
diff --git a/pkg/Microsoft.Private.CoreFx.NETCoreApp/Configurations.props b/pkg/Microsoft.Private.CoreFx.NETCoreApp/Configurations.props
index eb733ee25372..19236e72c58f 100644
--- a/pkg/Microsoft.Private.CoreFx.NETCoreApp/Configurations.props
+++ b/pkg/Microsoft.Private.CoreFx.NETCoreApp/Configurations.props
@@ -2,7 +2,6 @@
netcoreapp;
- netcoreappaot;
diff --git a/pkg/Microsoft.Private.CoreFx.NETCoreApp/Microsoft.Private.CoreFx.NETCoreApp.pkgproj b/pkg/Microsoft.Private.CoreFx.NETCoreApp/Microsoft.Private.CoreFx.NETCoreApp.pkgproj
index ca5a4bb4515c..783584839dfc 100644
--- a/pkg/Microsoft.Private.CoreFx.NETCoreApp/Microsoft.Private.CoreFx.NETCoreApp.pkgproj
+++ b/pkg/Microsoft.Private.CoreFx.NETCoreApp/Microsoft.Private.CoreFx.NETCoreApp.pkgproj
@@ -8,7 +8,6 @@
$(NETCoreAppPackageRefPath)
$(NETCoreAppPackageRuntimePath)
- $(NETCoreAppAotPackageRuntimePath)
true
diff --git a/pkg/Microsoft.Private.CoreFx.NETCoreApp/netcoreapp.rids.props b/pkg/Microsoft.Private.CoreFx.NETCoreApp/netcoreapp.rids.props
index f0c090b90870..7ce2ea9e2c70 100644
--- a/pkg/Microsoft.Private.CoreFx.NETCoreApp/netcoreapp.rids.props
+++ b/pkg/Microsoft.Private.CoreFx.NETCoreApp/netcoreapp.rids.props
@@ -24,7 +24,6 @@
x86
-
+ false
true
diff --git a/pkg/test/frameworkSettings/netcoreapp3.0/settings.targets b/pkg/test/frameworkSettings/netcoreapp3.0/settings.targets
index 988f2060f715..afde20c57942 100644
--- a/pkg/test/frameworkSettings/netcoreapp3.0/settings.targets
+++ b/pkg/test/frameworkSettings/netcoreapp3.0/settings.targets
@@ -4,19 +4,22 @@
3.0
$(MicrosoftNETCoreAppPackageVersion)
+ true
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
diff --git a/pkg/test/frameworkSettings/netstandard2.1/settings.targets b/pkg/test/frameworkSettings/netstandard2.1/settings.targets
new file mode 100644
index 000000000000..815786db5c51
--- /dev/null
+++ b/pkg/test/frameworkSettings/netstandard2.1/settings.targets
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.ActivityControl.cs b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.ActivityControl.cs
new file mode 100644
index 000000000000..34df748d39ab
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.ActivityControl.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ internal enum ActivityControl : uint
+ {
+ EVENT_ACTIVITY_CTRL_GET_ID = 1,
+ EVENT_ACTIVITY_CTRL_SET_ID = 2,
+ EVENT_ACTIVITY_CTRL_CREATE_ID = 3,
+ EVENT_ACTIVITY_CTRL_GET_SET_ID = 4,
+ EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5
+ }
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EVENT_INFO_CLASS.cs b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EVENT_INFO_CLASS.cs
new file mode 100644
index 000000000000..a122002e9abe
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EVENT_INFO_CLASS.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ internal enum EVENT_INFO_CLASS
+ {
+ BinaryTrackInfo,
+ SetEnableAllKeywords,
+ SetTraits,
+ }
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EtwEnableCallback.cs b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EtwEnableCallback.cs
new file mode 100644
index 000000000000..6bb157520f35
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EtwEnableCallback.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ internal const int EVENT_CONTROL_CODE_DISABLE_PROVIDER = 0;
+ internal const int EVENT_CONTROL_CODE_ENABLE_PROVIDER = 1;
+ internal const int EVENT_CONTROL_CODE_CAPTURE_STATE = 2;
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct EVENT_FILTER_DESCRIPTOR
+ {
+ public long Ptr;
+ public int Size;
+ public int Type;
+ }
+
+ internal unsafe delegate void EtwEnableCallback(
+ in Guid sourceId,
+ int isEnabled,
+ byte level,
+ long matchAnyKeywords,
+ long matchAllKeywords,
+ EVENT_FILTER_DESCRIPTOR* filterData,
+ void* callbackContext);
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventActivityIdControl.cs b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventActivityIdControl.cs
new file mode 100644
index 000000000000..886ff37d19fe
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventActivityIdControl.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ [DllImport(Libraries.Advapi32, ExactSpelling = true)]
+ internal static extern int EventActivityIdControl(ActivityControl ControlCode, ref Guid ActivityId);
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventRegister.cs b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventRegister.cs
new file mode 100644
index 000000000000..f5d245ec5d68
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventRegister.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ [DllImport(Libraries.Advapi32, ExactSpelling = true)]
+ internal static extern unsafe uint EventRegister(
+ in Guid providerId,
+ EtwEnableCallback enableCallback,
+ void* callbackContext,
+ ref long registrationHandle);
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventSetInformation.cs b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventSetInformation.cs
new file mode 100644
index 000000000000..381cb661c37e
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventSetInformation.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ [DllImport(Libraries.Advapi32, ExactSpelling = true)]
+ internal static unsafe extern int EventSetInformation(
+ long registrationHandle,
+ EVENT_INFO_CLASS informationClass,
+ void* eventInformation,
+ int informationLength);
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventTraceGuidsEx.cs b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventTraceGuidsEx.cs
new file mode 100644
index 000000000000..c5f6f3b18790
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventTraceGuidsEx.cs
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ internal enum TRACE_QUERY_INFO_CLASS
+ {
+ TraceGuidQueryList,
+ TraceGuidQueryInfo,
+ TraceGuidQueryProcess,
+ TraceStackTracingInfo,
+ MaxTraceSetInfoClass
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct TRACE_GUID_INFO
+ {
+ public int InstanceCount;
+ public int Reserved;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct TRACE_PROVIDER_INSTANCE_INFO
+ {
+ public int NextOffset;
+ public int EnableCount;
+ public int Pid;
+ public int Flags;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct TRACE_ENABLE_INFO
+ {
+ public int IsEnabled;
+ public byte Level;
+ public byte Reserved1;
+ public ushort LoggerId;
+ public int EnableProperty;
+ public int Reserved2;
+ public long MatchAnyKeyword;
+ public long MatchAllKeyword;
+ }
+
+ [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true)]
+ internal static unsafe extern int EnumerateTraceGuidsEx(
+ TRACE_QUERY_INFO_CLASS TraceQueryInfoClass,
+ void* InBuffer,
+ int InBufferSize,
+ void* OutBuffer,
+ int OutBufferSize,
+ out int ReturnLength);
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventUnregister.cs b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventUnregister.cs
new file mode 100644
index 000000000000..f387b3a9ab5c
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventUnregister.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ [DllImport(Libraries.Advapi32, ExactSpelling = true)]
+ internal static extern uint EventUnregister(long registrationHandle);
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventWriteString.cs b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventWriteString.cs
new file mode 100644
index 000000000000..a00a2f3a2c99
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventWriteString.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ [DllImport(Libraries.Advapi32, ExactSpelling = true)]
+ internal static extern int EventWriteString(
+ long registrationHandle,
+ byte level,
+ long keyword,
+ string msg);
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventWriteTransfer.cs b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventWriteTransfer.cs
new file mode 100644
index 000000000000..2d3f45e839be
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Advapi32/Interop.EventWriteTransfer.cs
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+#if ES_BUILD_STANDALONE
+using Microsoft.Diagnostics.Tracing;
+#else
+using System.Diagnostics.Tracing;
+#endif
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ ///
+ /// Call the ETW native API EventWriteTransfer and checks for invalid argument error.
+ /// The implementation of EventWriteTransfer on some older OSes (Windows 2008) does not accept null relatedActivityId.
+ /// So, for these cases we will retry the call with an empty Guid.
+ ///
+ internal static unsafe int EventWriteTransfer(
+ long registrationHandle,
+ in EventDescriptor eventDescriptor,
+ Guid* activityId,
+ Guid* relatedActivityId,
+ int userDataCount,
+ EventProvider.EventData* userData)
+ {
+ int HResult = EventWriteTransfer_PInvoke(registrationHandle, in eventDescriptor, activityId, relatedActivityId, userDataCount, userData);
+ if (HResult == Errors.ERROR_INVALID_PARAMETER && relatedActivityId == null)
+ {
+ Guid emptyGuid = Guid.Empty;
+ HResult = EventWriteTransfer_PInvoke(registrationHandle, in eventDescriptor, activityId, &emptyGuid, userDataCount, userData);
+ }
+
+ return HResult;
+ }
+
+ [DllImport(Interop.Libraries.Advapi32, ExactSpelling = true, EntryPoint = "EventWriteTransfer")]
+ private static unsafe extern int EventWriteTransfer_PInvoke(
+ long registrationHandle,
+ in EventDescriptor eventDescriptor,
+ Guid* activityId,
+ Guid* relatedActivityId,
+ int userDataCount,
+ EventProvider.EventData* userData);
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Interop.Errors.cs b/src/Common/src/CoreLib/Interop/Windows/Interop.Errors.cs
index 1a95db3c939b..2e4683dfd70a 100644
--- a/src/Common/src/CoreLib/Interop/Windows/Interop.Errors.cs
+++ b/src/Common/src/CoreLib/Interop/Windows/Interop.Errors.cs
@@ -18,6 +18,7 @@ internal partial class Errors
internal const int ERROR_NOT_READY = 0x15;
internal const int ERROR_SHARING_VIOLATION = 0x20;
internal const int ERROR_HANDLE_EOF = 0x26;
+ internal const int ERROR_NOT_SUPPORTED = 0x32;
internal const int ERROR_FILE_EXISTS = 0x50;
internal const int ERROR_INVALID_PARAMETER = 0x57;
internal const int ERROR_BROKEN_PIPE = 0x6D;
diff --git a/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.FileTimeToSystemTime.cs b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.FileTimeToSystemTime.cs
new file mode 100644
index 000000000000..067ee715870c
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.FileTimeToSystemTime.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Kernel32
+ {
+ [DllImport(Libraries.Kernel32)]
+ internal static unsafe extern Interop.BOOL FileTimeToSystemTime(long* lpFileTime, Interop.Kernel32.SYSTEMTIME* lpSystemTime);
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.GetProcessInformation.cs b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.GetProcessInformation.cs
new file mode 100644
index 000000000000..22e056937548
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.GetProcessInformation.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Kernel32
+ {
+ internal const int ProcessLeapSecondInfo = 8;
+
+ internal struct PROCESS_LEAP_SECOND_INFO
+ {
+ public uint Flags;
+ public uint Reserved;
+ }
+
+ [DllImport(Libraries.Kernel32)]
+ internal static unsafe extern Interop.BOOL GetProcessInformation(IntPtr hProcess, int ProcessInformationClass, void* ProcessInformation, int ProcessInformationSize);
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.GetSystemTime.cs b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.GetSystemTime.cs
new file mode 100644
index 000000000000..710db5e4b99f
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.GetSystemTime.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Kernel32
+ {
+ [DllImport(Libraries.Kernel32)]
+ internal static unsafe extern void GetSystemTime(Interop.Kernel32.SYSTEMTIME* lpSystemTime);
+ }
+}
diff --git a/src/Common/src/Interop/Windows/Kernel32/Interop.GetCurrentThreadId.cs b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.GetSystemTimeAsFileTime.cs
similarity index 56%
rename from src/Common/src/Interop/Windows/Kernel32/Interop.GetCurrentThreadId.cs
rename to src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.GetSystemTimeAsFileTime.cs
index a92936e291b0..e2dcd906c2ad 100644
--- a/src/Common/src/Interop/Windows/Kernel32/Interop.GetCurrentThreadId.cs
+++ b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.GetSystemTimeAsFileTime.cs
@@ -5,11 +5,11 @@
using System;
using System.Runtime.InteropServices;
-internal static partial class Interop
+internal partial class Interop
{
- internal static partial class Kernel32
+ internal partial class Kernel32
{
- [DllImport(Interop.Libraries.Kernel32, ExactSpelling = true)]
- public static extern int GetCurrentThreadId();
+ [DllImport(Libraries.Kernel32)]
+ internal static unsafe extern void GetSystemTimeAsFileTime(long* lpSystemTimeAsFileTime);
}
}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.GetSystemTimePreciseAsFileTime.cs b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.GetSystemTimePreciseAsFileTime.cs
new file mode 100644
index 000000000000..e3262799d132
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.GetSystemTimePreciseAsFileTime.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Kernel32
+ {
+ [DllImport(Libraries.Kernel32)]
+ internal static unsafe extern void GetSystemTimePreciseAsFileTime(long* lpSystemTimeAsFileTime);
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.SystemTimeToFileTime.cs b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.SystemTimeToFileTime.cs
new file mode 100644
index 000000000000..43db7b47164d
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.SystemTimeToFileTime.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Kernel32
+ {
+ [DllImport(Libraries.Kernel32)]
+ internal static unsafe extern Interop.BOOL SystemTimeToFileTime(Interop.Kernel32.SYSTEMTIME* lpSystemTime, long* lpFileTime);
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.TzSpecificLocalTimeToSystemTime.cs b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.TzSpecificLocalTimeToSystemTime.cs
new file mode 100644
index 000000000000..2cca7faed732
--- /dev/null
+++ b/src/Common/src/CoreLib/Interop/Windows/Kernel32/Interop.TzSpecificLocalTimeToSystemTime.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.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Kernel32
+ {
+ [DllImport(Libraries.Kernel32)]
+ internal static unsafe extern Interop.BOOL TzSpecificLocalTimeToSystemTime(
+ IntPtr lpTimeZoneInformation,
+ Interop.Kernel32.SYSTEMTIME* lpLocalTime,
+ Interop.Kernel32.SYSTEMTIME* lpUniversalTime);
+ }
+}
diff --git a/src/Common/src/CoreLib/Interop/Windows/NtDll/NtQueryInformationFile.cs b/src/Common/src/CoreLib/Interop/Windows/NtDll/Interop.NtQueryInformationFile.cs
similarity index 100%
rename from src/Common/src/CoreLib/Interop/Windows/NtDll/NtQueryInformationFile.cs
rename to src/Common/src/CoreLib/Interop/Windows/NtDll/Interop.NtQueryInformationFile.cs
diff --git a/src/Common/src/CoreLib/System.Private.CoreLib.Shared.projitems b/src/Common/src/CoreLib/System.Private.CoreLib.Shared.projitems
index 69fb5565a438..e51a210baea6 100644
--- a/src/Common/src/CoreLib/System.Private.CoreLib.Shared.projitems
+++ b/src/Common/src/CoreLib/System.Private.CoreLib.Shared.projitems
@@ -177,6 +177,7 @@
+
@@ -232,6 +233,7 @@
+
@@ -421,6 +423,7 @@
+
@@ -766,6 +769,7 @@
+
@@ -797,13 +801,17 @@
-
+
+
+
+
+
@@ -906,8 +914,11 @@
+
+
+
-
+
@@ -986,6 +997,13 @@
+
+
+
+
+
+
+
@@ -998,6 +1016,7 @@
+
@@ -1016,6 +1035,9 @@
+
+
+
@@ -1031,6 +1053,7 @@
+
@@ -1040,8 +1063,10 @@
+
+
@@ -1049,7 +1074,6 @@
-
@@ -1057,17 +1081,14 @@
+
-
-
-
-
@@ -1083,6 +1104,7 @@
+
@@ -1114,20 +1136,30 @@
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Common/src/CoreLib/System/Activator.RuntimeType.cs b/src/Common/src/CoreLib/System/Activator.RuntimeType.cs
index f328b9c25114..270aa6ad65cf 100644
--- a/src/Common/src/CoreLib/System/Activator.RuntimeType.cs
+++ b/src/Common/src/CoreLib/System/Activator.RuntimeType.cs
@@ -4,6 +4,7 @@
using System.Reflection;
using System.Globalization;
+using System.Runtime.Loader;
using System.Runtime.Remoting;
using System.Threading;
@@ -126,7 +127,7 @@ private static ObjectHandle CreateInstanceInternal(string assemblyString,
{
// Classic managed type
assembly = RuntimeAssembly.InternalLoadAssemblyName(
- assemblyName, ref stackMark);
+ assemblyName, ref stackMark, AssemblyLoadContext.CurrentContextualReflectionContext);
}
}
diff --git a/src/Common/src/CoreLib/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Default.cs b/src/Common/src/CoreLib/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Default.cs
index fdf79985ee12..4df370337d0a 100644
--- a/src/Common/src/CoreLib/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Default.cs
+++ b/src/Common/src/CoreLib/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Default.cs
@@ -83,12 +83,6 @@ private static bool TryParseDateTimeOffsetDefault(ReadOnlySpan source, out
offsetMinutes = (int)(digit1 * 10 + digit2);
}
- TimeSpan offset = new TimeSpan(hours: offsetHours, minutes: offsetMinutes, seconds: 0);
- if (sign == Utf8Constants.Minus)
- {
- offset = -offset;
- }
-
if (!TryCreateDateTimeOffset(dateTime: dateTime, offsetNegative: sign == Utf8Constants.Minus, offsetHours: offsetHours, offsetMinutes: offsetMinutes, out value))
{
bytesConsumed = 0;
diff --git a/src/Common/src/CoreLib/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs b/src/Common/src/CoreLib/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs
index 5c5fd994edc0..59e109a0431c 100644
--- a/src/Common/src/CoreLib/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs
+++ b/src/Common/src/CoreLib/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs
@@ -301,12 +301,12 @@ private static MemoryPressure GetMemoryPressure()
const double HighPressureThreshold = .90; // Percent of GC memory pressure threshold we consider "high"
const double MediumPressureThreshold = .70; // Percent of GC memory pressure threshold we consider "medium"
- GC.GetMemoryInfo(out uint threshold, out _, out uint lastLoad, out _, out _);
- if (lastLoad >= threshold * HighPressureThreshold)
+ GCMemoryInfo memoryInfo = GC.GetGCMemoryInfo();
+ if (memoryInfo.MemoryLoadBytes >= memoryInfo.HighMemoryLoadThresholdBytes * HighPressureThreshold)
{
return MemoryPressure.High;
}
- else if (lastLoad >= threshold * MediumPressureThreshold)
+ else if (memoryInfo.MemoryLoadBytes >= memoryInfo.HighMemoryLoadThresholdBytes * MediumPressureThreshold)
{
return MemoryPressure.Medium;
}
diff --git a/src/Common/src/CoreLib/System/Collections/Generic/Dictionary.cs b/src/Common/src/CoreLib/System/Collections/Generic/Dictionary.cs
index dbb0bdf56608..0a36cb5f7681 100644
--- a/src/Common/src/CoreLib/System/Collections/Generic/Dictionary.cs
+++ b/src/Common/src/CoreLib/System/Collections/Generic/Dictionary.cs
@@ -5,7 +5,6 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
-using System.Threading;
namespace System.Collections.Generic
{
@@ -38,8 +37,11 @@ public class Dictionary : IDictionary, IDictionary,
{
private struct Entry
{
- public int hashCode; // Lower 31 bits of hash code, -1 if unused
- public int next; // Index of next entry, -1 if last
+ // 0-based index of next entry in chain: -1 means end of chain
+ // also encodes whether this entry _itself_ is part of the free list by changing sign and subtracting 3,
+ // so -2 means end of free list, -3 means index 0 but on free list, -4 means index 1 but on free list, etc.
+ public int next;
+ public uint hashCode;
public TKey key; // Key of entry
public TValue value; // Value of entry
}
@@ -53,6 +55,7 @@ private struct Entry
private IEqualityComparer _comparer;
private KeyCollection _keys;
private ValueCollection _values;
+ private const int StartOfFreeList = -3;
// constants for serialization
private const string VersionName = "Version"; // Do not rename (binary serialization)
@@ -103,7 +106,7 @@ public Dictionary(IDictionary dictionary, IEqualityComparer
Entry[] entries = d._entries;
for (int i = 0; i < count; i++)
{
- if (entries[i].hashCode >= 0)
+ if (entries[i].next >= -1)
{
Add(entries[i].key, entries[i].value);
}
@@ -278,7 +281,7 @@ public bool ContainsValue(TValue value)
{
for (int i = 0; i < _count; i++)
{
- if (entries[i].hashCode >= 0 && entries[i].value == null) return true;
+ if (entries[i].next >= -1 && entries[i].value == null) return true;
}
}
else
@@ -288,7 +291,7 @@ public bool ContainsValue(TValue value)
// ValueType: Devirtualize with EqualityComparer.Default intrinsic
for (int i = 0; i < _count; i++)
{
- if (entries[i].hashCode >= 0 && EqualityComparer.Default.Equals(entries[i].value, value)) return true;
+ if (entries[i].next >= -1 && EqualityComparer.Default.Equals(entries[i].value, value)) return true;
}
}
else
@@ -299,7 +302,7 @@ public bool ContainsValue(TValue value)
EqualityComparer defaultComparer = EqualityComparer.Default;
for (int i = 0; i < _count; i++)
{
- if (entries[i].hashCode >= 0 && defaultComparer.Equals(entries[i].value, value)) return true;
+ if (entries[i].next >= -1 && defaultComparer.Equals(entries[i].value, value)) return true;
}
}
}
@@ -327,7 +330,7 @@ private void CopyTo(KeyValuePair[] array, int index)
Entry[] entries = _entries;
for (int i = 0; i < count; i++)
{
- if (entries[i].hashCode >= 0)
+ if (entries[i].next >= -1)
{
array[index++] = new KeyValuePair(entries[i].key, entries[i].value);
}
@@ -375,9 +378,9 @@ private int FindEntry(TKey key)
IEqualityComparer comparer = _comparer;
if (comparer == null)
{
- int hashCode = key.GetHashCode() & 0x7FFFFFFF;
+ uint hashCode = (uint)key.GetHashCode();
// Value in _buckets is 1-based
- i = buckets[hashCode % buckets.Length] - 1;
+ i = buckets[hashCode % (uint)buckets.Length] - 1;
if (default(TKey) != null)
{
// ValueType: Devirtualize with EqualityComparer.Default intrinsic
@@ -428,9 +431,9 @@ private int FindEntry(TKey key)
}
else
{
- int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
+ uint hashCode = (uint)comparer.GetHashCode(key);
// Value in _buckets is 1-based
- i = buckets[hashCode % buckets.Length] - 1;
+ i = buckets[hashCode % (uint)buckets.Length] - 1;
do
{
// Should be a while loop https://github.com/dotnet/coreclr/issues/15476
@@ -482,10 +485,10 @@ private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior)
Entry[] entries = _entries;
IEqualityComparer comparer = _comparer;
- int hashCode = ((comparer == null) ? key.GetHashCode() : comparer.GetHashCode(key)) & 0x7FFFFFFF;
+ uint hashCode = (uint)((comparer == null) ? key.GetHashCode() : comparer.GetHashCode(key));
int collisionCount = 0;
- ref int bucket = ref _buckets[hashCode % _buckets.Length];
+ ref int bucket = ref _buckets[hashCode % (uint)_buckets.Length];
// Value in _buckets is 1-based
int i = bucket - 1;
@@ -627,7 +630,7 @@ private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior)
if (count == entries.Length)
{
Resize();
- bucket = ref _buckets[hashCode % _buckets.Length];
+ bucket = ref _buckets[hashCode % (uint)_buckets.Length];
}
index = count;
_count = count + 1;
@@ -638,7 +641,9 @@ private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior)
if (updateFreeList)
{
- _freeList = entry.next;
+ Debug.Assert((StartOfFreeList - entries[_freeList].next) >= -1, "shouldn't overflow because `next` cannot underflow");
+
+ _freeList = StartOfFreeList - entries[_freeList].next;
}
entry.hashCode = hashCode;
// Value in _buckets is 1-based
@@ -725,19 +730,19 @@ private void Resize(int newSize, bool forceNewHashCodes)
{
for (int i = 0; i < count; i++)
{
- if (entries[i].hashCode >= 0)
+ if (entries[i].next >= -1)
{
Debug.Assert(_comparer == null);
- entries[i].hashCode = (entries[i].key.GetHashCode() & 0x7FFFFFFF);
+ entries[i].hashCode = (uint)entries[i].key.GetHashCode();
}
}
}
for (int i = 0; i < count; i++)
{
- if (entries[i].hashCode >= 0)
+ if (entries[i].next >= -1)
{
- int bucket = entries[i].hashCode % newSize;
+ uint bucket = entries[i].hashCode % (uint)newSize;
// Value in _buckets is 1-based
entries[i].next = buckets[bucket] - 1;
// Value in _buckets is 1-based
@@ -764,8 +769,8 @@ public bool Remove(TKey key)
int collisionCount = 0;
if (buckets != null)
{
- int hashCode = (_comparer?.GetHashCode(key) ?? key.GetHashCode()) & 0x7FFFFFFF;
- int bucket = hashCode % buckets.Length;
+ uint hashCode = (uint)(_comparer?.GetHashCode(key) ?? key.GetHashCode());
+ uint bucket = hashCode % (uint)buckets.Length;
int last = -1;
// Value in buckets is 1-based
int i = buckets[bucket] - 1;
@@ -784,8 +789,10 @@ public bool Remove(TKey key)
{
entries[last].next = entry.next;
}
- entry.hashCode = -1;
- entry.next = _freeList;
+
+ Debug.Assert((StartOfFreeList - _freeList) < 0, "shouldn't underflow because max hashtable length is MaxPrimeArrayLength = 0x7FEFFFFD(2146435069) _freelist underflow threshold 2147483646");
+
+ entry.next = StartOfFreeList - _freeList;
if (RuntimeHelpers.IsReferenceOrContainsReferences())
{
@@ -829,8 +836,8 @@ public bool Remove(TKey key, out TValue value)
int collisionCount = 0;
if (buckets != null)
{
- int hashCode = (_comparer?.GetHashCode(key) ?? key.GetHashCode()) & 0x7FFFFFFF;
- int bucket = hashCode % buckets.Length;
+ uint hashCode = (uint)(_comparer?.GetHashCode(key) ?? key.GetHashCode());
+ uint bucket = hashCode % (uint)buckets.Length;
int last = -1;
// Value in buckets is 1-based
int i = buckets[bucket] - 1;
@@ -852,8 +859,9 @@ public bool Remove(TKey key, out TValue value)
value = entry.value;
- entry.hashCode = -1;
- entry.next = _freeList;
+ Debug.Assert((StartOfFreeList - _freeList) < 0, "shouldn't underflow because max hashtable length is MaxPrimeArrayLength = 0x7FEFFFFD(2146435069) _freelist underflow threshold 2147483646");
+
+ entry.next = StartOfFreeList - _freeList;
if (RuntimeHelpers.IsReferenceOrContainsReferences())
{
@@ -925,7 +933,7 @@ void ICollection.CopyTo(Array array, int index)
Entry[] entries = _entries;
for (int i = 0; i < _count; i++)
{
- if (entries[i].hashCode >= 0)
+ if (entries[i].next >= -1)
{
dictEntryArray[index++] = new DictionaryEntry(entries[i].key, entries[i].value);
}
@@ -945,7 +953,7 @@ void ICollection.CopyTo(Array array, int index)
Entry[] entries = _entries;
for (int i = 0; i < count; i++)
{
- if (entries[i].hashCode >= 0)
+ if (entries[i].next >= -1)
{
objects[index++] = new KeyValuePair(entries[i].key, entries[i].value);
}
@@ -1018,12 +1026,12 @@ public void TrimExcess(int capacity)
int count = 0;
for (int i = 0; i < oldCount; i++)
{
- int hashCode = oldEntries[i].hashCode;
- if (hashCode >= 0)
+ uint hashCode = oldEntries[i].hashCode;
+ if (oldEntries[i].next >= -1)
{
ref Entry entry = ref entries[count];
entry = oldEntries[i];
- int bucket = hashCode % newSize;
+ uint bucket = hashCode % (uint)newSize;
// Value in _buckets is 1-based
entry.next = buckets[bucket] - 1;
// Value in _buckets is 1-based
@@ -1179,7 +1187,7 @@ public bool MoveNext()
{
ref Entry entry = ref _dictionary._entries[_index++];
- if (entry.hashCode >= 0)
+ if (entry.next >= -1)
{
_current = new KeyValuePair(entry.key, entry.value);
return true;
@@ -1307,7 +1315,7 @@ public void CopyTo(TKey[] array, int index)
Entry[] entries = _dictionary._entries;
for (int i = 0; i < count; i++)
{
- if (entries[i].hashCode >= 0) array[index++] = entries[i].key;
+ if (entries[i].next >= -1) array[index++] = entries[i].key;
}
}
@@ -1367,7 +1375,7 @@ void ICollection.CopyTo(Array array, int index)
{
for (int i = 0; i < count; i++)
{
- if (entries[i].hashCode >= 0) objects[index++] = entries[i].key;
+ if (entries[i].next >= -1) objects[index++] = entries[i].key;
}
}
catch (ArrayTypeMismatchException)
@@ -1411,7 +1419,7 @@ public bool MoveNext()
{
ref Entry entry = ref _dictionary._entries[_index++];
- if (entry.hashCode >= 0)
+ if (entry.next >= -1)
{
_currentKey = entry.key;
return true;
@@ -1490,7 +1498,7 @@ public void CopyTo(TValue[] array, int index)
Entry[] entries = _dictionary._entries;
for (int i = 0; i < count; i++)
{
- if (entries[i].hashCode >= 0) array[index++] = entries[i].value;
+ if (entries[i].next >= -1) array[index++] = entries[i].value;
}
}
@@ -1550,7 +1558,7 @@ void ICollection.CopyTo(Array array, int index)
{
for (int i = 0; i < count; i++)
{
- if (entries[i].hashCode >= 0) objects[index++] = entries[i].value;
+ if (entries[i].next >= -1) objects[index++] = entries[i].value;
}
}
catch (ArrayTypeMismatchException)
@@ -1594,7 +1602,7 @@ public bool MoveNext()
{
ref Entry entry = ref _dictionary._entries[_index++];
- if (entry.hashCode >= 0)
+ if (entry.next >= -1)
{
_currentValue = entry.value;
return true;
diff --git a/src/Common/src/CoreLib/System/ComponentModel/DefaultValueAttribute.cs b/src/Common/src/CoreLib/System/ComponentModel/DefaultValueAttribute.cs
index 136e4324ed74..fb2b49c94c10 100644
--- a/src/Common/src/CoreLib/System/ComponentModel/DefaultValueAttribute.cs
+++ b/src/Common/src/CoreLib/System/ComponentModel/DefaultValueAttribute.cs
@@ -2,39 +2,38 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;
using System.Threading;
namespace System.ComponentModel
{
- ///
- /// Specifies the default value for a property.
- ///
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments")]
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes")]
+ ///
+ /// Specifies the default value for a property.
+ ///
+ [SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments")]
+ [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes")]
[AttributeUsage(AttributeTargets.All)]
public class DefaultValueAttribute : Attribute
{
- ///
- /// This is the default value.
- ///
+ ///
+ /// This is the default value.
+ ///
private object _value;
// Delegate ad hoc created 'TypeDescriptor.ConvertFromInvariantString' reflection object cache
- static object s_convertFromInvariantString;
+ private static object s_convertFromInvariantString;
- ///
- /// Initializes a new instance of the class, converting the
- /// specified value to the
- /// specified type, and using the U.S. English culture as the
- /// translation
- /// context.
- ///
+ ///
+ /// Initializes a new instance of the
+ /// class, converting the specified value to the specified type, and using the U.S. English
+ /// culture as the translation context.
+ ///
public DefaultValueAttribute(Type type, string value)
{
- // The try/catch here is because attributes should never throw exceptions. We would fail to
- // load an otherwise normal class.
+ // The try/catch here is because attributes should never throw exceptions.
+ // We would fail to load an otherwise normal class.
try
{
if (TryConvertFromInvariantString(type, value, out object convertedValue))
@@ -54,8 +53,6 @@ public DefaultValueAttribute(Type type, string value)
_value = Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
}
- return;
-
// Looking for ad hoc created TypeDescriptor.ConvertFromInvariantString(Type, string)
bool TryConvertFromInvariantString(Type typeToConvert, string stringValue, out object conversionResult)
{
@@ -89,143 +86,140 @@ bool TryConvertFromInvariantString(Type typeToConvert, string stringValue, out o
}
}
- ///
- /// Initializes a new instance of the class using a Unicode
- /// character.
- ///
+ ///
+ /// Initializes a new instance of the
+ /// class using a Unicode character.
+ ///
public DefaultValueAttribute(char value)
{
_value = value;
}
- ///
- /// Initializes a new instance of the class using an 8-bit unsigned
- /// integer.
- ///
+
+ ///
+ /// Initializes a new instance of the
+ /// class using an 8-bit unsigned integer.
+ ///
public DefaultValueAttribute(byte value)
{
_value = value;
}
- ///
- /// Initializes a new instance of the class using a 16-bit signed
- /// integer.
- ///
+
+ ///
+ /// Initializes a new instance of the
+ /// class using a 16-bit signed integer.
+ ///
public DefaultValueAttribute(short value)
{
_value = value;
}
- ///
- /// Initializes a new instance of the class using a 32-bit signed
- /// integer.
- ///
+
+ ///
+ /// Initializes a new instance of the
+ /// class using a 32-bit signed integer.
+ ///
public DefaultValueAttribute(int value)
{
_value = value;
}
- ///
- /// Initializes a new instance of the class using a 64-bit signed
- /// integer.
- ///
+
+ ///
+ /// Initializes a new instance of the
+ /// class using a 64-bit signed integer.
+ ///
public DefaultValueAttribute(long value)
{
_value = value;
}
- ///
- /// Initializes a new instance of the class using a
- /// single-precision floating point
- /// number.
- ///
+
+ ///
+ /// Initializes a new instance of the
+ /// class using a single-precision floating point number.
+ ///
public DefaultValueAttribute(float value)
{
_value = value;
}
- ///
- /// Initializes a new instance of the class using a
- /// double-precision floating point
- /// number.
- ///
+
+ ///
+ /// Initializes a new instance of the
+ /// class using a double-precision floating point number.
+ ///
public DefaultValueAttribute(double value)
{
_value = value;
}
- ///
- /// Initializes a new instance of the class using a
- /// value.
- ///
+
+ ///
+ /// Initializes a new instance of the
+ /// class using a value.
+ ///
public DefaultValueAttribute(bool value)
{
_value = value;
}
- ///
- /// Initializes a new instance of the class using a .
- ///
+
+ ///
+ /// Initializes a new instance of the
+ /// class using a .
+ ///
public DefaultValueAttribute(string value)
{
_value = value;
}
- ///
- /// Initializes a new instance of the
- /// class.
- ///
+ ///
+ /// Initializes a new instance of the
+ /// class.
+ ///
public DefaultValueAttribute(object value)
{
_value = value;
}
- ///
- /// Initializes a new instance of the class using a
- /// value.
- ///
+ ///
+ /// Initializes a new instance of the
+ /// class using a value.
+ ///
[CLSCompliant(false)]
public DefaultValueAttribute(sbyte value)
{
_value = value;
}
- ///
- /// Initializes a new instance of the class using a
- /// value.
- ///
+ ///
+ /// Initializes a new instance of the
+ /// class using a value.
+ ///
[CLSCompliant(false)]
public DefaultValueAttribute(ushort value)
{
_value = value;
}
- ///
- /// Initializes a new instance of the class using a
- /// value.
- ///
+ ///
+ /// Initializes a new instance of the
+ /// class using a value.
+ ///
[CLSCompliant(false)]
public DefaultValueAttribute(uint value)
{
_value = value;
}
- ///
- /// Initializes a new instance of the class using a
- /// value.
- ///
+ ///
+ /// Initializes a new instance of the
+ /// class using a value.
+ ///
[CLSCompliant(false)]
public DefaultValueAttribute(ulong value)
{
_value = value;
}
- ///
- ///
- /// Gets the default value of the property this
- /// attribute is
- /// bound to.
- ///
- ///
- public virtual object Value
- {
- get
- {
- return _value;
- }
- }
+ ///
+ /// Gets the default value of the property this attribute is bound to.
+ ///
+ public virtual object Value => _value;
public override bool Equals(object obj)
{
@@ -233,29 +227,21 @@ public override bool Equals(object obj)
{
return true;
}
-
- if (obj is DefaultValueAttribute other)
+ if (!(obj is DefaultValueAttribute other))
{
- if (Value != null)
- {
- return Value.Equals(other.Value);
- }
- else
- {
- return (other.Value == null);
- }
+ return false;
+ }
+
+ if (Value == null)
+ {
+ return other.Value == null;
}
- return false;
- }
- public override int GetHashCode()
- {
- return base.GetHashCode();
+ return Value.Equals(other.Value);
}
- protected void SetValue(object value)
- {
- _value = value;
- }
+ public override int GetHashCode() => base.GetHashCode();
+
+ protected void SetValue(object value) => _value = value;
}
}
diff --git a/src/Common/src/CoreLib/System/ComponentModel/EditorBrowsableAttribute.cs b/src/Common/src/CoreLib/System/ComponentModel/EditorBrowsableAttribute.cs
index a59ee839bc40..de69538532f6 100644
--- a/src/Common/src/CoreLib/System/ComponentModel/EditorBrowsableAttribute.cs
+++ b/src/Common/src/CoreLib/System/ComponentModel/EditorBrowsableAttribute.cs
@@ -7,20 +7,17 @@ namespace System.ComponentModel
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Delegate | AttributeTargets.Interface)]
public sealed class EditorBrowsableAttribute : Attribute
{
- private EditorBrowsableState browsableState;
-
public EditorBrowsableAttribute(EditorBrowsableState state)
{
- browsableState = state;
+ State = state;
}
- public EditorBrowsableAttribute() : this(EditorBrowsableState.Always) { }
-
- public EditorBrowsableState State
+ public EditorBrowsableAttribute() : this(EditorBrowsableState.Always)
{
- get { return browsableState; }
}
+ public EditorBrowsableState State { get; }
+
public override bool Equals(object obj)
{
if (obj == this)
@@ -28,19 +25,9 @@ public override bool Equals(object obj)
return true;
}
- return (obj is EditorBrowsableAttribute other) && other.browsableState == browsableState;
- }
-
- public override int GetHashCode()
- {
- return base.GetHashCode();
+ return (obj is EditorBrowsableAttribute other) && other.State == State;
}
- }
- public enum EditorBrowsableState
- {
- Always,
- Never,
- Advanced
+ public override int GetHashCode() => base.GetHashCode();
}
}
diff --git a/src/Common/src/CoreLib/System/ComponentModel/EditorBrowsableState.cs b/src/Common/src/CoreLib/System/ComponentModel/EditorBrowsableState.cs
new file mode 100644
index 000000000000..a98669c4e963
--- /dev/null
+++ b/src/Common/src/CoreLib/System/ComponentModel/EditorBrowsableState.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.ComponentModel
+{
+ public enum EditorBrowsableState
+ {
+ Always,
+ Never,
+ Advanced
+ }
+}
diff --git a/src/Common/src/CoreLib/System/DateTime.Unix.cs b/src/Common/src/CoreLib/System/DateTime.Unix.cs
index 6cf018115bac..2c4de3e1a85e 100644
--- a/src/Common/src/CoreLib/System/DateTime.Unix.cs
+++ b/src/Common/src/CoreLib/System/DateTime.Unix.cs
@@ -18,8 +18,8 @@ public static DateTime UtcNow
}
#endif
- internal static DateTime FromFileTimeLeapSecondsAware(long fileTime) => default;
- internal static long ToFileTimeLeapSecondsAware(long ticks) => default;
+ private static DateTime FromFileTimeLeapSecondsAware(long fileTime) => default;
+ private static long ToFileTimeLeapSecondsAware(long ticks) => default;
// IsValidTimeWithLeapSeconds is not expected to be called at all for now on non-Windows platforms
internal static bool IsValidTimeWithLeapSeconds(int year, int month, int day, int hour, int minute, int second, DateTimeKind kind) => false;
diff --git a/src/Common/src/CoreLib/System/DateTime.Win32.cs b/src/Common/src/CoreLib/System/DateTime.Win32.cs
new file mode 100644
index 000000000000..d742c891c7c0
--- /dev/null
+++ b/src/Common/src/CoreLib/System/DateTime.Win32.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace System
+{
+ public readonly partial struct DateTime
+ {
+ private static unsafe bool SystemSupportsLeapSeconds()
+ {
+ Interop.NtDll.SYSTEM_LEAP_SECOND_INFORMATION slsi;
+
+ return Interop.NtDll.NtQuerySystemInformation(
+ Interop.NtDll.SystemLeapSecondInformation,
+ (void *) &slsi,
+ sizeof(Interop.NtDll.SYSTEM_LEAP_SECOND_INFORMATION),
+ null) == 0 && slsi.Enabled;
+ }
+ }
+}
diff --git a/src/Common/src/CoreLib/System/DateTime.WinRT.cs b/src/Common/src/CoreLib/System/DateTime.WinRT.cs
new file mode 100644
index 000000000000..30a9a61aa3da
--- /dev/null
+++ b/src/Common/src/CoreLib/System/DateTime.WinRT.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace System
+{
+ public readonly partial struct DateTime
+ {
+ private static unsafe bool SystemSupportsLeapSeconds()
+ {
+ Interop.Kernel32.PROCESS_LEAP_SECOND_INFO info;
+
+ // Store apps don't have access to an API that would let us find out whether leap seconds have been
+ // disabled by policy: this implementation will produce slightly different results from what
+ // we have for Win32. If GetProcessInformation succeeds, we have to act as if leap seconds existed.
+ // They could still have been disabled by policy, but we have no way to check for that.
+ return Interop.Kernel32.GetProcessInformation(
+ Interop.Kernel32.GetCurrentProcess(),
+ Interop.Kernel32.ProcessLeapSecondInfo,
+ &info,
+ sizeof(Interop.Kernel32.PROCESS_LEAP_SECOND_INFO)) != Interop.BOOL.FALSE;
+ }
+ }
+}
diff --git a/src/Common/src/CoreLib/System/DateTime.Windows.cs b/src/Common/src/CoreLib/System/DateTime.Windows.cs
new file mode 100644
index 000000000000..ba9df5c4536b
--- /dev/null
+++ b/src/Common/src/CoreLib/System/DateTime.Windows.cs
@@ -0,0 +1,216 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace System
+{
+ public readonly partial struct DateTime
+ {
+ internal static readonly bool s_systemSupportsLeapSeconds = SystemSupportsLeapSeconds();
+
+ public static unsafe DateTime UtcNow
+ {
+ get
+ {
+ if (s_systemSupportsLeapSeconds)
+ {
+ FullSystemTime time;
+ GetSystemTimeWithLeapSecondsHandling(&time);
+ return CreateDateTimeFromSystemTime(in time);
+ }
+
+ return new DateTime(((ulong)(GetSystemTimeAsFileTime() + FileTimeOffset)) | KindUtc);
+ }
+ }
+
+ internal static unsafe bool IsValidTimeWithLeapSeconds(int year, int month, int day, int hour, int minute, int second, DateTimeKind kind)
+ {
+ DateTime dt = new DateTime(year, month, day);
+ FullSystemTime time = new FullSystemTime(year, month, dt.DayOfWeek, day, hour, minute, second);
+
+ switch (kind)
+ {
+ case DateTimeKind.Local: return ValidateSystemTime(&time.systemTime, localTime: true);
+ case DateTimeKind.Utc: return ValidateSystemTime(&time.systemTime, localTime: false);
+ default:
+ return ValidateSystemTime(&time.systemTime, localTime: true) || ValidateSystemTime(&time.systemTime, localTime: false);
+ }
+ }
+
+ private static unsafe DateTime FromFileTimeLeapSecondsAware(long fileTime)
+ {
+ FullSystemTime time;
+ if (FileTimeToSystemTime(fileTime, &time))
+ {
+ return CreateDateTimeFromSystemTime(in time);
+ }
+
+ throw new ArgumentOutOfRangeException(nameof(fileTime), SR.ArgumentOutOfRange_DateTimeBadTicks);
+ }
+
+ private static unsafe long ToFileTimeLeapSecondsAware(long ticks)
+ {
+ FullSystemTime time = new FullSystemTime(ticks);
+ long fileTime;
+
+ if (SystemTimeToFileTime(&time.systemTime, &fileTime))
+ {
+ return fileTime + ticks % TicksPerMillisecond;
+ }
+
+ throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_FileTimeInvalid);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static DateTime CreateDateTimeFromSystemTime(in FullSystemTime time)
+ {
+ long ticks = DateToTicks(time.systemTime.Year, time.systemTime.Month, time.systemTime.Day);
+ ticks += TimeToTicks(time.systemTime.Hour, time.systemTime.Minute, time.systemTime.Second);
+ ticks += time.systemTime.Milliseconds * TicksPerMillisecond;
+ ticks += time.hundredNanoSecond;
+ return new DateTime( ((UInt64)(ticks)) | KindUtc);
+ }
+
+ // FullSystemTime struct is the SYSTEMTIME struct with extra hundredNanoSecond field to store more precise time.
+ [StructLayout(LayoutKind.Sequential)]
+ private struct FullSystemTime
+ {
+ internal Interop.Kernel32.SYSTEMTIME systemTime;
+ internal long hundredNanoSecond;
+
+ internal FullSystemTime(int year, int month, DayOfWeek dayOfWeek, int day, int hour, int minute, int second)
+ {
+ systemTime.Year = (ushort) year;
+ systemTime.Month = (ushort) month;
+ systemTime.DayOfWeek = (ushort) dayOfWeek;
+ systemTime.Day = (ushort) day;
+ systemTime.Hour = (ushort) hour;
+ systemTime.Minute = (ushort) minute;
+ systemTime.Second = (ushort) second;
+ systemTime.Milliseconds = 0;
+ hundredNanoSecond = 0;
+ }
+
+ internal FullSystemTime(long ticks)
+ {
+ DateTime dt = new DateTime(ticks);
+
+ int year, month, day;
+ dt.GetDatePart(out year, out month, out day);
+
+ systemTime.Year = (ushort) year;
+ systemTime.Month = (ushort) month;
+ systemTime.DayOfWeek = (ushort) dt.DayOfWeek;
+ systemTime.Day = (ushort) day;
+ systemTime.Hour = (ushort) dt.Hour;
+ systemTime.Minute = (ushort) dt.Minute;
+ systemTime.Second = (ushort) dt.Second;
+ systemTime.Milliseconds = (ushort) dt.Millisecond;
+ hundredNanoSecond = 0;
+ }
+ };
+
+#if !CORECLR
+ internal static readonly bool s_systemSupportsPreciseSystemTime = SystemSupportsPreciseSystemTime();
+
+ private static unsafe bool SystemSupportsPreciseSystemTime()
+ {
+ if (Environment.IsWindows8OrAbove)
+ {
+ // GetSystemTimePreciseAsFileTime exists and we'd like to use it. However, on
+ // misconfigured systems, it's possible for the "precise" time to be inaccurate:
+ // https://github.com/dotnet/coreclr/issues/14187
+ // If it's inaccurate, though, we expect it to be wildly inaccurate, so as a
+ // workaround/heuristic, we get both the "normal" and "precise" times, and as
+ // long as they're close, we use the precise one. This workaround can be removed
+ // when we better understand what's causing the drift and the issue is no longer
+ // a problem or can be better worked around on all targeted OSes.
+
+ long systemTimeResult;
+ Interop.Kernel32.GetSystemTimeAsFileTime(&systemTimeResult);
+
+ long preciseSystemTimeResult;
+ Interop.Kernel32.GetSystemTimePreciseAsFileTime(&preciseSystemTimeResult);
+
+ return Math.Abs(preciseSystemTimeResult - systemTimeResult) <= 100 * TicksPerMillisecond;
+ }
+
+ return false;
+ }
+
+ private static unsafe bool ValidateSystemTime(Interop.Kernel32.SYSTEMTIME* time, bool localTime)
+ {
+ if (localTime)
+ {
+ Interop.Kernel32.SYSTEMTIME st;
+ return Interop.Kernel32.TzSpecificLocalTimeToSystemTime(IntPtr.Zero, time, &st) != Interop.BOOL.FALSE;
+ }
+ else
+ {
+ long timestamp;
+ return Interop.Kernel32.SystemTimeToFileTime(time, ×tamp) != Interop.BOOL.FALSE;
+ }
+ }
+
+ private static unsafe bool FileTimeToSystemTime(long fileTime, FullSystemTime* time)
+ {
+ if (Interop.Kernel32.FileTimeToSystemTime(&fileTime, &time->systemTime) != Interop.BOOL.FALSE)
+ {
+ // to keep the time precision
+ time->hundredNanoSecond = fileTime % TicksPerMillisecond;
+ if (time->systemTime.Second > 59)
+ {
+ // we have a leap second, force it to last second in the minute as DateTime doesn't account for leap seconds in its calculation.
+ // we use the maxvalue from the milliseconds and the 100-nano seconds to avoid reporting two out of order 59 seconds
+ time->systemTime.Second = 59;
+ time->systemTime.Milliseconds = 999;
+ time->hundredNanoSecond = 9999;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private static unsafe void GetSystemTimeWithLeapSecondsHandling(FullSystemTime* time)
+ {
+ if (!FileTimeToSystemTime(GetSystemTimeAsFileTime(), time))
+ {
+ Interop.Kernel32.GetSystemTime(&time->systemTime);
+ time->hundredNanoSecond = 0;
+ if (time->systemTime.Second > 59)
+ {
+ // we have a leap second, force it to last second in the minute as DateTime doesn't account for leap seconds in its calculation.
+ // we use the maxvalue from the milliseconds and the 100-nano seconds to avoid reporting two out of order 59 seconds
+ time->systemTime.Second = 59;
+ time->systemTime.Milliseconds = 999;
+ time->hundredNanoSecond = 9999;
+ }
+ }
+ }
+
+ private static unsafe bool SystemTimeToFileTime(Interop.Kernel32.SYSTEMTIME* time, long* fileTime)
+ {
+ return Interop.Kernel32.SystemTimeToFileTime(time, fileTime) != Interop.BOOL.FALSE;
+ }
+
+ private static unsafe long GetSystemTimeAsFileTime()
+ {
+ long timestamp;
+
+ if (s_systemSupportsPreciseSystemTime)
+ {
+ Interop.Kernel32.GetSystemTimePreciseAsFileTime(×tamp);
+ }
+ else
+ {
+ Interop.Kernel32.GetSystemTimeAsFileTime(×tamp);
+ }
+
+ return timestamp;
+ }
+#endif
+ }
+}
diff --git a/src/Common/src/CoreLib/System/Delegate.cs b/src/Common/src/CoreLib/System/Delegate.cs
index 1e8b8c967a7f..0c60ba5c40fb 100644
--- a/src/Common/src/CoreLib/System/Delegate.cs
+++ b/src/Common/src/CoreLib/System/Delegate.cs
@@ -11,10 +11,6 @@ namespace System
{
public abstract partial class Delegate : ICloneable, ISerializable
{
- private Delegate()
- {
- }
-
public virtual object Clone() => MemberwiseClone();
public static Delegate? Combine(Delegate? a, Delegate? b)
@@ -37,8 +33,6 @@ private Delegate()
return d;
}
- protected virtual Delegate CombineImpl(Delegate? d) => throw new MulticastNotSupportedException(SR.Multicast_Combine);
-
// V2 api: Creates open or closed delegates to static or instance methods - relaxed signature checking allowed.
public static Delegate CreateDelegate(Type type, object? firstArgument, MethodInfo method) => CreateDelegate(type, firstArgument, method, throwOnBindFailure: true)!;
@@ -53,19 +47,23 @@ private Delegate()
public static Delegate CreateDelegate(Type type, Type target, string method) => CreateDelegate(type, target, method, ignoreCase: false, throwOnBindFailure: true)!;
public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase) => CreateDelegate(type, target, method, ignoreCase, throwOnBindFailure: true)!;
+#if !CORERT
+ protected virtual Delegate CombineImpl(Delegate? d) => throw new MulticastNotSupportedException(SR.Multicast_Combine);
+
+ protected virtual Delegate? RemoveImpl(Delegate d) => d.Equals(this) ? null : this;
+
+ public virtual Delegate[] GetInvocationList() => new Delegate[] { this };
+
public object? DynamicInvoke(params object?[]? args)
{
return DynamicInvokeImpl(args);
}
-
- public virtual Delegate[] GetInvocationList() => new Delegate[] { this };
+#endif
public virtual void GetObjectData(SerializationInfo info, StreamingContext context) => throw new PlatformNotSupportedException();
public MethodInfo Method => GetMethodImpl();
- protected virtual Delegate? RemoveImpl(Delegate d) => d.Equals(this) ? null : this;
-
public static Delegate? Remove(Delegate? source, Delegate? value)
{
if (source == null)
diff --git a/src/Common/src/CoreLib/System/Diagnostics/Tracing/CounterGroup.cs b/src/Common/src/CoreLib/System/Diagnostics/Tracing/CounterGroup.cs
index 010cbd508fb3..0382556f3b56 100644
--- a/src/Common/src/CoreLib/System/Diagnostics/Tracing/CounterGroup.cs
+++ b/src/Common/src/CoreLib/System/Diagnostics/Tracing/CounterGroup.cs
@@ -20,22 +20,22 @@ namespace System.Diagnostics.Tracing
internal class CounterGroup
{
private readonly EventSource _eventSource;
- private readonly List _counters;
+ private readonly List _counters;
internal CounterGroup(EventSource eventSource)
{
_eventSource = eventSource;
- _counters = new List();
+ _counters = new List();
RegisterCommandCallback();
}
- internal void Add(BaseCounter eventCounter)
+ internal void Add(DiagnosticCounter eventCounter)
{
lock (this) // Lock the CounterGroup
_counters.Add(eventCounter);
}
- internal void Remove(BaseCounter eventCounter)
+ internal void Remove(DiagnosticCounter eventCounter)
{
lock (this) // Lock the CounterGroup
_counters.Remove(eventCounter);
diff --git a/src/Common/src/CoreLib/System/Diagnostics/Tracing/CounterPayload.cs b/src/Common/src/CoreLib/System/Diagnostics/Tracing/CounterPayload.cs
index ae4a1a7280f2..1be7d5494ae9 100644
--- a/src/Common/src/CoreLib/System/Diagnostics/Tracing/CounterPayload.cs
+++ b/src/Common/src/CoreLib/System/Diagnostics/Tracing/CounterPayload.cs
@@ -17,52 +17,6 @@ namespace Microsoft.Diagnostics.Tracing
namespace System.Diagnostics.Tracing
#endif
{
- // TODO: This should be removed as we make the new payloads public
- [EventData]
- internal class EventCounterPayload : IEnumerable>
- {
- public string Name { get; set; }
-
- public float Mean { get; set; }
-
- public float StandardDeviation { get; set; }
-
- public int Count { get; set; }
-
- public float Min { get; set; }
-
- public float Max { get; set; }
-
- public float IntervalSec { get; internal set; }
-
- #region Implementation of the IEnumerable interface
-
- public IEnumerator> GetEnumerator()
- {
- return ForEnumeration.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return ForEnumeration.GetEnumerator();
- }
-
- private IEnumerable> ForEnumeration
- {
- get
- {
- yield return new KeyValuePair("Name", Name);
- yield return new KeyValuePair("Mean", Mean);
- yield return new KeyValuePair("StandardDeviation", StandardDeviation);
- yield return new KeyValuePair("Count", Count);
- yield return new KeyValuePair("Min", Min);
- yield return new KeyValuePair("Max", Max);
- }
- }
-
- #endregion // Implementation of the IEnumerable interface
- }
-
[EventData]
internal class CounterPayload : IEnumerable>
{
@@ -70,19 +24,19 @@ internal class CounterPayload : IEnumerable>
public string DisplayName { get; set; }
- public float Mean { get; set; }
+ public double Mean { get; set; }
- public float StandardDeviation { get; set; }
+ public double StandardDeviation { get; set; }
public int Count { get; set; }
- public float Min { get; set; }
+ public double Min { get; set; }
- public float Max { get; set; }
+ public double Max { get; set; }
public float IntervalSec { get; internal set; }
- public string MetaData { get; set; }
+ public string Metadata { get; set; }
#region Implementation of the IEnumerable interface
@@ -110,7 +64,7 @@ private IEnumerable> ForEnumeration
yield return new KeyValuePair("IntervalSec", IntervalSec);
yield return new KeyValuePair("Series", $"Interval={IntervalSec}");
yield return new KeyValuePair("CounterType", "Mean");
- yield return new KeyValuePair("MetaData", MetaData);
+ yield return new KeyValuePair("Metadata", Metadata);
}
}
@@ -126,11 +80,11 @@ internal class IncrementingCounterPayload : IEnumerable> ForEnumeration
yield return new KeyValuePair("IntervalSec", IntervalSec);
yield return new KeyValuePair("Series", $"Interval={IntervalSec}");
yield return new KeyValuePair("CounterType", "Sum");
- yield return new KeyValuePair("MetaData", MetaData);
+ yield return new KeyValuePair("Metadata", Metadata);
}
}
diff --git a/src/Common/src/CoreLib/System/Diagnostics/Tracing/BaseCounter.cs b/src/Common/src/CoreLib/System/Diagnostics/Tracing/DiagnosticCounter.cs
similarity index 71%
rename from src/Common/src/CoreLib/System/Diagnostics/Tracing/BaseCounter.cs
rename to src/Common/src/CoreLib/System/Diagnostics/Tracing/DiagnosticCounter.cs
index 447852e84a99..ea4cb92612b1 100644
--- a/src/Common/src/CoreLib/System/Diagnostics/Tracing/BaseCounter.cs
+++ b/src/Common/src/CoreLib/System/Diagnostics/Tracing/DiagnosticCounter.cs
@@ -19,10 +19,10 @@ namespace System.Diagnostics.Tracing
#endif
{
///
- /// BaseCounter is an abstract class that serves as the parent class for various Counter* classes,
+ /// DiagnosticCounter is an abstract class that serves as the parent class for various Counter* classes,
/// namely EventCounter, PollingCounter, IncrementingEventCounter, and IncrementingPollingCounter.
///
- public abstract class BaseCounter : IDisposable
+ public abstract class DiagnosticCounter : IDisposable
{
///
/// All Counters live as long as the EventSource that they are attached to unless they are
@@ -30,23 +30,22 @@ public abstract class BaseCounter : IDisposable
///
/// The name.
/// The event source.
- public BaseCounter(string name, EventSource eventSource)
+ public DiagnosticCounter(string name, EventSource eventSource)
{
if (name == null)
{
- throw new ArgumentNullException(nameof(_name));
+ throw new ArgumentNullException(nameof(Name));
}
if (eventSource == null)
{
- throw new ArgumentNullException(nameof(eventSource));
+ throw new ArgumentNullException(nameof(EventSource));
}
_group = CounterGroup.GetCounterGroup(eventSource);
_group.Add(this);
- _eventSource = eventSource;
- _name = name;
- _metaData = new Dictionary();
+ Name = name;
+ EventSource = eventSource;
}
///
@@ -67,38 +66,45 @@ public void Dispose()
///
/// Adds a key-value metadata to the EventCounter that will be included as a part of the payload
///
- internal void AddMetaData(string key, string value)
+ public void AddMetadata(string key, string value)
{
lock (MyLock)
{
- _metaData.Add(key, value);
+ _metadata = _metadata ?? new Dictionary();
+ _metadata.Add(key, value);
}
}
- internal string DisplayName { get; set; }
+ public string DisplayName { get; set; }
- #region private implementation
+ public string Name { get; }
+
+ public EventSource EventSource { get; }
- internal readonly string _name;
+ #region private implementation
private CounterGroup _group;
- private Dictionary _metaData;
- internal EventSource _eventSource;
+ private Dictionary _metadata;
internal abstract void WritePayload(float intervalSec);
// arbitrarily we use name as the lock object.
- internal object MyLock { get { return _name; } }
+ internal object MyLock { get { return Name; } }
internal void ReportOutOfBandMessage(string message)
{
- _eventSource.ReportOutOfBandMessage(message, true);
+ EventSource.ReportOutOfBandMessage(message, true);
}
- internal string GetMetaDataString()
+ internal string GetMetadataString()
{
+ if (_metadata == null)
+ {
+ return "";
+ }
+
StringBuilder sb = new StringBuilder("");
- foreach(KeyValuePair kvPair in _metaData)
+ foreach(KeyValuePair kvPair in _metadata)
{
sb.Append($"{kvPair.Key}:{kvPair.Value},");
}
diff --git a/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventCounter.cs b/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventCounter.cs
index 85fc40a08cc6..a9fc0895c9a8 100644
--- a/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventCounter.cs
+++ b/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventCounter.cs
@@ -26,7 +26,7 @@ namespace System.Diagnostics.Tracing
/// See https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestEventCounter.cs
/// which shows tests, which are also useful in seeing actual use.
///
- public partial class EventCounter : BaseCounter
+ public partial class EventCounter : DiagnosticCounter
{
///
/// Initializes a new instance of the class.
@@ -37,8 +37,8 @@ public partial class EventCounter : BaseCounter
/// The event source.
public EventCounter(string name, EventSource eventSource) : base(name, eventSource)
{
- _min = float.PositiveInfinity;
- _max = float.NegativeInfinity;
+ _min = double.PositiveInfinity;
+ _max = double.NegativeInfinity;
InitializeBuffer();
}
@@ -49,22 +49,27 @@ public EventCounter(string name, EventSource eventSource) : base(name, eventSour
///
/// The value.
public void WriteMetric(float value)
+ {
+ Enqueue((double)value);
+ }
+
+ public void WriteMetric(double value)
{
Enqueue(value);
}
- public override string ToString() => $"EventCounter '{_name}' Count {_count} Mean {(((double)_sum) / _count).ToString("n3")}";
+ public override string ToString() => $"EventCounter '{Name}' Count {_count} Mean {(_sum / _count).ToString("n3")}";
#region Statistics Calculation
// Statistics
private int _count;
- private float _sum;
- private float _sumSquared;
- private float _min;
- private float _max;
+ private double _sum;
+ private double _sumSquared;
+ private double _min;
+ private double _max;
- internal void OnMetricWritten(float value)
+ internal void OnMetricWritten(double value)
{
Debug.Assert(Monitor.IsEntered(MyLock));
_sum += value;
@@ -83,14 +88,13 @@ internal override void WritePayload(float intervalSec)
lock (MyLock)
{
Flush();
- EventCounterPayload payload = new EventCounterPayload();
- payload.Name = _name;
+ CounterPayload payload = new CounterPayload();
payload.Count = _count;
payload.IntervalSec = intervalSec;
if (0 < _count)
{
payload.Mean = _sum / _count;
- payload.StandardDeviation = (float)Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count);
+ payload.StandardDeviation = Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count);
}
else
{
@@ -99,8 +103,12 @@ internal override void WritePayload(float intervalSec)
}
payload.Min = _min;
payload.Max = _max;
+
+ payload.Metadata = GetMetadataString();
+ payload.DisplayName = DisplayName;
+ payload.Name = Name;
ResetStatistics();
- _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new EventCounterPayloadType(payload));
+ EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new CounterPayloadType(payload));
}
}
private void ResetStatistics()
@@ -109,35 +117,35 @@ private void ResetStatistics()
_count = 0;
_sum = 0;
_sumSquared = 0;
- _min = float.PositiveInfinity;
- _max = float.NegativeInfinity;
+ _min = double.PositiveInfinity;
+ _max = double.NegativeInfinity;
}
#endregion // Statistics Calculation
// Values buffering
private const int BufferedSize = 10;
- private const float UnusedBufferSlotValue = float.NegativeInfinity;
+ private const double UnusedBufferSlotValue = double.NegativeInfinity;
private const int UnsetIndex = -1;
- private volatile float[] _bufferedValues;
+ private volatile double[] _bufferedValues;
private volatile int _bufferedValuesIndex;
private void InitializeBuffer()
{
- _bufferedValues = new float[BufferedSize];
+ _bufferedValues = new double[BufferedSize];
for (int i = 0; i < _bufferedValues.Length; i++)
{
_bufferedValues[i] = UnusedBufferSlotValue;
}
}
- protected void Enqueue(float value)
+ private void Enqueue(double value)
{
// It is possible that two threads read the same bufferedValuesIndex, but only one will be able to write the slot, so that is okay.
int i = _bufferedValuesIndex;
while (true)
{
- float result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue);
+ double result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue);
i++;
if (_bufferedValues.Length <= i)
{
@@ -178,10 +186,10 @@ protected void Flush()
/// This is the payload that is sent in the with EventSource.Write
///
[EventData]
- class EventCounterPayloadType
+ class CounterPayloadType
{
- public EventCounterPayloadType(EventCounterPayload payload) { Payload = payload; }
- public EventCounterPayload Payload { get; set; }
+ public CounterPayloadType(CounterPayload payload) { Payload = payload; }
+ public CounterPayload Payload { get; set; }
}
}
diff --git a/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventProvider.cs b/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventProvider.cs
index 345a9cf66cd9..a8622a8fb817 100644
--- a/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventProvider.cs
+++ b/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventProvider.cs
@@ -63,7 +63,7 @@ internal enum ControllerCommand
#if ES_BUILD_STANDALONE
[System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
#endif
- internal partial class EventProvider : IDisposable
+ internal class EventProvider : IDisposable
{
// This is the windows EVENT_DATA_DESCRIPTOR structure. We expose it because this is what
// subclasses of EventProvider use when creating efficient (but unsafe) version of
@@ -92,10 +92,8 @@ internal SessionInfo(int sessionIdBit_, int etwSessionId_)
{ sessionIdBit = sessionIdBit_; etwSessionId = etwSessionId_; }
}
- private static bool m_setInformationMissing;
-
internal IEventProvider m_eventProvider; // The interface that implements the specific logging mechanism functions.
- UnsafeNativeMethods.ManifestEtw.EtwEnableCallback m_etwCallback; // Trace Callback function
+ Interop.Advapi32.EtwEnableCallback m_etwCallback; // Trace Callback function
private long m_regHandle; // Trace Registration Handle
private byte m_level; // Tracing Level
private long m_anyKeywordMask; // Trace Enable Flags
@@ -165,14 +163,14 @@ internal EventProvider(EventProviderType providerType)
/// reason the ETW Register call failed a NotSupported exception will be thrown.
///
//
- //
+ //
//
//
//
internal unsafe void Register(EventSource eventSource)
{
uint status;
- m_etwCallback = new UnsafeNativeMethods.ManifestEtw.EtwEnableCallback(EtwEnableCallBack);
+ m_etwCallback = new Interop.Advapi32.EtwEnableCallback(EtwEnableCallBack);
status = EventRegister(eventSource, m_etwCallback);
if (status != 0)
@@ -264,13 +262,13 @@ public virtual void Close()
//
//
unsafe void EtwEnableCallBack(
- [In] ref System.Guid sourceId,
- [In] int controlCode,
- [In] byte setLevel,
- [In] long anyKeyword,
- [In] long allKeyword,
- [In] UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
- [In] void* callbackContext
+ in System.Guid sourceId,
+ int controlCode,
+ byte setLevel,
+ long anyKeyword,
+ long allKeyword,
+ Interop.Advapi32.EVENT_FILTER_DESCRIPTOR* filterData,
+ void* callbackContext
)
{
// This is an optional callback API. We will therefore ignore any failures that happen as a
@@ -281,7 +279,7 @@ [In] void* callbackContext
ControllerCommand command = ControllerCommand.Update;
IDictionary args = null;
bool skipFinalOnControllerCommand = false;
- if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_ENABLE_PROVIDER)
+ if (controlCode == Interop.Advapi32.EVENT_CONTROL_CODE_ENABLE_PROVIDER)
{
m_enabled = true;
m_level = setLevel;
@@ -342,7 +340,7 @@ [In] void* callbackContext
OnControllerCommand(command, args, (bEnabling ? sessionChanged : -sessionChanged), etwSessionId);
}
}
- else if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_DISABLE_PROVIDER)
+ else if (controlCode == Interop.Advapi32.EVENT_CONTROL_CODE_DISABLE_PROVIDER)
{
m_enabled = false;
m_level = 0;
@@ -350,7 +348,7 @@ [In] void* callbackContext
m_allKeywordMask = 0;
m_liveSessions = null;
}
- else if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_CAPTURE_STATE)
+ else if (controlCode == Interop.Advapi32.EVENT_CONTROL_CODE_CAPTURE_STATE)
{
command = ControllerCommand.SendManifest;
}
@@ -491,24 +489,24 @@ private unsafe void GetSessionInfo(SessionInfoCallback action, ref ListInstanceCount; i++)
{
if (providerInstance->Pid == processId)
{
- var enabledInfos = (UnsafeNativeMethods.ManifestEtw.TRACE_ENABLE_INFO*)&providerInstance[1];
+ var enabledInfos = (Interop.Advapi32.TRACE_ENABLE_INFO*)&providerInstance[1];
// iterate over the list of active ETW sessions "listening" to the current provider
for (int j = 0; j < providerInstance->EnableCount; j++)
action(enabledInfos[j].LoggerId, enabledInfos[j].MatchAllKeyword, ref sessionList);
@@ -517,7 +515,7 @@ private unsafe void GetSessionInfo(SessionInfoCallback action, ref ListNextOffset && providerInstance->NextOffset < buffSize);
var structBase = (byte*)providerInstance;
- providerInstance = (UnsafeNativeMethods.ManifestEtw.TRACE_PROVIDER_INSTANCE_INFO*)&structBase[providerInstance->NextOffset];
+ providerInstance = (Interop.Advapi32.TRACE_PROVIDER_INSTANCE_INFO*)&structBase[providerInstance->NextOffset];
}
#else
#if !ES_BUILD_PCL && PLATFORM_WINDOWS // TODO command arguments don't work on PCL builds...
@@ -602,7 +600,7 @@ private static int IndexOfSessionInList(List sessions, int etwSessi
/// starts, and the command being issued associated with that data.
///
private unsafe bool GetDataFromController(int etwSessionId,
- UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart)
+ Interop.Advapi32.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart)
{
data = null;
dataStart = 0;
@@ -704,18 +702,9 @@ public static WriteEventErrorCode GetLastWriteEventError()
//
// Helper function to set the last error on the thread
//
- private static void SetLastError(int error)
+ private static void SetLastError(WriteEventErrorCode error)
{
- switch (error)
- {
- case UnsafeNativeMethods.ManifestEtw.ERROR_ARITHMETIC_OVERFLOW:
- case UnsafeNativeMethods.ManifestEtw.ERROR_MORE_DATA:
- s_returnCode = WriteEventErrorCode.EventTooBig;
- break;
- case UnsafeNativeMethods.ManifestEtw.ERROR_NOT_ENOUGH_MEMORY:
- s_returnCode = WriteEventErrorCode.NoFreeBuffers;
- break;
- }
+ s_returnCode = error;
}
//
@@ -961,7 +950,7 @@ to fill the passed in ETW data descriptor.
/// Payload for the ETW event.
///
//
- //
+ //
//
//
//
@@ -981,7 +970,7 @@ to fill the passed in ETW data descriptor.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, params object[] eventPayload)
{
- int status = 0;
+ WriteEventErrorCode status = WriteEventErrorCode.NoError;
if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
{
@@ -1109,7 +1098,7 @@ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr even
userDataPtr[refObjPosition[7]].Ptr = (ulong)v7;
}
- status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
+ status = m_eventProvider.EventWriteTransfer(m_regHandle, in eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
}
}
else
@@ -1135,7 +1124,7 @@ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr even
}
}
- status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
+ status = m_eventProvider.EventWriteTransfer(m_regHandle, in eventDescriptor, eventHandle, activityID, childActivityID, argCount, userData);
for (int i = 0; i < refObjIndex; ++i)
{
@@ -1145,9 +1134,9 @@ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr even
}
}
- if (status != 0)
+ if (status != WriteEventErrorCode.NoError)
{
- SetLastError((int)status);
+ SetLastError(status);
return false;
}
@@ -1174,7 +1163,7 @@ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr even
/// pointer do the event data
///
//
- //
+ //
//
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
internal protected unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
@@ -1188,7 +1177,7 @@ internal protected unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, I
(EventOpcode)eventDescriptor.Opcode == EventOpcode.Stop);
}
- int status = m_eventProvider.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, eventHandle, activityID, childActivityID, dataCount, (EventData*)data);
+ WriteEventErrorCode status = m_eventProvider.EventWriteTransfer(m_regHandle, in eventDescriptor, eventHandle, activityID, childActivityID, dataCount, (EventData*)data);
if (status != 0)
{
@@ -1207,29 +1196,30 @@ internal unsafe bool WriteEventRaw(
int dataCount,
IntPtr data)
{
- int status;
+ WriteEventErrorCode status;
- status = m_eventProvider.EventWriteTransferWrapper(
+ status = m_eventProvider.EventWriteTransfer(
m_regHandle,
- ref eventDescriptor,
+ in eventDescriptor,
eventHandle,
activityID,
relatedActivityID,
dataCount,
(EventData*)data);
- if (status != 0)
+ if (status != WriteEventErrorCode.NoError)
{
SetLastError(status);
return false;
}
+
return true;
}
// These are look-alikes to the Manifest based ETW OS APIs that have been shimmed to work
// either with Manifest ETW or Classic ETW (if Manifest based ETW is not available).
- private unsafe uint EventRegister(EventSource eventSource, UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback)
+ private unsafe uint EventRegister(EventSource eventSource, Interop.Advapi32.EtwEnableCallback enableCallback)
{
m_providerName = eventSource.Name;
m_providerId = eventSource.Guid;
@@ -1241,6 +1231,36 @@ private uint EventUnregister(long registrationHandle)
{
return m_eventProvider.EventUnregister(registrationHandle);
}
+
+#if PLATFORM_WINDOWS
+ private static bool m_setInformationMissing;
+
+ internal unsafe int SetInformation(
+ Interop.Advapi32.EVENT_INFO_CLASS eventInfoClass,
+ IntPtr data,
+ uint dataSize)
+ {
+ int status = Interop.Errors.ERROR_NOT_SUPPORTED;
+
+ if (!m_setInformationMissing)
+ {
+ try
+ {
+ status = Interop.Advapi32.EventSetInformation(
+ m_regHandle,
+ eventInfoClass,
+ (void*)data,
+ (int)dataSize);
+ }
+ catch (TypeLoadException)
+ {
+ m_setInformationMissing = true;
+ }
+ }
+
+ return status;
+ }
+#endif
}
#if PLATFORM_WINDOWS
@@ -1251,13 +1271,13 @@ internal sealed class EtwEventProvider : IEventProvider
// Register an event provider.
unsafe uint IEventProvider.EventRegister(
EventSource eventSource,
- UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
+ Interop.Advapi32.EtwEnableCallback enableCallback,
void* callbackContext,
ref long registrationHandle)
{
Guid providerId = eventSource.Guid;
- return UnsafeNativeMethods.ManifestEtw.EventRegister(
- ref providerId,
+ return Interop.Advapi32.EventRegister(
+ in providerId,
enableCallback,
callbackContext,
ref registrationHandle);
@@ -1266,32 +1286,43 @@ unsafe uint IEventProvider.EventRegister(
// Unregister an event provider.
uint IEventProvider.EventUnregister(long registrationHandle)
{
- return UnsafeNativeMethods.ManifestEtw.EventUnregister(registrationHandle);
+ return Interop.Advapi32.EventUnregister(registrationHandle);
}
// Write an event.
- unsafe int IEventProvider.EventWriteTransferWrapper(
+ unsafe EventProvider.WriteEventErrorCode IEventProvider.EventWriteTransfer(
long registrationHandle,
- ref EventDescriptor eventDescriptor,
+ in EventDescriptor eventDescriptor,
IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
int userDataCount,
EventProvider.EventData* userData)
{
- return UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(
+ int error = Interop.Advapi32.EventWriteTransfer(
registrationHandle,
- ref eventDescriptor,
+ in eventDescriptor,
activityId,
relatedActivityId,
userDataCount,
userData);
+
+ switch (error)
+ {
+ case Interop.Errors.ERROR_ARITHMETIC_OVERFLOW:
+ case Interop.Errors.ERROR_MORE_DATA:
+ return EventProvider.WriteEventErrorCode.EventTooBig;
+ case Interop.Errors.ERROR_NOT_ENOUGH_MEMORY:
+ return EventProvider.WriteEventErrorCode.NoFreeBuffers;
+ }
+
+ return EventProvider.WriteEventErrorCode.NoError;
}
// Get or set the per-thread activity ID.
- int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId)
+ int IEventProvider.EventActivityIdControl(Interop.Advapi32.ActivityControl ControlCode, ref Guid ActivityId)
{
- return UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
+ return Interop.Advapi32.EventActivityIdControl(
ControlCode,
ref ActivityId);
}
@@ -1308,7 +1339,7 @@ internal sealed class NoOpEventProvider : IEventProvider
{
unsafe uint IEventProvider.EventRegister(
EventSource eventSource,
- UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
+ Interop.Advapi32.EtwEnableCallback enableCallback,
void* callbackContext,
ref long registrationHandle)
{
@@ -1320,19 +1351,19 @@ uint IEventProvider.EventUnregister(long registrationHandle)
return 0;
}
- unsafe int IEventProvider.EventWriteTransferWrapper(
+ unsafe EventProvider.WriteEventErrorCode IEventProvider.EventWriteTransfer(
long registrationHandle,
- ref EventDescriptor eventDescriptor,
+ in EventDescriptor eventDescriptor,
IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
int userDataCount,
EventProvider.EventData* userData)
{
- return 0;
+ return EventProvider.WriteEventErrorCode.NoError;
}
- int IEventProvider.EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId)
+ int IEventProvider.EventActivityIdControl(Interop.Advapi32.ActivityControl ControlCode, ref Guid ActivityId)
{
return 0;
}
diff --git a/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventSource.cs b/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventSource.cs
index 95ac1da80d13..50343b4c5f3d 100644
--- a/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventSource.cs
+++ b/src/Common/src/CoreLib/System/Diagnostics/Tracing/EventSource.cs
@@ -132,8 +132,7 @@
// where it will write it to
//
// All ETW writes eventually call
-// EventWriteTransfer (native PINVOKE wrapper)
-// EventWriteTransferWrapper (fixes compat problem if you pass null as the related activityID)
+// EventWriteTransfer
// EventProvider.WriteEventRaw - sets last error
// EventSource.WriteEventRaw - Does EventSource exception handling logic
// WriteMultiMerge
@@ -499,6 +498,123 @@ public event EventHandler EventCommandExecuted
}
}
+#region ActivityID
+
+ ///
+ /// When a thread starts work that is on behalf of 'something else' (typically another
+ /// thread or network request) it should mark the thread as working on that other work.
+ /// This API marks the current thread as working on activity 'activityID'. This API
+ /// should be used when the caller knows the thread's current activity (the one being
+ /// overwritten) has completed. Otherwise, callers should prefer the overload that
+ /// return the oldActivityThatWillContinue (below).
+ ///
+ /// All events created with the EventSource on this thread are also tagged with the
+ /// activity ID of the thread.
+ ///
+ /// It is common, and good practice after setting the thread to an activity to log an event
+ /// with a 'start' opcode to indicate that precise time/thread where the new activity
+ /// started.
+ ///
+ /// A Guid that represents the new activity with which to mark
+ /// the current thread
+ public static void SetCurrentThreadActivityId(Guid activityId)
+ {
+ if (TplEventSource.Log != null)
+ TplEventSource.Log.SetActivityId(activityId);
+
+ // We ignore errors to keep with the convention that EventSources do not throw errors.
+ // Note we can't access m_throwOnWrites because this is a static method.
+#if FEATURE_MANAGED_ETW
+#if FEATURE_PERFTRACING
+ // Set the activity id via EventPipe.
+ EventPipeInternal.EventActivityIdControl(
+ (uint)Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID,
+ ref activityId);
+#endif // FEATURE_PERFTRACING
+#if PLATFORM_WINDOWS
+ // Set the activity id via ETW.
+ Interop.Advapi32.EventActivityIdControl(
+ Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID,
+ ref activityId);
+#endif // PLATFORM_WINDOWS
+#endif // FEATURE_MANAGED_ETW
+ }
+
+ ///
+ /// Retrieves the ETW activity ID associated with the current thread.
+ ///
+ public static Guid CurrentThreadActivityId
+ {
+ get
+ {
+ // We ignore errors to keep with the convention that EventSources do not throw
+ // errors. Note we can't access m_throwOnWrites because this is a static method.
+ Guid retVal = new Guid();
+#if FEATURE_MANAGED_ETW
+#if PLATFORM_WINDOWS
+ Interop.Advapi32.EventActivityIdControl(
+ Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID,
+ ref retVal);
+#elif FEATURE_PERFTRACING
+ EventPipeInternal.EventActivityIdControl(
+ (uint)Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID,
+ ref retVal);
+#endif // PLATFORM_WINDOWS
+#endif // FEATURE_MANAGED_ETW
+ return retVal;
+ }
+ }
+
+ ///
+ /// When a thread starts work that is on behalf of 'something else' (typically another
+ /// thread or network request) it should mark the thread as working on that other work.
+ /// This API marks the current thread as working on activity 'activityID'. It returns
+ /// whatever activity the thread was previously marked with. There is a convention that
+ /// callers can assume that callees restore this activity mark before the callee returns.
+ /// To encourage this, this API returns the old activity, so that it can be restored later.
+ ///
+ /// All events created with the EventSource on this thread are also tagged with the
+ /// activity ID of the thread.
+ ///
+ /// It is common, and good practice after setting the thread to an activity to log an event
+ /// with a 'start' opcode to indicate that precise time/thread where the new activity
+ /// started.
+ ///
+ /// A Guid that represents the new activity with which to mark
+ /// the current thread
+ /// The Guid that represents the current activity
+ /// which will continue at some point in the future, on the current thread
+ public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue)
+ {
+ oldActivityThatWillContinue = activityId;
+#if FEATURE_MANAGED_ETW
+ // We ignore errors to keep with the convention that EventSources do not throw errors.
+ // Note we can't access m_throwOnWrites because this is a static method.
+
+#if FEATURE_PERFTRACING && PLATFORM_WINDOWS
+ EventPipeInternal.EventActivityIdControl(
+ (uint)Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_SET_ID,
+ ref oldActivityThatWillContinue);
+#elif FEATURE_PERFTRACING
+ EventPipeInternal.EventActivityIdControl(
+ (uint)Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
+ ref oldActivityThatWillContinue);
+#endif // FEATURE_PERFTRACING && PLATFORM_WINDOWS
+
+#if PLATFORM_WINDOWS
+ Interop.Advapi32.EventActivityIdControl(
+ Interop.Advapi32.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
+ ref oldActivityThatWillContinue);
+#endif // PLATFORM_WINDOWS
+#endif // FEATURE_MANAGED_ETW
+
+ // We don't call the activityDying callback here because the caller has declared that
+ // it is not dying.
+ if (TplEventSource.Log != null)
+ TplEventSource.Log.SetActivityId(activityId);
+ }
+#endregion
+
#region protected
///
/// This is the constructor that most users will use to create their eventSource. It takes
@@ -1390,7 +1506,7 @@ private unsafe void Initialize(Guid eventSourceGuid, string eventSourceName, str
IntPtr providerMetadata = metadataHandle.AddrOfPinnedObject();
setInformationResult = m_etwProvider.SetInformation(
- UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS.SetTraits,
+ Interop.Advapi32.EVENT_INFO_CLASS.SetTraits,
providerMetadata,
(uint)this.providerMetadata.Length);
@@ -2321,12 +2437,40 @@ For now I'm simply marking them as public again.A cleaner solution might be to u
root them and modify shared library definition to force export them.
*/
#if ES_BUILD_PN
- public
+ public
#else
- internal
+ internal
#endif
partial struct EventMetadata
{
+#if ES_BUILD_PN
+ public EventMetadata(EventDescriptor descriptor,
+ EventTags tags,
+ bool enabledForAnyListener,
+ bool enabledForETW,
+ string name,
+ string message,
+ EventParameterType[] parameterTypes)
+ {
+ this.Descriptor = descriptor;
+ this.Tags = tags;
+ this.EnabledForAnyListener = enabledForAnyListener;
+ this.EnabledForETW = enabledForETW;
+#if FEATURE_PERFTRACING
+ this.EnabledForEventPipe = false;
+#endif
+ this.TriggersActivityTracking = 0;
+ this.Name = name;
+ this.Message = message;
+ this.Parameters = null;
+ this.TraceLoggingEventTypes = null;
+ this.ActivityOptions = EventActivityOptions.None;
+ this.ParameterTypes = parameterTypes;
+ this.HasRelatedActivityID = false;
+ this.EventHandle = IntPtr.Zero;
+ }
+#endif
+
public EventDescriptor Descriptor;
public IntPtr EventHandle; // EventPipeEvent handle.
public EventTags Tags;
@@ -2352,6 +2496,114 @@ partial struct EventMetadata
#endif
};
+#if !ES_BUILD_PN
+ private int GetParameterCount(EventMetadata eventData)
+ {
+ return eventData.Parameters.Length;
+ }
+
+ private Type GetDataType(EventMetadata eventData, int parameterId)
+ {
+ return eventData.Parameters[parameterId].ParameterType;
+ }
+
+ private static readonly bool m_EventSourcePreventRecursion = false;
+#else
+ private int GetParameterCount(EventMetadata eventData)
+ {
+ int paramCount;
+ if(eventData.Parameters == null)
+ {
+ paramCount = eventData.ParameterTypes.Length;
+ }
+ else
+ {
+ paramCount = eventData.Parameters.Length;
+ }
+
+ return paramCount;
+ }
+
+ private Type GetDataType(EventMetadata eventData, int parameterId)
+ {
+ Type dataType;
+ if(eventData.Parameters == null)
+ {
+ dataType = EventTypeToType(eventData.ParameterTypes[parameterId]);
+ }
+ else
+ {
+ dataType = eventData.Parameters[parameterId].ParameterType;
+ }
+
+ return dataType;
+ }
+
+ private static readonly bool m_EventSourcePreventRecursion = true;
+
+ public enum EventParameterType
+ {
+ Boolean,
+ Byte,
+ SByte,
+ Char,
+ Int16,
+ UInt16,
+ Int32,
+ UInt32,
+ Int64,
+ UInt64,
+ IntPtr,
+ Single,
+ Double,
+ Decimal,
+ Guid,
+ String
+ }
+
+ private Type EventTypeToType(EventParameterType type)
+ {
+ switch (type)
+ {
+ case EventParameterType.Boolean:
+ return typeof(bool);
+ case EventParameterType.Byte:
+ return typeof(byte);
+ case EventParameterType.SByte:
+ return typeof(sbyte);
+ case EventParameterType.Char:
+ return typeof(char);
+ case EventParameterType.Int16:
+ return typeof(short);
+ case EventParameterType.UInt16:
+ return typeof(ushort);
+ case EventParameterType.Int32:
+ return typeof(int);
+ case EventParameterType.UInt32:
+ return typeof(uint);
+ case EventParameterType.Int64:
+ return typeof(long);
+ case EventParameterType.UInt64:
+ return typeof(ulong);
+ case EventParameterType.IntPtr:
+ return typeof(IntPtr);
+ case EventParameterType.Single:
+ return typeof(float);
+ case EventParameterType.Double:
+ return typeof(double);
+ case EventParameterType.Decimal:
+ return typeof(decimal);
+ case EventParameterType.Guid:
+ return typeof(Guid);
+ case EventParameterType.String:
+ return typeof(string);
+ default:
+ // TODO: should I throw an exception here?
+ return null;
+ }
+ }
+#endif
+
// This is the internal entry point that code:EventListeners call when wanting to send a command to a
// eventSource. The logic is as follows
//
@@ -5102,7 +5354,7 @@ public enum EventManifestOptions
/// ManifestBuilder is designed to isolate the details of the message of the event from the
/// rest of EventSource. This one happens to create XML.
///
- internal partial class ManifestBuilder
+ internal class ManifestBuilder
{
///
/// Build a manifest for 'providerName' with the given GUID, which will be packaged into 'dllName'.
@@ -5839,7 +6091,46 @@ private string GetTypeName(Type type)
return typeName.Replace("win:Int", "win:UInt"); // ETW requires enums to be unsigned.
}
- return GetTypeNameHelper(type);
+ switch (type.GetTypeCode())
+ {
+ case TypeCode.Boolean:
+ return "win:Boolean";
+ case TypeCode.Byte:
+ return "win:UInt8";
+ case TypeCode.Char:
+ case TypeCode.UInt16:
+ return "win:UInt16";
+ case TypeCode.UInt32:
+ return "win:UInt32";
+ case TypeCode.UInt64:
+ return "win:UInt64";
+ case TypeCode.SByte:
+ return "win:Int8";
+ case TypeCode.Int16:
+ return "win:Int16";
+ case TypeCode.Int32:
+ return "win:Int32";
+ case TypeCode.Int64:
+ return "win:Int64";
+ case TypeCode.String:
+ return "win:UnicodeString";
+ case TypeCode.Single:
+ return "win:Float";
+ case TypeCode.Double:
+ return "win:Double";
+ case TypeCode.DateTime:
+ return "win:FILETIME";
+ default:
+ if (type == typeof(Guid))
+ return "win:GUID";
+ else if (type == typeof(IntPtr))
+ return "win:Pointer";
+ else if ((type.IsArray || type.IsPointer) && type.GetElementType() == typeof(byte))
+ return "win:Binary";
+
+ ManifestError(SR.Format(SR.EventSource_UnsupportedEventTypeInManifest, type.Name), true);
+ return string.Empty;
+ }
}
private static void UpdateStringBuilder(ref StringBuilder stringBuilder, string eventMessage, int startIndex, int count)
diff --git a/src/Common/src/CoreLib/System/Diagnostics/Tracing/IEventProvider.cs b/src/Common/src/CoreLib/System/Diagnostics/Tracing/IEventProvider.cs
index 9bbebc79ed23..bc7ab9aee002 100644
--- a/src/Common/src/CoreLib/System/Diagnostics/Tracing/IEventProvider.cs
+++ b/src/Common/src/CoreLib/System/Diagnostics/Tracing/IEventProvider.cs
@@ -17,7 +17,7 @@ internal interface IEventProvider
// Register an event provider.
unsafe uint EventRegister(
EventSource eventSource,
- UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback,
+ Interop.Advapi32.EtwEnableCallback enableCallback,
void* callbackContext,
ref long registrationHandle);
@@ -25,9 +25,9 @@ unsafe uint EventRegister(
uint EventUnregister(long registrationHandle);
// Write an event.
- unsafe int EventWriteTransferWrapper(
+ unsafe EventProvider.WriteEventErrorCode EventWriteTransfer(
long registrationHandle,
- ref EventDescriptor eventDescriptor,
+ in EventDescriptor eventDescriptor,
IntPtr eventHandle,
Guid* activityId,
Guid* relatedActivityId,
@@ -35,7 +35,7 @@ unsafe int EventWriteTransferWrapper(
EventProvider.EventData* userData);
// Get or set the per-thread activity ID.
- int EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId);
+ int EventActivityIdControl(Interop.Advapi32.ActivityControl ControlCode, ref Guid ActivityId);
// Define an EventPipeEvent handle.
unsafe IntPtr DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength);
diff --git a/src/Common/src/CoreLib/System/Diagnostics/Tracing/IncrementingEventCounter.cs b/src/Common/src/CoreLib/System/Diagnostics/Tracing/IncrementingEventCounter.cs
index 569c9a011353..40581051cc9f 100644
--- a/src/Common/src/CoreLib/System/Diagnostics/Tracing/IncrementingEventCounter.cs
+++ b/src/Common/src/CoreLib/System/Diagnostics/Tracing/IncrementingEventCounter.cs
@@ -23,7 +23,7 @@ namespace System.Diagnostics.Tracing
/// It does not calculate statistics like mean, standard deviation, etc. because it only accumulates
/// the counter value.
///
- internal partial class IncrementingEventCounter : BaseCounter
+ public partial class IncrementingEventCounter : DiagnosticCounter
{
///
/// Initializes a new instance of the class.
@@ -41,7 +41,7 @@ public IncrementingEventCounter(string name, EventSource eventSource) : base(nam
/// be logged on the next timer interval.
///
/// The value to increment by.
- public void Increment(float increment = 1)
+ public void Increment(double increment = 1)
{
lock(MyLock)
{
@@ -49,25 +49,25 @@ public void Increment(float increment = 1)
}
}
- internal TimeSpan DisplayRateTimeScale { get; set; }
- private float _increment;
- private float _prevIncrement;
+ public TimeSpan DisplayRateTimeScale { get; set; }
+ private double _increment;
+ private double _prevIncrement;
- public override string ToString() => $"IncrementingEventCounter '{_name}' Increment {_increment}";
+ public override string ToString() => $"IncrementingEventCounter '{Name}' Increment {_increment}";
internal override void WritePayload(float intervalSec)
{
lock (MyLock) // Lock the counter
{
IncrementingCounterPayload payload = new IncrementingCounterPayload();
- payload.Name = _name;
+ payload.Name = Name;
payload.IntervalSec = intervalSec;
payload.DisplayName = DisplayName ?? "";
payload.DisplayRateTimeScale = (DisplayRateTimeScale == TimeSpan.Zero) ? "" : DisplayRateTimeScale.ToString("c");
- payload.MetaData = GetMetaDataString();
+ payload.Metadata = GetMetadataString();
payload.Increment = _increment - _prevIncrement;
_prevIncrement = _increment;
- _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingEventCounterPayloadType(payload));
+ EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingEventCounterPayloadType(payload));
}
}
}
diff --git a/src/Common/src/CoreLib/System/Diagnostics/Tracing/IncrementingPollingCounter.cs b/src/Common/src/CoreLib/System/Diagnostics/Tracing/IncrementingPollingCounter.cs
index 8bad728a1807..1b8ee7553e4d 100644
--- a/src/Common/src/CoreLib/System/Diagnostics/Tracing/IncrementingPollingCounter.cs
+++ b/src/Common/src/CoreLib/System/Diagnostics/Tracing/IncrementingPollingCounter.cs
@@ -25,7 +25,7 @@ namespace System.Diagnostics.Tracing
/// Unlike IncrementingEventCounter, this takes in a polling callback that it can call to update
/// its own metric periodically.
///
- internal partial class IncrementingPollingCounter : BaseCounter
+ public partial class IncrementingPollingCounter : DiagnosticCounter
{
///
/// Initializes a new instance of the class.
@@ -34,20 +34,20 @@ internal partial class IncrementingPollingCounter : BaseCounter
///
/// The name.
/// The event source.
- public IncrementingPollingCounter(string name, EventSource eventSource, Func getCountFunction) : base(name, eventSource)
+ public IncrementingPollingCounter(string name, EventSource eventSource, Func totalValueProvider) : base(name, eventSource)
{
- _getCountFunction = getCountFunction;
+ _totalValueProvider = totalValueProvider;
}
- public override string ToString() => $"IncrementingPollingCounter '{_name}' Increment {_increment}";
+ public override string ToString() => $"IncrementingPollingCounter '{Name}' Increment {_increment}";
- internal TimeSpan DisplayRateTimeScale { get; set; }
- private float _increment;
- private float _prevIncrement;
- private Func _getCountFunction;
+ public TimeSpan DisplayRateTimeScale { get; set; }
+ private double _increment;
+ private double _prevIncrement;
+ private Func _totalValueProvider;
///
- /// Calls "_getCountFunction" to enqueue the counter value to the queue.
+ /// Calls "_totalValueProvider" to enqueue the counter value to the queue.
///
private void UpdateMetric()
{
@@ -55,12 +55,12 @@ private void UpdateMetric()
{
lock(MyLock)
{
- _increment = _getCountFunction();
+ _increment = _totalValueProvider();
}
}
catch (Exception ex)
{
- ReportOutOfBandMessage($"ERROR: Exception during EventCounter {_name} getMetricFunction callback: " + ex.Message);
+ ReportOutOfBandMessage($"ERROR: Exception during EventCounter {Name} getMetricFunction callback: " + ex.Message);
}
}
@@ -70,14 +70,14 @@ internal override void WritePayload(float intervalSec)
lock (MyLock) // Lock the counter
{
IncrementingCounterPayload payload = new IncrementingCounterPayload();
- payload.Name = _name;
+ payload.Name = Name;
payload.DisplayName = DisplayName ?? "";
payload.DisplayRateTimeScale = (DisplayRateTimeScale == TimeSpan.Zero) ? "" : DisplayRateTimeScale.ToString("c");
payload.IntervalSec = intervalSec;
- payload.MetaData = GetMetaDataString();
+ payload.Metadata = GetMetadataString();
payload.Increment = _increment - _prevIncrement;
_prevIncrement = _increment;
- _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingPollingCounterPayloadType(payload));
+ EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new IncrementingPollingCounterPayloadType(payload));
}
}
}
diff --git a/src/Common/src/CoreLib/System/Diagnostics/Tracing/PollingCounter.cs b/src/Common/src/CoreLib/System/Diagnostics/Tracing/PollingCounter.cs
index 695b357f45a9..e0577181facc 100644
--- a/src/Common/src/CoreLib/System/Diagnostics/Tracing/PollingCounter.cs
+++ b/src/Common/src/CoreLib/System/Diagnostics/Tracing/PollingCounter.cs
@@ -23,7 +23,7 @@ namespace System.Diagnostics.Tracing
/// function to collect metrics on its own rather than the user having to call WriteMetric()
/// every time.
///
- internal partial class PollingCounter : BaseCounter
+ public partial class PollingCounter : DiagnosticCounter
{
///
/// Initializes a new instance of the class.
@@ -32,41 +32,42 @@ internal partial class PollingCounter : BaseCounter
///
/// The name.
/// The event source.
- public PollingCounter(string name, EventSource eventSource, Func getMetricFunction) : base(name, eventSource)
+ public PollingCounter(string name, EventSource eventSource, Func metricProvider) : base(name, eventSource)
{
- _getMetricFunction = getMetricFunction;
+ _metricProvider = metricProvider;
}
- public override string ToString() => $"PollingCounter '{_name}' Count {1} Mean {_lastVal.ToString("n3")}";
+ public override string ToString() => $"PollingCounter '{Name}' Count {1} Mean {_lastVal.ToString("n3")}";
- private Func _getMetricFunction;
- private float _lastVal;
+ private Func _metricProvider;
+ private double _lastVal;
internal override void WritePayload(float intervalSec)
{
lock (MyLock)
{
- float value = 0;
+ double value = 0;
try
{
- value = _getMetricFunction();
+ value = _metricProvider();
}
catch (Exception ex)
{
- ReportOutOfBandMessage($"ERROR: Exception during EventCounter {_name} getMetricFunction callback: " + ex.Message);
+ ReportOutOfBandMessage($"ERROR: Exception during EventCounter {Name} metricProvider callback: " + ex.Message);
}
CounterPayload payload = new CounterPayload();
- payload.Name = _name;
+ payload.Name = Name;
payload.DisplayName = DisplayName ?? "";
payload.Count = 1; // NOTE: These dumb-looking statistics is intentional
payload.IntervalSec = intervalSec;
payload.Mean = value;
payload.Max = value;
payload.Min = value;
+ payload.Metadata = GetMetadataString();
payload.StandardDeviation = 0;
_lastVal = value;
- _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new PollingPayloadType(payload));
+ EventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new PollingPayloadType(payload));
}
}
}
diff --git a/src/Common/src/CoreLib/System/Enum.cs b/src/Common/src/CoreLib/System/Enum.cs
index 52ae2908e7c2..a979fe9a8da2 100644
--- a/src/Common/src/CoreLib/System/Enum.cs
+++ b/src/Common/src/CoreLib/System/Enum.cs
@@ -494,7 +494,7 @@ private static bool TryParse(string? value, bool ignoreCase, bool throwOn
default:
parsed = TryParseRareEnum(rt, value, valueSpan, ignoreCase, throwOnFailure, out object? objectResult);
- result = parsed ? (TEnum)objectResult : default;
+ result = parsed ? (TEnum)objectResult! : default; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34976
return parsed;
}
}
diff --git a/src/Common/src/CoreLib/System/Environment.Win32.cs b/src/Common/src/CoreLib/System/Environment.Win32.cs
index f7b87ff7866b..90e1ca92a668 100644
--- a/src/Common/src/CoreLib/System/Environment.Win32.cs
+++ b/src/Common/src/CoreLib/System/Environment.Win32.cs
@@ -14,6 +14,8 @@ namespace System
{
public static partial class Environment
{
+ internal static bool IsWindows8OrAbove => WindowsVersion.IsWindows8OrAbove;
+
private static string GetEnvironmentVariableFromRegistry(string variable, bool fromMachine)
{
Debug.Assert(variable != null);
@@ -418,5 +420,35 @@ public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption opt
}
}
#endif
+
+ // Seperate type so a .cctor is not created for Enviroment which then would be triggered during startup
+ private static class WindowsVersion
+ {
+ // Cache the value in readonly static that can be optimized out by the JIT
+ internal readonly static bool IsWindows8OrAbove = GetIsWindows8OrAbove();
+
+ private static bool GetIsWindows8OrAbove()
+ {
+ ulong conditionMask = Interop.Kernel32.VerSetConditionMask(0, Interop.Kernel32.VER_MAJORVERSION, Interop.Kernel32.VER_GREATER_EQUAL);
+ conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_MINORVERSION, Interop.Kernel32.VER_GREATER_EQUAL);
+ conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_SERVICEPACKMAJOR, Interop.Kernel32.VER_GREATER_EQUAL);
+ conditionMask = Interop.Kernel32.VerSetConditionMask(conditionMask, Interop.Kernel32.VER_SERVICEPACKMINOR, Interop.Kernel32.VER_GREATER_EQUAL);
+
+ // Windows 8 version is 6.2
+ Interop.Kernel32.OSVERSIONINFOEX version = default;
+ unsafe
+ {
+ version.dwOSVersionInfoSize = sizeof(Interop.Kernel32.OSVERSIONINFOEX);
+ }
+ version.dwMajorVersion = 6;
+ version.dwMinorVersion = 2;
+ version.wServicePackMajor = 0;
+ version.wServicePackMinor = 0;
+
+ return Interop.Kernel32.VerifyVersionInfoW(ref version,
+ Interop.Kernel32.VER_MAJORVERSION | Interop.Kernel32.VER_MINORVERSION | Interop.Kernel32.VER_SERVICEPACKMAJOR | Interop.Kernel32.VER_SERVICEPACKMINOR,
+ conditionMask);
+ }
+ }
}
}
diff --git a/src/Common/src/CoreLib/System/Environment.WinRT.cs b/src/Common/src/CoreLib/System/Environment.WinRT.cs
index a8e3dbced807..27e0fc243167 100644
--- a/src/Common/src/CoreLib/System/Environment.WinRT.cs
+++ b/src/Common/src/CoreLib/System/Environment.WinRT.cs
@@ -13,6 +13,8 @@ public static partial class Environment
public static string UserDomainName => "Windows Domain";
+ internal static readonly bool IsWindows8OrAbove = true;
+
private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOption option)
{
WinRTInteropCallbacks callbacks = WinRTInterop.UnsafeCallbacks;
diff --git a/src/Common/src/CoreLib/System/GCMemoryInfo.cs b/src/Common/src/CoreLib/System/GCMemoryInfo.cs
new file mode 100644
index 000000000000..72c2aca14da2
--- /dev/null
+++ b/src/Common/src/CoreLib/System/GCMemoryInfo.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.
+// See the LICENSE file in the project root for more information.
+
+namespace System
+{
+ public readonly struct GCMemoryInfo
+ {
+ ///
+ /// High memory load threshold when the last GC occured
+ ///
+ public long HighMemoryLoadThresholdBytes { get; }
+
+ ///
+ /// Memory load when the last GC ocurred
+ ///
+ public long MemoryLoadBytes { get; }
+
+ ///
+ /// Total available memory for the GC to use when the last GC ocurred. By default this is the physical memory on the machine, but it may be customized by specifying a HardLimit.
+ ///
+ public long TotalAvailableMemoryBytes { get; }
+
+ ///
+ /// The total heap size when the last GC ocurred
+ ///
+ public long HeapSizeBytes { get; }
+
+ ///
+ /// The total fragmentation when the last GC ocurred
+ ///
+ /// Let's take the example below:
+ /// | OBJ_A | OBJ_B | OBJ_C | OBJ_D | OBJ_E |
+ ///
+ /// Let's say OBJ_B, OBJ_C and and OBJ_E are garbage and get collected, but the heap does not get compacted, the resulting heap will look like the following:
+ /// | OBJ_A | F | OBJ_D |
+ ///
+ /// The memory between OBJ_A and OBJ_D marked `F` is considered part of the FragmentedBytes, and will be used to allocate new objects. The memory after OBJ_D will not be
+ /// considered part of the FragmentedBytes, and will also be used to allocate new objects
+ ///
+ public long FragmentedBytes { get; }
+
+ internal GCMemoryInfo(long highMemoryLoadThresholdBytes,
+ long memoryLoadBytes,
+ long totalAvailableMemoryBytes,
+ long heapSizeBytes,
+ long fragmentedBytes)
+ {
+ HighMemoryLoadThresholdBytes = highMemoryLoadThresholdBytes;
+ MemoryLoadBytes = memoryLoadBytes;
+ TotalAvailableMemoryBytes = totalAvailableMemoryBytes;
+ HeapSizeBytes = heapSizeBytes;
+ FragmentedBytes = fragmentedBytes;
+ }
+ }
+}
diff --git a/src/Common/src/CoreLib/System/Gen2GcCallback.cs b/src/Common/src/CoreLib/System/Gen2GcCallback.cs
index acc415b6d10d..1f8de9628e63 100644
--- a/src/Common/src/CoreLib/System/Gen2GcCallback.cs
+++ b/src/Common/src/CoreLib/System/Gen2GcCallback.cs
@@ -71,10 +71,7 @@ private void Setup(Func callback, object targetObj)
}
// Resurrect ourselves by re-registering for finalization.
- if (!Environment.HasShutdownStarted)
- {
- GC.ReRegisterForFinalize(this);
- }
+ GC.ReRegisterForFinalize(this);
}
}
}
diff --git a/src/Common/src/CoreLib/System/Globalization/CompareInfo.cs b/src/Common/src/CoreLib/System/Globalization/CompareInfo.cs
index f5bba908b560..ef2eb4945afc 100644
--- a/src/Common/src/CoreLib/System/Globalization/CompareInfo.cs
+++ b/src/Common/src/CoreLib/System/Globalization/CompareInfo.cs
@@ -8,7 +8,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
-using System.Text;
+using System.Text.Unicode;
using Internal.Runtime.CompilerServices;
namespace System.Globalization
diff --git a/src/Common/src/CoreLib/System/Globalization/CultureData.cs b/src/Common/src/CoreLib/System/Globalization/CultureData.cs
index 7e1e66857f50..c86bab5afacb 100644
--- a/src/Common/src/CoreLib/System/Globalization/CultureData.cs
+++ b/src/Common/src/CoreLib/System/Globalization/CultureData.cs
@@ -11,6 +11,7 @@
namespace System.Globalization
{
#if CORERT
+ #pragma warning restore nullable
using StringStringDictionary = LowLevelDictionary;
using StringCultureDataDictionary = LowLevelDictionary;
using LcidToCultureNameDictionary = LowLevelDictionary;
diff --git a/src/Common/src/CoreLib/System/Globalization/TextInfo.cs b/src/Common/src/CoreLib/System/Globalization/TextInfo.cs
index cf89dff6a2e9..4391dec044fd 100644
--- a/src/Common/src/CoreLib/System/Globalization/TextInfo.cs
+++ b/src/Common/src/CoreLib/System/Globalization/TextInfo.cs
@@ -8,6 +8,7 @@
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
+using System.Text.Unicode;
using Internal.Runtime.CompilerServices;
#if BIT64
diff --git a/src/Common/src/CoreLib/System/IO/BinaryReader.cs b/src/Common/src/CoreLib/System/IO/BinaryReader.cs
index 0636b15c9e50..273d4c7cf983 100644
--- a/src/Common/src/CoreLib/System/IO/BinaryReader.cs
+++ b/src/Common/src/CoreLib/System/IO/BinaryReader.cs
@@ -26,11 +26,10 @@ public class BinaryReader : IDisposable
{
private const int MaxCharBytesSize = 128;
- private Stream _stream;
- private byte[] _buffer;
- private Decoder _decoder;
+ private readonly Stream _stream;
+ private readonly byte[] _buffer;
+ private readonly Decoder _decoder;
private byte[] _charBytes;
- private char[] _singleChar;
private char[] _charBuffer;
private int _maxCharsSize; // From MaxCharBytesSize & Encoding
@@ -38,6 +37,7 @@ public class BinaryReader : IDisposable
private bool _2BytesPerChar;
private bool _isMemoryStream; // "do we sit on MemoryStream?" for Read/ReadInt32 perf
private bool _leaveOpen;
+ private bool _disposed;
public BinaryReader(Stream input) : this(input, Encoding.UTF8, false)
{
@@ -95,22 +95,14 @@ public virtual Stream BaseStream
protected virtual void Dispose(bool disposing)
{
- if (disposing)
+ if (!_disposed)
{
- Stream copyOfStream = _stream;
- _stream = null;
- if (copyOfStream != null && !_leaveOpen)
+ if (disposing && !_leaveOpen)
{
- copyOfStream.Close();
+ _stream.Close();
}
+ _disposed = true;
}
- _isMemoryStream = false;
- _stream = null;
- _buffer = null;
- _decoder = null;
- _charBytes = null;
- _singleChar = null;
- _charBuffer = null;
}
public void Dispose()
@@ -126,12 +118,17 @@ public virtual void Close()
Dispose(true);
}
- public virtual int PeekChar()
+ private void ThrowIfDisposed()
{
- if (_stream == null)
+ if (_disposed)
{
throw Error.GetFileNotOpen();
}
+ }
+
+ public virtual int PeekChar()
+ {
+ ThrowIfDisposed();
if (!_stream.CanSeek)
{
@@ -146,13 +143,10 @@ public virtual int PeekChar()
public virtual int Read()
{
- if (_stream == null)
- {
- throw Error.GetFileNotOpen();
- }
+ ThrowIfDisposed();
int charsRead = 0;
- int numBytes = 0;
+ int numBytes;
long posSav = 0;
if (_stream.CanSeek)
@@ -164,10 +158,8 @@ public virtual int Read()
{
_charBytes = new byte[MaxCharBytesSize]; //REVIEW: We need at most 2 bytes/char here?
}
- if (_singleChar == null)
- {
- _singleChar = new char[1];
- }
+
+ Span singleChar = stackalloc char[1];
while (charsRead == 0)
{
@@ -202,7 +194,7 @@ public virtual int Read()
try
{
- charsRead = _decoder.GetChars(_charBytes, 0, numBytes, _singleChar, 0);
+ charsRead = _decoder.GetChars(new ReadOnlySpan(_charBytes, 0, numBytes), singleChar, flush: false);
}
catch
{
@@ -220,19 +212,15 @@ public virtual int Read()
Debug.Assert(charsRead < 2, "BinaryReader::ReadOneChar - assuming we only got 0 or 1 char, not 2!");
}
Debug.Assert(charsRead > 0);
- return _singleChar[0];
+ return singleChar[0];
}
public virtual byte ReadByte() => InternalReadByte();
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)] // Inlined to avoid some method call overhead with InternalRead.
private byte InternalReadByte()
{
- // Inlined to avoid some method call overhead with InternalRead.
- if (_stream == null)
- {
- throw Error.GetFileNotOpen();
- }
+ ThrowIfDisposed();
int b = _stream.ReadByte();
if (b == -1)
@@ -287,10 +275,7 @@ public virtual decimal ReadDecimal()
public virtual string ReadString()
{
- if (_stream == null)
- {
- throw Error.GetFileNotOpen();
- }
+ ThrowIfDisposed();
int currPos = 0;
int n;
@@ -368,10 +353,7 @@ public virtual int Read(char[] buffer, int index, int count)
{
throw new ArgumentException(SR.Argument_InvalidOffLen);
}
- if (_stream == null)
- {
- throw Error.GetFileNotOpen();
- }
+ ThrowIfDisposed();
// SafeCritical: index and count have already been verified to be a valid range for the buffer
return InternalReadChars(new Span(buffer, index, count));
@@ -379,17 +361,13 @@ public virtual int Read(char[] buffer, int index, int count)
public virtual int Read(Span buffer)
{
- if (_stream == null)
- {
- throw Error.GetFileNotOpen();
- }
-
+ ThrowIfDisposed();
return InternalReadChars(buffer);
}
private int InternalReadChars(Span buffer)
{
- Debug.Assert(_stream != null);
+ Debug.Assert(!_disposed);
int numBytes = 0;
int index = 0;
@@ -478,10 +456,7 @@ public virtual char[] ReadChars(int count)
{
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
}
- if (_stream == null)
- {
- throw Error.GetFileNotOpen();
- }
+ ThrowIfDisposed();
if (count == 0)
{
@@ -519,21 +494,14 @@ public virtual int Read(byte[] buffer, int index, int count)
{
throw new ArgumentException(SR.Argument_InvalidOffLen);
}
- if (_stream == null)
- {
- throw Error.GetFileNotOpen();
- }
+ ThrowIfDisposed();
return _stream.Read(buffer, index, count);
}
public virtual int Read(Span buffer)
{
- if (_stream == null)
- {
- throw Error.GetFileNotOpen();
- }
-
+ ThrowIfDisposed();
return _stream.Read(buffer);
}
@@ -543,10 +511,7 @@ public virtual byte[] ReadBytes(int count)
{
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
- }
+ ThrowIfDisposed();
if (count == 0)
{
@@ -584,18 +549,13 @@ private ReadOnlySpan InternalRead(int numBytes)
if (_isMemoryStream)
{
- // no need to check if _stream == null as we will never have null _stream when _isMemoryStream = true
-
// read directly from MemoryStream buffer
Debug.Assert(_stream is MemoryStream);
return ((MemoryStream)_stream).InternalReadSpan(numBytes);
}
else
{
- if (_stream == null)
- {
- throw Error.GetFileNotOpen();
- }
+ ThrowIfDisposed();
int bytesRead = 0;
int n = 0;
@@ -628,10 +588,7 @@ protected virtual void FillBuffer(int numBytes)
int bytesRead = 0;
int n = 0;
- if (_stream == null)
- {
- throw Error.GetFileNotOpen();
- }
+ ThrowIfDisposed();
// Need to find a good threshold for calling ReadByte() repeatedly
// vs. calling Read(byte[], int, int) for both buffered & unbuffered
diff --git a/src/Common/src/CoreLib/System/IO/BinaryWriter.cs b/src/Common/src/CoreLib/System/IO/BinaryWriter.cs
index dea1f0397f11..9b6f865fe575 100644
--- a/src/Common/src/CoreLib/System/IO/BinaryWriter.cs
+++ b/src/Common/src/CoreLib/System/IO/BinaryWriter.cs
@@ -18,9 +18,9 @@ public class BinaryWriter : IDisposable, IAsyncDisposable
public static readonly BinaryWriter Null = new BinaryWriter();
protected Stream OutStream;
- private byte[] _buffer; // temp space for writing primitives to.
- private Encoding _encoding;
- private Encoder _encoder;
+ private readonly byte[] _buffer; // temp space for writing primitives to.
+ private readonly Encoding _encoding;
+ private readonly Encoder _encoder;
private bool _leaveOpen;
diff --git a/src/Common/src/CoreLib/System/IO/FileStream.WinRT.cs b/src/Common/src/CoreLib/System/IO/FileStream.WinRT.cs
index 16b64be4ac39..752a6d9d8a96 100644
--- a/src/Common/src/CoreLib/System/IO/FileStream.WinRT.cs
+++ b/src/Common/src/CoreLib/System/IO/FileStream.WinRT.cs
@@ -2,10 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#nullable enable
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
-#nullable enable
namespace System.IO
{
public partial class FileStream : Stream
diff --git a/src/Common/src/CoreLib/System/IO/StreamReader.cs b/src/Common/src/CoreLib/System/IO/StreamReader.cs
index 5c3cc9157d1a..bc5c00f986bb 100644
--- a/src/Common/src/CoreLib/System/IO/StreamReader.cs
+++ b/src/Common/src/CoreLib/System/IO/StreamReader.cs
@@ -4,7 +4,6 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
-using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -28,10 +27,10 @@ public class StreamReader : TextReader
private const int DefaultFileStreamBufferSize = 4096;
private const int MinBufferSize = 128;
- private Stream _stream;
+ private readonly Stream _stream;
private Encoding _encoding;
private Decoder _decoder;
- private byte[] _byteBuffer;
+ private readonly byte[] _byteBuffer;
private char[] _charBuffer;
private int _charPos;
private int _charLen;
@@ -45,6 +44,9 @@ public class StreamReader : TextReader
// a user's char[] directly, instead of our internal char[].
private int _maxCharsPerBuffer;
+ /// True if the writer has been disposed; otherwise, false.
+ private bool _disposed;
+
// We will support looking for byte order marks in the stream and trying
// to decide what the encoding might be from the byte order marks, IF they
// exist. But that's all we'll do.
@@ -90,8 +92,10 @@ private static void ThrowAsyncIOInProgress() =>
// The high level goal is to be tolerant of encoding errors when we read and very strict
// when we write. Hence, default StreamWriter encoding will throw on error.
- internal StreamReader()
+ private StreamReader()
{
+ _stream = Stream.Null;
+ _closable = true;
}
public StreamReader(Stream stream)
@@ -144,7 +148,23 @@ public StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByt
throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum);
}
- Init(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, leaveOpen);
+ _stream = stream;
+ _encoding = encoding;
+ _decoder = encoding.GetDecoder();
+ if (bufferSize < MinBufferSize)
+ {
+ bufferSize = MinBufferSize;
+ }
+
+ _byteBuffer = new byte[bufferSize];
+ _maxCharsPerBuffer = encoding.GetMaxCharCount(bufferSize);
+ _charBuffer = new char[_maxCharsPerBuffer];
+ _byteLen = 0;
+ _bytePos = 0;
+ _detectEncoding = detectEncodingFromByteOrderMarks;
+ _checkPreamble = encoding.Preamble.Length > 0;
+ _isBlocked = false;
+ _closable = !leaveOpen;
}
public StreamReader(string path)
@@ -167,7 +187,12 @@ public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteO
{
}
- public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
+ public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize) :
+ this(ValidateArgsAndOpenPath(path, encoding, bufferSize), encoding, detectEncodingFromByteOrderMarks, bufferSize, leaveOpen: false)
+ {
+ }
+
+ private static Stream ValidateArgsAndOpenPath(string path, Encoding encoding, int bufferSize)
{
if (path == null)
throw new ArgumentNullException(nameof(path));
@@ -178,37 +203,7 @@ public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteO
if (bufferSize <= 0)
throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum);
- Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read,
- DefaultFileStreamBufferSize, FileOptions.SequentialScan);
- Init(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, leaveOpen: false);
- }
-
- private void Init(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen)
- {
- _stream = stream;
- _encoding = encoding;
- _decoder = encoding.GetDecoder();
- if (bufferSize < MinBufferSize)
- {
- bufferSize = MinBufferSize;
- }
-
- _byteBuffer = new byte[bufferSize];
- _maxCharsPerBuffer = encoding.GetMaxCharCount(bufferSize);
- _charBuffer = new char[_maxCharsPerBuffer];
- _byteLen = 0;
- _bytePos = 0;
- _detectEncoding = detectEncodingFromByteOrderMarks;
- _checkPreamble = encoding.Preamble.Length > 0;
- _isBlocked = false;
- _closable = !leaveOpen;
- }
-
- // Init used by NullStreamReader, to delay load encoding
- internal void Init(Stream stream)
- {
- _stream = stream;
- _closable = true;
+ return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan);
}
public override void Close()
@@ -218,26 +213,26 @@ public override void Close()
protected override void Dispose(bool disposing)
{
+ if (_disposed)
+ {
+ return;
+ }
+ _disposed = true;
+
// Dispose of our resources if this StreamReader is closable.
- // Note that Console.In should be left open.
- try
+ if (!LeaveOpen)
{
- // Note that Stream.Close() can potentially throw here. So we need to
- // ensure cleaning up internal resources, inside the finally block.
- if (!LeaveOpen && disposing && (_stream != null))
+ try
{
- _stream.Close();
+ // Note that Stream.Close() can potentially throw here. So we need to
+ // ensure cleaning up internal resources, inside the finally block.
+ if (disposing)
+ {
+ _stream.Close();
+ }
}
- }
- finally
- {
- if (!LeaveOpen && (_stream != null))
+ finally
{
- _stream = null;
- _encoding = null;
- _decoder = null;
- _byteBuffer = null;
- _charBuffer = null;
_charPos = 0;
_charLen = 0;
base.Dispose(disposing);
@@ -287,11 +282,7 @@ public bool EndOfStream
{
get
{
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ReaderClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
if (_charPos < _charLen)
@@ -307,11 +298,7 @@ public bool EndOfStream
public override int Peek()
{
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ReaderClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
if (_charPos == _charLen)
@@ -326,11 +313,7 @@ public override int Peek()
public override int Read()
{
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ReaderClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
if (_charPos == _charLen)
@@ -369,11 +352,7 @@ public override int Read(Span buffer) =>
private int ReadSpan(Span buffer)
{
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ReaderClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
int charsRead = 0;
@@ -418,11 +397,7 @@ private int ReadSpan(Span buffer)
public override string ReadToEnd()
{
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ReaderClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
// Call ReadBuffer, then pull data out of charBuffer.
@@ -450,11 +425,7 @@ public override int ReadBlock(char[] buffer, int index, int count)
{
throw new ArgumentException(SR.Argument_InvalidOffLen);
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ReaderClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
return base.ReadBlock(buffer, index, count);
@@ -800,11 +771,7 @@ private int ReadBuffer(Span userBuffer, out bool readToUserBuffer)
//
public override string ReadLine()
{
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ReaderClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
if (_charPos == _charLen)
@@ -858,7 +825,6 @@ public override string ReadLine()
return sb.ToString();
}
- #region Task based Async APIs
public override Task ReadLineAsync()
{
// If we have been inherited into a subclass, the following implementation could be incorrect
@@ -870,11 +836,7 @@ public override Task ReadLineAsync()
return base.ReadLineAsync();
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ReaderClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
Task task = ReadLineAsyncInternal();
@@ -958,11 +920,7 @@ public override Task ReadToEndAsync()
return base.ReadToEndAsync();
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ReaderClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
Task task = ReadToEndAsyncInternal();
@@ -1010,11 +968,7 @@ public override Task ReadAsync(char[] buffer, int index, int count)
return base.ReadAsync(buffer, index, count);
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ReaderClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
Task task = ReadAsyncInternal(new Memory(buffer, index, count), default).AsTask();
@@ -1031,11 +985,7 @@ public override ValueTask ReadAsync(Memory buffer, CancellationToken
return base.ReadAsync(buffer, cancellationToken);
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ReaderClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
if (cancellationToken.IsCancellationRequested)
@@ -1241,11 +1191,7 @@ public override Task ReadBlockAsync(char[] buffer, int index, int count)
return base.ReadBlockAsync(buffer, index, count);
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ReaderClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
Task task = base.ReadBlockAsync(buffer, index, count);
@@ -1263,11 +1209,7 @@ public override ValueTask ReadBlockAsync(Memory buffer, CancellationT
return base.ReadBlockAsync(buffer, cancellationToken);
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_ReaderClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
if (cancellationToken.IsCancellationRequested)
@@ -1359,24 +1301,21 @@ private async Task ReadBufferAsync()
return _charLen;
}
-#endregion
-
- // No data, class doesn't need to be serializable.
- // Note this class is threadsafe.
- private class NullStreamReader : StreamReader
+ private void ThrowIfDisposed()
{
- // Instantiating Encoding causes unnecessary perf hit.
- internal NullStreamReader()
+ if (_disposed)
{
- Init(Stream.Null);
+ ThrowObjectDisposedException();
}
- public override Stream BaseStream
- {
- get { return Stream.Null; }
- }
+ void ThrowObjectDisposedException() => throw new ObjectDisposedException(GetType().Name, SR.ObjectDisposed_ReaderClosed);
+ }
+ // No data, class doesn't need to be serializable.
+ // Note this class is threadsafe.
+ private sealed class NullStreamReader : StreamReader
+ {
public override Encoding CurrentEncoding
{
get { return Encoding.Unicode; }
diff --git a/src/Common/src/CoreLib/System/IO/StreamWriter.cs b/src/Common/src/CoreLib/System/IO/StreamWriter.cs
index d55eaae582ac..8140d796480a 100644
--- a/src/Common/src/CoreLib/System/IO/StreamWriter.cs
+++ b/src/Common/src/CoreLib/System/IO/StreamWriter.cs
@@ -26,21 +26,20 @@ public class StreamWriter : TextWriter
private const int DefaultFileStreamBufferSize = 4096;
private const int MinBufferSize = 128;
- private const int DontCopyOnWriteLineThreshold = 512;
-
// Bit bucket - Null has no backing store. Non closable.
- public new static readonly StreamWriter Null = new StreamWriter(Stream.Null, UTF8NoBOM, MinBufferSize, true);
+ public new static readonly StreamWriter Null = new StreamWriter(Stream.Null, UTF8NoBOM, MinBufferSize, leaveOpen: true);
- private Stream _stream;
- private Encoding _encoding;
- private Encoder _encoder;
- private byte[] _byteBuffer;
- private char[] _charBuffer;
+ private readonly Stream _stream;
+ private readonly Encoding _encoding;
+ private readonly Encoder _encoder;
+ private readonly byte[] _byteBuffer;
+ private readonly char[] _charBuffer;
private int _charPos;
private int _charLen;
private bool _autoFlush;
private bool _haveWrittenPreamble;
- private bool _closable;
+ private readonly bool _closable;
+ private bool _disposed;
// We don't guarantee thread safety on StreamWriter, but we should at
// least prevent users from trying to write anything while an Async
@@ -71,11 +70,6 @@ private static void ThrowAsyncIOInProgress() =>
// StreamReader though for different reason). Either way, the buffered data will be lost!
private static Encoding UTF8NoBOM => EncodingCache.UTF8NoBOM;
-
- internal StreamWriter() : base(null)
- { // Ask for CurrentCulture all the time
- }
-
public StreamWriter(Stream stream)
: this(stream, UTF8NoBOM, DefaultBufferSize, false)
{
@@ -111,7 +105,25 @@ public StreamWriter(Stream stream, Encoding encoding, int bufferSize, bool leave
throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum);
}
- Init(stream, encoding, bufferSize, leaveOpen);
+ _stream = stream;
+ _encoding = encoding;
+ _encoder = _encoding.GetEncoder();
+ if (bufferSize < MinBufferSize)
+ {
+ bufferSize = MinBufferSize;
+ }
+
+ _charBuffer = new char[bufferSize];
+ _byteBuffer = new byte[_encoding.GetMaxByteCount(bufferSize)];
+ _charLen = bufferSize;
+ // If we're appending to a Stream that already has data, don't write
+ // the preamble.
+ if (_stream.CanSeek && _stream.Position > 0)
+ {
+ _haveWrittenPreamble = true;
+ }
+
+ _closable = !leaveOpen;
}
public StreamWriter(string path)
@@ -129,8 +141,13 @@ public StreamWriter(string path, bool append, Encoding encoding)
{
}
- public StreamWriter(string path, bool append, Encoding encoding, int bufferSize)
+ public StreamWriter(string path, bool append, Encoding encoding, int bufferSize) :
+ this(ValidateArgsAndOpenPath(path, append, encoding, bufferSize), encoding, bufferSize, leaveOpen: false)
{
+ }
+
+ private static Stream ValidateArgsAndOpenPath(string path, bool append, Encoding encoding, int bufferSize)
+ {
if (path == null)
throw new ArgumentNullException(nameof(path));
if (encoding == null)
@@ -140,32 +157,7 @@ public StreamWriter(string path, bool append, Encoding encoding, int bufferSize)
if (bufferSize <= 0)
throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum);
- Stream stream = new FileStream(path, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.Read,
- DefaultFileStreamBufferSize, FileOptions.SequentialScan);
- Init(stream, encoding, bufferSize, shouldLeaveOpen: false);
- }
-
- private void Init(Stream streamArg, Encoding encodingArg, int bufferSize, bool shouldLeaveOpen)
- {
- _stream = streamArg;
- _encoding = encodingArg;
- _encoder = _encoding.GetEncoder();
- if (bufferSize < MinBufferSize)
- {
- bufferSize = MinBufferSize;
- }
-
- _charBuffer = new char[bufferSize];
- _byteBuffer = new byte[_encoding.GetMaxByteCount(bufferSize)];
- _charLen = bufferSize;
- // If we're appending to a Stream that already has data, don't write
- // the preamble.
- if (_stream.CanSeek && _stream.Position > 0)
- {
- _haveWrittenPreamble = true;
- }
-
- _closable = !shouldLeaveOpen;
+ return new FileStream(path, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan);
}
public override void Close()
@@ -182,15 +174,11 @@ protected override void Dispose(bool disposing)
// Also, we never close the handles for stdout & friends. So we can safely
// write any buffered data to those streams even during finalization, which
// is generally the right thing to do.
- if (_stream != null)
+ if (!_disposed && disposing)
{
// Note: flush on the underlying stream can throw (ex., low disk space)
- if (disposing /* || (LeaveOpen && stream is __ConsoleStream) */)
- {
- CheckAsyncTaskInProgress();
-
- Flush(true, true);
- }
+ CheckAsyncTaskInProgress();
+ Flush(flushStream: true, flushEncoder: true);
}
}
finally
@@ -202,7 +190,7 @@ protected override void Dispose(bool disposing)
private void CloseStreamFromDispose(bool disposing)
{
// Dispose of our resources if this StreamWriter is closable.
- if (!LeaveOpen && _stream != null)
+ if (!LeaveOpen && !_disposed)
{
try
{
@@ -217,11 +205,7 @@ private void CloseStreamFromDispose(bool disposing)
}
finally
{
- _stream = null;
- _byteBuffer = null;
- _charBuffer = null;
- _encoding = null;
- _encoder = null;
+ _disposed = true;
_charLen = 0;
base.Dispose(disposing);
}
@@ -239,7 +223,7 @@ private async ValueTask DisposeAsyncCore()
Debug.Assert(GetType() == typeof(StreamWriter));
try
{
- if (_stream != null)
+ if (!_disposed)
{
await FlushAsync().ConfigureAwait(false);
}
@@ -263,11 +247,8 @@ private void Flush(bool flushStream, bool flushEncoder)
// flushEncoder should be true at the end of the file and if
// the user explicitly calls Flush (though not if AutoFlush is true).
// This is required to flush any dangling characters from our UTF-7
- // and UTF-8 encoders.
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_WriterClosed);
- }
+ // and UTF-8 encoders.
+ ThrowIfDisposed();
// Perf boost for Flush on non-dirty writers.
if (_charPos == 0 && !flushStream && !flushEncoder)
@@ -420,11 +401,8 @@ private unsafe void WriteSpan(ReadOnlySpan buffer, bool appendNewLine)
// else) due to temporaries that need to be cleared. Given the use of unsafe code, we also
// make local copies of instance state to protect against potential concurrent misuse.
+ ThrowIfDisposed();
char[] charBuffer = _charBuffer;
- if (charBuffer == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_WriterClosed);
- }
fixed (char* bufferPtr = &MemoryMarshal.GetReference(buffer))
fixed (char* dstPtr = &charBuffer[0])
@@ -620,7 +598,6 @@ public override void WriteLine(string format, params object[] arg)
}
}
- #region Task based Async APIs
public override Task WriteAsync(char value)
{
// If we have been inherited into a subclass, the following implementation could be incorrect
@@ -632,11 +609,7 @@ public override Task WriteAsync(char value)
return base.WriteAsync(value);
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_WriterClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
Task task = WriteAsyncInternal(this, value, _charBuffer, _charPos, _charLen, CoreNewLine, _autoFlush, appendNewLine: false);
@@ -701,11 +674,7 @@ public override Task WriteAsync(string value)
if (value != null)
{
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_WriterClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
Task task = WriteAsyncInternal(this, value, _charBuffer, _charPos, _charLen, CoreNewLine, _autoFlush, appendNewLine: false);
@@ -809,11 +778,7 @@ public override Task WriteAsync(char[] buffer, int index, int count)
return base.WriteAsync(buffer, index, count);
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_WriterClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
Task task = WriteAsyncInternal(this, new ReadOnlyMemory(buffer, index, count), _charBuffer, _charPos, _charLen, CoreNewLine, _autoFlush, appendNewLine: false, cancellationToken: default);
@@ -830,11 +795,7 @@ public override Task WriteAsync(ReadOnlyMemory buffer, CancellationToken c
return base.WriteAsync(buffer, cancellationToken);
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_WriterClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
if (cancellationToken.IsCancellationRequested)
@@ -909,11 +870,7 @@ public override Task WriteLineAsync()
return base.WriteLineAsync();
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_WriterClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
Task task = WriteAsyncInternal(this, ReadOnlyMemory.Empty, _charBuffer, _charPos, _charLen, CoreNewLine, _autoFlush, appendNewLine: true, cancellationToken: default);
@@ -934,11 +891,7 @@ public override Task WriteLineAsync(char value)
return base.WriteLineAsync(value);
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_WriterClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
Task task = WriteAsyncInternal(this, value, _charBuffer, _charPos, _charLen, CoreNewLine, _autoFlush, appendNewLine: true);
@@ -964,11 +917,7 @@ public override Task WriteLineAsync(string value)
return base.WriteLineAsync(value);
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_WriterClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
Task task = WriteAsyncInternal(this, value, _charBuffer, _charPos, _charLen, CoreNewLine, _autoFlush, appendNewLine: true);
@@ -1006,11 +955,7 @@ public override Task WriteLineAsync(char[] buffer, int index, int count)
return base.WriteLineAsync(buffer, index, count);
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_WriterClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
Task task = WriteAsyncInternal(this, new ReadOnlyMemory(buffer, index, count), _charBuffer, _charPos, _charLen, CoreNewLine, _autoFlush, appendNewLine: true, cancellationToken: default);
@@ -1026,11 +971,7 @@ public override Task WriteLineAsync(ReadOnlyMemory buffer, CancellationTok
return base.WriteLineAsync(buffer, cancellationToken);
}
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_WriterClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
if (cancellationToken.IsCancellationRequested)
@@ -1060,11 +1001,7 @@ public override Task FlushAsync()
// the user explicitly calls Flush (though not if AutoFlush is true).
// This is required to flush any dangling characters from our UTF-7
// and UTF-8 encoders.
- if (_stream == null)
- {
- throw new ObjectDisposedException(null, SR.ObjectDisposed_WriterClosed);
- }
-
+ ThrowIfDisposed();
CheckAsyncTaskInProgress();
Task task = FlushAsyncInternal(true, true, _charBuffer, _charPos);
@@ -1135,6 +1072,15 @@ private static async Task FlushAsyncInternal(StreamWriter _this, bool flushStrea
await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
}
}
- #endregion
+
+ private void ThrowIfDisposed()
+ {
+ if (_disposed)
+ {
+ ThrowObjectDisposedException();
+ }
+
+ void ThrowObjectDisposedException() => throw new ObjectDisposedException(GetType().Name, SR.ObjectDisposed_WriterClosed);
+ }
} // class StreamWriter
} // namespace
diff --git a/src/Common/src/CoreLib/System/Marvin.OrdinalIgnoreCase.cs b/src/Common/src/CoreLib/System/Marvin.OrdinalIgnoreCase.cs
index beab0cfe02e8..9e9bb3162304 100644
--- a/src/Common/src/CoreLib/System/Marvin.OrdinalIgnoreCase.cs
+++ b/src/Common/src/CoreLib/System/Marvin.OrdinalIgnoreCase.cs
@@ -5,7 +5,7 @@
using System.Buffers;
using System.Diagnostics;
using System.Runtime.InteropServices;
-using System.Text;
+using System.Text.Unicode;
using Internal.Runtime.CompilerServices;
#if BIT64
diff --git a/src/Common/src/CoreLib/System/Math.cs b/src/Common/src/CoreLib/System/Math.cs
index 1c36c9d23071..ac9be486734c 100644
--- a/src/Common/src/CoreLib/System/Math.cs
+++ b/src/Common/src/CoreLib/System/Math.cs
@@ -538,31 +538,23 @@ public static decimal Max(decimal val1, decimal val2)
public static double Max(double val1, double val2)
{
- // When val1 and val2 are both finite or infinite, return the larger
- // * We count +0.0 as larger than -0.0 to match MSVC
- // When val1 or val2, but not both, are NaN return the opposite
- // * We return the opposite if either is NaN to match MSVC
+ // This matches the IEEE 754:2019 `maximum` function
+ //
+ // It propagates NaN inputs back to the caller and
+ // otherwise returns the larger of the inputs. It
+ // treats +0 as larger than -0 as per the specification.
- if (double.IsNaN(val1))
- {
- return val2;
- }
-
- if (double.IsNaN(val2))
+ if ((val1 > val2) || double.IsNaN(val1))
{
return val1;
}
- // We do this comparison first and separately to handle the -0.0 to +0.0 comparision
- // * Doing (val1 < val2) first could get transformed into (val2 >= val1) by the JIT
- // which would then return an incorrect value
-
if (val1 == val2)
{
return double.IsNegative(val1) ? val2 : val1;
}
- return (val1 < val2) ? val2 : val1;
+ return val2;
}
[NonVersionable]
@@ -592,31 +584,23 @@ public static sbyte Max(sbyte val1, sbyte val2)
public static float Max(float val1, float val2)
{
- // When val1 and val2 are both finite or infinite, return the larger
- // * We count +0.0 as larger than -0.0 to match MSVC
- // When val1 or val2, but not both, are NaN return the opposite
- // * We return the opposite if either is NaN to match MSVC
+ // This matches the IEEE 754:2019 `maximum` function
+ //
+ // It propagates NaN inputs back to the caller and
+ // otherwise returns the larger of the inputs. It
+ // treats +0 as larger than -0 as per the specification.
- if (float.IsNaN(val1))
- {
- return val2;
- }
-
- if (float.IsNaN(val2))
+ if ((val1 > val2) || float.IsNaN(val1))
{
return val1;
}
- // We do this comparison first and separately to handle the -0.0 to +0.0 comparision
- // * Doing (val1 < val2) first could get transformed into (val2 >= val1) by the JIT
- // which would then return an incorrect value
-
if (val1 == val2)
{
return float.IsNegative(val1) ? val2 : val1;
}
- return (val1 < val2) ? val2 : val1;
+ return val2;
}
[CLSCompliant(false)]
@@ -642,34 +626,26 @@ public static ulong Max(ulong val1, ulong val2)
public static double MaxMagnitude(double x, double y)
{
- // When x and y are both finite or infinite, return the larger magnitude
- // * We count +0.0 as larger than -0.0 to match MSVC
- // When x or y, but not both, are NaN return the opposite
- // * We return the opposite if either is NaN to match MSVC
+ // This matches the IEEE 754:2019 `maximumMagnitude` function
+ //
+ // It propagates NaN inputs back to the caller and
+ // otherwise returns the input with a larger magnitude.
+ // It treats +0 as larger than -0 as per the specification.
- if (double.IsNaN(x))
- {
- return y;
- }
+ double ax = Abs(x);
+ double ay = Abs(y);
- if (double.IsNaN(y))
+ if ((ax > ay) || double.IsNaN(ax))
{
return x;
}
- // We do this comparison first and separately to handle the -0.0 to +0.0 comparision
- // * Doing (ax < ay) first could get transformed into (ay >= ax) by the JIT which would
- // then return an incorrect value
-
- double ax = Abs(x);
- double ay = Abs(y);
-
if (ax == ay)
{
return double.IsNegative(x) ? y : x;
}
- return (ax < ay) ? y : x;
+ return y;
}
[NonVersionable]
@@ -686,31 +662,23 @@ public static decimal Min(decimal val1, decimal val2)
public static double Min(double val1, double val2)
{
- // When val1 and val2 are both finite or infinite, return the smaller
- // * We count -0.0 as smaller than -0.0 to match MSVC
- // When val1 or val2, but not both, are NaN return the opposite
- // * We return the opposite if either is NaN to match MSVC
+ // This matches the IEEE 754:2019 `minimum` function
+ //
+ // It propagates NaN inputs back to the caller and
+ // otherwise returns the larger of the inputs. It
+ // treats +0 as larger than -0 as per the specification.
- if (double.IsNaN(val1))
- {
- return val2;
- }
-
- if (double.IsNaN(val2))
+ if ((val1 < val2) || double.IsNaN(val1))
{
return val1;
}
- // We do this comparison first and separately to handle the -0.0 to +0.0 comparision
- // * Doing (val1 < val2) first could get transformed into (val2 >= val1) by the JIT
- // which would then return an incorrect value
-
if (val1 == val2)
{
return double.IsNegative(val1) ? val1 : val2;
}
- return (val1 < val2) ? val1 : val2;
+ return val2;
}
[NonVersionable]
@@ -740,31 +708,23 @@ public static sbyte Min(sbyte val1, sbyte val2)
public static float Min(float val1, float val2)
{
- // When val1 and val2 are both finite or infinite, return the smaller
- // * We count -0.0 as smaller than -0.0 to match MSVC
- // When val1 or val2, but not both, are NaN return the opposite
- // * We return the opposite if either is NaN to match MSVC
+ // This matches the IEEE 754:2019 `minimum` function
+ //
+ // It propagates NaN inputs back to the caller and
+ // otherwise returns the larger of the inputs. It
+ // treats +0 as larger than -0 as per the specification.
- if (float.IsNaN(val1))
- {
- return val2;
- }
-
- if (float.IsNaN(val2))
+ if ((val1 < val2) || float.IsNaN(val1))
{
return val1;
}
- // We do this comparison first and separately to handle the -0.0 to +0.0 comparision
- // * Doing (val1 < val2) first could get transformed into (val2 >= val1) by the JIT
- // which would then return an incorrect value
-
if (val1 == val2)
{
return float.IsNegative(val1) ? val1 : val2;
}
- return (val1 < val2) ? val1 : val2;
+ return val2;
}
[CLSCompliant(false)]
@@ -790,34 +750,26 @@ public static ulong Min(ulong val1, ulong val2)
public static double MinMagnitude(double x, double y)
{
- // When x and y are both finite or infinite, return the smaller magnitude
- // * We count -0.0 as smaller than -0.0 to match MSVC
- // When x or y, but not both, are NaN return the opposite
- // * We return the opposite if either is NaN to match MSVC
+ // This matches the IEEE 754:2019 `minimumMagnitude` function
+ //
+ // It propagates NaN inputs back to the caller and
+ // otherwise returns the input with a larger magnitude.
+ // It treats +0 as larger than -0 as per the specification.
- if (double.IsNaN(x))
- {
- return y;
- }
+ double ax = Abs(x);
+ double ay = Abs(y);
- if (double.IsNaN(y))
+ if ((ax < ay) || double.IsNaN(ax))
{
return x;
}
- // We do this comparison first and separately to handle the -0.0 to +0.0 comparision
- // * Doing (ax < ay) first could get transformed into (ay >= ax) by the JIT which would
- // then return an incorrect value
-
- double ax = Abs(x);
- double ay = Abs(y);
-
if (ax == ay)
{
return double.IsNegative(x) ? x : y;
}
- return (ax < ay) ? x : y;
+ return y;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/Common/src/CoreLib/System/MathF.cs b/src/Common/src/CoreLib/System/MathF.cs
index 1defa4e40baa..bf324866ec75 100644
--- a/src/Common/src/CoreLib/System/MathF.cs
+++ b/src/Common/src/CoreLib/System/MathF.cs
@@ -190,34 +190,26 @@ public static float Max(float x, float y)
public static float MaxMagnitude(float x, float y)
{
- // When x and y are both finite or infinite, return the larger magnitude
- // * We count +0.0 as larger than -0.0 to match MSVC
- // When x or y, but not both, are NaN return the opposite
- // * We return the opposite if either is NaN to match MSVC
+ // This matches the IEEE 754:2019 `maximumMagnitude` function
+ //
+ // It propagates NaN inputs back to the caller and
+ // otherwise returns the input with a larger magnitude.
+ // It treats +0 as larger than -0 as per the specification.
- if (float.IsNaN(x))
- {
- return y;
- }
+ float ax = Abs(x);
+ float ay = Abs(y);
- if (float.IsNaN(y))
+ if ((ax > ay) || float.IsNaN(ax))
{
return x;
}
- // We do this comparison first and separately to handle the -0.0 to +0.0 comparision
- // * Doing (ax < ay) first could get transformed into (ay >= ax) by the JIT which would
- // then return an incorrect value
-
- float ax = Abs(x);
- float ay = Abs(y);
-
if (ax == ay)
{
return float.IsNegative(x) ? y : x;
}
- return (ax < ay) ? y : x;
+ return y;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -228,34 +220,26 @@ public static float Min(float x, float y)
public static float MinMagnitude(float x, float y)
{
- // When x and y are both finite or infinite, return the smaller magnitude
- // * We count -0.0 as smaller than -0.0 to match MSVC
- // When x or y, but not both, are NaN return the opposite
- // * We return the opposite if either is NaN to match MSVC
+ // This matches the IEEE 754:2019 `minimumMagnitude` function
+ //
+ // It propagates NaN inputs back to the caller and
+ // otherwise returns the input with a larger magnitude.
+ // It treats +0 as larger than -0 as per the specification.
- if (float.IsNaN(x))
- {
- return y;
- }
+ float ax = Abs(x);
+ float ay = Abs(y);
- if (float.IsNaN(y))
+ if ((ax < ay) || float.IsNaN(ax))
{
return x;
}
- // We do this comparison first and separately to handle the -0.0 to +0.0 comparision
- // * Doing (ax < ay) first could get transformed into (ay >= ax) by the JIT which would
- // then return an incorrect value
-
- float ax = Abs(x);
- float ay = Abs(y);
-
if (ax == ay)
{
return float.IsNegative(x) ? x : y;
}
- return (ax < ay) ? x : y;
+ return y;
}
[Intrinsic]
diff --git a/src/Common/src/CoreLib/System/Memory.cs b/src/Common/src/CoreLib/System/Memory.cs
index d468a8ca2470..e3d0347f11a8 100644
--- a/src/Common/src/CoreLib/System/Memory.cs
+++ b/src/Common/src/CoreLib/System/Memory.cs
@@ -12,6 +12,14 @@
using Internal.Runtime.CompilerServices;
+#if BIT64
+using nint = System.Int64;
+using nuint = System.UInt64;
+#else // BIT64
+using nint = System.Int32;
+using nuint = System.UInt32;
+#endif // BIT64
+
namespace System
{
///
@@ -273,35 +281,6 @@ public Memory Slice(int start, int length)
return new Memory(_object, _index + start, length);
}
- ///
- /// Forms a slice out of the given memory, beginning at 'startIndex'
- ///
- /// The index at which to begin this slice.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Memory Slice(Index startIndex)
- {
- int actualIndex = startIndex.GetOffset(_length);
- return Slice(actualIndex);
- }
-
- ///
- /// Forms a slice out of the given memory using the range start and end indexes.
- ///
- /// The range used to slice the memory using its start and end indexes.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Memory Slice(Range range)
- {
- (int start, int length) = range.GetOffsetAndLength(_length);
- // It is expected for _index + start to be negative if the memory is already pre-pinned.
- return new Memory(_object, _index + start, length);
- }
-
- ///
- /// Forms a slice out of the given memory using the range start and end indexes.
- ///
- /// The range used to slice the memory using its start and end indexes.
- public Memory this[Range range] => Slice(range);
-
///
/// Returns a span from the memory.
///
@@ -372,12 +351,12 @@ public unsafe Span Span
// least to be in-bounds when compared with the original Memory instance, so using the span won't
// AV the process.
- int desiredStartIndex = _index & ReadOnlyMemory.RemoveFlagsBitMask;
+ nuint desiredStartIndex = (uint)_index & (uint)ReadOnlyMemory.RemoveFlagsBitMask;
int desiredLength = _length;
#if BIT64
// See comment in Span.Slice for how this works.
- if ((ulong)(uint)desiredStartIndex + (ulong)(uint)desiredLength > (ulong)(uint)lengthOfUnderlyingSpan)
+ if ((ulong)desiredStartIndex + (ulong)(uint)desiredLength > (ulong)(uint)lengthOfUnderlyingSpan)
{
ThrowHelper.ThrowArgumentOutOfRangeException();
}
@@ -388,7 +367,7 @@ public unsafe Span Span
}
#endif
- refToReturn = ref Unsafe.Add(ref refToReturn, desiredStartIndex);
+ refToReturn = ref Unsafe.Add(ref refToReturn, (IntPtr)(void*)desiredStartIndex);
lengthOfUnderlyingSpan = desiredLength;
}
diff --git a/src/Common/src/CoreLib/System/MemoryExtensions.Trim.cs b/src/Common/src/CoreLib/System/MemoryExtensions.Trim.cs
index be98bb1fba7f..96581c7c0183 100644
--- a/src/Common/src/CoreLib/System/MemoryExtensions.Trim.cs
+++ b/src/Common/src/CoreLib/System/MemoryExtensions.Trim.cs
@@ -18,7 +18,7 @@ public static Memory Trim(this Memory memory, T trimElement)
{
ReadOnlySpan span = memory.Span;
int start = ClampStart(span, trimElement);
- int length = ClampEnd(span, start + 1, trimElement);
+ int length = ClampEnd(span, start, trimElement);
return memory.Slice(start, length);
}
@@ -50,7 +50,7 @@ public static ReadOnlyMemory Trim(this ReadOnlyMemory memory, T trimEle
{
ReadOnlySpan span = memory.Span;
int start = ClampStart(span, trimElement);
- int length = ClampEnd(span, start + 1, trimElement);
+ int length = ClampEnd(span, start, trimElement);
return memory.Slice(start, length);
}
@@ -81,7 +81,7 @@ public static Span Trim(this Span span, T trimElement)
where T : IEquatable
{
int start = ClampStart(span, trimElement);
- int length = ClampEnd(span, start + 1, trimElement);
+ int length = ClampEnd(span, start, trimElement);
return span.Slice(start, length);
}
@@ -112,7 +112,7 @@ public static ReadOnlySpan Trim(this ReadOnlySpan span, T trimElement)
where T : IEquatable
{
int start = ClampStart(span, trimElement);
- int length = ClampEnd(span, start + 1, trimElement);
+ int length = ClampEnd(span, start, trimElement);
return span.Slice(start, length);
}
@@ -220,7 +220,7 @@ public static Memory Trim(this Memory memory, ReadOnlySpan trimEleme
{
ReadOnlySpan span = memory.Span;
int start = ClampStart(span, trimElements);
- int length = ClampEnd(span, start + 1, trimElements);
+ int length = ClampEnd(span, start, trimElements);
return memory.Slice(start, length);
}
@@ -292,7 +292,7 @@ public static ReadOnlyMemory Trim(this ReadOnlyMemory memory, ReadOnlyS
{
ReadOnlySpan span = memory.Span;
int start = ClampStart(span, trimElements);
- int length = ClampEnd(span, start + 1, trimElements);
+ int length = ClampEnd(span, start, trimElements);
return memory.Slice(start, length);
}
@@ -364,7 +364,7 @@ public static Span Trim(this Span span, ReadOnlySpan trimElements)
if (trimElements.Length > 1)
{
int start = ClampStart(span, trimElements);
- int length = ClampEnd(span, start + 1, trimElements);
+ int length = ClampEnd(span, start, trimElements);
return span.Slice(start, length);
}
@@ -435,7 +435,7 @@ public static ReadOnlySpan Trim(this ReadOnlySpan span, ReadOnlySpan
if (trimElements.Length > 1)
{
int start = ClampStart(span, trimElements);
- int length = ClampEnd(span, start + 1, trimElements);
+ int length = ClampEnd(span, start, trimElements);
return span.Slice(start, length);
}
@@ -547,7 +547,7 @@ public static Memory Trim(this Memory memory)
{
ReadOnlySpan span = memory.Span;
int start = ClampStart(span);
- int length = ClampEnd(span, start + 1);
+ int length = ClampEnd(span, start);
return memory.Slice(start, length);
}
@@ -573,7 +573,7 @@ public static ReadOnlyMemory Trim(this ReadOnlyMemory memory)
{
ReadOnlySpan span = memory.Span;
int start = ClampStart(span);
- int length = ClampEnd(span, start + 1);
+ int length = ClampEnd(span, start);
return memory.Slice(start, length);
}
@@ -803,7 +803,7 @@ public static ReadOnlySpan TrimEnd(this ReadOnlySpan span, ReadOnlyS
public static Span Trim(this Span span)
{
int start = ClampStart(span);
- int length = ClampEnd(span, start + 1);
+ int length = ClampEnd(span, start);
return span.Slice(start, length);
}
diff --git a/src/Common/src/CoreLib/System/ObjectDisposedException.cs b/src/Common/src/CoreLib/System/ObjectDisposedException.cs
index d5d488447f9c..450a9597e34a 100644
--- a/src/Common/src/CoreLib/System/ObjectDisposedException.cs
+++ b/src/Common/src/CoreLib/System/ObjectDisposedException.cs
@@ -4,16 +4,16 @@
#nullable enable
using System.Globalization;
+using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
namespace System
{
- ///
- /// The exception that is thrown when accessing an object that was
- /// disposed.
- ///
+ ///
+ /// The exception that is thrown when accessing an object that was disposed.
+ ///
[Serializable]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class ObjectDisposedException : InvalidOperationException
{
private string? _objectName;
@@ -53,16 +53,18 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont
info.AddValue("ObjectName", ObjectName, typeof(string));
}
- ///
- /// Gets the text for the message for this exception.
- ///
+ ///
+ /// Gets the text for the message for this exception.
+ ///
public override string Message
{
get
{
string name = ObjectName;
if (string.IsNullOrEmpty(name))
+ {
return base.Message;
+ }
string objectDisposed = SR.Format(SR.ObjectDisposed_ObjectName_Name, name);
return base.Message + Environment.NewLine + objectDisposed;
diff --git a/src/Common/src/CoreLib/System/Range.cs b/src/Common/src/CoreLib/System/Range.cs
index 0098dea17ff7..fc5ec5242343 100644
--- a/src/Common/src/CoreLib/System/Range.cs
+++ b/src/Common/src/CoreLib/System/Range.cs
@@ -95,15 +95,15 @@ public override string ToString()
/// Create a Range object starting from first element to the end.
public static Range All => new Range(Index.Start, Index.End);
- /// Destruct the range object according to a collection length and return the start offset from the beginning and the length of this range.
- /// The length of the collection that the range will be used with. length has to be a positive value
+ /// Calculate the start offset and length of range object using a collection length.
+ /// The length of the collection that the range will be used with. length has to be a positive value.
///
/// For performance reason, we don't validate the input length parameter against negative values.
/// It is expected Range will be used with collections which always have non negative length/count.
/// We validate the range is inside the length scope though.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public OffsetAndLength GetOffsetAndLength(int length)
+ public (int Offset, int Length) GetOffsetAndLength(int length)
{
int start;
Index startIndex = Start;
@@ -124,25 +124,7 @@ public OffsetAndLength GetOffsetAndLength(int length)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
}
- return new OffsetAndLength(start, end - start);
- }
-
- public readonly struct OffsetAndLength
- {
- public int Offset { get; }
- public int Length { get; }
-
- public OffsetAndLength(int offset, int length)
- {
- Offset = offset;
- Length = length;
- }
-
- public void Deconstruct(out int offset, out int length)
- {
- offset = Offset;
- length = Length;
- }
+ return (start, end - start);
}
}
}
diff --git a/src/Common/src/CoreLib/System/ReadOnlyMemory.cs b/src/Common/src/CoreLib/System/ReadOnlyMemory.cs
index be664e62325a..67c85eb2b383 100644
--- a/src/Common/src/CoreLib/System/ReadOnlyMemory.cs
+++ b/src/Common/src/CoreLib/System/ReadOnlyMemory.cs
@@ -12,6 +12,14 @@
using Internal.Runtime.CompilerServices;
+#if BIT64
+using nint = System.Int64;
+using nuint = System.UInt64;
+#else // BIT64
+using nint = System.Int32;
+using nuint = System.UInt32;
+#endif // BIT64
+
namespace System
{
///
@@ -202,35 +210,6 @@ public ReadOnlyMemory Slice(int start, int length)
return new ReadOnlyMemory(_object, _index + start, length);
}
- ///
- /// Forms a slice out of the given memory, beginning at 'startIndex'
- ///
- /// The index at which to begin this slice.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ReadOnlyMemory Slice(Index startIndex)
- {
- int actualIndex = startIndex.GetOffset(_length);
- return Slice(actualIndex);
- }
-
- ///
- /// Forms a slice out of the given memory using the range start and end indexes.
- ///
- /// The range used to slice the memory using its start and end indexes.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ReadOnlyMemory Slice(Range range)
- {
- (int start, int length) = range.GetOffsetAndLength(_length);
- // It is expected for _index + start to be negative if the memory is already pre-pinned.
- return new ReadOnlyMemory(_object, _index + start, length);
- }
-
- ///
- /// Forms a slice out of the given memory using the range start and end indexes.
- ///
- /// The range used to slice the memory using its start and end indexes.
- public ReadOnlyMemory this[Range range] => Slice(range);
-
///
/// Returns a span from the memory.
///
@@ -294,12 +273,12 @@ public unsafe ReadOnlySpan Span
// least to be in-bounds when compared with the original Memory instance, so using the span won't
// AV the process.
- int desiredStartIndex = _index & RemoveFlagsBitMask;
+ nuint desiredStartIndex = (uint)_index & (uint)RemoveFlagsBitMask;
int desiredLength = _length;
#if BIT64
// See comment in Span.Slice for how this works.
- if ((ulong)(uint)desiredStartIndex + (ulong)(uint)desiredLength > (ulong)(uint)lengthOfUnderlyingSpan)
+ if ((ulong)desiredStartIndex + (ulong)(uint)desiredLength > (ulong)(uint)lengthOfUnderlyingSpan)
{
ThrowHelper.ThrowArgumentOutOfRangeException();
}
@@ -310,7 +289,7 @@ public unsafe ReadOnlySpan Span
}
#endif
- refToReturn = ref Unsafe.Add(ref refToReturn, desiredStartIndex);
+ refToReturn = ref Unsafe.Add(ref refToReturn, (IntPtr)(void*)desiredStartIndex);
lengthOfUnderlyingSpan = desiredLength;
}
diff --git a/src/Common/src/CoreLib/System/ReadOnlySpan.Fast.cs b/src/Common/src/CoreLib/System/ReadOnlySpan.Fast.cs
index 00337a5fd7f5..df4933766130 100644
--- a/src/Common/src/CoreLib/System/ReadOnlySpan.Fast.cs
+++ b/src/Common/src/CoreLib/System/ReadOnlySpan.Fast.cs
@@ -153,18 +153,6 @@ public ref readonly T this[int index]
#endif
}
- public ref readonly T this[Index index]
- {
- get
- {
- // Evaluate the actual index first because it helps performance
- int actualIndex = index.GetOffset(_length);
- return ref this [actualIndex];
- }
- }
-
- public ReadOnlySpan this[Range range] => Slice(range);
-
///
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns null reference.
/// It can be used for pinning and is required to support the use of span within a fixed statement.
@@ -292,33 +280,6 @@ public ReadOnlySpan Slice(int start, int length)
return new ReadOnlySpan(ref Unsafe.Add(ref _pointer.Value, start), length);
}
- ///
- /// Forms a slice out of the given read-only span, beginning at 'startIndex'
- ///
- /// The index at which to begin this slice.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ReadOnlySpan Slice(Index startIndex)
- {
- int actualIndex;
- if (startIndex.IsFromEnd)
- actualIndex = _length - startIndex.Value;
- else
- actualIndex = startIndex.Value;
-
- return Slice(actualIndex);
- }
-
- ///
- /// Forms a slice out of the given read-only span, beginning at range start index to the range end
- ///
- /// The range which has the start and end indexes used to slice the span.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ReadOnlySpan Slice(Range range)
- {
- (int start, int length) = range.GetOffsetAndLength(_length);
- return new ReadOnlySpan(ref Unsafe.Add(ref _pointer.Value, start), length);
- }
-
///
/// Copies the contents of this read-only span into a new array. This heap
/// allocates, so should generally be avoided, however it is sometimes
diff --git a/src/Common/src/CoreLib/System/Reflection/Assembly.cs b/src/Common/src/CoreLib/System/Reflection/Assembly.cs
index 3db428ed7937..1e9699f62f27 100644
--- a/src/Common/src/CoreLib/System/Reflection/Assembly.cs
+++ b/src/Common/src/CoreLib/System/Reflection/Assembly.cs
@@ -205,7 +205,17 @@ public static Assembly LoadWithPartialName(string partialName)
if (partialName == null)
throw new ArgumentNullException(nameof(partialName));
- return Load(partialName);
+ if ((partialName.Length == 0) || (partialName[0] == '\0'))
+ throw new ArgumentException(SR.Format_StringZeroLength, nameof(partialName));
+
+ try
+ {
+ return Load(partialName);
+ }
+ catch (FileNotFoundException)
+ {
+ return null;
+ }
}
// Loads the assembly with a COFF based IMAGE containing
diff --git a/src/Common/src/CoreLib/System/Reflection/AssemblyName.cs b/src/Common/src/CoreLib/System/Reflection/AssemblyName.cs
new file mode 100644
index 000000000000..5acf5cf2a82f
--- /dev/null
+++ b/src/Common/src/CoreLib/System/Reflection/AssemblyName.cs
@@ -0,0 +1,498 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Configuration.Assemblies;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Text;
+using CultureInfo = System.Globalization.CultureInfo;
+
+namespace System.Reflection
+{
+ public sealed partial class AssemblyName : ICloneable, IDeserializationCallback, ISerializable
+ {
+ // If you modify any of these fields, you must also update the
+ // AssemblyBaseObject structure in object.h
+ private string _name;
+ private byte[] _publicKey;
+ private byte[] _publicKeyToken;
+ private CultureInfo _cultureInfo;
+ private string _codeBase;
+ private Version _version;
+
+ private StrongNameKeyPair _strongNameKeyPair;
+
+ private AssemblyHashAlgorithm _hashAlgorithm;
+
+ private AssemblyVersionCompatibility _versionCompatibility;
+ private AssemblyNameFlags _flags;
+
+ public AssemblyName()
+ {
+ _versionCompatibility = AssemblyVersionCompatibility.SameMachine;
+ }
+
+ // Set and get the name of the assembly. If this is a weak Name
+ // then it optionally contains a site. For strong assembly names,
+ // the name partitions up the strong name's namespace
+ public string Name
+ {
+ get { return _name; }
+ set { _name = value; }
+ }
+
+ public Version Version
+ {
+ get { return _version; }
+ set { _version = value; }
+ }
+
+ // Locales, internally the LCID is used for the match.
+ public CultureInfo CultureInfo
+ {
+ get { return _cultureInfo; }
+ set { _cultureInfo = value; }
+ }
+
+ public string CultureName
+ {
+ get
+ {
+ return (_cultureInfo == null) ? null : _cultureInfo.Name;
+ }
+ set
+ {
+ _cultureInfo = (value == null) ? null : new CultureInfo(value);
+ }
+ }
+
+ public string CodeBase
+ {
+ get { return _codeBase; }
+ set { _codeBase = value; }
+ }
+
+ public string EscapedCodeBase
+ {
+ get
+ {
+ if (_codeBase == null)
+ return null;
+ else
+ return EscapeCodeBase(_codeBase);
+ }
+ }
+
+ public ProcessorArchitecture ProcessorArchitecture
+ {
+ get
+ {
+ int x = (((int)_flags) & 0x70) >> 4;
+ if (x > 5)
+ x = 0;
+ return (ProcessorArchitecture)x;
+ }
+ set
+ {
+ int x = ((int)value) & 0x07;
+ if (x <= 5)
+ {
+ _flags = (AssemblyNameFlags)((int)_flags & 0xFFFFFF0F);
+ _flags |= (AssemblyNameFlags)(x << 4);
+ }
+ }
+ }
+
+ public AssemblyContentType ContentType
+ {
+ get
+ {
+ int x = (((int)_flags) & 0x00000E00) >> 9;
+ if (x > 1)
+ x = 0;
+ return (AssemblyContentType)x;
+ }
+ set
+ {
+ int x = ((int)value) & 0x07;
+ if (x <= 1)
+ {
+ _flags = (AssemblyNameFlags)((int)_flags & 0xFFFFF1FF);
+ _flags |= (AssemblyNameFlags)(x << 9);
+ }
+ }
+ }
+
+ // Make a copy of this assembly name.
+ public object Clone()
+ {
+ var name = new AssemblyName
+ {
+ _name = _name,
+ _publicKey = (byte[])_publicKey?.Clone(),
+ _publicKeyToken = (byte[])_publicKeyToken?.Clone(),
+ _cultureInfo = _cultureInfo,
+ _version = (Version)_version?.Clone(),
+ _flags = _flags,
+ _codeBase = _codeBase,
+ _hashAlgorithm = _hashAlgorithm,
+ _versionCompatibility = _versionCompatibility,
+ };
+ return name;
+ }
+
+ /*
+ * Get the AssemblyName for a given file. This will only work
+ * if the file contains an assembly manifest. This method causes
+ * the file to be opened and closed.
+ */
+ public static AssemblyName GetAssemblyName(string assemblyFile)
+ {
+ if (assemblyFile == null)
+ throw new ArgumentNullException(nameof(assemblyFile));
+
+ return GetFileInformationCore(assemblyFile);
+ }
+
+ public byte[] GetPublicKey()
+ {
+ return _publicKey;
+ }
+
+ public void SetPublicKey(byte[] publicKey)
+ {
+ _publicKey = publicKey;
+
+ if (publicKey == null)
+ _flags &= ~AssemblyNameFlags.PublicKey;
+ else
+ _flags |= AssemblyNameFlags.PublicKey;
+ }
+
+ // The compressed version of the public key formed from a truncated hash.
+ // Will throw a SecurityException if _publicKey is invalid
+ public byte[] GetPublicKeyToken()
+ {
+ if (_publicKeyToken == null)
+ _publicKeyToken = ComputePublicKeyToken();
+ return _publicKeyToken;
+ }
+
+ public void SetPublicKeyToken(byte[] publicKeyToken)
+ {
+ _publicKeyToken = publicKeyToken;
+ }
+
+ // Flags modifying the name. So far the only flag is PublicKey, which
+ // indicates that a full public key and not the compressed version is
+ // present.
+ // Processor Architecture flags are set only through ProcessorArchitecture
+ // property and can't be set or retrieved directly
+ // Content Type flags are set only through ContentType property and can't be
+ // set or retrieved directly
+ public AssemblyNameFlags Flags
+ {
+ get { return (AssemblyNameFlags)((uint)_flags & 0xFFFFF10F); }
+ set
+ {
+ _flags &= unchecked((AssemblyNameFlags)0x00000EF0);
+ _flags |= (value & unchecked((AssemblyNameFlags)0xFFFFF10F));
+ }
+ }
+
+ public AssemblyHashAlgorithm HashAlgorithm
+ {
+ get { return _hashAlgorithm; }
+ set { _hashAlgorithm = value; }
+ }
+
+ public AssemblyVersionCompatibility VersionCompatibility
+ {
+ get { return _versionCompatibility; }
+ set { _versionCompatibility = value; }
+ }
+
+ public StrongNameKeyPair KeyPair
+ {
+ get { return _strongNameKeyPair; }
+ set { _strongNameKeyPair = value; }
+ }
+
+ public string FullName
+ {
+ get
+ {
+ if (this.Name == null)
+ return string.Empty;
+ // Do not call GetPublicKeyToken() here - that latches the result into AssemblyName which isn't a side effect we want.
+ byte[] pkt = _publicKeyToken ?? ComputePublicKeyToken();
+ return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, Flags, ContentType);
+ }
+ }
+
+ public override string ToString()
+ {
+ string s = FullName;
+ if (s == null)
+ return base.ToString();
+ else
+ return s;
+ }
+
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ public void OnDeserialization(object sender)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ ///
+ /// Compares the simple names disregarding Version, Culture and PKT. While this clearly does not
+ /// match the intent of this api, this api has been broken this way since its debut and we cannot
+ /// change its behavior now.
+ ///
+ public static bool ReferenceMatchesDefinition(AssemblyName reference, AssemblyName definition)
+ {
+ if (object.ReferenceEquals(reference, definition))
+ return true;
+
+ if (reference == null)
+ throw new ArgumentNullException(nameof(reference));
+
+ if (definition == null)
+ throw new ArgumentNullException(nameof(definition));
+
+ string refName = reference.Name ?? string.Empty;
+ string defName = definition.Name ?? string.Empty;
+ return refName.Equals(defName, StringComparison.OrdinalIgnoreCase);
+ }
+
+ internal static string EscapeCodeBase(string codebase)
+ {
+ if (codebase == null)
+ return string.Empty;
+
+ int position = 0;
+ char[] dest = EscapeString(codebase, 0, codebase.Length, null, ref position, true, c_DummyChar, c_DummyChar, c_DummyChar);
+ if (dest == null)
+ return codebase;
+
+ return new string(dest, 0, position);
+ }
+
+ // This implementation of EscapeString has been copied from System.Private.Uri from corefx repo
+ // - forceX characters are always escaped if found
+ // - rsvd character will remain unescaped
+ //
+ // start - starting offset from input
+ // end - the exclusive ending offset in input
+ // destPos - starting offset in dest for output, on return this will be an exclusive "end" in the output.
+ //
+ // In case "dest" has lack of space it will be reallocated by preserving the _whole_ content up to current destPos
+ //
+ // Returns null if nothing has to be escaped AND passed dest was null, otherwise the resulting array with the updated destPos
+ //
+ internal static unsafe char[] EscapeString(string input, int start, int end, char[] dest, ref int destPos,
+ bool isUriString, char force1, char force2, char rsvd)
+ {
+ int i = start;
+ int prevInputPos = start;
+ byte* bytes = stackalloc byte[c_MaxUnicodeCharsReallocate * c_MaxUTF_8BytesPerUnicodeChar]; // 40*4=160
+
+ fixed (char* pStr = input)
+ {
+ for (; i < end; ++i)
+ {
+ char ch = pStr[i];
+
+ // a Unicode ?
+ if (ch > '\x7F')
+ {
+ short maxSize = (short)Math.Min(end - i, (int)c_MaxUnicodeCharsReallocate - 1);
+
+ short count = 1;
+ for (; count < maxSize && pStr[i + count] > '\x7f'; ++count)
+ ;
+
+ // Is the last a high surrogate?
+ if (pStr[i + count - 1] >= 0xD800 && pStr[i + count - 1] <= 0xDBFF)
+ {
+ // Should be a rare case where the app tries to feed an invalid Unicode surrogates pair
+ if (count == 1 || count == end - i)
+ throw new FormatException(SR.Arg_FormatException);
+ // need to grab one more char as a Surrogate except when it's a bogus input
+ ++count;
+ }
+
+ dest = EnsureDestinationSize(pStr, dest, i,
+ (short)(count * c_MaxUTF_8BytesPerUnicodeChar * c_EncodedCharsPerByte),
+ c_MaxUnicodeCharsReallocate * c_MaxUTF_8BytesPerUnicodeChar * c_EncodedCharsPerByte,
+ ref destPos, prevInputPos);
+
+ short numberOfBytes = (short)Encoding.UTF8.GetBytes(pStr + i, count, bytes,
+ c_MaxUnicodeCharsReallocate * c_MaxUTF_8BytesPerUnicodeChar);
+
+ // This is the only exception that built in UriParser can throw after a Uri ctor.
+ // Should not happen unless the app tries to feed an invalid Unicode string
+ if (numberOfBytes == 0)
+ throw new FormatException(SR.Arg_FormatException);
+
+ i += (count - 1);
+
+ for (count = 0; count < numberOfBytes; ++count)
+ EscapeAsciiChar((char)bytes[count], dest, ref destPos);
+
+ prevInputPos = i + 1;
+ }
+ else if (ch == '%' && rsvd == '%')
+ {
+ // Means we don't reEncode '%' but check for the possible escaped sequence
+ dest = EnsureDestinationSize(pStr, dest, i, c_EncodedCharsPerByte,
+ c_MaxAsciiCharsReallocate * c_EncodedCharsPerByte, ref destPos, prevInputPos);
+ if (i + 2 < end && EscapedAscii(pStr[i + 1], pStr[i + 2]) != c_DummyChar)
+ {
+ // leave it escaped
+ dest[destPos++] = '%';
+ dest[destPos++] = pStr[i + 1];
+ dest[destPos++] = pStr[i + 2];
+ i += 2;
+ }
+ else
+ {
+ EscapeAsciiChar('%', dest, ref destPos);
+ }
+ prevInputPos = i + 1;
+ }
+ else if (ch == force1 || ch == force2)
+ {
+ dest = EnsureDestinationSize(pStr, dest, i, c_EncodedCharsPerByte,
+ c_MaxAsciiCharsReallocate * c_EncodedCharsPerByte, ref destPos, prevInputPos);
+ EscapeAsciiChar(ch, dest, ref destPos);
+ prevInputPos = i + 1;
+ }
+ else if (ch != rsvd && (isUriString ? !IsReservedUnreservedOrHash(ch) : !IsUnreserved(ch)))
+ {
+ dest = EnsureDestinationSize(pStr, dest, i, c_EncodedCharsPerByte,
+ c_MaxAsciiCharsReallocate * c_EncodedCharsPerByte, ref destPos, prevInputPos);
+ EscapeAsciiChar(ch, dest, ref destPos);
+ prevInputPos = i + 1;
+ }
+ }
+
+ if (prevInputPos != i)
+ {
+ // need to fill up the dest array ?
+ if (prevInputPos != start || dest != null)
+ dest = EnsureDestinationSize(pStr, dest, i, 0, 0, ref destPos, prevInputPos);
+ }
+ }
+
+ return dest;
+ }
+
+ //
+ // ensure destination array has enough space and contains all the needed input stuff
+ //
+ private static unsafe char[] EnsureDestinationSize(char* pStr, char[] dest, int currentInputPos,
+ short charsToAdd, short minReallocateChars, ref int destPos, int prevInputPos)
+ {
+ if ((object)dest == null || dest.Length < destPos + (currentInputPos - prevInputPos) + charsToAdd)
+ {
+ // allocating or reallocating array by ensuring enough space based on maxCharsToAdd.
+ char[] newresult = new char[destPos + (currentInputPos - prevInputPos) + minReallocateChars];
+
+ if ((object)dest != null && destPos != 0)
+ Buffer.BlockCopy(dest, 0, newresult, 0, destPos << 1);
+ dest = newresult;
+ }
+
+ // ensuring we copied everything form the input string left before last escaping
+ while (prevInputPos != currentInputPos)
+ dest[destPos++] = pStr[prevInputPos++];
+ return dest;
+ }
+
+ internal static void EscapeAsciiChar(char ch, char[] to, ref int pos)
+ {
+ to[pos++] = '%';
+ to[pos++] = s_hexUpperChars[(ch & 0xf0) >> 4];
+ to[pos++] = s_hexUpperChars[ch & 0xf];
+ }
+
+ internal static char EscapedAscii(char digit, char next)
+ {
+ if (!(((digit >= '0') && (digit <= '9'))
+ || ((digit >= 'A') && (digit <= 'F'))
+ || ((digit >= 'a') && (digit <= 'f'))))
+ {
+ return c_DummyChar;
+ }
+
+ int res = (digit <= '9')
+ ? ((int)digit - (int)'0')
+ : (((digit <= 'F')
+ ? ((int)digit - (int)'A')
+ : ((int)digit - (int)'a'))
+ + 10);
+
+ if (!(((next >= '0') && (next <= '9'))
+ || ((next >= 'A') && (next <= 'F'))
+ || ((next >= 'a') && (next <= 'f'))))
+ {
+ return c_DummyChar;
+ }
+
+ return (char)((res << 4) + ((next <= '9')
+ ? ((int)next - (int)'0')
+ : (((next <= 'F')
+ ? ((int)next - (int)'A')
+ : ((int)next - (int)'a'))
+ + 10)));
+ }
+
+ private static bool IsReservedUnreservedOrHash(char c)
+ {
+ if (IsUnreserved(c))
+ {
+ return true;
+ }
+ return (RFC3986ReservedMarks.Contains(c));
+ }
+
+ internal static bool IsUnreserved(char c)
+ {
+ if (IsAsciiLetterOrDigit(c))
+ {
+ return true;
+ }
+ return (RFC3986UnreservedMarks.Contains(c));
+ }
+
+ //Only consider ASCII characters
+ internal static bool IsAsciiLetter(char character)
+ {
+ return (character >= 'a' && character <= 'z') ||
+ (character >= 'A' && character <= 'Z');
+ }
+
+ internal static bool IsAsciiLetterOrDigit(char character)
+ {
+ return IsAsciiLetter(character) || (character >= '0' && character <= '9');
+ }
+
+ private static readonly char[] s_hexUpperChars = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ internal const char c_DummyChar = (char)0xFFFF; //An Invalid Unicode character used as a dummy char passed into the parameter
+ private const short c_MaxAsciiCharsReallocate = 40;
+ private const short c_MaxUnicodeCharsReallocate = 40;
+ private const short c_MaxUTF_8BytesPerUnicodeChar = 4;
+ private const short c_EncodedCharsPerByte = 3;
+ private const string RFC3986ReservedMarks = @":/?#[]@!$&'()*+,;=";
+ private const string RFC3986UnreservedMarks = @"-._~";
+ }
+}
diff --git a/src/Common/src/CoreLib/System/Resources/ResourceSet.cs b/src/Common/src/CoreLib/System/Resources/ResourceSet.cs
index 2d33f3a8b086..b076f29617b0 100644
--- a/src/Common/src/CoreLib/System/Resources/ResourceSet.cs
+++ b/src/Common/src/CoreLib/System/Resources/ResourceSet.cs
@@ -36,7 +36,7 @@ protected ResourceSet()
{
// To not inconvenience people subclassing us, we should allocate a new
// hashtable here just so that Table is set to something.
- CommonInit();
+ Table = new Hashtable();
}
// For RuntimeResourceSet, ignore the Table parameter - it's a wasted
@@ -50,9 +50,9 @@ internal ResourceSet(bool junk)
// on disk.
//
public ResourceSet(string fileName)
+ : this()
{
Reader = new ResourceReader(fileName);
- CommonInit();
ReadResources();
}
@@ -61,26 +61,21 @@ public ResourceSet(string fileName)
// of data.
//
public ResourceSet(Stream stream)
+ : this()
{
Reader = new ResourceReader(stream);
- CommonInit();
ReadResources();
}
public ResourceSet(IResourceReader reader)
+ : this()
{
if (reader == null)
throw new ArgumentNullException(nameof(reader));
Reader = reader;
- CommonInit();
ReadResources();
}
- private void CommonInit()
- {
- Table = new Hashtable();
- }
-
// Closes and releases any resources used by this ResourceSet, if any.
// All calls to methods on the ResourceSet after a call to close may
// fail. Close is guaranteed to be safely callable multiple times on a
diff --git a/src/Common/src/CoreLib/System/Runtime/CompilerServices/ConditionalWeakTable.cs b/src/Common/src/CoreLib/System/Runtime/CompilerServices/ConditionalWeakTable.cs
index a7ea972b4113..505134a5cc20 100644
--- a/src/Common/src/CoreLib/System/Runtime/CompilerServices/ConditionalWeakTable.cs
+++ b/src/Common/src/CoreLib/System/Runtime/CompilerServices/ConditionalWeakTable.cs
@@ -750,11 +750,9 @@ private void VerifyIntegrity()
~Container()
{
- // We're just freeing per-appdomain unmanaged handles here. If we're already shutting down the AD,
- // don't bother. (Despite its name, Environment.HasShutdownStart also returns true if the current
- // AD is finalizing.) We also skip doing anything if the container is invalid, including if someone
+ // Skip doing anything if the container is invalid, including if somehow
// the container object was allocated but its associated table never set.
- if (Environment.HasShutdownStarted || _invalid || _parent is null)
+ if (_invalid || _parent is null)
{
return;
}
diff --git a/src/Common/src/CoreLib/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/Common/src/CoreLib/System/Runtime/CompilerServices/RuntimeHelpers.cs
index fcb69eceecef..6925d97b9b16 100644
--- a/src/Common/src/CoreLib/System/Runtime/CompilerServices/RuntimeHelpers.cs
+++ b/src/Common/src/CoreLib/System/Runtime/CompilerServices/RuntimeHelpers.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Runtime.Serialization;
+using Internal.Runtime.CompilerServices;
namespace System.Runtime.CompilerServices
{
@@ -13,22 +14,39 @@ public static partial class RuntimeHelpers
public delegate void CleanupCode(object userData, bool exceptionThrown);
///
- /// GetSubArray helper method for the compiler to slice an array using a range.
+ /// Slices the specified array using the specified range.
///
public static T[] GetSubArray(T[] array, Range range)
{
- Type elementType = array.GetType().GetElementType();
- Span source = array.AsSpan(range);
+ if (array == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ (int offset, int length) = range.GetOffsetAndLength(array.Length);
- if (elementType.IsValueType)
+ if (default(T) != null || typeof(T[]) == array.GetType())
{
- return source.ToArray();
+ // We know the type of the array to be exactly T[].
+
+ if (length == 0)
+ {
+ return Array.Empty();
+ }
+
+ var dest = new T[length];
+ Buffer.Memmove(
+ ref Unsafe.As(ref dest.GetRawSzArrayData()),
+ ref Unsafe.Add(ref Unsafe.As(ref array.GetRawSzArrayData()), offset),
+ (uint)length);
+ return dest;
}
else
{
- T[] newArray = (T[])Array.CreateInstance(elementType, source.Length);
- source.CopyTo(newArray);
- return newArray;
+ // The array is actually a U[] where U:T.
+ T[] dest = (T[])Array.CreateInstance(array.GetType().GetElementType(), length);
+ Array.Copy(array, offset, dest, 0, length);
+ return dest;
}
}
@@ -38,7 +56,7 @@ public static object GetUninitializedObject(Type type)
{
throw new ArgumentNullException(nameof(type), SR.ArgumentNull_Type);
}
-
+
if (!type.IsRuntimeImplemented())
{
throw new SerializationException(SR.Format(SR.Serialization_InvalidType, type.ToString()));
@@ -63,4 +81,4 @@ public static void PrepareConstrainedRegionsNoOP()
{
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Common/src/CoreLib/System/Runtime/InteropServices/Marshal.cs b/src/Common/src/CoreLib/System/Runtime/InteropServices/Marshal.cs
index 99ab1010c73f..65d4b4fc6a4b 100644
--- a/src/Common/src/CoreLib/System/Runtime/InteropServices/Marshal.cs
+++ b/src/Common/src/CoreLib/System/Runtime/InteropServices/Marshal.cs
@@ -57,7 +57,7 @@ public static unsafe string PtrToStringAnsi(IntPtr ptr, int len)
}
if (len < 0)
{
- throw new ArgumentException(null, nameof(len));
+ throw new ArgumentOutOfRangeException(nameof(len), len, SR.ArgumentOutOfRange_NeedNonNegNum);
}
return new string((sbyte*)ptr, 0, len);
@@ -81,7 +81,7 @@ public static unsafe string PtrToStringUni(IntPtr ptr, int len)
}
if (len < 0)
{
- throw new ArgumentException(SR.ArgumentOutOfRange_NeedNonNegNum, nameof(len));
+ throw new ArgumentOutOfRangeException(nameof(len), len, SR.ArgumentOutOfRange_NeedNonNegNum);
}
return new string((char*)ptr, 0, len);
@@ -89,7 +89,7 @@ public static unsafe string PtrToStringUni(IntPtr ptr, int len)
public static unsafe string PtrToStringUTF8(IntPtr ptr)
{
- if (ptr == IntPtr.Zero)
+ if (ptr == IntPtr.Zero || IsWin32Atom(ptr))
{
return null;
}
@@ -100,14 +100,13 @@ public static unsafe string PtrToStringUTF8(IntPtr ptr)
public static unsafe string PtrToStringUTF8(IntPtr ptr, int byteLen)
{
- if (byteLen < 0)
+ if (ptr == IntPtr.Zero)
{
- throw new ArgumentOutOfRangeException(nameof(byteLen), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentNullException(nameof(ptr));
}
-
- if (ptr == IntPtr.Zero || IsWin32Atom(ptr))
+ if (byteLen < 0)
{
- return null;
+ throw new ArgumentOutOfRangeException(nameof(byteLen), byteLen, SR.ArgumentOutOfRange_NeedNonNegNum);
}
return string.CreateStringFromEncoding((byte*)ptr, byteLen, Encoding.UTF8);
diff --git a/src/Common/src/CoreLib/System/Runtime/InteropServices/MarshalAsAttribute.cs b/src/Common/src/CoreLib/System/Runtime/InteropServices/MarshalAsAttribute.cs
index 4a64050ed109..816a4627e599 100644
--- a/src/Common/src/CoreLib/System/Runtime/InteropServices/MarshalAsAttribute.cs
+++ b/src/Common/src/CoreLib/System/Runtime/InteropServices/MarshalAsAttribute.cs
@@ -5,7 +5,7 @@
namespace System.Runtime.InteropServices
{
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.ReturnValue, Inherited = false)]
- public sealed class MarshalAsAttribute : Attribute
+ public sealed partial class MarshalAsAttribute : Attribute
{
public MarshalAsAttribute(UnmanagedType unmanagedType)
{
diff --git a/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Aes.PlatformNotSupported.cs b/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Aes.PlatformNotSupported.cs
index ba9c310a6359..086589389f3a 100644
--- a/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Aes.PlatformNotSupported.cs
+++ b/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Aes.PlatformNotSupported.cs
@@ -17,7 +17,8 @@ namespace System.Runtime.Intrinsics.Arm.Arm64
[CLSCompliant(false)]
public static class Aes
{
- public static bool IsSupported { get { return false; } }
+ public static bool IsSupported { [Intrinsic] get { return false; } }
+
///
/// Performs AES single round decryption
/// vaesdq_u8 (uint8x16_t data, uint8x16_t key)
diff --git a/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Base.PlatformNotSupported.cs b/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Base.PlatformNotSupported.cs
index a74e23829f54..99fabb0a6a97 100644
--- a/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Base.PlatformNotSupported.cs
+++ b/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Base.PlatformNotSupported.cs
@@ -16,7 +16,7 @@ namespace System.Runtime.Intrinsics.Arm.Arm64
[CLSCompliant(false)]
public static class Base
{
- public static bool IsSupported { get { return false; }}
+ public static bool IsSupported { [Intrinsic] get { return false; }}
///
/// Vector LeadingSignCount
diff --git a/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Sha1.PlatformNotSupported.cs b/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Sha1.PlatformNotSupported.cs
index 16a73c639364..61474ea3826f 100644
--- a/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Sha1.PlatformNotSupported.cs
+++ b/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Sha1.PlatformNotSupported.cs
@@ -17,8 +17,7 @@ namespace System.Runtime.Intrinsics.Arm.Arm64
[CLSCompliant(false)]
public static class Sha1
{
-
- public static bool IsSupported { get { return false; } }
+ public static bool IsSupported { [Intrinsic] get { return false; } }
///
/// Performs SHA1 hash update choose form.
diff --git a/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Sha256.PlatformNotSupported.cs b/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Sha256.PlatformNotSupported.cs
index f56cfa4597d9..2fbaf05eda84 100644
--- a/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Sha256.PlatformNotSupported.cs
+++ b/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Sha256.PlatformNotSupported.cs
@@ -17,7 +17,7 @@ namespace System.Runtime.Intrinsics.Arm.Arm64
[CLSCompliant(false)]
public static class Sha256
{
- public static bool IsSupported { get { return false; } }
+ public static bool IsSupported { [Intrinsic] get { return false; } }
///
/// Performs SHA256 hash update (part 1).
diff --git a/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Simd.PlatformNotSupported.cs b/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Simd.PlatformNotSupported.cs
index cefa1ed37ce8..e7184b5739f6 100644
--- a/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Simd.PlatformNotSupported.cs
+++ b/src/Common/src/CoreLib/System/Runtime/Intrinsics/Arm/Arm64/Simd.PlatformNotSupported.cs
@@ -21,7 +21,7 @@ public static class Simd
/// IsSupported property indicates whether any method provided
/// by this class is supported by the current runtime.
///
- public static bool IsSupported { get { return false; }}
+ public static bool IsSupported { [Intrinsic] get { return false; }}
///
/// Vector abs
diff --git a/src/Common/src/CoreLib/System/Runtime/Intrinsics/Vector256_1.cs b/src/Common/src/CoreLib/System/Runtime/Intrinsics/Vector256_1.cs
index 903d2cd9410c..e0ab5c28bfec 100644
--- a/src/Common/src/CoreLib/System/Runtime/Intrinsics/Vector256_1.cs
+++ b/src/Common/src/CoreLib/System/Runtime/Intrinsics/Vector256_1.cs
@@ -105,13 +105,13 @@ public bool Equals(Vector256 other)
{
if (typeof(T) == typeof(float))
{
- Vector256 result = Avx.Compare(this.AsSingle(), other.AsSingle(), FloatComparisonMode.EqualOrderedNonSignaling);
+ Vector256 result = Avx.Compare(this.AsSingle(), other.AsSingle(), FloatComparisonMode.OrderedEqualNonSignaling);
return Avx.MoveMask(result) == 0b1111_1111; // We have one bit per element
}
if (typeof(T) == typeof(double))
{
- Vector256 result = Avx.Compare(this.AsDouble(), other.AsDouble(), FloatComparisonMode.EqualOrderedNonSignaling);
+ Vector256 result = Avx.Compare(this.AsDouble(), other.AsDouble(), FloatComparisonMode.OrderedEqualNonSignaling);
return Avx.MoveMask(result) == 0b1111; // We have one bit per element
}
}
diff --git a/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Aes.PlatformNotSupported.cs b/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Aes.PlatformNotSupported.cs
index 1a0dc5e8f0fa..3d261d7c6698 100644
--- a/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Aes.PlatformNotSupported.cs
+++ b/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Aes.PlatformNotSupported.cs
@@ -4,6 +4,7 @@
#nullable enable
using System;
+using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
namespace System.Runtime.Intrinsics.X86
@@ -16,7 +17,7 @@ public abstract class Aes : Sse2
{
internal Aes() { }
- public new static bool IsSupported { get { return false; } }
+ public new static bool IsSupported { [Intrinsic] get { return false; } }
///
/// __m128i _mm_aesdec_si128 (__m128i a, __m128i RoundKey)
diff --git a/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Avx.PlatformNotSupported.cs b/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Avx.PlatformNotSupported.cs
index 97d545dc3b92..a873913579d9 100644
--- a/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Avx.PlatformNotSupported.cs
+++ b/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Avx.PlatformNotSupported.cs
@@ -4,6 +4,7 @@
#nullable enable
using System;
+using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
namespace System.Runtime.Intrinsics.X86
@@ -16,7 +17,7 @@ public abstract class Avx : Sse42
{
internal Avx() { }
- public new static bool IsSupported { get { return false; } }
+ public new static bool IsSupported { [Intrinsic] get { return false; } }
///
/// __m256 _mm256_add_ps (__m256 a, __m256 b)
diff --git a/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs b/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs
index ad2244b7b1c3..2696c866b799 100644
--- a/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs
+++ b/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs
@@ -4,6 +4,7 @@
#nullable enable
using System;
+using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
namespace System.Runtime.Intrinsics.X86
@@ -16,7 +17,7 @@ public abstract class Avx2 : Avx
{
internal Avx2() { }
- public new static bool IsSupported { get { return false; } }
+ public new static bool IsSupported { [Intrinsic] get { return false; } }
///
/// __m256i _mm256_abs_epi8 (__m256i a)
@@ -673,64 +674,125 @@ internal Avx2() { }
///
/// __m256i _mm256_cvtepi8_epi16 (__m128i a)
- /// VPMOVSXBW ymm, xmm/m128
+ /// VPMOVSXBW ymm, xmm
///
public static Vector256 ConvertToVector256Int16(Vector128 value) { throw new PlatformNotSupportedException(); }
///
/// __m256i _mm256_cvtepu8_epi16 (__m128i a)
- /// VPMOVZXBW ymm, xmm/m128
+ /// VPMOVZXBW ymm, xmm
///
- public static Vector256 ConvertToVector256UInt16(Vector128 value) { throw new PlatformNotSupportedException(); }
+ public static Vector256 ConvertToVector256Int16(Vector128 value) { throw new PlatformNotSupportedException(); }
///
/// __m256i _mm256_cvtepi8_epi32 (__m128i a)
- /// VPMOVSXBD ymm, xmm/m128
+ /// VPMOVSXBD ymm, xmm
///
public static Vector256 ConvertToVector256Int32(Vector128 value) { throw new PlatformNotSupportedException(); }
///
- /// __m256i _mm256_cvtepi16_epi32 (__m128i a)
- /// VPMOVSXWD ymm, xmm/m128
+ /// __m256i _mm256_cvtepu8_epi32 (__m128i a)
+ /// VPMOVZXBD ymm, xmm
///
- public static Vector256 ConvertToVector256Int32(Vector128 value) { throw new PlatformNotSupportedException(); }
+ public static Vector256 ConvertToVector256Int32(Vector128 value) { throw new PlatformNotSupportedException(); }
///
- /// __m256i _mm256_cvtepu8_epi32 (__m128i a)
- /// VPMOVZXBD ymm, xmm/m128
+ /// __m256i _mm256_cvtepi16_epi32 (__m128i a)
+ /// VPMOVSXWD ymm, xmm
///
- public static Vector256 ConvertToVector256UInt32(Vector128 value) { throw new PlatformNotSupportedException(); }
+ public static Vector256 ConvertToVector256Int32(Vector128 value) { throw new PlatformNotSupportedException(); }
///
/// __m256i _mm256_cvtepu16_epi32 (__m128i a)
- /// VPMOVZXWD ymm, xmm/m128
+ /// VPMOVZXWD ymm, xmm
///
- public static Vector256 ConvertToVector256UInt32(Vector128 value) { throw new PlatformNotSupportedException(); }
+ public static Vector256 ConvertToVector256Int32(Vector128 value) { throw new PlatformNotSupportedException(); }
///
/// __m256i _mm256_cvtepi8_epi64 (__m128i a)
- /// VPMOVSXBQ ymm, xmm/m128
+ /// VPMOVSXBQ ymm, xmm
///
public static Vector256 ConvertToVector256Int64(Vector128 value) { throw new PlatformNotSupportedException(); }
///
+ /// __m256i _mm256_cvtepu8_epi64 (__m128i a)
+ /// VPMOVZXBQ ymm, xmm
+ ///
+ public static Vector256 ConvertToVector256Int64(Vector128 value) { throw new PlatformNotSupportedException(); }
+ ///
/// __m256i _mm256_cvtepi16_epi64 (__m128i a)
- /// VPMOVSXWQ ymm, xmm/m128
+ /// VPMOVSXWQ ymm, xmm
///
public static Vector256 ConvertToVector256Int64(Vector128 value) { throw new PlatformNotSupportedException(); }
///
+ /// __m256i _mm256_cvtepu16_epi64 (__m128i a)
+ /// VPMOVZXWQ ymm, xmm
+ ///
+ public static Vector256 ConvertToVector256Int64(Vector128 value) { throw new PlatformNotSupportedException(); }
+ ///
/// __m256i _mm256_cvtepi32_epi64 (__m128i a)
- /// VPMOVSXDQ ymm, xmm/m128
+ /// VPMOVSXDQ ymm, xmm
///
public static Vector256 ConvertToVector256Int64(Vector128 value) { throw new PlatformNotSupportedException(); }
///
- /// __m256i _mm256_cvtepu8_epi64 (__m128i a)
- /// VPMOVZXBQ ymm, xmm/m128
+ /// __m256i _mm256_cvtepu32_epi64 (__m128i a)
+ /// VPMOVZXDQ ymm, xmm
///
- public static Vector256 ConvertToVector256UInt64(Vector128 value) { throw new PlatformNotSupportedException(); }
+ public static Vector256 ConvertToVector256Int64(Vector128 value) { throw new PlatformNotSupportedException(); }
+
///
- /// __m256i _mm256_cvtepu16_epi64 (__m128i a)
- /// VPMOVZXWQ ymm, xmm/m128
+ /// VPMOVSXBW ymm, m128
+ /// The native signature does not exist. We provide this additional overload for completeness.
///
- public static Vector256 ConvertToVector256UInt64(Vector128 value) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector256 ConvertToVector256Int16(sbyte* address) { throw new PlatformNotSupportedException(); }
///
- /// __m256i _mm256_cvtepu32_epi64 (__m128i a)
- /// VPMOVZXDQ ymm, xmm/m128
+ /// VPMOVZXBW ymm, m128
+ /// The native signature does not exist. We provide this additional overload for completeness.
+ ///
+ public static unsafe Vector256 ConvertToVector256Int16(byte* address) { throw new PlatformNotSupportedException(); }
+ ///
+ /// VPMOVSXBD ymm, m64
+ /// The native signature does not exist. We provide this additional overload for completeness.
+ ///
+ public static unsafe Vector256 ConvertToVector256Int32(sbyte* address) { throw new PlatformNotSupportedException(); }
+ ///
+ /// VPMOVZXBD ymm, m64
+ /// The native signature does not exist. We provide this additional overload for completeness.
+ ///
+ public static unsafe Vector256 ConvertToVector256Int32(byte* address) { throw new PlatformNotSupportedException(); }
+ ///
+ /// VPMOVSXWD ymm, m128
+ /// The native signature does not exist. We provide this additional overload for completeness.
+ ///
+ public static unsafe Vector256 ConvertToVector256Int32(short* address) { throw new PlatformNotSupportedException(); }
+ ///
+ /// VPMOVZXWD ymm, m128
+ /// The native signature does not exist. We provide this additional overload for completeness.
+ ///
+ public static unsafe Vector256 ConvertToVector256Int32(ushort* address) { throw new PlatformNotSupportedException(); }
+ ///
+ /// VPMOVSXBQ ymm, m32
+ /// The native signature does not exist. We provide this additional overload for completeness.
+ ///
+ public static unsafe Vector256 ConvertToVector256Int64(sbyte* address) { throw new PlatformNotSupportedException(); }
+ ///
+ /// VPMOVZXBQ ymm, m32
+ /// The native signature does not exist. We provide this additional overload for completeness.
+ ///
+ public static unsafe Vector256 ConvertToVector256Int64(byte* address) { throw new PlatformNotSupportedException(); }
+ ///
+ /// VPMOVSXWQ ymm, m64
+ /// The native signature does not exist. We provide this additional overload for completeness.
+ ///
+ public static unsafe Vector256 ConvertToVector256Int64(short* address) { throw new PlatformNotSupportedException(); }
+ ///
+ /// VPMOVZXWQ ymm, m64
+ /// The native signature does not exist. We provide this additional overload for completeness.
+ ///
+ public static unsafe Vector256 ConvertToVector256Int64(ushort* address) { throw new PlatformNotSupportedException(); }
+ ///
+ /// VPMOVSXDQ ymm, m128
+ /// The native signature does not exist. We provide this additional overload for completeness.
+ ///
+ public static unsafe Vector256 ConvertToVector256Int64(int* address) { throw new PlatformNotSupportedException(); }
+ ///
+ /// VPMOVZXDQ ymm, m128
+ /// The native signature does not exist. We provide this additional overload for completeness.
///
- public static Vector256 ConvertToVector256UInt64(Vector128 value) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector256 ConvertToVector256Int64(uint* address) { throw new PlatformNotSupportedException(); }
///
/// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
diff --git a/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Avx2.cs b/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Avx2.cs
index 33b101b96211..9b6f2a61622c 100644
--- a/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Avx2.cs
+++ b/src/Common/src/CoreLib/System/Runtime/Intrinsics/X86/Avx2.cs
@@ -674,64 +674,125 @@ internal Avx2() { }
///
/// __m256i _mm256_cvtepi8_epi16 (__m128i a)
- /// VPMOVSXBW ymm, xmm/m128
+ /// VPMOVSXBW ymm, xmm
///
public static Vector256 ConvertToVector256Int16(Vector128 value) => ConvertToVector256Int16(value);
///
/// __m256i _mm256_cvtepu8_epi16 (__m128i a)
- /// VPMOVZXBW ymm, xmm/m128
+ /// VPMOVZXBW ymm, xmm
///
- public static Vector256 ConvertToVector256UInt16(Vector128 value) => ConvertToVector256UInt16(value);
+ public static Vector256 ConvertToVector256Int16(Vector128 value) => ConvertToVector256Int16(value);
///
/// __m256i _mm256_cvtepi8_epi32 (__m128i a)
- /// VPMOVSXBD ymm, xmm/m128
+ /// VPMOVSXBD ymm, xmm
///
public static Vector256 ConvertToVector256Int32(Vector128 value) => ConvertToVector256Int32(value);
///