diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 5e9013310e4e9..d731c6dd1f16d 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "1.0.0-prerelease.21501.2", + "version": "1.0.0-prerelease.21511.3", "commands": [ "xharness" ] diff --git a/.github/ISSUE_TEMPLATE/01_bug_report.yml b/.github/ISSUE_TEMPLATE/01_bug_report.yml index ee28f6b233a15..4aa6545ec43bd 100644 --- a/.github/ISSUE_TEMPLATE/01_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/01_bug_report.yml @@ -5,7 +5,7 @@ body: - type: markdown attributes: value: | - We welcome bug reports! Please see our [contribution guidelines](https://github.com/dotnet/runtime/blob/main/CONTRIBUTING.md) for more information on writing a good bug report. This template will help us gather the information we need to start the triage process. + We welcome bug reports! Please see our [contribution guidelines](https://github.com/dotnet/runtime/blob/main/CONTRIBUTING.md#writing-a-good-bug-report) for more information on writing a good bug report. This template will help us gather the information we need to start the triage process. - type: textarea id: background attributes: diff --git a/.github/ISSUE_TEMPLATE/02_api_proposal.yml b/.github/ISSUE_TEMPLATE/02_api_proposal.yml index 1462b38ad80d4..145095e3bb42b 100644 --- a/.github/ISSUE_TEMPLATE/02_api_proposal.yml +++ b/.github/ISSUE_TEMPLATE/02_api_proposal.yml @@ -55,6 +55,15 @@ body: ``` validations: required: true + - type: textarea + id: alternative-designs + attributes: + label: Alternative Designs + description: | + Please provide alternative designs. This might not be APIs; for example instead of providing new APIs an option might be to change the behavior of an existing API. + placeholder: Alternative designs + validations: + required: false - type: textarea id: risks attributes: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0b5c363bdc32c..9b87e2ce453d9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,9 +1,63 @@ -Contribution to .NET Runtime -===================== +# Contribution to .NET Runtime You can contribute to .NET Runtime with issues and PRs. Simply filing issues for problems you encounter is a great way to contribute. Contributing implementations is greatly appreciated. -## Contribution "Bar" +## Reporting Issues + +We always welcome bug reports, API proposals and overall feedback. Here are a few tips on how you can make reporting your issue as effective as possible. + +### Identify Where to Report + +The .NET codebase is distributed across multiple repositories in the [dotnet organization](https://github.com/dotnet). Depending on the feedback you might want to file the issue on a different repo. Here are a few common repos: + +* [dotnet/runtime](https://github.com/dotnet/runtime) .NET runtime, libraries and shared host installers. +* [dotnet/roslyn](https://github.com/dotnet/roslyn) C# and VB compiler. +* [dotnet/aspnetcore](https://github.com/dotnet/aspnetcore) ASP.NET Core. +* [dotnet/core](https://github.com/dotnet/core) Can be used to submit feedback if not sure what repo to use. + +### Finding Existing Issues + +Before filing a new issue, please search our [open issues](https://github.com/dotnet/runtime/issues) to check if it already exists. + +If you do find an existing issue, please include your own feedback in the discussion. Do consider upvoting (👍 reaction) the original post, as this helps us prioritize popular issues in our backlog. + +### Writing a Good API Proposal + +Please review our [API review process](https://github.com/dotnet/runtime/blob/main/docs/project/api-review-process.md) documents for guidelines on how to submit an API review. When ready to submit a proposal, please use the [API Suggestion issue template](https://github.com/dotnet/runtime/issues/new?assignees=&labels=api-suggestion&template=02_api_proposal.yml&title=%5BAPI+Proposal%5D%3A+). + +### Writing a Good Bug Report + +Good bug reports make it easier for maintainers to verify and root cause the underlying problem. The better a bug report, the faster the problem will be resolved. Ideally, a bug report should contain the following information: + +* A high-level description of the problem. +* A _minimal reproduction_, i.e. the smallest size of code/configuration required to reproduce the wrong behavior. +* A description of the _expected behavior_, contrasted with the _actual behavior_ observed. +* Information on the environment: OS/distro, CPU arch, SDK version, etc. +* Additional information, e.g. is it a regression from previous versions? are there any known workarounds? + +When ready to submit a bug report, please use the [Bug Report issue template](https://github.com/dotnet/runtime/issues/new?assignees=&labels=&template=01_bug_report.yml). + +#### Why are Minimal Reproductions Important? + +A reproduction lets maintainers verify the presence of a bug, and diagnose the issue using a debugger. A _minimal_ reproduction is the smallest possible console application demonstrating that bug. Minimal reproductions are generally preferable since they: + +1. Focus debugging efforts on a simple code snippet, +2. Ensure that the problem is not caused by unrelated dependencies/configuration, +3. Avoid the need to share production codebases. + +#### Are Minimal Reproductions Required? + +In certain cases, creating a minimal reproduction might not be practical (e.g. due to nondeterministic factors, external dependencies). In such cases you would be asked to provide as much information as possible, for example by sharing a memory dump of the failing application. If maintainers are unable to root cause the problem, they might still close the issue as not actionable. While not required, minimal reproductions are strongly encouraged and will significantly improve the chances of your issue being prioritized and fixed by the maintainers. + +#### How to Create a Minimal Reproduction + +The best way to create a minimal reproduction is gradually removing code and dependencies from a reproducing app, until the problem no longer occurs. A good minimal reproduction: + +* Excludes all unnecessary types, methods, code blocks, source files, nuget dependencies and project configurations. +* Contains documentation or code comments illustrating expected vs actual behavior. +* If possible, avoids performing any unneeded IO or system calls. For example, can the ASP.NET based reproduction be converted to a plain old console app? + +## Contributing Changes Project maintainers will merge changes that improve the product significantly and broadly align with the [.NET Roadmap](https://github.com/dotnet/core/blob/master/roadmap.md). @@ -11,7 +65,7 @@ Maintainers will not merge changes that have narrowly-defined benefits, due to c Contributions must also satisfy the other published guidelines defined in this document. -## DOs and DON'Ts +### DOs and DON'Ts Please do: @@ -33,11 +87,11 @@ Please do not: * **DON'T** submit PRs that alter licensing related files or headers. If you believe there's a problem with them, file an issue and we'll be happy to discuss it. * **DON'T** add API additions without filing an issue and discussing with us first. See [API Review Process](docs/project/api-review-process.md). -## Breaking Changes +### Breaking Changes Contributions must maintain [API signature](docs/coding-guidelines/breaking-changes.md#bucket-1-public-contract) and behavioral compatibility. Contributions that include [breaking changes](docs/coding-guidelines/breaking-changes.md) will be rejected. Please file an issue to discuss your idea or change if you believe that it may affect managed code compatibility. -## Suggested Workflow +### Suggested Workflow We use and recommend the following workflow: @@ -67,11 +121,11 @@ We use and recommend the following workflow: - The next official build will automatically include your change. - You can delete the branch you used for making the change. -## Up for Grabs +### Up for Grabs The team marks the most straightforward issues as [up for grabs](https://github.com/dotnet/runtime/labels/up-for-grabs). This set of issues is the place to start if you are interested in contributing but new to the codebase. -## Commit Messages +### Commit Messages Please format commit messages as follows (based on [A Note About Git Commit Messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)): @@ -90,7 +144,7 @@ Fix #42 Also do your best to factor commits appropriately, not too large with unrelated things in the same commit, and not too small with the same small change applied N times in N different commits. -## Contributor License Agreement +### Contributor License Agreement You must sign a [.NET Foundation Contribution License Agreement (CLA)](https://cla.dotnetfoundation.org) before your PR will be merged. This is a one-time requirement for projects in the .NET Foundation. You can read more about [Contribution License Agreements (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) on Wikipedia. @@ -98,7 +152,7 @@ The agreement: [net-foundation-contribution-license-agreement.pdf](https://githu You don't have to do this up-front. You can simply clone, fork, and submit your pull-request as usual. When your pull-request is created, it is classified by a CLA bot. If the change is trivial (for example, you just fixed a typo), then the PR is labelled with `cla-not-required`. Otherwise it's classified as `cla-required`. Once you signed a CLA, the current and all future pull-requests will be labelled as `cla-signed`. -## File Headers +### File Headers The following file header is the used for .NET Core. Please use it for new files. @@ -110,13 +164,13 @@ The following file header is the used for .NET Core. Please use it for new files - See [class.cpp](./src/coreclr/vm/class.cpp) for an example of the header in a C++ file. - See [List.cs](./src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs) for an example of the header in a C# file. -## PR - CI Process +### PR - CI Process The [dotnet continuous integration](https://dev.azure.com/dnceng/public/) (CI) system will automatically perform the required builds and run tests (including the ones you are expected to run) for PRs. Builds and test runs must be clean. If the CI build fails for any reason, the PR issue will be updated with a link that can be used to determine the cause of the failure. -## PR Feedback +### PR Feedback Microsoft team and community members will provide feedback on your change. Community feedback is highly valued. You will often see the absence of team feedback if the community has already provided good review feedback. @@ -124,7 +178,7 @@ One or more Microsoft team members will review every PR prior to merge. They wil There are lots of thoughts and [approaches](https://github.com/antlr/antlr4-cpp/blob/master/CONTRIBUTING.md#emoji) for how to efficiently discuss changes. It is best to be clear and explicit with your feedback. Please be patient with people who might not understand the finer details about your approach to feedback. -## Contributing Ports +### Contributing Ports We encourage ports of CoreCLR to other platforms. There are multiple ports ongoing at any one time. You may be interested in one of the following ports: @@ -145,7 +199,7 @@ Note: Add links to install instructions for each of these ports. Ports have a weaker contribution bar, at least initially. A functionally correct implementation is considered an important first goal. Performance, reliability and compatibility are all important concerns after that. -### Copying Files from Other Projects +#### Copying Files from Other Projects .NET Core uses some files from other projects, typically where a binary distribution does not exist or would be inconvenient. @@ -157,7 +211,7 @@ The following rules must be followed for PRs that include files from another pro See [IdnMapping.cs](./src/libraries/System.Private.CoreLib/src/System/Globalization/IdnMapping.cs) for an example of a file copied from another project and attributed in the [CoreCLR 3rd party notices](./THIRD-PARTY-NOTICES.TXT) file. -### Porting Files from Other Projects +#### Porting Files from Other Projects There are many good algorithms implemented in other languages that would benefit the .NET Core project. The rules for porting a Java file to C#, for example, are the same as would be used for copying the same file, as described above. diff --git a/Directory.Build.props b/Directory.Build.props index 42d713f8e0d22..92bcbf935a9c5 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -62,6 +62,8 @@ net462 net472 + + diff --git a/README.md b/README.md index 1444df567a8e1..350b72cc5b2c9 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Official Starting Page: https://dotnet.microsoft.com/ We welcome contributions! Many people all over the world have helped make this project better. -* [Contributing](CONTRIBUTING.md) explains what kinds of changes we welcome +* [Contributing](CONTRIBUTING.md) explains what kinds of contributions we welcome - [Workflow Instructions](docs/workflow/README.md) explains how to build and test * [Get Up and Running on .NET Core](docs/project/dogfooding.md) explains how to get nightly builds of the runtime and its libraries to test them in your own projects. diff --git a/docs/workflow/testing/mono/testing.md b/docs/workflow/testing/mono/testing.md index 4c37f634de45c..8a03414e02a18 100644 --- a/docs/workflow/testing/mono/testing.md +++ b/docs/workflow/testing/mono/testing.md @@ -20,6 +20,10 @@ cd src/tests ./build.sh excludemonofailures ``` +To build an individual test, test directory, or a whole subdirectory tree, use the `-test:`, `-dir:` or `-tree:` options (without the src/tests prefix) +For example: `./build.sh excludemonofailures release -test:JIT/opt/InstructionCombining/DivToMul.csproj` + + Run individual test: ``` cd src/mono @@ -32,6 +36,24 @@ cd src/mono make run-tests-coreclr-all ``` +To debug a single test with `lldb`: + +1. Run the test at least once normally (or manually run the `mono.proj` `PatchCoreClrCoreRoot` target) +2. Edit the `.sh` file for the test and change the line +``` + LAUNCHER="$_DebuggerFullPath "$CORE_ROOT/corerun" -p "System.Reflection.Metadata.MetadataUpdater.IsSupported=false" ${__DotEnvArg}" +``` +to add `--` after the debugger full path +``` + LAUNCHER="$_DebuggerFullPath -- "$CORE_ROOT/corerun" -p "System.Reflection.Metadata.MetadataUpdater.IsSupported=false" ${__DotEnvArg}" +``` +3. Run the shell script for the test case manually: +``` +bash ./artifacts/tests/coreclr/OSX.x64.Release/JIT/opt/InstructionCombining/DivToMul/DivToMul.sh -coreroot=`pwd`/artifacts/tests/coreclr/OSX.x64.Release/Tests/Core_Root -debug=/usr/bin/lldb +``` +4. In LLDB add the debug symbols for mono: `add-dsym /libcoreclr.dylib.dwarf` +5. Run/debug the test + ### WebAssembly: Build the runtime tests for WebAssembly ``` diff --git a/eng/Subsets.props b/eng/Subsets.props index 3fd61d12f163b..7638fc78f5901 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -72,7 +72,7 @@ host.native packs.product - $(DefaultPacksSubsets)+packs.tests + $(DefaultPacksSubsets)+packs.tests $(DefaultPacksSubsets)+packs.installers diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 44b371499f890..ab38b44b996af 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,12 +1,12 @@ - + https://github.com/dotnet/icu - 848e383f845cee4ab9edb8b20b40154910792599 + ca9a6d29a62dd66925f5377d09b3d7e6afb2acd5 - + https://github.com/dotnet/msquic - 9b90833648c8f4f24bb79f362562779667888068 + feebeb23023b2806e5c6604e751b699fa8e83424 https://github.com/dotnet/emsdk @@ -18,229 +18,229 @@ - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc https://github.com/microsoft/vstest 140434f7109d357d0158ade9e5164a4861513965 - + https://github.com/dotnet/runtime-assets - 426f10a0dcb1a9b5fa3bf5901f88bd3a54ccaa0a + f800c64524ca148d3a5e8e9204fcbc9cf5055148 - + https://github.com/dotnet/runtime-assets - 426f10a0dcb1a9b5fa3bf5901f88bd3a54ccaa0a + f800c64524ca148d3a5e8e9204fcbc9cf5055148 - + https://github.com/dotnet/runtime-assets - 426f10a0dcb1a9b5fa3bf5901f88bd3a54ccaa0a + f800c64524ca148d3a5e8e9204fcbc9cf5055148 - + https://github.com/dotnet/runtime-assets - 426f10a0dcb1a9b5fa3bf5901f88bd3a54ccaa0a + f800c64524ca148d3a5e8e9204fcbc9cf5055148 - + https://github.com/dotnet/runtime-assets - 426f10a0dcb1a9b5fa3bf5901f88bd3a54ccaa0a + f800c64524ca148d3a5e8e9204fcbc9cf5055148 - + https://github.com/dotnet/runtime-assets - 426f10a0dcb1a9b5fa3bf5901f88bd3a54ccaa0a + f800c64524ca148d3a5e8e9204fcbc9cf5055148 - + https://github.com/dotnet/runtime-assets - 426f10a0dcb1a9b5fa3bf5901f88bd3a54ccaa0a + f800c64524ca148d3a5e8e9204fcbc9cf5055148 - + https://github.com/dotnet/runtime-assets - 426f10a0dcb1a9b5fa3bf5901f88bd3a54ccaa0a + f800c64524ca148d3a5e8e9204fcbc9cf5055148 - + https://github.com/dotnet/runtime-assets - 426f10a0dcb1a9b5fa3bf5901f88bd3a54ccaa0a + f800c64524ca148d3a5e8e9204fcbc9cf5055148 - + https://github.com/dotnet/runtime-assets - 426f10a0dcb1a9b5fa3bf5901f88bd3a54ccaa0a + f800c64524ca148d3a5e8e9204fcbc9cf5055148 - + https://github.com/dotnet/llvm-project - fadaad69ceb75cd54372336dde2193a39348e740 + e20c0dbcf2fdc8979584b178cafd01db37121d64 - + https://github.com/dotnet/llvm-project - fadaad69ceb75cd54372336dde2193a39348e740 + e20c0dbcf2fdc8979584b178cafd01db37121d64 - + https://github.com/dotnet/llvm-project - fadaad69ceb75cd54372336dde2193a39348e740 + e20c0dbcf2fdc8979584b178cafd01db37121d64 - + https://github.com/dotnet/llvm-project - fadaad69ceb75cd54372336dde2193a39348e740 + e20c0dbcf2fdc8979584b178cafd01db37121d64 - + https://github.com/dotnet/llvm-project - fadaad69ceb75cd54372336dde2193a39348e740 + e20c0dbcf2fdc8979584b178cafd01db37121d64 - + https://github.com/dotnet/llvm-project - fadaad69ceb75cd54372336dde2193a39348e740 + e20c0dbcf2fdc8979584b178cafd01db37121d64 - + https://github.com/dotnet/llvm-project - fadaad69ceb75cd54372336dde2193a39348e740 + e20c0dbcf2fdc8979584b178cafd01db37121d64 - + https://github.com/dotnet/llvm-project - fadaad69ceb75cd54372336dde2193a39348e740 + e20c0dbcf2fdc8979584b178cafd01db37121d64 - + https://github.com/dotnet/runtime - 78ac8430e8480742181170eef91a6fb016535aa4 + 565ff522bf630ff0556f3dc590dcb7337696a5d4 - + https://github.com/dotnet/runtime - 78ac8430e8480742181170eef91a6fb016535aa4 + 565ff522bf630ff0556f3dc590dcb7337696a5d4 - + https://github.com/dotnet/runtime - 78ac8430e8480742181170eef91a6fb016535aa4 + 565ff522bf630ff0556f3dc590dcb7337696a5d4 - + https://github.com/dotnet/runtime - 78ac8430e8480742181170eef91a6fb016535aa4 + 565ff522bf630ff0556f3dc590dcb7337696a5d4 - + https://github.com/dotnet/runtime - 78ac8430e8480742181170eef91a6fb016535aa4 + 565ff522bf630ff0556f3dc590dcb7337696a5d4 - + https://github.com/dotnet/runtime - 78ac8430e8480742181170eef91a6fb016535aa4 + 565ff522bf630ff0556f3dc590dcb7337696a5d4 - + https://github.com/dotnet/runtime - 78ac8430e8480742181170eef91a6fb016535aa4 + 565ff522bf630ff0556f3dc590dcb7337696a5d4 - + https://github.com/dotnet/runtime - 78ac8430e8480742181170eef91a6fb016535aa4 + 565ff522bf630ff0556f3dc590dcb7337696a5d4 - + https://github.com/dotnet/linker - b0b20476551dacaf86946aeb957973a8540fb960 + 0f1bca76ee6a360d67a624c12b5b8d427db66226 - + https://github.com/dotnet/xharness - 27779945a6f28639f526ec3d1e02f76436c6d22d + 9eaf2814afcd7627059e5ea0ee2f5169a6409689 - + https://github.com/dotnet/xharness - 27779945a6f28639f526ec3d1e02f76436c6d22d + 9eaf2814afcd7627059e5ea0ee2f5169a6409689 - + https://github.com/dotnet/arcade - 3ea0d860c6973f2cbadc9e895c7ec2cbdaec4ad5 + 9030d71b47f5a885a1f1d81ace8ec469249d88bc - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - deb41ed73af3390e435a68fe6b5671f37113d526 + a033eea960941a4aa1c2cd8084747a29535683ac - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - deb41ed73af3390e435a68fe6b5671f37113d526 + a033eea960941a4aa1c2cd8084747a29535683ac - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - deb41ed73af3390e435a68fe6b5671f37113d526 + a033eea960941a4aa1c2cd8084747a29535683ac - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - deb41ed73af3390e435a68fe6b5671f37113d526 + a033eea960941a4aa1c2cd8084747a29535683ac - + https://github.com/dotnet/hotreload-utils - fc3252e58fef2651652702298107f3fc3e3784cb + 1aa5a751a0c659c90f51b9d6b23c8cbd9d0a8dbb - + https://github.com/dotnet/runtime-assets - 426f10a0dcb1a9b5fa3bf5901f88bd3a54ccaa0a + f800c64524ca148d3a5e8e9204fcbc9cf5055148 - + https://github.com/dotnet/roslyn-analyzers - 5e80ab913df6662e4c94b6bdaa443684706f8e52 + ccd85bc350c9a994b74642f3b7613d8a98f5be2d https://github.com/dotnet/sdk diff --git a/eng/Versions.props b/eng/Versions.props index 2649b6910290c..c33e0d6f64eec 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -51,36 +51,36 @@ 3.3.2 4.0.0-4.final 4.0.0-4.final - 7.0.0-preview1.21502.1 + 7.0.0-preview1.21513.4 4.0.0-5.21453.15 1.0.0-rc.2.21501.51 - 7.0.0-beta.21474.2 - 7.0.0-beta.21474.2 - 7.0.0-beta.21474.2 - 7.0.0-beta.21474.2 - 7.0.0-beta.21474.2 - 7.0.0-beta.21474.2 - 2.5.1-beta.21474.2 - 7.0.0-beta.21474.2 - 7.0.0-beta.21474.2 - 7.0.0-beta.21474.2 - 7.0.0-beta.21474.2 - 7.0.0-beta.21474.2 - 7.0.0-beta.21474.2 - 7.0.0-beta.21474.2 - 7.0.0-beta.21474.2 + 7.0.0-beta.21514.3 + 7.0.0-beta.21514.3 + 7.0.0-beta.21514.3 + 7.0.0-beta.21514.3 + 7.0.0-beta.21514.3 + 7.0.0-beta.21514.3 + 2.5.1-beta.21514.3 + 7.0.0-beta.21514.3 + 7.0.0-beta.21514.3 + 7.0.0-beta.21514.3 + 7.0.0-beta.21514.3 + 7.0.0-beta.21514.3 + 7.0.0-beta.21514.3 + 7.0.0-beta.21514.3 + 7.0.0-beta.21514.3 6.0.0-preview.1.102 - 7.0.0-alpha.1.21476.2 - 7.0.0-alpha.1.21476.2 - 7.0.0-alpha.1.21476.2 + 7.0.0-alpha.1.21511.2 + 7.0.0-alpha.1.21511.2 + 7.0.0-alpha.1.21511.2 3.1.0 - 7.0.0-alpha.1.21476.2 + 7.0.0-alpha.1.21511.2 5.0.0 4.3.0 @@ -114,28 +114,28 @@ 5.0.0 5.0.0 4.9.0-rc2.21473.1 - 7.0.0-alpha.1.21476.2 - 7.0.0-alpha.1.21476.2 + 7.0.0-alpha.1.21511.2 + 7.0.0-alpha.1.21511.2 4.5.4 4.5.0 - 7.0.0-alpha.1.21476.2 + 7.0.0-alpha.1.21511.2 - 7.0.0-beta.21479.3 - 7.0.0-beta.21479.3 - 7.0.0-beta.21479.3 - 7.0.0-beta.21479.3 - 7.0.0-beta.21479.3 - 7.0.0-beta.21479.3 - 7.0.0-beta.21479.3 - 7.0.0-beta.21479.3 - 7.0.0-beta.21479.3 - 7.0.0-beta.21479.3 - 7.0.0-beta.21479.3 + 7.0.0-beta.21512.1 + 7.0.0-beta.21512.1 + 7.0.0-beta.21512.1 + 7.0.0-beta.21512.1 + 7.0.0-beta.21512.1 + 7.0.0-beta.21512.1 + 7.0.0-beta.21512.1 + 7.0.0-beta.21512.1 + 7.0.0-beta.21512.1 + 7.0.0-beta.21512.1 + 7.0.0-beta.21512.1 - 1.0.0-prerelease.21502.2 - 1.0.0-prerelease.21502.2 - 1.0.0-prerelease.21502.2 - 1.0.0-prerelease.21502.2 + 1.0.0-prerelease.21514.8 + 1.0.0-prerelease.21514.8 + 1.0.0-prerelease.21514.8 + 1.0.0-prerelease.21514.8 16.9.0-beta1.21055.5 2.0.0-beta1.20253.1 @@ -147,22 +147,16 @@ 1.0.4-preview6.19326.1 0.2.61701 1.0.26 - - 16.10.0 - $(RefOnlyMicrosoftBuildVersion) - $(RefOnlyMicrosoftBuildVersion) - $(RefOnlyMicrosoftBuildVersion) - 5.8.0 - 5.8.0 + 16.10.0 + $(MicrosoftBuildVersion) + 5.8.0 + 5.8.0 1.0.1-prerelease-00006 16.9.0-preview-20201201-01 - 1.0.0-prerelease.21501.2 - 1.0.0-prerelease.21501.2 - 1.0.2-alpha.0.21479.1 + 1.0.0-prerelease.21511.3 + 1.0.0-prerelease.21511.3 + 1.0.2-alpha.0.21512.2 2.4.2-pre.9 2.4.2 1.3.0 @@ -175,21 +169,21 @@ 6.0.0-preview-20210916.1 - 7.0.100-1.21504.4 + 7.0.100-1.21513.1 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-alpha.1.21477.1 + 7.0.0-alpha.1.21511.1 - 6.0.0-preview.7.21480.1 + 6.0.0-preview.7.21514.2 - 11.1.0-alpha.1.21477.1 - 11.1.0-alpha.1.21477.1 - 11.1.0-alpha.1.21477.1 - 11.1.0-alpha.1.21477.1 - 11.1.0-alpha.1.21477.1 - 11.1.0-alpha.1.21477.1 - 11.1.0-alpha.1.21477.1 - 11.1.0-alpha.1.21477.1 + 11.1.0-alpha.1.21511.1 + 11.1.0-alpha.1.21511.1 + 11.1.0-alpha.1.21511.1 + 11.1.0-alpha.1.21511.1 + 11.1.0-alpha.1.21511.1 + 11.1.0-alpha.1.21511.1 + 11.1.0-alpha.1.21511.1 + 11.1.0-alpha.1.21511.1 6.0.0-rc.1.21416.1 $(MicrosoftNETWorkloadEmscriptenManifest60100Version) diff --git a/eng/common/native/init-compiler.sh b/eng/common/native/init-compiler.sh index 28f5145a6f794..8c944f30b2864 100644 --- a/eng/common/native/init-compiler.sh +++ b/eng/common/native/init-compiler.sh @@ -50,8 +50,8 @@ if [[ -z "$CLR_CC" ]]; then # Set default versions if [[ -z "$majorVersion" ]]; then # note: gcc (all versions) and clang versions higher than 6 do not have minor version in file name, if it is zero. - if [[ "$compiler" == "clang" ]]; then versions=( 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 ) - elif [[ "$compiler" == "gcc" ]]; then versions=( 11 10 9 8 7 6 5 4.9 ); fi + if [[ "$compiler" == "clang" ]]; then versions=( 13 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 ) + elif [[ "$compiler" == "gcc" ]]; then versions=( 12 11 10 9 8 7 6 5 4.9 ); fi for version in "${versions[@]}"; do parts=(${version//./ }) diff --git a/eng/common/templates/steps/send-to-helix.yml b/eng/common/templates/steps/send-to-helix.yml index cd02ae1607f3b..09a223989f7ec 100644 --- a/eng/common/templates/steps/send-to-helix.yml +++ b/eng/common/templates/steps/send-to-helix.yml @@ -20,7 +20,6 @@ parameters: IncludeDotNetCli: false # optional -- true will download a version of the .NET CLI onto the Helix machine as a correlation payload; requires DotNetCliPackageType and DotNetCliVersion DotNetCliPackageType: '' # optional -- either 'sdk', 'runtime' or 'aspnetcore-runtime'; determines whether the sdk or runtime will be sent to Helix; see https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json DotNetCliVersion: '' # optional -- version of the CLI to send to Helix; based on this: https://raw.githubusercontent.com/dotnet/core/main/release-notes/releases-index.json - EnableXUnitReporter: false # optional -- true enables XUnit result reporting to Mission Control WaitForWorkItemCompletion: true # optional -- true will make the task wait until work items have been completed and fail the build if work items fail. False is "fire and forget." IsExternal: false # [DEPRECATED] -- doesn't do anything, jobs are external if HelixAccessToken is empty and Creator is set HelixBaseUri: 'https://helix.dot.net/' # optional -- sets the Helix API base URI (allows targeting int) @@ -54,7 +53,6 @@ steps: IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} HelixBaseUri: ${{ parameters.HelixBaseUri }} Creator: ${{ parameters.Creator }} @@ -85,7 +83,6 @@ steps: IncludeDotNetCli: ${{ parameters.IncludeDotNetCli }} DotNetCliPackageType: ${{ parameters.DotNetCliPackageType }} DotNetCliVersion: ${{ parameters.DotNetCliVersion }} - EnableXUnitReporter: ${{ parameters.EnableXUnitReporter }} WaitForWorkItemCompletion: ${{ parameters.WaitForWorkItemCompletion }} HelixBaseUri: ${{ parameters.HelixBaseUri }} Creator: ${{ parameters.Creator }} diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index 3e819071f6111..a29857451bc79 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -367,6 +367,8 @@ if (CLR_CMAKE_HOST_UNIX) #These seem to indicate real issues add_compile_options($<$:-Wno-invalid-offsetof>) + add_compile_options(-Wno-unused-but-set-variable) + if (CMAKE_C_COMPILER_ID MATCHES "Clang") add_compile_options(-Wno-unknown-warning-option) @@ -376,8 +378,6 @@ if (CLR_CMAKE_HOST_UNIX) # Disabled warnings add_compile_options(-Wno-unused-private-field) - # Explicit constructor calls are not supported by clang (this->ClassName::ClassName()) - add_compile_options(-Wno-microsoft) # There are constants of type BOOL used in a condition. But BOOL is defined as int # and so the compiler thinks that there is a mistake. add_compile_options(-Wno-constant-logical-operand) @@ -390,8 +390,9 @@ if (CLR_CMAKE_HOST_UNIX) # to a struct or a class that has virtual members or a base class. In that case, clang # may not generate the same object layout as MSVC. add_compile_options(-Wno-incompatible-ms-struct) + + add_compile_options(-Wno-reserved-identifier) else() - add_compile_options(-Wno-unused-but-set-variable) add_compile_options(-Wno-uninitialized) add_compile_options(-Wno-strict-aliasing) add_compile_options(-Wno-array-bounds) diff --git a/eng/native/init-distro-rid.sh b/eng/native/init-distro-rid.sh index eea8eca2d26d1..5f6b194600124 100644 --- a/eng/native/init-distro-rid.sh +++ b/eng/native/init-distro-rid.sh @@ -41,7 +41,7 @@ initNonPortableDistroRid() # We have forced __PortableBuild=0. This is because -portablebuld # has been passed as false. if (( isPortable == 0 )); then - if [ "${ID}" = "rhel" || "${ID}" = "rocky" ]; then + if [ "${ID}" = "rhel" ] || [ "${ID}" = "rocky" ]; then # remove the last version digit VERSION_ID="${VERSION_ID%.*}" fi diff --git a/eng/pipelines/common/platform-matrix.yml b/eng/pipelines/common/platform-matrix.yml index 3672691bbb05a..ff13637a92a14 100644 --- a/eng/pipelines/common/platform-matrix.yml +++ b/eng/pipelines/common/platform-matrix.yml @@ -209,6 +209,32 @@ jobs: ${{ insert }}: ${{ parameters.jobParameters }} buildingOnSourceBuildImage: true +# Linux s390x + +- ${{ if containsValue(parameters.platforms, 'Linux_s390x') }}: + - template: xplat-setup.yml + parameters: + jobTemplate: ${{ parameters.jobTemplate }} + helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }} + variables: ${{ parameters.variables }} + osGroup: Linux + archType: s390x + targetRid: linux-s390x + platform: Linux_s390x + container: + image: ubuntu-18.04-cross-s390x-20201102145728-d6e0352 + registry: mcr + jobParameters: + runtimeFlavor: ${{ parameters.runtimeFlavor }} + stagedBuild: ${{ parameters.stagedBuild }} + buildConfig: ${{ parameters.buildConfig }} + ${{ if eq(parameters.passPlatforms, true) }}: + platforms: ${{ parameters.platforms }} + helixQueueGroup: ${{ parameters.helixQueueGroup }} + crossBuild: true + crossrootfsDir: '/crossrootfs/s390x' + ${{ insert }}: ${{ parameters.jobParameters }} + # WebAssembly - ${{ if containsValue(parameters.platforms, 'Browser_wasm') }}: @@ -628,6 +654,33 @@ jobs: helixQueueGroup: ${{ parameters.helixQueueGroup }} ${{ insert }}: ${{ parameters.jobParameters }} +# Tizen armel + +- ${{ if containsValue(parameters.platforms, 'Tizen_armel') }}: + - template: xplat-setup.yml + parameters: + jobTemplate: ${{ parameters.jobTemplate }} + helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }} + variables: ${{ parameters.variables }} + osGroup: Tizen + archType: armel + targetRid: tizen-armel + platform: Tizen_armel + container: + image: ubuntu-18.04-cross-armel-tizen-20210719212651-8b02f56 + registry: mcr + jobParameters: + runtimeFlavor: ${{ parameters.runtimeFlavor }} + stagedBuild: ${{ parameters.stagedBuild }} + buildConfig: ${{ parameters.buildConfig }} + ${{ if eq(parameters.passPlatforms, true) }}: + platforms: ${{ parameters.platforms }} + helixQueueGroup: ${{ parameters.helixQueueGroup }} + crossBuild: true + crossrootfsDir: '/crossrootfs/armel' + disableClrTest: true + ${{ insert }}: ${{ parameters.jobParameters }} + # Windows x64 - ${{ if or(containsValue(parameters.platforms, 'windows_x64'), in(parameters.platformGroup, 'all', 'gcstress')) }}: diff --git a/eng/pipelines/common/xplat-setup.yml b/eng/pipelines/common/xplat-setup.yml index 586a474175895..85a96ae5fce85 100644 --- a/eng/pipelines/common/xplat-setup.yml +++ b/eng/pipelines/common/xplat-setup.yml @@ -114,12 +114,12 @@ jobs: ${{ if eq(parameters.jobParameters.pool, '') }}: pool: # Public Linux Build Pool - ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Android'), eq(parameters.hostedOs, 'Linux')), eq(variables['System.TeamProject'], 'public')) }}: + ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Android', 'Tizen'), eq(parameters.hostedOs, 'Linux')), eq(variables['System.TeamProject'], 'public')) }}: name: NetCore1ESPool-Public demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open # Official Build Linux Pool - ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Browser', 'Android'), eq(parameters.hostedOs, 'Linux')), ne(variables['System.TeamProject'], 'public')) }}: + ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Browser', 'Android', 'Tizen'), eq(parameters.hostedOs, 'Linux')), ne(variables['System.TeamProject'], 'public')) }}: name: NetCore1ESPool-Internal demands: ImageOverride -equals Build.Ubuntu.1804.Amd64 diff --git a/eng/pipelines/coreclr/superpmi.yml b/eng/pipelines/coreclr/superpmi-collect.yml similarity index 91% rename from eng/pipelines/coreclr/superpmi.yml rename to eng/pipelines/coreclr/superpmi-collect.yml index d6325d87b74eb..7b285903a5fef 100644 --- a/eng/pipelines/coreclr/superpmi.yml +++ b/eng/pipelines/coreclr/superpmi-collect.yml @@ -58,7 +58,7 @@ jobs: - template: /eng/pipelines/common/platform-matrix.yml parameters: - jobTemplate: /eng/pipelines/coreclr/templates/superpmi-job.yml + jobTemplate: /eng/pipelines/coreclr/templates/superpmi-collect-job.yml buildConfig: checked platforms: # Linux tests are built on the OSX machines. @@ -79,7 +79,7 @@ jobs: - template: /eng/pipelines/common/platform-matrix.yml parameters: - jobTemplate: /eng/pipelines/coreclr/templates/superpmi-job.yml + jobTemplate: /eng/pipelines/coreclr/templates/superpmi-collect-job.yml buildConfig: checked platforms: # Linux tests are built on the OSX machines. @@ -101,7 +101,7 @@ jobs: - template: /eng/pipelines/common/platform-matrix.yml parameters: - jobTemplate: /eng/pipelines/coreclr/templates/superpmi-job.yml + jobTemplate: /eng/pipelines/coreclr/templates/superpmi-collect-job.yml buildConfig: checked platforms: # Linux tests are built on the OSX machines. @@ -123,7 +123,7 @@ jobs: - template: /eng/pipelines/common/platform-matrix.yml parameters: - jobTemplate: /eng/pipelines/coreclr/templates/superpmi-job.yml + jobTemplate: /eng/pipelines/coreclr/templates/superpmi-collect-job.yml buildConfig: checked platforms: # Linux tests are built on the OSX machines. @@ -144,7 +144,7 @@ jobs: - template: /eng/pipelines/common/platform-matrix.yml parameters: - jobTemplate: /eng/pipelines/coreclr/templates/superpmi-job.yml + jobTemplate: /eng/pipelines/coreclr/templates/superpmi-collect-job.yml buildConfig: checked platforms: # Linux tests are built on the OSX machines. diff --git a/eng/pipelines/coreclr/superpmi-replay.yml b/eng/pipelines/coreclr/superpmi-replay.yml index 83b4d2ac6237b..90ed1896c03af 100644 --- a/eng/pipelines/coreclr/superpmi-replay.yml +++ b/eng/pipelines/coreclr/superpmi-replay.yml @@ -8,10 +8,6 @@ trigger: - src/coreclr/jit/* - src/coreclr/inc/jiteeversionguid.h -# This pipeline is supposed to be run only on merged changes -# and should not be triggerable from a PR. -pr: none - jobs: - template: /eng/pipelines/common/platform-matrix.yml diff --git a/eng/pipelines/coreclr/templates/build-job.yml b/eng/pipelines/coreclr/templates/build-job.yml index e94d630ba2e95..c5efb8c77bdd2 100644 --- a/eng/pipelines/coreclr/templates/build-job.yml +++ b/eng/pipelines/coreclr/templates/build-job.yml @@ -9,6 +9,7 @@ parameters: crossBuild: false crossrootfsDir: '' dependOnEvaluatePaths: false + disableClrTest: false isOfficialBuild: false osGroup: '' osSubgroup: '' @@ -38,6 +39,7 @@ jobs: pool: ${{ parameters.pool }} condition: ${{ parameters.condition }} dependOnEvaluatePaths: ${{ parameters.dependOnEvaluatePaths }} + disableClrTest: ${{ parameters.disableClrTest }} pgoType: ${{ parameters.pgoType }} # Compute job name from template parameters @@ -141,6 +143,12 @@ jobs: - name: SignType value: $[ coalesce(variables.OfficialSignType, 'real') ] + - name: clrRuntimePortableBuildArg + value: '' + - ${{ if eq(parameters.archType, 'armel' )}}: + - name: clrRuntimePortableBuildArg + value: '-portablebuild=false' + - ${{ parameters.variables }} steps: @@ -188,7 +196,7 @@ jobs: # Build CoreCLR Runtime - ${{ if ne(parameters.osGroup, 'windows') }}: - - script: $(Build.SourcesDirectory)/src/coreclr/build-runtime$(scriptExt) $(buildConfig) $(archType) $(crossArg) $(osArg) -ci $(compilerArg) $(clrBuildPALTestsBuildArg) $(pgoInstrumentArg) $(officialBuildIdArg) $(clrInterpreterBuildArg) + - script: $(Build.SourcesDirectory)/src/coreclr/build-runtime$(scriptExt) $(buildConfig) $(archType) $(crossArg) $(osArg) -ci $(compilerArg) $(clrBuildPALTestsBuildArg) $(pgoInstrumentArg) $(officialBuildIdArg) $(clrInterpreterBuildArg) $(clrRuntimePortableBuildArg) displayName: Build CoreCLR Runtime - ${{ if eq(parameters.osGroup, 'windows') }}: - script: set __TestIntermediateDir=int&&$(Build.SourcesDirectory)/src/coreclr/build-runtime$(scriptExt) $(buildConfig) $(archType) -ci $(enforcePgoArg) $(pgoInstrumentArg) $(officialBuildIdArg) $(clrInterpreterBuildArg) @@ -210,7 +218,7 @@ jobs: displayName: Run CoreCLR Tools unit tests # Build native test components - - ${{ if ne(parameters.isOfficialBuild, true) }}: + - ${{ if and(ne(parameters.isOfficialBuild, true), ne(parameters.disableClrTest, true)) }}: - script: $(Build.SourcesDirectory)/src/tests/build$(scriptExt) skipmanaged skipgeneratelayout $(buildConfig) $(archType) $(crossArg) $(osArg) $(priorityArg) $(compilerArg) displayName: Build native test components @@ -257,7 +265,7 @@ jobs: condition: always() # Builds using gcc are not tested, and clrTools unitests do not publish the build artifacts - - ${{ if and(ne(parameters.compilerName, 'gcc'), ne(parameters.testGroup, 'clrTools')) }}: + - ${{ if and(ne(parameters.compilerName, 'gcc'), ne(parameters.testGroup, 'clrTools'), ne(parameters.disableClrTest, true)) }}: # Publish product output directory for consumption by tests. - template: /eng/pipelines/common/upload-artifact-step.yml parameters: @@ -276,7 +284,7 @@ jobs: osGroup: ${{ parameters.osGroup }} osSubgroup: ${{ parameters.osSubgroup }} - - ${{ if and(ne(parameters.compilerName, 'gcc'), ne(parameters.testGroup, ''), ne(parameters.testGroup, 'clrTools')) }}: + - ${{ if and(ne(parameters.compilerName, 'gcc'), ne(parameters.testGroup, ''), ne(parameters.testGroup, 'clrTools'), ne(parameters.disableClrTest, true)) }}: # Publish test native components for consumption by test execution. - ${{ if and(ne(parameters.isOfficialBuild, true), eq(parameters.pgoType, '')) }}: - template: /eng/pipelines/common/upload-artifact-step.yml diff --git a/eng/pipelines/coreclr/templates/jit-exploratory-job.yml b/eng/pipelines/coreclr/templates/jit-exploratory-job.yml index 5992b1088bd0d..b3e1e9d089e56 100644 --- a/eng/pipelines/coreclr/templates/jit-exploratory-job.yml +++ b/eng/pipelines/coreclr/templates/jit-exploratory-job.yml @@ -3,7 +3,6 @@ parameters: archType: '' osGroup: '' osSubgroup: '' - container: '' runtimeVariant: '' testGroup: '' framework: net6.0 # Specify the appropriate framework when running release branches (ie netcoreapp3.0 for release/3.0) @@ -13,8 +12,6 @@ parameters: runtimeType: 'coreclr' pool: '' codeGenType: 'JIT' - projetFile: '' - runKind: '' runJobTemplate: '/eng/pipelines/coreclr/templates/jit-run-exploratory-job.yml' additionalSetupParameters: '' @@ -27,8 +24,8 @@ jobs: - template: ${{ parameters.runJobTemplate }} parameters: # Compute job name from template parameters - jobName: ${{ format('exploratory_{0}{1}_{2}_{3}_{4}_{5}_{6}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType, parameters.runKind) }} - displayName: ${{ format('Exploratory {0}{1} {2} {3} {4} {5} {6}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType, parameters.runKind) }} + jobName: ${{ format('exploratory_{0}{1}_{2}_{3}_{4}_{5}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType) }} + displayName: ${{ format('Exploratory {0}{1} {2} {3} {4} {5}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType) }} pool: ${{ parameters.pool }} buildConfig: ${{ parameters.buildConfig }} archType: ${{ parameters.archType }} @@ -38,7 +35,6 @@ jobs: liveLibrariesBuildConfig: ${{ parameters.liveLibrariesBuildConfig }} runtimeType: ${{ parameters.runtimeType }} codeGenType: ${{ parameters.codeGenType }} - runKind: ${{ parameters.runKind }} testGroup: ${{ parameters.testGroup }} helixQueues: ${{ parameters.helixQueues }} additionalSetupParameters: ${{ parameters.additionalSetupParameters }} diff --git a/eng/pipelines/coreclr/templates/jit-run-exploratory-job.yml b/eng/pipelines/coreclr/templates/jit-run-exploratory-job.yml index 427bba150c812..3c0dbbbfea3fc 100644 --- a/eng/pipelines/coreclr/templates/jit-run-exploratory-job.yml +++ b/eng/pipelines/coreclr/templates/jit-run-exploratory-job.yml @@ -9,8 +9,6 @@ parameters: archType: '' # required -- targeting CPU architecture osGroup: '' # required -- operating system for the job osSubgroup: '' # optional -- operating system subgroup - extraSetupParameters: '' # optional -- extra arguments to pass to the setup script - frameworks: ['net6.0'] # optional -- list of frameworks to run against continueOnError: 'false' # optional -- determines whether to continue the build if the step errors dependsOn: '' # optional -- dependencies of the job timeoutInMinutes: 320 # optional -- timeout for the job @@ -18,8 +16,7 @@ parameters: liveLibrariesBuildConfig: '' # optional -- live-live libraries configuration to use for the run runtimeType: 'coreclr' # optional -- Sets the runtime as coreclr or mono codeGenType: 'JIT' # optional -- Decides on the codegen technology if running on mono - runKind: '' # required -- test category - helixQueues: '' # required -- Helix queue + helixQueues: '' # required -- Helix queues dependOnEvaluatePaths: false jobs: @@ -54,6 +51,12 @@ jobs: - HelixApiAccessToken: '' - HelixPreCommand: '' + - ${{ if in(variables['Build.Reason'], 'Schedule') }}: + - name: RunReason + value: 'Scheduled' + - ${{ if notin(variables['Build.Reason'], 'Schedule') }}: + - name: RunReason + value: 'PR' - ${{ if eq(parameters.osGroup, 'windows') }}: - name: PythonScript value: 'py -3' @@ -65,6 +68,8 @@ jobs: value: '$(Build.SourcesDirectory)\artifacts\helixresults\' - name: IssuesSummaryLocation value: '$(Build.SourcesDirectory)\artifacts\issues_summary\' + - name: AntigenLogsLocation + value: '$(Build.SourcesDirectory)\artifacts\antigen_logs\' - ${{ if ne(parameters.osGroup, 'windows') }}: - name: PythonScript @@ -77,16 +82,14 @@ jobs: value: '$(Build.SourcesDirectory)/artifacts/helixresults/' - name: IssuesSummaryLocation value: '$(Build.SourcesDirectory)/artifacts/issues_summary/' + - name: AntigenLogsLocation + value: '$(Build.SourcesDirectory)/artifacts/antigen_logs/' + workspace: clean: all pool: ${{ parameters.pool }} container: ${{ parameters.container }} - strategy: - matrix: - ${{ each framework in parameters.frameworks }}: - ${{ framework }}: - _Framework: ${{ framework }} steps: - ${{ parameters.steps }} @@ -110,6 +113,7 @@ jobs: osGroup: ${{ parameters.osGroup }} RunConfiguration: '$(RunConfiguration)' ToolName: '$(ToolName)' + RunReason: '$(RunReason)' continueOnError: true - template: /eng/pipelines/common/upload-artifact-step.yml @@ -129,20 +133,43 @@ jobs: sourceFolder: '$(IssuesLocation)' contents: '**/issues-summary-*.txt' targetFolder: '$(IssuesSummaryLocation)' + continueOnError: true + condition: always() - task: PublishPipelineArtifact@1 displayName: Publish issues-summary.txt files inputs: targetPath: $(IssuesSummaryLocation) artifactName: 'Issues_Summary_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' + continueOnError: true + condition: always() + + # Always upload the available Antigen.log files + - task: CopyFiles@2 + displayName: Copying Antigen.logs of all partitions + inputs: + sourceFolder: '$(IssuesLocation)' + contents: '**/Antigen-*.log' + targetFolder: '$(AntigenLogsLocation)' + continueOnError: true + condition: always() + + - task: PublishPipelineArtifact@1 + displayName: Publish Antigen.log files + inputs: + targetPath: $(AntigenLogsLocation) + artifactName: 'Antigen_Logs_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' + continueOnError: true + condition: always() - script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/antigen_unique_issues.py -issues_directory $(IssuesSummaryLocation) displayName: ${{ format('Print unique issues ({0})', parameters.osGroup) }} continueOnError: true + condition: always() - task: PublishPipelineArtifact@1 displayName: Publish Antigen build logs inputs: targetPath: $(Build.SourcesDirectory)/artifacts/log - artifactName: 'Antigen_BuildLogs__$(archType)_$(buildConfig)' + artifactName: 'Antigen_BuildLogs_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' condition: always() \ No newline at end of file diff --git a/eng/pipelines/coreclr/templates/run-superpmi-job.yml b/eng/pipelines/coreclr/templates/run-superpmi-collect-job.yml similarity index 87% rename from eng/pipelines/coreclr/templates/run-superpmi-job.yml rename to eng/pipelines/coreclr/templates/run-superpmi-collect-job.yml index 78a4e778c733f..01726c6b1a339 100644 --- a/eng/pipelines/coreclr/templates/run-superpmi-job.yml +++ b/eng/pipelines/coreclr/templates/run-superpmi-collect-job.yml @@ -9,16 +9,11 @@ parameters: archType: '' # required -- targeting CPU architecture osGroup: '' # required -- operating system for the job osSubgroup: '' # optional -- operating system subgroup - extraSetupParameters: '' # optional -- extra arguments to pass to the setup script - frameworks: ['netcoreapp3.0'] # optional -- list of frameworks to run against continueOnError: 'false' # optional -- determines whether to continue the build if the step errors dependsOn: '' # optional -- dependencies of the job timeoutInMinutes: 320 # optional -- timeout for the job enableTelemetry: false # optional -- enable for telemetry liveLibrariesBuildConfig: '' # optional -- live-live libraries configuration to use for the run - runtimeType: 'coreclr' # optional -- Sets the runtime as coreclr or mono - codeGenType: 'JIT' # optional -- Decides on the codegen technology if running on mono - runKind: '' # required -- test category collectionType: '' collectionName: '' dependOnEvaluatePaths: false @@ -108,15 +103,10 @@ jobs: pool: ${{ parameters.pool }} container: ${{ parameters.container }} - strategy: - matrix: - ${{ each framework in parameters.frameworks }}: - ${{ framework }}: - _Framework: ${{ framework }} steps: - ${{ parameters.steps }} - - script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/superpmi_setup.py -source_directory $(Build.SourcesDirectory) -core_root_directory $(Core_Root_Dir) -arch $(archType) -mch_file_tag $(MchFileTag) -input_directory $(InputDirectory) -collection_name $(CollectionName) -collection_type $(CollectionType) -max_size 50 # size in MB + - script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/superpmi_collect_setup.py -source_directory $(Build.SourcesDirectory) -core_root_directory $(Core_Root_Dir) -arch $(archType) -mch_file_tag $(MchFileTag) -input_directory $(InputDirectory) -collection_name $(CollectionName) -collection_type $(CollectionType) -max_size 50 # size in MB displayName: ${{ format('SuperPMI setup ({0})', parameters.osGroup) }} # Create required directories for merged mch collection and superpmi logs @@ -135,7 +125,7 @@ jobs: - template: /eng/pipelines/coreclr/templates/superpmi-send-to-helix.yml parameters: HelixSource: '$(HelixSourcePrefix)/$(Build.Repository.Name)/$(Build.SourceBranch)' # sources must start with pr/, official/, prodcon/, or agent/ - HelixType: 'test/superpmi/$(CollectionName)/$(CollectionType)/$(_Framework)/$(Architecture)' + HelixType: 'test/superpmi/$(CollectionName)/$(CollectionType)/$(Architecture)' HelixAccessToken: $(HelixApiAccessToken) HelixTargetQueues: $(Queue) HelixPreCommands: $(HelixPreCommand) @@ -143,7 +133,7 @@ jobs: WorkItemTimeout: 4:00 # 4 hours WorkItemDirectory: '$(WorkItemDirectory)' CorrelationPayloadDirectory: '$(CorrelationPayloadDirectory)' - ProjectFile: 'superpmi.proj' + ProjectFile: 'superpmi-collect.proj' BuildConfig: ${{ parameters.buildConfig }} osGroup: ${{ parameters.osGroup }} InputArtifacts: '$(InputArtifacts)' @@ -151,7 +141,7 @@ jobs: CollectionName: '$(CollectionName)' continueOnError: true # Run the future step i.e. merge-mch step even if this step fails. - # Always run merged step even if collection of some partition fails so we can store collection + # Always run merge step even if collection of some partition fails so we can store collection # of the partitions that succeeded. If all the partitions fail, merge-mch would fail and we won't # run future steps like uploading superpmi collection. - script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/superpmi.py merge-mch -log_level DEBUG -pattern $(MchFilesLocation)$(CollectionName).$(CollectionType)*.mch -output_mch_path $(MergedMchFileLocation)$(CollectionName).$(CollectionType).$(MchFileTag).mch @@ -166,7 +156,7 @@ jobs: archiveType: $(archiveType) tarCompression: $(tarCompression) archiveExtension: $(archiveExtension) - artifactName: 'SuperPMI_Collection_$(CollectionName)_$(CollectionType)_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.runtimeType }}_${{ parameters.codeGenType }}_${{ parameters.runKind }}' + artifactName: 'SuperPMI_Collection_$(CollectionName)_$(CollectionType)_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' displayName: ${{ format('Upload artifacts SuperPMI {0}-{1} collection', parameters.collectionName, parameters.collectionType) }} - script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/superpmi.py upload -log_level DEBUG -arch $(archType) -build_type $(buildConfig) -mch_files $(MergedMchFileLocation)$(CollectionName).$(CollectionType).$(MchFileTag).mch -core_root $(Build.SourcesDirectory)/artifacts/bin/coreclr/$(osGroup).x64.$(buildConfigUpper) @@ -184,15 +174,15 @@ jobs: condition: always() - task: PublishPipelineArtifact@1 - displayName: Publish Superpmi logs + displayName: Publish SuperPMI logs inputs: targetPath: $(SpmiLogsLocation) - artifactName: 'SuperPMI_Logs_$(CollectionName)_$(CollectionType)_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.runtimeType }}_${{ parameters.codeGenType }}_${{ parameters.runKind }}' + artifactName: 'SuperPMI_Logs_$(CollectionName)_$(CollectionType)_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' condition: always() - task: PublishPipelineArtifact@1 displayName: Publish SuperPMI build logs inputs: targetPath: $(Build.SourcesDirectory)/artifacts/log - artifactName: 'SuperPMI_BuildLogs_$(CollectionName)_$(CollectionType)_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.runtimeType }}_${{ parameters.codeGenType }}_${{ parameters.runKind }}' + artifactName: 'SuperPMI_BuildLogs_$(CollectionName)_$(CollectionType)_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)' condition: always() diff --git a/eng/pipelines/coreclr/templates/run-superpmi-replay-job.yml b/eng/pipelines/coreclr/templates/run-superpmi-replay-job.yml index f267329a86760..979d0912388bc 100644 --- a/eng/pipelines/coreclr/templates/run-superpmi-replay-job.yml +++ b/eng/pipelines/coreclr/templates/run-superpmi-replay-job.yml @@ -9,18 +9,12 @@ parameters: archType: '' # required -- targeting CPU architecture osGroup: '' # required -- operating system for the job osSubgroup: '' # optional -- operating system subgroup - extraSetupParameters: '' # optional -- extra arguments to pass to the setup script - frameworks: ['netcoreapp3.0'] # optional -- list of frameworks to run against continueOnError: 'false' # optional -- determines whether to continue the build if the step errors dependsOn: '' # optional -- dependencies of the job timeoutInMinutes: 320 # optional -- timeout for the job enableTelemetry: false # optional -- enable for telemetry liveLibrariesBuildConfig: '' # optional -- live-live libraries configuration to use for the run - runtimeType: 'coreclr' # optional -- Sets the runtime as coreclr or mono - codeGenType: 'JIT' # optional -- Decides on the codegen technology if running on mono - runKind: '' # required -- test category - collectionType: '' - collectionName: '' + helixQueues: '' # required -- Helix queues dependOnEvaluatePaths: false jobs: @@ -35,8 +29,6 @@ jobs: enableTelemetry: ${{ parameters.enableTelemetry }} enablePublishBuildArtifacts: true continueOnError: ${{ parameters.continueOnError }} - collectionType: $ {{ parameters.collectionType }} - collectionName: ${{ parameters.collectionName }} dependOnEvaluatePaths: ${{ parameters.dependOnEvaluatePaths }} timeoutInMinutes: ${{ parameters.timeoutInMinutes }} @@ -46,6 +38,7 @@ jobs: displayName: '${{ parameters.jobName }}' variables: + - ${{ each variable in parameters.variables }}: - ${{ if ne(variable.name, '') }}: - name: ${{ variable.name }} @@ -69,11 +62,6 @@ jobs: pool: ${{ parameters.pool }} container: ${{ parameters.container }} - strategy: - matrix: - ${{ each framework in parameters.frameworks }}: - ${{ framework }}: - _Framework: ${{ framework }} steps: - ${{ parameters.steps }} @@ -85,17 +73,18 @@ jobs: displayName: ${{ format('SuperPMI replay setup ({0} {1})', parameters.osGroup, parameters.archType) }} # Run superpmi replay in helix - - template: /eng/pipelines/coreclr/templates/superpmi-send-to-helix.yml + - template: /eng/pipelines/common/templates/runtimes/send-to-helix-step.yml parameters: - HelixSource: '$(HelixSourcePrefix)/$(Build.Repository.Name)/$(Build.SourceBranch)' # sources must start with pr/, official/, prodcon/, or agent/ - HelixAccessToken: $(HelixApiAccessToken) - HelixTargetQueues: $(Queue) - HelixPreCommands: $(HelixPreCommand) - Creator: $(Creator) + displayName: 'Send job to Helix' + helixBuild: $(Build.BuildNumber) + helixSource: $(_HelixSource) + helixType: 'build/tests/' + helixQueues: ${{ join(',', parameters.helixQueues) }} + creator: dotnet-bot WorkItemTimeout: 4:00 # 4 hours WorkItemDirectory: '$(WorkItemDirectory)' CorrelationPayloadDirectory: '$(CorrelationPayloadDirectory)' - ProjectFile: 'superpmi-replay.proj' + helixProjectArguments: '$(Build.SourcesDirectory)/src/coreclr/scripts/superpmi-replay.proj' BuildConfig: ${{ parameters.buildConfig }} osGroup: ${{ parameters.osGroup }} archType: ${{ parameters.archType }} @@ -111,7 +100,7 @@ jobs: condition: always() - task: PublishPipelineArtifact@1 - displayName: Publish Superpmi logs + displayName: Publish SuperPMI logs inputs: targetPath: $(SpmiLogsLocation) artifactName: 'SuperPMI_Logs_$(archType)_$(buildConfig)' @@ -121,5 +110,5 @@ jobs: displayName: Publish SuperPMI build logs inputs: targetPath: $(Build.SourcesDirectory)/artifacts/log - artifactName: 'SuperPMI_BuildLogs__$(archType)_$(buildConfig)' - condition: always() \ No newline at end of file + artifactName: 'SuperPMI_BuildLogs_$(archType)_$(buildConfig)' + condition: always() diff --git a/eng/pipelines/coreclr/templates/superpmi-job.yml b/eng/pipelines/coreclr/templates/superpmi-collect-job.yml similarity index 69% rename from eng/pipelines/coreclr/templates/superpmi-job.yml rename to eng/pipelines/coreclr/templates/superpmi-collect-job.yml index c51ca723c9e60..6c990a25ff4aa 100644 --- a/eng/pipelines/coreclr/templates/superpmi-job.yml +++ b/eng/pipelines/coreclr/templates/superpmi-collect-job.yml @@ -3,62 +3,43 @@ parameters: archType: '' osGroup: '' osSubgroup: '' - container: '' - runtimeVariant: '' - testGroup: '' - framework: net5.0 # Specify the appropriate framework when running release branches (ie netcoreapp3.0 for release/3.0) liveLibrariesBuildConfig: '' variables: {} - runtimeType: 'coreclr' pool: '' - codeGenType: 'JIT' - projetFile: '' - runKind: '' - runJobTemplate: '/eng/pipelines/coreclr/templates/run-superpmi-job.yml' - additionalSetupParameters: '' + runJobTemplate: '/eng/pipelines/coreclr/templates/run-superpmi-collect-job.yml' collectionType: '' collectionName: '' ### SuperPMI job - -### Each superpmi job depends on a corresponding build job with the same -### buildConfig and archType. +### Each collection job depends on a corresponding build job with the same buildConfig and archType. jobs: - template: ${{ parameters.runJobTemplate }} parameters: # Compute job name from template parameters - jobName: ${{ format('superpmibuild_{0}{1}_{2}_{3}_{4}_{5}_{6}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType, parameters.runKind) }} - displayName: ${{ format('SuperPMI {7} {8} {0}{1} {2} {3} {4} {5} {6}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType, parameters.runKind, parameters.collectionName, parameters.collectionType) }} + jobName: ${{ format('superpmi_collect_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} + displayName: ${{ format('SuperPMI collect {4} {5} {0}{1} {2} {3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.collectionName, parameters.collectionType) }} pool: ${{ parameters.pool }} buildConfig: ${{ parameters.buildConfig }} archType: ${{ parameters.archType }} osGroup: ${{ parameters.osGroup }} osSubgroup: ${{ parameters.osSubgroup }} - runtimeVariant: ${{ parameters.runtimeVariant }} liveLibrariesBuildConfig: ${{ parameters.liveLibrariesBuildConfig }} - runtimeType: ${{ parameters.runtimeType }} - codeGenType: ${{ parameters.codeGenType }} - runKind: ${{ parameters.runKind }} - testGroup: ${{ parameters.testGroup }} collectionType: ${{ parameters.collectionType }} collectionName: ${{ parameters.collectionName }} - additionalSetupParameters: ${{ parameters.additionalSetupParameters }} # Test job depends on the corresponding build job dependsOn: - - ${{ format('coreclr_{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} + - ${{ format('coreclr__product_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} # Depend on coreclr x64 so we can download it and use mcs.exe from it while publishing non-x64 arch SPMI collection - ${{ if ne(parameters.archType, 'x64') }}: - - ${{ format('coreclr_{0}_product_build_{1}{2}_x64_{3}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.buildConfig) }} + - ${{ format('coreclr__product_build_{0}{1}_x64_{2}', parameters.osGroup, parameters.osSubgroup, parameters.buildConfig) }} - ${{ if ne(parameters.liveLibrariesBuildConfig, '') }}: - ${{ format('libraries_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveLibrariesBuildConfig) }} - ${{ if eq(parameters.collectionName, 'coreclr_tests') }}: - - '${{ parameters.runtimeType }}_common_test_build_p1_AnyOS_AnyCPU_${{parameters.buildConfig }}' + - 'coreclr_common_test_build_p1_AnyOS_AnyCPU_${{parameters.buildConfig }}' variables: ${{ parameters.variables }} - frameworks: - - ${{ parameters.framework }} steps: # Extra steps that will be passed to the superpmi template and run before sending the job to helix (all of which is done in the template) @@ -85,8 +66,8 @@ jobs: - template: /eng/pipelines/common/download-artifact-step.yml parameters: unpackFolder: '$(Build.SourcesDirectory)/artifacts/bin/coreclr/$(osGroup).x64.$(buildConfigUpper)' - artifactFileName: 'CoreCLRProduct__${{ parameters.runtimeVariant }}_$(osGroup)$(osSubgroup)_x64_$(buildConfig)$(archiveExtension)' - artifactName: 'CoreCLRProduct__${{ parameters.runtimeVariant }}_$(osGroup)$(osSubgroup)_x64_$(buildConfig)' + artifactFileName: 'CoreCLRProduct___$(osGroup)$(osSubgroup)_x64_$(buildConfig)$(archiveExtension)' + artifactName: 'CoreCLRProduct___$(osGroup)$(osSubgroup)_x64_$(buildConfig)' displayName: 'Coreclr product build (x64)' # Download and unzip managed test artifacts diff --git a/eng/pipelines/coreclr/templates/superpmi-replay-job.yml b/eng/pipelines/coreclr/templates/superpmi-replay-job.yml index ab481ee6a78f3..c0aac714341fd 100644 --- a/eng/pipelines/coreclr/templates/superpmi-replay-job.yml +++ b/eng/pipelines/coreclr/templates/superpmi-replay-job.yml @@ -4,18 +4,17 @@ parameters: osGroup: '' # required -- operating system for the job osSubgroup: '' # optional -- operating system subgroup pool: '' - stagedBuild: false timeoutInMinutes: 320 # build timeout - framework: net5.0 # Specify the appropriate framework when running release branches (ie netcoreapp3.0 for release/3.0) variables: {} + helixQueues: '' dependOnEvaluatePaths: false runJobTemplate: '/eng/pipelines/coreclr/templates/run-superpmi-replay-job.yml' jobs: - template: ${{ parameters.runJobTemplate }} parameters: - jobName: ${{ format('superpmibuild_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - displayName: ${{ format('SuperPMI replay {0} {1}', parameters.osGroup, parameters.archType) }} + jobName: ${{ format('superpmi_replay_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} + displayName: ${{ format('SuperPMI replay {0}{1} {2} {3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} pool: ${{ parameters.pool }} buildConfig: ${{ parameters.buildConfig }} archType: ${{ parameters.archType }} @@ -23,15 +22,12 @@ jobs: osSubgroup: ${{ parameters.osSubgroup }} dependOnEvaluatePaths: ${{ parameters.dependOnEvaluatePaths }} timeoutInMinutes: ${{ parameters.timeoutInMinutes }} - additionalSetupParameters: ${{ parameters.additionalSetupParameters }} + helixQueues: ${{ parameters.helixQueues }} dependsOn: - ${{ format('coreclr_jit_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} variables: ${{ parameters.variables }} - frameworks: - - ${{ parameters.framework }} - steps: # Download jit builds diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index 5a82951839ff4..73432c9c408b1 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -82,6 +82,10 @@ jobs: # Limiting interp runs as we don't need as much coverage. - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20210304164434-56c6673 + # Linux s390x + - ${{ if eq(parameters.platform, 'Linux_s390x') }}: + - Ubuntu.2004.S390X.Experimental.Open + # OSX arm64 - ${{ if eq(parameters.platform, 'OSX_arm64') }}: - OSX.1100.ARM64.Open diff --git a/eng/pipelines/runtime-community.yml b/eng/pipelines/runtime-community.yml new file mode 100644 index 0000000000000..5bebcc00a2663 --- /dev/null +++ b/eng/pipelines/runtime-community.yml @@ -0,0 +1,59 @@ +trigger: none + +schedules: + - cron: "0 7,19 * * *" # run at 7:00 and 19:00 (UTC) which is 23:00 and 11:00 (PST). + displayName: Runtime-community default schedule + branches: + include: + - main + always: false # run only if there were changes since the last successful scheduled run. + +variables: + - template: /eng/pipelines/common/variables.yml + +jobs: +# +# Evaluate paths +# +- ${{ if eq(variables.dependOnEvaluatePaths, true) }}: + - template: /eng/pipelines/common/evaluate-default-paths.yml + +# +# s390x +# Build the whole product using Mono and run libraries tests +# +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + buildConfig: Release + runtimeFlavor: mono + platforms: + - Linux_s390x + variables: + # map dependencies variables to local variables + - name: librariesContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ] + - name: monoContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] + jobParameters: + testGroup: innerloop + nameSuffix: AllSubsets_Mono + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true + timeoutInMinutes: 180 + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), + eq(variables['isFullMatrix'], true)) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig) + condition: >- + or( + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isFullMatrix'], true)) diff --git a/eng/pipelines/runtime-staging.yml b/eng/pipelines/runtime-staging.yml index 580c695a01319..49fd3cdecb98d 100644 --- a/eng/pipelines/runtime-staging.yml +++ b/eng/pipelines/runtime-staging.yml @@ -1,3 +1,27 @@ +# Setting batch to true, triggers one build at a time. +# if there is a push while a build in progress, it will wait, +# until the running build finishes, and produce a build with all the changes +# that happened during the last build. +trigger: + batch: true + branches: + include: + - release/*.* + paths: + include: + - '*' + exclude: + - eng/Version.Details.xml + - .github/* + - docs/* + - CODE-OF-CONDUCT.md + - CONTRIBUTING.md + - LICENSE.TXT + - PATENTS.TXT + - README.md + - SECURITY.md + - THIRD-PARTY-NOTICES.TXT + schedules: - cron: "0 7,19 * * *" # run at 7:00 and 19:00 (UTC) which is 23:00 and 11:00 (PST). displayName: Runtime-staging default schedule @@ -160,7 +184,6 @@ jobs: extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: creator: dotnet-bot - interpreter: true testRunNamePrefixSuffix: Mono_$(_BuildConfig) condition: >- or( @@ -401,12 +424,13 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), eq(variables['isFullMatrix'], true)) # don't run tests on PRs until we can get significantly more devices - ${{ if eq(variables['isFullMatrix'], true) }}: - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: Mono_$(_BuildConfig) + # Turn off the testing for now, until https://github.com/dotnet/xharness/issues/663 gets resolved + # ${{ if eq(variables['isFullMatrix'], true) }}: + # # extra steps, run tests + # extraStepsTemplate: /eng/pipelines/common/templates/runtimes/android-runtime-and-send-to-helix.yml + # extraStepsParameters: + # creator: dotnet-bot + # testRunNamePrefixSuffix: Mono_$(_BuildConfig) # Run disabled installer tests on Linux x64 - template: /eng/pipelines/common/platform-matrix.yml diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index ddeca884f3229..b18a7ae71393b 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -79,6 +79,7 @@ jobs: - Linux_musl_arm64 - Linux_musl_x64 - OSX_arm64 + - Tizen_armel - windows_x86 - windows_x64 - windows_arm diff --git a/eng/testing/performance/blazor_perf.proj b/eng/testing/performance/blazor_perf.proj index 000bcaa43fecd..144de9f06aed2 100644 --- a/eng/testing/performance/blazor_perf.proj +++ b/eng/testing/performance/blazor_perf.proj @@ -39,13 +39,13 @@ $(WorkItemDirectory) - cd $(BlazorMinDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true%3B/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions="%24(AdditionalMonoLinkerOptions) --dump-dependencies" + cd $(BlazorMinDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true;;/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions="%24(AdditionalMonoLinkerOptions) --dump-dependencies" $(Python) test.py sod --scenario-name "%(Identity)" $(WorkItemDirectory) - cd $(BlazorMinAOTDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true%3B/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions="%24(AdditionalMonoLinkerOptions) --dump-dependencies" + cd $(BlazorMinAOTDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true;;/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions="%24(AdditionalMonoLinkerOptions) --dump-dependencies" $(Python) test.py sod --scenario-name "%(Identity)" @@ -56,7 +56,7 @@ $(WorkItemDirectory) - cd $(BlazorAOTDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true%3B/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions=%27"%24(AdditionalMonoLinkerOptions) --dump-dependencies"%27 --binlog %27./traces/blazor_publish.binlog%27 + cd $(BlazorAOTDirectory);$(Python) pre.py publish --msbuild "/p:_TrimmerDumpDependencies=true;;/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions=%27"%24(AdditionalMonoLinkerOptions) --dump-dependencies"%27 --binlog %27./traces/blazor_publish.binlog%27 $(Python) test.py sod --scenario-name "%(Identity)" $(Python) post.py @@ -70,7 +70,7 @@ $(WorkItemDirectory) - cd $(BlazorPizzaAOTDirectory);$(Python) pre.py publish -f $(PerflabTargetFrameworks) --msbuild "/p:_TrimmerDumpDependencies=true%3B/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions=%27"%24(AdditionalMonoLinkerOptions) --dump-dependencies"%27 --binlog %27./traces/blazor_publish.binlog%27 + cd $(BlazorPizzaAOTDirectory);$(Python) pre.py publish -f $(PerflabTargetFrameworks) --msbuild "/p:_TrimmerDumpDependencies=true;;/p:_MonoRuntimeComponentManifestJsonFilePath=$(WASMRuntimeConfigPath)" --msbuild-static AdditionalMonoLinkerOptions=%27"%24(AdditionalMonoLinkerOptions) --dump-dependencies"%27 --binlog %27./traces/blazor_publish.binlog%27 $(Python) test.py sod --scenario-name "%(Identity)" --dirs $(PizzaAppPubLocation) $(Python) post.py 1:00 diff --git a/eng/testing/performance/performance-setup.ps1 b/eng/testing/performance/performance-setup.ps1 index b4db23932ce34..ae30e9bac80ea 100644 --- a/eng/testing/performance/performance-setup.ps1 +++ b/eng/testing/performance/performance-setup.ps1 @@ -28,51 +28,6 @@ Param( [switch] $iOSLlvmBuild ) -function Verified-Move-Item { - [CmdletBinding()] - param( - [Parameter(mandatory=$true)] - [string]$Path, - [Parameter(mandatory=$true)] - [string]$Destination - ) - - Move-Item -Path $Path -Destination $Destination - if (!$?) { - Write-Output "Failed to move $Path to $Destination" - exit 1 - } -} - -function Verified-Copy-Item { - [CmdletBinding()] - param( - [Parameter(mandatory=$true)] - [string]$Path, - [Parameter(mandatory=$true)] - [string]$Destination - ) - - Copy-Item -path $Path $Destination - if (!$?) { - Write-Output "Failed to copy $Path to $Destination" - exit 1 - } -} - -function Verify-Robocopy { - [CmdletBinding()] - param( - [Parameter(mandatory=$true)] - [string]$Source - ) - - if ($LASTEXITCODE -ne 0 -or !$?) { - Write-Output "Failed to copy ${Source}: exit code $LASTEXITCODE" - exit $LASTEXITCODE - } -} - $RunFromPerformanceRepo = ($Repository -eq "dotnet/performance") -or ($Repository -eq "dotnet-performance") $UseCoreRun = ($CoreRootDirectory -ne [string]::Empty) $UseBaselineCoreRun = ($BaselineCoreRootDirectory -ne [string]::Empty) @@ -167,30 +122,25 @@ if ($RunFromPerformanceRepo) { $SetupArguments = "--perf-hash $CommitSha $CommonSetupArguments" robocopy $SourceDirectory $PerformanceDirectory /E /XD $PayloadDirectory $SourceDirectory\artifacts $SourceDirectory\.git - Verify-Robocopy $SourceDirectory } else { git clone --branch main --depth 1 --quiet https://github.com/dotnet/performance $PerformanceDirectory - if ($LASTEXITCODE -ne 0) { - Write-Output "git clone failed with code $LASTEXITCODE" - exit 1 - } } if($MonoDotnet -ne "") { $UsingMono = "true" $MonoDotnetPath = (Join-Path $PayloadDirectory "dotnet-mono") - Verified-Move-Item -Path $MonoDotnet -Destination $MonoDotnetPath + Move-Item -Path $MonoDotnet -Destination $MonoDotnetPath } if ($UseCoreRun) { $NewCoreRoot = (Join-Path $PayloadDirectory "Core_Root") - Verified-Move-Item -Path $CoreRootDirectory -Destination $NewCoreRoot + Move-Item -Path $CoreRootDirectory -Destination $NewCoreRoot } if ($UseBaselineCoreRun) { $NewBaselineCoreRoot = (Join-Path $PayloadDirectory "Baseline_Core_Root") - Verified-Move-Item -Path $BaselineCoreRootDirectory -Destination $NewBaselineCoreRoot + Move-Item -Path $BaselineCoreRootDirectory -Destination $NewBaselineCoreRoot } if ($AndroidMono) { @@ -198,7 +148,7 @@ if ($AndroidMono) { { mkdir $WorkItemDirectory } - Verified-Copy-Item -Path "$SourceDirectory\artifacts\bin\AndroidSampleApp\arm64\Release\android-arm64\publish\apk\bin\HelloAndroid.apk" $PayloadDirectory + Copy-Item -path "$SourceDirectory\artifacts\bin\AndroidSampleApp\arm64\Release\android-arm64\publish\apk\bin\HelloAndroid.apk" $PayloadDirectory $SetupArguments = $SetupArguments -replace $Architecture, 'arm64' } @@ -208,9 +158,9 @@ if ($iOSMono) { mkdir $WorkItemDirectory } if($iOSLlvmBuild) { - Verified-Copy-Item -Path "$SourceDirectory\iosHelloWorld\llvm" $PayloadDirectory\iosHelloWorld\llvm -Recurse + Copy-Item -path "$SourceDirectory\iosHelloWorld\llvm" $PayloadDirectory\iosHelloWorld\llvm -Recurse } else { - Verified-Copy-Item -Path "$SourceDirectory\iosHelloWorld\nollvm" $PayloadDirectory\iosHelloWorld\nollvm -Recurse + Copy-Item -path "$SourceDirectory\iosHelloWorld\nollvm" $PayloadDirectory\iosHelloWorld\nollvm -Recurse } $SetupArguments = $SetupArguments -replace $Architecture, 'arm64' @@ -218,7 +168,6 @@ if ($iOSMono) { $DocsDir = (Join-Path $PerformanceDirectory "docs") robocopy $DocsDir $WorkItemDirectory -Verify-Robocopy $DocsDir # Set variables that we will need to have in future steps $ci = $true diff --git a/eng/testing/performance/performance-setup.sh b/eng/testing/performance/performance-setup.sh index c897b1019aae6..cffd9ca8d6cdb 100755 --- a/eng/testing/performance/performance-setup.sh +++ b/eng/testing/performance/performance-setup.sh @@ -31,24 +31,6 @@ use_latest_dotnet=false logical_machine= javascript_engine="v8" -verified_mv() -{ - mv $1 $2 - if [ "$?" -ne "0" ]; then - echo "Failed to move $1 to $2" - exit 1 - fi -} - -verified_rsync() -{ - rsync -a --progress $1 $2 - if [ "$?" -ne "0" ]; then - echo "Failed to sync $1 to $2" - exit 1 - fi -} - while (($# > 0)); do lowerI="$(echo $1 | tr "[:upper:]" "[:lower:]")" case $lowerI in @@ -289,28 +271,24 @@ else git clone --branch main --depth 1 --quiet https://github.com/dotnet/performance.git $performance_directory # uncomment to use BenchmarkDotNet sources instead of nuget packages # git clone https://github.com/dotnet/BenchmarkDotNet.git $benchmark_directory - if [ "$?" -ne "0" ]; then - echo "git clone failed with code $?" - exit 1 - fi - + docs_directory=$performance_directory/docs - verified_mv $docs_directory $workitem_directory + mv $docs_directory $workitem_directory fi if [[ "$wasm_runtime_loc" != "" ]]; then using_wasm=true wasm_dotnet_path=$payload_directory/dotnet-wasm - verified_mv $wasm_runtime_loc $wasm_dotnet_path + mv $wasm_runtime_loc $wasm_dotnet_path # install emsdk, $source_directory/src/mono/wasm/ has the nuget.config with require feed. EMSDK may be available in the payload in a different directory, should visit this install to avoid deplicated payload. pushd $source_directory/src/mono/wasm/ make provision-wasm EMSDK_PATH = $source_directory/src/mono/wasm/emsdk popd # wasm aot and interpreter need some source code from dotnet\runtime repo - verified_rsync -aq --progress $source_directory/* $wasm_dotnet_path --exclude Payload --exclude docs --exclude src/coreclr --exclude src/tests --exclude artifacts/obj --exclude artifacts/log --exclude artifacts/tests --exclude __download__ + rsync -aq --progress $source_directory/* $wasm_dotnet_path --exclude Payload --exclude docs --exclude src/coreclr --exclude src/tests --exclude artifacts/obj --exclude artifacts/log --exclude artifacts/tests --exclude __download__ # copy wasm build drop to the location that aot and interpreter build expects - verified_rsync -a --progress $wasm_dotnet_path/artifacts/BrowserWasm/artifacts/* $wasm_dotnet_path/artifacts + rsync -a --progress $wasm_dotnet_path/artifacts/BrowserWasm/artifacts/* $wasm_dotnet_path/artifacts rm -r $wasm_dotnet_path/artifacts/BrowserWasm/artifacts if [[ "$wasmaot" == "true" ]]; then extra_benchmark_dotnet_arguments="$extra_benchmark_dotnet_arguments --wasmEngine /home/helixbot/.jsvu/$javascript_engine --runtimeSrcDir \$HELIX_CORRELATION_PAYLOAD/dotnet-wasm --aotcompilermode wasm --buildTimeout 3600" @@ -322,23 +300,23 @@ fi if [[ "$mono_dotnet" != "" ]] && [[ "$monoaot" == "false" ]]; then using_mono=true mono_dotnet_path=$payload_directory/dotnet-mono - verified_mv $mono_dotnet $mono_dotnet_path + mv $mono_dotnet $mono_dotnet_path fi if [[ "$monoaot" == "true" ]]; then monoaot_dotnet_path=$payload_directory/monoaot - verified_mv $monoaot_path $monoaot_dotnet_path + mv $monoaot_path $monoaot_dotnet_path extra_benchmark_dotnet_arguments="$extra_benchmark_dotnet_arguments --runtimes monoaotllvm --aotcompilerpath \$HELIX_CORRELATION_PAYLOAD/monoaot/sgen/mini/mono-sgen --customruntimepack \$HELIX_CORRELATION_PAYLOAD/monoaot/pack --aotcompilermode llvm" fi if [[ "$use_core_run" = true ]]; then new_core_root=$payload_directory/Core_Root - verified_mv $core_root_directory $new_core_root + mv $core_root_directory $new_core_root fi if [[ "$use_baseline_core_run" = true ]]; then - new_baseline_core_root=$payload_directory/Baseline_Core_Root - verified_mv $baseline_core_root_directory $new_baseline_core_root + new_baseline_core_root=$payload_directory/Baseline_Core_Root + mv $baseline_core_root_directory $new_baseline_core_root fi ci=true diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index 58dbfac94db89..acce583b8a96c 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -42,6 +42,12 @@ $(AdditionalXHarnessArguments) --arg=-c=$(XUnitClassName) + + + $(AdditionalXHarnessArguments) -- -m=$(XUnitMethodName) + $(AdditionalXHarnessArguments) -- -c=$(XUnitClassName) + + diff --git a/global.json b/global.json index 6eac323f59052..7d377cb4057e7 100644 --- a/global.json +++ b/global.json @@ -12,12 +12,12 @@ "python3": "3.7.1" }, "msbuild-sdks": { - "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "7.0.0-beta.21474.2", - "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.21474.2", - "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.21474.2", - "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.21474.2", + "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "7.0.0-beta.21514.3", + "Microsoft.DotNet.Arcade.Sdk": "7.0.0-beta.21514.3", + "Microsoft.DotNet.Helix.Sdk": "7.0.0-beta.21514.3", + "Microsoft.DotNet.SharedFramework.Sdk": "7.0.0-beta.21514.3", "Microsoft.Build.NoTargets": "3.1.0", "Microsoft.Build.Traversal": "3.0.23", - "Microsoft.NET.Sdk.IL": "7.0.0-alpha.1.21476.2" + "Microsoft.NET.Sdk.IL": "7.0.0-alpha.1.21511.2" } } diff --git a/src/coreclr/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.pkgproj b/src/coreclr/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.pkgproj index 95d6c747fb428..6c95feffc7d0e 100644 --- a/src/coreclr/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.pkgproj +++ b/src/coreclr/.nuget/Microsoft.NETCore.TestHost/Microsoft.NETCore.TestHost.pkgproj @@ -2,6 +2,8 @@ + + false CoreCLR application host for test applications. diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs index 74849de7d1ed8..fda6459b2551d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs @@ -30,9 +30,6 @@ internal RuntimeType[] GetDefinedTypes() { return GetTypes(this); } - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool IsResource(RuntimeModule module); #endregion #region Module overrides @@ -472,7 +469,8 @@ public override Guid ModuleVersionId public override bool IsResource() { - return IsResource(this); + // CoreClr does not support resource-only modules. + return false; } [RequiresUnreferencedCode("Fields might be removed")] diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/standardpch.h b/src/coreclr/ToolBox/superpmi/superpmi-shared/standardpch.h index 731e8305da695..1dfae365bc4db 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shared/standardpch.h +++ b/src/coreclr/ToolBox/superpmi/superpmi-shared/standardpch.h @@ -68,12 +68,14 @@ #ifdef TARGET_UNIX #include "clr_std/string" #include "clr_std/algorithm" +#include "clr_std/vector" #else // !TARGET_UNIX #ifndef USE_STL #define USE_STL #endif // USE_STL #include #include +#include #endif // !TARGET_UNIX #ifdef USE_MSVCDIS diff --git a/src/coreclr/ToolBox/superpmi/superpmi/CMakeLists.txt b/src/coreclr/ToolBox/superpmi/superpmi/CMakeLists.txt index 92cda6d5600fe..4827c195dc299 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi/CMakeLists.txt +++ b/src/coreclr/ToolBox/superpmi/superpmi/CMakeLists.txt @@ -22,6 +22,7 @@ set(SUPERPMI_SOURCES jitdebugger.cpp jitinstance.cpp methodstatsemitter.cpp + metricssummary.cpp neardiffer.cpp parallelsuperpmi.cpp superpmi.cpp diff --git a/src/coreclr/ToolBox/superpmi/superpmi/commandline.cpp b/src/coreclr/ToolBox/superpmi/superpmi/commandline.cpp index e4d98a13752d6..c4735b23d7527 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi/commandline.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi/commandline.cpp @@ -81,6 +81,16 @@ void CommandLine::DumpHelp(const char* program) printf(" t - method throughput time\n"); printf(" * - all available method stats\n"); printf("\n"); + printf(" -metricsSummary , -baseMetricsSummary \n"); + printf(" Emit a summary of metrics to the specified file\n"); + printf(" Currently includes:\n"); + printf(" Total number of successful SPMI compiles\n"); + printf(" Total number of failing SPMI compiles\n"); + printf(" Total amount of ASM code in bytes\n"); + printf("\n"); + printf(" -diffMetricsSummary \n"); + printf(" Same as above, but emit for the diff/second JIT"); + printf("\n"); printf(" -a[pplyDiff]\n"); printf(" Compare the compile result generated from the provided JIT with the\n"); printf(" compile result stored with the MC. If two JITs are provided, this\n"); @@ -374,6 +384,26 @@ bool CommandLine::Parse(int argc, char* argv[], /* OUT */ Options* o) o->methodStatsTypes = argv[i]; } + else if ((_strnicmp(&argv[i][1], "metricsSummary", argLen) == 0) || (_strnicmp(&argv[i][1], "baseMetricsSummary", argLen) == 0)) + { + if (++i >= argc) + { + DumpHelp(argv[0]); + return false; + } + + o->baseMetricsSummaryFile = argv[i]; + } + else if ((_strnicmp(&argv[i][1], "diffMetricsSummary", argLen) == 0)) + { + if (++i >= argc) + { + DumpHelp(argv[0]); + return false; + } + + o->diffMetricsSummaryFile = argv[i]; + } else if ((_strnicmp(&argv[i][1], "applyDiff", argLen) == 0)) { o->applyDiff = true; diff --git a/src/coreclr/ToolBox/superpmi/superpmi/commandline.h b/src/coreclr/ToolBox/superpmi/superpmi/commandline.h index e9bae5740262b..055adf00295cd 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi/commandline.h +++ b/src/coreclr/ToolBox/superpmi/superpmi/commandline.h @@ -36,6 +36,8 @@ class CommandLine , indexes(nullptr) , hash(nullptr) , methodStatsTypes(nullptr) + , baseMetricsSummaryFile(nullptr) + , diffMetricsSummaryFile(nullptr) , mclFilename(nullptr) , diffMCLFilename(nullptr) , targetArchitecture(nullptr) @@ -67,6 +69,8 @@ class CommandLine int* indexes; char* hash; char* methodStatsTypes; + char* baseMetricsSummaryFile; + char* diffMetricsSummaryFile; char* mclFilename; char* diffMCLFilename; char* targetArchitecture; diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jitinstance.cpp b/src/coreclr/ToolBox/superpmi/superpmi/jitinstance.cpp index fafc367669d47..96484d4b86bcd 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi/jitinstance.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi/jitinstance.cpp @@ -8,6 +8,7 @@ #include "jithost.h" #include "errorhandling.h" #include "spmiutil.h" +#include "metricssummary.h" JitInstance* JitInstance::InitJit(char* nameOfJit, bool breakOnAssert, @@ -276,7 +277,7 @@ bool JitInstance::reLoad(MethodContext* firstContext) return true; } -JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, int mcIndex, bool collectThroughput) +JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, int mcIndex, bool collectThroughput, MetricsSummary* metrics) { struct Param : FilterSuperPMIExceptionsParam_CaptureException { @@ -286,12 +287,14 @@ JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, i unsigned flags; int mcIndex; bool collectThroughput; + MetricsSummary* metrics; } param; param.pThis = this; param.result = RESULT_SUCCESS; // assume success param.flags = 0; param.mcIndex = mcIndex; param.collectThroughput = collectThroughput; + param.metrics = metrics; // store to instance field our raw values, so we can figure things out a bit later... mc = MethodToCompile; @@ -365,11 +368,16 @@ JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, i pParam->pThis->mc->cr->recAllocGCInfoCapture(); pParam->pThis->mc->cr->recMessageLog("Successful Compile"); + + pParam->metrics->SuccessfulCompiles++; + pParam->metrics->NumCodeBytes += NCodeSizeBlock; } else { LogDebug("compileMethod failed with result %d", jitResult); pParam->result = RESULT_ERROR; + + pParam->metrics->FailingCompiles++; } } PAL_EXCEPT_FILTER(FilterSuperPMIExceptions_CaptureExceptionAndStop) diff --git a/src/coreclr/ToolBox/superpmi/superpmi/jitinstance.h b/src/coreclr/ToolBox/superpmi/superpmi/jitinstance.h index c572008481a65..8e8fbabf82ead 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi/jitinstance.h +++ b/src/coreclr/ToolBox/superpmi/superpmi/jitinstance.h @@ -60,7 +60,7 @@ class JitInstance bool resetConfig(MethodContext* firstContext); - Result CompileMethod(MethodContext* MethodToCompile, int mcIndex, bool collectThroughput); + Result CompileMethod(MethodContext* MethodToCompile, int mcIndex, bool collectThroughput, class MetricsSummary* summary); const WCHAR* getForceOption(const WCHAR* key); const WCHAR* getOption(const WCHAR* key); diff --git a/src/coreclr/ToolBox/superpmi/superpmi/methodstatsemitter.h b/src/coreclr/ToolBox/superpmi/superpmi/methodstatsemitter.h index 083d24fe852a9..40d38698b3d44 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi/methodstatsemitter.h +++ b/src/coreclr/ToolBox/superpmi/superpmi/methodstatsemitter.h @@ -24,4 +24,5 @@ class MethodStatsEmitter void Emit(int methodNumber, MethodContext* mc, ULONGLONG firstTime, ULONGLONG secondTime); void SetStatsTypes(char* types); }; + #endif diff --git a/src/coreclr/ToolBox/superpmi/superpmi/metricssummary.cpp b/src/coreclr/ToolBox/superpmi/superpmi/metricssummary.cpp new file mode 100644 index 0000000000000..e7c725d7845bf --- /dev/null +++ b/src/coreclr/ToolBox/superpmi/superpmi/metricssummary.cpp @@ -0,0 +1,90 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "standardpch.h" +#include "metricssummary.h" +#include "logging.h" + +struct HandleCloser +{ + void operator()(HANDLE hFile) + { + CloseHandle(hFile); + } +}; + +struct FileHandleWrapper +{ + FileHandleWrapper(HANDLE hFile) + : hFile(hFile) + { + } + + ~FileHandleWrapper() + { + CloseHandle(hFile); + } + + HANDLE get() { return hFile; } + +private: + HANDLE hFile; +}; + +bool MetricsSummary::SaveToFile(const char* path) +{ + FileHandleWrapper file(CreateFile(path, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr)); + if (file.get() == INVALID_HANDLE_VALUE) + { + return false; + } + + char buffer[4096]; + int len = + sprintf_s(buffer, sizeof(buffer), "Successful compiles,Failing compiles,Code bytes\n%d,%d,%lld\n", + SuccessfulCompiles, FailingCompiles, NumCodeBytes); + DWORD numWritten; + if (!WriteFile(file.get(), buffer, static_cast(len), &numWritten, nullptr) || numWritten != static_cast(len)) + { + return false; + } + + return true; +} + +bool MetricsSummary::LoadFromFile(const char* path, MetricsSummary* metrics) +{ + FileHandleWrapper file(CreateFile(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr)); + if (file.get() == INVALID_HANDLE_VALUE) + { + return false; + } + + LARGE_INTEGER len; + if (!GetFileSizeEx(file.get(), &len)) + { + return false; + } + + std::vector content(static_cast(len.QuadPart)); + DWORD numRead; + if (!ReadFile(file.get(), content.data(), static_cast(content.size()), &numRead, nullptr) || numRead != content.size()) + { + return false; + } + + if (sscanf_s(content.data(), "Successful compiles,Failing compiles,Code bytes\n%d,%d,%lld\n", + &metrics->SuccessfulCompiles, &metrics->FailingCompiles, &metrics->NumCodeBytes) != 3) + { + return false; + } + + return true; +} + +void MetricsSummary::AggregateFrom(const MetricsSummary& other) +{ + SuccessfulCompiles += other.SuccessfulCompiles; + FailingCompiles += other.FailingCompiles; + NumCodeBytes += other.NumCodeBytes; +} diff --git a/src/coreclr/ToolBox/superpmi/superpmi/metricssummary.h b/src/coreclr/ToolBox/superpmi/superpmi/metricssummary.h new file mode 100644 index 0000000000000..4f7d825c2d43a --- /dev/null +++ b/src/coreclr/ToolBox/superpmi/superpmi/metricssummary.h @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef _MetricsSummary +#define _MetricsSummary + +class MetricsSummary +{ +public: + int SuccessfulCompiles; + int FailingCompiles; + long long NumCodeBytes; + + MetricsSummary() + : SuccessfulCompiles(0) + , FailingCompiles(0) + , NumCodeBytes(0) + { + } + + bool SaveToFile(const char* path); + static bool LoadFromFile(const char* path, MetricsSummary* metrics); + void AggregateFrom(const MetricsSummary& other); +}; + +#endif diff --git a/src/coreclr/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp b/src/coreclr/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp index 46c1a7a91132d..92b172e196d1c 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp @@ -8,6 +8,7 @@ #include "lightweightmap.h" #include "commandline.h" #include "errorhandling.h" +#include "metricssummary.h" #define MAX_LOG_LINE_SIZE 0x1000 // 4 KB @@ -293,6 +294,35 @@ void ProcessChildStdOut(const CommandLine::Options& o, } } +static bool ProcessChildMetrics(const char* baseMetricsSummaryPath, const char* diffMetricsSummaryPath, MetricsSummary* baseMetrics, MetricsSummary* diffMetrics) +{ + if (baseMetricsSummaryPath != nullptr) + { + MetricsSummary childBaseMetrics; + if (!MetricsSummary::LoadFromFile(baseMetricsSummaryPath, &childBaseMetrics)) + { + LogError("Couldn't load base metrics summary created by child process"); + return false; + } + + baseMetrics->AggregateFrom(childBaseMetrics); + } + + if (diffMetricsSummaryPath != nullptr) + { + MetricsSummary childDiffMetrics; + if (!MetricsSummary::LoadFromFile(diffMetricsSummaryPath, &childDiffMetrics)) + { + LogError("Couldn't load diff metrics summary created by child process"); + return false; + } + + diffMetrics->AggregateFrom(childDiffMetrics); + } + + return true; +} + #ifndef TARGET_UNIX // TODO-Porting: handle Ctrl-C signals gracefully on Unix BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) { @@ -309,15 +339,39 @@ int __cdecl compareInt(const void* arg1, const void* arg2) return (*(const int*)arg1) - (*(const int*)arg2); } -// 'arrWorkerMCLPath' is an array of strings of size 'workerCount'. -void MergeWorkerMCLs(char* mclFilename, char** arrWorkerMCLPath, int workerCount) +struct PerWorkerData +{ + HANDLE hStdOutput; + HANDLE hStdError; + + char* failingMCListPath; + char* diffMCListPath; + char* stdOutputPath; + char* stdErrorPath; + char* baseMetricsSummaryPath; + char* diffMetricsSummaryPath; + + PerWorkerData() + : hStdOutput(INVALID_HANDLE_VALUE) + , hStdError(INVALID_HANDLE_VALUE) + , failingMCListPath(nullptr) + , diffMCListPath(nullptr) + , stdOutputPath(nullptr) + , stdErrorPath(nullptr) + , baseMetricsSummaryPath(nullptr) + , diffMetricsSummaryPath(nullptr) + { + } +}; + +void MergeWorkerMCLs(char* mclFilename, PerWorkerData* workerData, int workerCount, char* PerWorkerData::*mclPath) { int **MCL = new int *[workerCount], *MCLCount = new int[workerCount], totalCount = 0; for (int i = 0; i < workerCount; i++) { // Read the next partial MCL file - ReadMCLToArray(arrWorkerMCLPath[i], &MCL[i], &MCLCount[i]); + ReadMCLToArray(workerData[i].*mclPath, &MCL[i], &MCLCount[i]); totalCount += MCLCount[i]; } @@ -474,14 +528,7 @@ int doParallelSuperPMI(CommandLine::Options& o) LogVerbose(" diffMCLFilename=%s", o.diffMCLFilename); LogVerbose(" workerCount=%d, skipCleanup=%d.", o.workerCount, o.skipCleanup); - HANDLE* hProcesses = new HANDLE[o.workerCount]; - HANDLE* hStdOutput = new HANDLE[o.workerCount]; - HANDLE* hStdError = new HANDLE[o.workerCount]; - - char** arrFailingMCListPath = new char*[o.workerCount]; - char** arrDiffMCListPath = new char*[o.workerCount]; - char** arrStdOutputPath = new char*[o.workerCount]; - char** arrStdErrorPath = new char*[o.workerCount]; + PerWorkerData* perWorkerData = new PerWorkerData[o.workerCount]; // Add a random number to the temporary file names to allow multiple parallel SuperPMI to happen at once. unsigned int randNumber = 0; @@ -493,51 +540,71 @@ int doParallelSuperPMI(CommandLine::Options& o) for (int i = 0; i < o.workerCount; i++) { + PerWorkerData& wd = perWorkerData[i]; if (o.mclFilename != nullptr) { - arrFailingMCListPath[i] = new char[MAX_PATH]; - sprintf_s(arrFailingMCListPath[i], MAX_PATH, "%sParallelSuperPMI-%u-%d.mcl", tempPath, randNumber, i); + wd.failingMCListPath = new char[MAX_PATH]; + sprintf_s(wd.failingMCListPath, MAX_PATH, "%sParallelSuperPMI-%u-%d.mcl", tempPath, randNumber, i); } - else + + if (o.diffMCLFilename != nullptr) { - arrFailingMCListPath[i] = nullptr; + wd.diffMCListPath = new char[MAX_PATH]; + sprintf_s(wd.diffMCListPath, MAX_PATH, "%sParallelSuperPMI-Diff-%u-%d.mcl", tempPath, randNumber, i); } - if (o.diffMCLFilename != nullptr) + if (o.baseMetricsSummaryFile != nullptr) { - arrDiffMCListPath[i] = new char[MAX_PATH]; - sprintf_s(arrDiffMCListPath[i], MAX_PATH, "%sParallelSuperPMI-Diff-%u-%d.mcl", tempPath, randNumber, i); + wd.baseMetricsSummaryPath = new char[MAX_PATH]; + sprintf_s(wd.baseMetricsSummaryPath, MAX_PATH, "%sParallelSuperPMI-BaseMetricsSummary-%u-%d.txt", tempPath, randNumber, i); } - else + + if (o.diffMetricsSummaryFile != nullptr) { - arrDiffMCListPath[i] = nullptr; + wd.diffMetricsSummaryPath = new char[MAX_PATH]; + sprintf_s(wd.diffMetricsSummaryPath, MAX_PATH, "%sParallelSuperPMI-DiffMetricsSummary-%u-%d.txt", tempPath, randNumber, i); } - arrStdOutputPath[i] = new char[MAX_PATH]; - arrStdErrorPath[i] = new char[MAX_PATH]; + wd.stdOutputPath = new char[MAX_PATH]; + wd.stdErrorPath = new char[MAX_PATH]; - sprintf_s(arrStdOutputPath[i], MAX_PATH, "%sParallelSuperPMI-stdout-%u-%d.txt", tempPath, randNumber, i); - sprintf_s(arrStdErrorPath[i], MAX_PATH, "%sParallelSuperPMI-stderr-%u-%d.txt", tempPath, randNumber, i); + sprintf_s(wd.stdOutputPath, MAX_PATH, "%sParallelSuperPMI-stdout-%u-%d.txt", tempPath, randNumber, i); + sprintf_s(wd.stdErrorPath, MAX_PATH, "%sParallelSuperPMI-stderr-%u-%d.txt", tempPath, randNumber, i); } char cmdLine[MAX_CMDLINE_SIZE]; cmdLine[0] = '\0'; int bytesWritten; + HANDLE* hProcesses = new HANDLE[o.workerCount]; for (int i = 0; i < o.workerCount; i++) { bytesWritten = sprintf_s(cmdLine, MAX_CMDLINE_SIZE, "%s -stride %d %d", spmiFilename, i + 1, o.workerCount); - if (o.mclFilename != nullptr) + PerWorkerData& wd = perWorkerData[i]; + + if (wd.failingMCListPath != nullptr) { bytesWritten += sprintf_s(cmdLine + bytesWritten, MAX_CMDLINE_SIZE - bytesWritten, " -failingMCList %s", - arrFailingMCListPath[i]); + wd.failingMCListPath); } - if (o.diffMCLFilename != nullptr) + if (wd.diffMCListPath != nullptr) { bytesWritten += sprintf_s(cmdLine + bytesWritten, MAX_CMDLINE_SIZE - bytesWritten, " -diffMCList %s", - arrDiffMCListPath[i]); + wd.diffMCListPath); + } + + if (wd.baseMetricsSummaryPath != nullptr) + { + bytesWritten += sprintf_s(cmdLine + bytesWritten, MAX_CMDLINE_SIZE - bytesWritten, " -baseMetricsSummary %s", + wd.baseMetricsSummaryPath); + } + + if (wd.diffMetricsSummaryPath != nullptr) + { + bytesWritten += sprintf_s(cmdLine + bytesWritten, MAX_CMDLINE_SIZE - bytesWritten, " -diffMetricsSummary %s", + wd.diffMetricsSummaryPath); } if (o.failureLimit > 0) @@ -553,26 +620,26 @@ int doParallelSuperPMI(CommandLine::Options& o) sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; // Let newly created stdout/stderr handles be inherited. - LogDebug("stdout %i=%s", i, arrStdOutputPath[i]); - hStdOutput[i] = CreateFileA(arrStdOutputPath[i], GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, + LogDebug("stdout %i=%s", i, wd.stdOutputPath); + wd.hStdOutput = CreateFileA(wd.stdOutputPath, GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hStdOutput[i] == INVALID_HANDLE_VALUE) + if (wd.hStdOutput == INVALID_HANDLE_VALUE) { - LogError("Unable to open '%s'. GetLastError()=%u", arrStdOutputPath[i], GetLastError()); + LogError("Unable to open '%s'. GetLastError()=%u", wd.stdOutputPath, GetLastError()); return -1; } - LogDebug("stderr %i=%s", i, arrStdErrorPath[i]); - hStdError[i] = CreateFileA(arrStdErrorPath[i], GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, + LogDebug("stderr %i=%s", i, wd.stdErrorPath); + wd.hStdError = CreateFileA(wd.stdErrorPath, GENERIC_WRITE, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hStdError[i] == INVALID_HANDLE_VALUE) + if (wd.hStdError == INVALID_HANDLE_VALUE) { - LogError("Unable to open '%s'. GetLastError()=%u", arrStdErrorPath[i], GetLastError()); + LogError("Unable to open '%s'. GetLastError()=%u", wd.stdErrorPath, GetLastError()); return -1; } // Create a SuperPMI worker process and redirect its output to file - if (!StartProcess(cmdLine, hStdOutput[i], hStdError[i], &hProcesses[i])) + if (!StartProcess(cmdLine, wd.hStdOutput, wd.hStdError, &hProcesses[i])) { return -1; } @@ -583,8 +650,8 @@ int doParallelSuperPMI(CommandLine::Options& o) // Close stdout/stderr for (int i = 0; i < o.workerCount; i++) { - CloseHandle(hStdOutput[i]); - CloseHandle(hStdError[i]); + CloseHandle(perWorkerData[i].hStdOutput); + CloseHandle(perWorkerData[i].hStdError); } SpmiResult result = SpmiResult::Success; @@ -626,13 +693,18 @@ int doParallelSuperPMI(CommandLine::Options& o) bool usageError = false; // variable to flag if we hit a usage error in SuperPMI int loaded = 0, jitted = 0, failed = 0, excluded = 0, missing = 0, diffs = 0; + MetricsSummary baseMetrics; + MetricsSummary diffMetrics; // Read the stderr files and log them as errors // Read the stdout files and parse them for counts and log any MISSING or ISSUE errors for (int i = 0; i < o.workerCount; i++) { - ProcessChildStdErr(arrStdErrorPath[i]); - ProcessChildStdOut(o, arrStdOutputPath[i], &loaded, &jitted, &failed, &excluded, &missing, &diffs, &usageError); + PerWorkerData& wd = perWorkerData[i]; + ProcessChildStdErr(wd.stdErrorPath); + ProcessChildStdOut(o, wd.stdOutputPath, &loaded, &jitted, &failed, &excluded, &missing, &diffs, &usageError); + ProcessChildMetrics(wd.baseMetricsSummaryPath, wd.diffMetricsSummaryPath, &baseMetrics, &diffMetrics); + if (usageError) break; } @@ -640,13 +712,23 @@ int doParallelSuperPMI(CommandLine::Options& o) if (o.mclFilename != nullptr && !usageError) { // Concat the resulting .mcl files - MergeWorkerMCLs(o.mclFilename, arrFailingMCListPath, o.workerCount); + MergeWorkerMCLs(o.mclFilename, perWorkerData, o.workerCount, &PerWorkerData::failingMCListPath); } if (o.diffMCLFilename != nullptr && !usageError) { // Concat the resulting diff .mcl files - MergeWorkerMCLs(o.diffMCLFilename, arrDiffMCListPath, o.workerCount); + MergeWorkerMCLs(o.diffMCLFilename, perWorkerData, o.workerCount, &PerWorkerData::diffMCListPath); + } + + if (o.baseMetricsSummaryFile != nullptr && !usageError) + { + baseMetrics.SaveToFile(o.baseMetricsSummaryFile); + } + + if (o.diffMetricsSummaryFile != nullptr && !usageError) + { + diffMetrics.SaveToFile(o.diffMetricsSummaryFile); } if (!usageError) @@ -670,16 +752,25 @@ int doParallelSuperPMI(CommandLine::Options& o) // Delete all temporary files generated for (int i = 0; i < o.workerCount; i++) { - if (arrFailingMCListPath[i] != nullptr) + PerWorkerData& wd = perWorkerData[i]; + if (wd.failingMCListPath != nullptr) + { + DeleteFile(wd.failingMCListPath); + } + if (wd.diffMCListPath != nullptr) + { + DeleteFile(wd.diffMCListPath); + } + if (wd.baseMetricsSummaryPath != nullptr) { - DeleteFile(arrFailingMCListPath[i]); + DeleteFile(wd.baseMetricsSummaryPath); } - if (arrDiffMCListPath[i] != nullptr) + if (wd.diffMetricsSummaryPath != nullptr) { - DeleteFile(arrDiffMCListPath[i]); + DeleteFile(wd.diffMetricsSummaryPath); } - DeleteFile(arrStdOutputPath[i]); - DeleteFile(arrStdErrorPath[i]); + DeleteFile(wd.stdOutputPath); + DeleteFile(wd.stdErrorPath); } } diff --git a/src/coreclr/ToolBox/superpmi/superpmi/superpmi.cpp b/src/coreclr/ToolBox/superpmi/superpmi/superpmi.cpp index 640dfd367a7f3..5410240bdad33 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi/superpmi.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi/superpmi.cpp @@ -18,6 +18,7 @@ #include "mclist.h" #include "methodstatsemitter.h" #include "spmiutil.h" +#include "metricssummary.h" extern int doParallelSuperPMI(CommandLine::Options& o); @@ -264,6 +265,9 @@ int __cdecl main(int argc, char* argv[]) } } + MetricsSummary baseMetrics; + MetricsSummary diffMetrics; + while (true) { MethodContextBuffer mcb = reader->GetNextMethodContext(); @@ -360,7 +364,7 @@ int __cdecl main(int argc, char* argv[]) jittedCount++; st3.Start(); - res = jit->CompileMethod(mc, reader->GetMethodContextIndex(), collectThroughput); + res = jit->CompileMethod(mc, reader->GetMethodContextIndex(), collectThroughput, &baseMetrics); st3.Stop(); LogDebug("Method %d compiled in %fms, result %d", reader->GetMethodContextIndex(), st3.GetMilliseconds(), res); @@ -378,7 +382,7 @@ int __cdecl main(int argc, char* argv[]) mc->cr = new CompileResult(); st4.Start(); - res2 = jit2->CompileMethod(mc, reader->GetMethodContextIndex(), collectThroughput); + res2 = jit2->CompileMethod(mc, reader->GetMethodContextIndex(), collectThroughput, &diffMetrics); st4.Stop(); LogDebug("Method %d compiled by JIT2 in %fms, result %d", reader->GetMethodContextIndex(), st4.GetMilliseconds(), res2); @@ -603,6 +607,16 @@ int __cdecl main(int argc, char* argv[]) st2.Stop(); LogVerbose("Total time: %fms", st2.GetMilliseconds()); + if (o.baseMetricsSummaryFile != nullptr) + { + baseMetrics.SaveToFile(o.baseMetricsSummaryFile); + } + + if (o.diffMetricsSummaryFile != nullptr) + { + diffMetrics.SaveToFile(o.diffMetricsSummaryFile); + } + if (methodStatsEmitter != nullptr) { delete methodStatsEmitter; diff --git a/src/coreclr/binder/bindertracing.cpp b/src/coreclr/binder/bindertracing.cpp index b03eb2f66db5f..499e20d928887 100644 --- a/src/coreclr/binder/bindertracing.cpp +++ b/src/coreclr/binder/bindertracing.cpp @@ -147,12 +147,12 @@ namespace DomainAssembly *parentAssembly = spec->GetParentAssembly(); if (parentAssembly != nullptr) { - PEAssembly *peAssembly = parentAssembly->GetFile(); - _ASSERTE(peAssembly != nullptr); - peAssembly->GetDisplayName(request.RequestingAssembly); + PEAssembly *pPEAssembly = parentAssembly->GetPEAssembly(); + _ASSERTE(pPEAssembly != nullptr); + pPEAssembly->GetDisplayName(request.RequestingAssembly); AppDomain *domain = parentAssembly->GetAppDomain(); - AssemblyBinder *binder = peAssembly->GetAssemblyBinder(); + AssemblyBinder *binder = pPEAssembly->GetAssemblyBinder(); GetAssemblyLoadContextNameFromBinder(binder, domain, request.RequestingAssemblyLoadContext); } diff --git a/src/coreclr/debug/createdump/crashinfo.cpp b/src/coreclr/debug/createdump/crashinfo.cpp index 8ab327eb15578..70e0007d6925b 100644 --- a/src/coreclr/debug/createdump/crashinfo.cpp +++ b/src/coreclr/debug/createdump/crashinfo.cpp @@ -13,6 +13,8 @@ CrashInfo::CrashInfo(pid_t pid, bool gatherFrames, pid_t crashThread, uint32_t s m_pid(pid), m_ppid(-1), m_hdac(nullptr), + m_pClrDataEnumRegions(nullptr), + m_pClrDataProcess(nullptr), m_gatherFrames(gatherFrames), m_crashThread(crashThread), m_signal(signal), @@ -44,6 +46,15 @@ CrashInfo::~CrashInfo() } m_moduleInfos.clear(); + // Clean up DAC interfaces + if (m_pClrDataEnumRegions != nullptr) + { + m_pClrDataEnumRegions->Release(); + } + if (m_pClrDataProcess != nullptr) + { + m_pClrDataProcess->Release(); + } // Unload DAC module if (m_hdac != nullptr) { @@ -190,8 +201,16 @@ CrashInfo::GatherCrashInfo(MINIDUMP_TYPE minidumpType) thread->GetThreadStack(); } } - // Gather all the useful memory regions from the DAC - if (!EnumerateMemoryRegionsWithDAC(minidumpType)) + // Load and initialize DAC interfaces + if (!InitializeDAC()) + { + return false; + } + if (!EnumerateManagedModules()) + { + return false; + } + if (!UnwindAllThreads()) { return false; } @@ -204,19 +223,15 @@ CrashInfo::GatherCrashInfo(MINIDUMP_TYPE minidumpType) // Enumerate all the memory regions using the DAC memory region support given a minidump type // bool -CrashInfo::EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType) +CrashInfo::InitializeDAC() { ReleaseHolder dataTarget = new DumpDataTarget(*this); PFN_CLRDataCreateInstance pfnCLRDataCreateInstance = nullptr; - ICLRDataEnumMemoryRegions* pClrDataEnumRegions = nullptr; - IXCLRDataProcess* pClrDataProcess = nullptr; - HRESULT hr = S_OK; bool result = false; + HRESULT hr = S_OK; if (!m_coreclrPath.empty()) { - TRACE("EnumerateMemoryRegionsWithDAC: Memory enumeration STARTED\n"); - // We assume that the DAC is in the same location as the libcoreclr.so module std::string dacPath; dacPath.append(m_coreclrPath); @@ -235,140 +250,156 @@ CrashInfo::EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType) fprintf(stderr, "GetProcAddress(CLRDataCreateInstance) FAILED %d\n", GetLastError()); goto exit; } - if ((minidumpType & MiniDumpWithFullMemory) == 0) - { - hr = pfnCLRDataCreateInstance(__uuidof(ICLRDataEnumMemoryRegions), dataTarget, (void**)&pClrDataEnumRegions); - if (FAILED(hr)) - { - fprintf(stderr, "CLRDataCreateInstance(ICLRDataEnumMemoryRegions) FAILED %08x\n", hr); - goto exit; - } - // Calls CrashInfo::EnumMemoryRegion for each memory region found by the DAC - hr = pClrDataEnumRegions->EnumMemoryRegions(this, minidumpType, CLRDATA_ENUM_MEM_DEFAULT); - if (FAILED(hr)) - { - fprintf(stderr, "EnumMemoryRegions FAILED %08x\n", hr); - goto exit; - } - } - hr = pfnCLRDataCreateInstance(__uuidof(IXCLRDataProcess), dataTarget, (void**)&pClrDataProcess); + hr = pfnCLRDataCreateInstance(__uuidof(ICLRDataEnumMemoryRegions), dataTarget, (void**)&m_pClrDataEnumRegions); if (FAILED(hr)) { - fprintf(stderr, "CLRDataCreateInstance(IXCLRDataProcess) FAILED %08x\n", hr); + fprintf(stderr, "CLRDataCreateInstance(ICLRDataEnumMemoryRegions) FAILED %08x\n", hr); goto exit; } - TRACE("EnumerateMemoryRegionsWithDAC: Memory enumeration FINISHED\n"); - if (!EnumerateManagedModules(pClrDataProcess)) + hr = pfnCLRDataCreateInstance(__uuidof(IXCLRDataProcess), dataTarget, (void**)&m_pClrDataProcess); + if (FAILED(hr)) { + fprintf(stderr, "CLRDataCreateInstance(IXCLRDataProcess) FAILED %08x\n", hr); goto exit; } } - else { - TRACE("EnumerateMemoryRegionsWithDAC: coreclr not found; not using DAC\n"); - } - if (!UnwindAllThreads(pClrDataProcess)) + else { - goto exit; + TRACE("InitializeDAC: coreclr not found; not using DAC\n"); } result = true; exit: - if (pClrDataEnumRegions != nullptr) - { - pClrDataEnumRegions->Release(); - } - if (pClrDataProcess != nullptr) + return result; +} + +// +// Enumerate all the memory regions using the DAC memory region support given a minidump type +// +bool +CrashInfo::EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType) +{ + if (m_pClrDataEnumRegions != nullptr && (minidumpType & MiniDumpWithFullMemory) == 0) { - pClrDataProcess->Release(); + TRACE("EnumerateMemoryRegionsWithDAC: Memory enumeration STARTED\n"); + + // Since on both Linux and MacOS all the RW regions will be added for heap + // dumps by createdump, the only thing differentiating a MiniDumpNormal and + // a MiniDumpWithPrivateReadWriteMemory is that the later uses the EnumMemory + // APIs. This is kind of expensive on larger applications (4 minutes, or even + // more), and this should already be in RW pages. Change the dump type to the + // faster normal one. This one already ensures necessary DAC globals, etc. + // without the costly assembly, module, class, type runtime data structures + // enumeration. + if (minidumpType & MiniDumpWithPrivateReadWriteMemory) + { + char* fastHeapDumps = getenv("COMPlus_DbgEnableFastHeapDumps"); + if (fastHeapDumps != nullptr && strcmp(fastHeapDumps, "1") == 0) + { + minidumpType = MiniDumpNormal; + } + } + // Calls CrashInfo::EnumMemoryRegion for each memory region found by the DAC + HRESULT hr = m_pClrDataEnumRegions->EnumMemoryRegions(this, minidumpType, CLRDATA_ENUM_MEM_DEFAULT); + if (FAILED(hr)) + { + fprintf(stderr, "EnumMemoryRegions FAILED %08x\n", hr); + return false; + } + TRACE("EnumerateMemoryRegionsWithDAC: Memory enumeration FINISHED\n"); } - return result; + return true; } // // Enumerate all the managed modules and replace the module mapping with the module name found. // bool -CrashInfo::EnumerateManagedModules(IXCLRDataProcess* pClrDataProcess) +CrashInfo::EnumerateManagedModules() { CLRDATA_ENUM enumModules = 0; - bool result = true; HRESULT hr = S_OK; - if (FAILED(hr = pClrDataProcess->StartEnumModules(&enumModules))) { - fprintf(stderr, "StartEnumModules FAILED %08x\n", hr); - return false; - } - - while (true) + if (m_pClrDataProcess != nullptr) { - ReleaseHolder pClrDataModule; - if ((hr = pClrDataProcess->EnumModule(&enumModules, &pClrDataModule)) != S_OK) { - break; - } + TRACE("EnumerateManagedModules: Module enumeration STARTED\n"); - // Skip any dynamic modules. The Request call below on some DACs crashes on dynamic modules. - ULONG32 flags; - if ((hr = pClrDataModule->GetFlags(&flags)) != S_OK) { - TRACE("MODULE: GetFlags FAILED %08x\n", hr); - continue; - } - if (flags & CLRDATA_MODULE_IS_DYNAMIC) { - TRACE("MODULE: Skipping dynamic module\n"); - continue; + if (FAILED(hr = m_pClrDataProcess->StartEnumModules(&enumModules))) { + fprintf(stderr, "StartEnumModules FAILED %08x\n", hr); + return false; } - DacpGetModuleData moduleData; - if (SUCCEEDED(hr = moduleData.Request(pClrDataModule.GetPtr()))) + while (true) { - TRACE("MODULE: %" PRIA PRIx64 " dyn %d inmem %d file %d pe %" PRIA PRIx64 " pdb %" PRIA PRIx64, (uint64_t)moduleData.LoadedPEAddress, moduleData.IsDynamic, - moduleData.IsInMemory, moduleData.IsFileLayout, (uint64_t)moduleData.PEFile, (uint64_t)moduleData.InMemoryPdbAddress); + ReleaseHolder pClrDataModule; + if ((hr = m_pClrDataProcess->EnumModule(&enumModules, &pClrDataModule)) != S_OK) { + break; + } - if (!moduleData.IsDynamic && moduleData.LoadedPEAddress != 0) + // Skip any dynamic modules. The Request call below on some DACs crashes on dynamic modules. + ULONG32 flags; + if ((hr = pClrDataModule->GetFlags(&flags)) != S_OK) { + TRACE("MODULE: GetFlags FAILED %08x\n", hr); + continue; + } + if (flags & CLRDATA_MODULE_IS_DYNAMIC) { + TRACE("MODULE: Skipping dynamic module\n"); + continue; + } + + DacpGetModuleData moduleData; + if (SUCCEEDED(hr = moduleData.Request(pClrDataModule.GetPtr()))) { - ArrayHolder wszUnicodeName = new WCHAR[MAX_LONGPATH + 1]; - if (SUCCEEDED(hr = pClrDataModule->GetFileName(MAX_LONGPATH, nullptr, wszUnicodeName))) + TRACE("MODULE: %" PRIA PRIx64 " dyn %d inmem %d file %d pe %" PRIA PRIx64 " pdb %" PRIA PRIx64, (uint64_t)moduleData.LoadedPEAddress, moduleData.IsDynamic, + moduleData.IsInMemory, moduleData.IsFileLayout, (uint64_t)moduleData.PEAssembly, (uint64_t)moduleData.InMemoryPdbAddress); + + if (!moduleData.IsDynamic && moduleData.LoadedPEAddress != 0) { - std::string moduleName = FormatString("%S", wszUnicodeName.GetPtr()); + ArrayHolder wszUnicodeName = new WCHAR[MAX_LONGPATH + 1]; + if (SUCCEEDED(hr = pClrDataModule->GetFileName(MAX_LONGPATH, nullptr, wszUnicodeName))) + { + std::string moduleName = FormatString("%S", wszUnicodeName.GetPtr()); - // Change the module mapping name - ReplaceModuleMapping(moduleData.LoadedPEAddress, moduleData.LoadedPESize, moduleName); + // Change the module mapping name + ReplaceModuleMapping(moduleData.LoadedPEAddress, moduleData.LoadedPESize, moduleName); - // Add managed module info - AddModuleInfo(true, moduleData.LoadedPEAddress, pClrDataModule, moduleName); + // Add managed module info + AddModuleInfo(true, moduleData.LoadedPEAddress, pClrDataModule, moduleName); + } + else { + TRACE("\nModule.GetFileName FAILED %08x\n", hr); + } } else { - TRACE("\nModule.GetFileName FAILED %08x\n", hr); + TRACE("\n"); } } else { - TRACE("\n"); + TRACE("moduleData.Request FAILED %08x\n", hr); } } - else { - TRACE("moduleData.Request FAILED %08x\n", hr); - } - } - if (enumModules != 0) { - pClrDataProcess->EndEnumModules(enumModules); + if (enumModules != 0) { + m_pClrDataProcess->EndEnumModules(enumModules); + } + TRACE("EnumerateManagedModules: Module enumeration FINISHED\n"); } - - return result; + return true; } // // Unwind all the native threads to ensure that the dwarf unwind info is added to the core dump. // bool -CrashInfo::UnwindAllThreads(IXCLRDataProcess* pClrDataProcess) +CrashInfo::UnwindAllThreads() { ReleaseHolder pSos = nullptr; - if (pClrDataProcess != nullptr) { - pClrDataProcess->QueryInterface(__uuidof(ISOSDacInterface), (void**)&pSos); + if (m_pClrDataProcess != nullptr) { + m_pClrDataProcess->QueryInterface(__uuidof(ISOSDacInterface), (void**)&pSos); } // For each native and managed thread for (ThreadInfo* thread : m_threads) { - if (!thread->UnwindThread(pClrDataProcess, pSos)) { + if (!thread->UnwindThread(m_pClrDataProcess, pSos)) { return false; } } @@ -827,5 +858,5 @@ FormatGuid(const GUID* guid) { uint8_t* bytes = (uint8_t*)guid; return FormatString("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - bytes[3], bytes[2], bytes[1], bytes[0], bytes[5], bytes[4], bytes[7], bytes[6], bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]); + bytes[3], bytes[2], bytes[1], bytes[0], bytes[5], bytes[4], bytes[7], bytes[6], bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]); } diff --git a/src/coreclr/debug/createdump/crashinfo.h b/src/coreclr/debug/createdump/crashinfo.h index ca8f77994ac75..e100b7f216102 100644 --- a/src/coreclr/debug/createdump/crashinfo.h +++ b/src/coreclr/debug/createdump/crashinfo.h @@ -47,6 +47,8 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, pid_t m_ppid; // parent pid pid_t m_tgid; // process group HMODULE m_hdac; // dac module handle when loaded + ICLRDataEnumMemoryRegions* m_pClrDataEnumRegions; // dac enumerate memory interface instance + IXCLRDataProcess* m_pClrDataProcess; // dac process interface instance bool m_gatherFrames; // if true, add the native and managed stack frames to the thread info pid_t m_crashThread; // crashing thread id or 0 if none uint32_t m_signal; // crash signal code or 0 if none @@ -84,6 +86,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, void CleanupAndResumeProcess(); bool EnumerateAndSuspendThreads(); bool GatherCrashInfo(MINIDUMP_TYPE minidumpType); + bool EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType); bool ReadMemory(void* address, void* buffer, size_t size); // read memory and add to dump bool ReadProcessMemory(void* address, void* buffer, size_t size, size_t* read); // read raw memory uint64_t GetBaseAddressFromAddress(uint64_t address); @@ -137,9 +140,9 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, void VisitProgramHeader(uint64_t loadbias, uint64_t baseAddress, ElfW(Phdr)* phdr); bool EnumerateModuleMappings(); #endif - bool EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType); - bool EnumerateManagedModules(IXCLRDataProcess* pClrDataProcess); - bool UnwindAllThreads(IXCLRDataProcess* pClrDataProcess); + bool InitializeDAC(); + bool EnumerateManagedModules(); + bool UnwindAllThreads(); void ReplaceModuleMapping(CLRDATA_ADDRESS baseAddress, ULONG64 size, const std::string& pszName); void InsertMemoryBackedRegion(const MemoryRegion& region); void InsertMemoryRegion(const MemoryRegion& region); diff --git a/src/coreclr/debug/createdump/createdumpunix.cpp b/src/coreclr/debug/createdump/createdumpunix.cpp index b789c98b820f1..6107adc625efc 100644 --- a/src/coreclr/debug/createdump/createdumpunix.cpp +++ b/src/coreclr/debug/createdump/createdumpunix.cpp @@ -47,7 +47,12 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP CrashReportWriter crashReportWriter(*crashInfo); crashReportWriter.WriteCrashReport(dumpPath); } - printf("Writing %s to file %s\n", dumpType, dumpPath.c_str()); + // Gather all the useful memory regions from the DAC + if (!crashInfo->EnumerateMemoryRegionsWithDAC(minidumpType)) + { + goto exit; + } + fprintf(stdout, "Writing %s to file %s\n", dumpType, dumpPath.c_str()); // Write the actual dump file if (!dumpWriter.OpenDump(dumpPath.c_str())) diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index 0630cfa710a37..35b834542c91c 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -679,11 +679,6 @@ MetaEnum::New(Module* mod, *handle = TO_CDENUM(NULL); } - if (!mod->GetFile()->HasMetadata()) - { - return S_FALSE; - } - metaEnum = new (nothrow) MetaEnum; if (!metaEnum) { @@ -4079,9 +4074,9 @@ ClrDataAccess::GetModuleByAddress( { TADDR base; ULONG32 length; - PEFile* file = modDef->GetFile(); + PEAssembly* pPEAssembly = modDef->GetPEAssembly(); - if ((base = PTR_TO_TADDR(file->GetLoadedImageContents(&length)))) + if ((base = PTR_TO_TADDR(pPEAssembly->GetLoadedImageContents(&length)))) { if (TO_CDADDR(base) <= address && TO_CDADDR(base + length) > address) @@ -4133,9 +4128,9 @@ ClrDataAccess::StartEnumMethodDefinitionsByAddress( { TADDR base; ULONG32 length; - PEFile* file = modDef->GetFile(); + PEAssembly* assembly = modDef->GetPEAssembly(); - if ((base = PTR_TO_TADDR(file->GetLoadedImageContents(&length)))) + if ((base = PTR_TO_TADDR(assembly->GetLoadedImageContents(&length)))) { if (TO_CDADDR(base) <= address && TO_CDADDR(base + length) > address) @@ -6459,7 +6454,7 @@ ClrDataAccess::GetHostGcNotificationTable() } /* static */ bool -ClrDataAccess::GetMetaDataFileInfoFromPEFile(PEFile *pPEFile, +ClrDataAccess::GetMetaDataFileInfoFromPEFile(PEAssembly *pPEAssembly, DWORD &dwTimeStamp, DWORD &dwSize, DWORD &dwDataSize, @@ -6477,7 +6472,7 @@ ClrDataAccess::GetMetaDataFileInfoFromPEFile(PEFile *pPEFile, isNGEN = false; if (pDir == NULL || pDir->Size == 0) { - mdImage = pPEFile->GetILimage(); + mdImage = pPEAssembly->GetPEImage(); if (mdImage != NULL) { layout = mdImage->GetLoadedLayout(); @@ -6526,7 +6521,7 @@ ClrDataAccess::GetMetaDataFileInfoFromPEFile(PEFile *pPEFile, } /* static */ -bool ClrDataAccess::GetILImageInfoFromNgenPEFile(PEFile *peFile, +bool ClrDataAccess::GetILImageInfoFromNgenPEFile(PEAssembly *pPEAssembly, DWORD &dwTimeStamp, DWORD &dwSize, __out_ecount(cchFilePath) LPWSTR wszFilePath, @@ -6536,10 +6531,10 @@ bool ClrDataAccess::GetILImageInfoFromNgenPEFile(PEFile *peFile, DWORD dwWritten = 0; // use the IL File name - if (!peFile->GetPath().DacGetUnicode(cchFilePath, wszFilePath, (COUNT_T *)(&dwWritten))) + if (!pPEAssembly->GetPath().DacGetUnicode(cchFilePath, wszFilePath, (COUNT_T *)(&dwWritten))) { // Use DAC hint to retrieve the IL name. - peFile->GetModuleFileNameHint().DacGetUnicode(cchFilePath, wszFilePath, (COUNT_T *)(&dwWritten)); + pPEAssembly->GetModuleFileNameHint().DacGetUnicode(cchFilePath, wszFilePath, (COUNT_T *)(&dwWritten)); } dwTimeStamp = 0; dwSize = 0; @@ -6603,7 +6598,7 @@ bool ClrDataAccess::GetILImageNameFromNgenImage( LPCWSTR ilExtension, #endif // FEATURE_CORESYSTEM void * -ClrDataAccess::GetMetaDataFromHost(PEFile* peFile, +ClrDataAccess::GetMetaDataFromHost(PEAssembly* pPEAssembly, bool* isAlternate) { DWORD imageTimestamp, imageSize, dataSize; @@ -6634,7 +6629,7 @@ ClrDataAccess::GetMetaDataFromHost(PEFile* peFile, // so the field remains for now. if (!ClrDataAccess::GetMetaDataFileInfoFromPEFile( - peFile, + pPEAssembly, imageTimestamp, imageSize, dataSize, @@ -6647,7 +6642,7 @@ ClrDataAccess::GetMetaDataFromHost(PEFile* peFile, } // try direct match for the image that is loaded into the managed process - peFile->GetLoadedMetadata((COUNT_T *)(&dataSize)); + pPEAssembly->GetLoadedMetadata((COUNT_T *)(&dataSize)); DWORD allocSize = 0; if (!ClrSafeInt::addition(dataSize, sizeof(DAC_INSTANCE), allocSize)) @@ -6665,7 +6660,7 @@ ClrDataAccess::GetMetaDataFromHost(PEFile* peFile, buffer = (void*)(inst + 1); // APIs implemented by hosting debugger. It can use the path/filename, timestamp, and - // file size to find an exact match for the image. If that fails for an ngen'ed image, + // pPEAssembly size to find an exact match for the image. If that fails for an ngen'ed image, // we can request the IL image which it came from. if (m_legacyMetaDataLocator) { @@ -6701,7 +6696,7 @@ ClrDataAccess::GetMetaDataFromHost(PEFile* peFile, // isAlt = true; if (!ClrDataAccess::GetILImageInfoFromNgenPEFile( - peFile, + pPEAssembly, imageTimestamp, imageSize, uniPath, @@ -6781,13 +6776,13 @@ ClrDataAccess::GetMetaDataFromHost(PEFile* peFile, //++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // -// Given a PEFile or a ReflectionModule try to find the corresponding metadata +// Given a PEAssembly or a ReflectionModule try to find the corresponding metadata // We will first ask debugger to locate it. If fail, we will try // to get it from the target process // //++++++++++++++++++++++++++++++++++++++++++++++++++++++++ IMDInternalImport* -ClrDataAccess::GetMDImport(const PEFile* peFile, const ReflectionModule* reflectionModule, bool throwEx) +ClrDataAccess::GetMDImport(const PEAssembly* pPEAssembly, const ReflectionModule* reflectionModule, bool throwEx) { HRESULT status; PTR_CVOID mdBaseTarget = NULL; @@ -6796,22 +6791,22 @@ ClrDataAccess::GetMDImport(const PEFile* peFile, const ReflectionModule* reflect PVOID mdBaseHost = NULL; bool isAlternate = false; - _ASSERTE((peFile == NULL && reflectionModule != NULL) || (peFile != NULL && reflectionModule == NULL)); - TADDR peFileAddr = (peFile != NULL) ? dac_cast(peFile) : dac_cast(reflectionModule); + _ASSERTE((pPEAssembly == NULL && reflectionModule != NULL) || (pPEAssembly != NULL && reflectionModule == NULL)); + TADDR peAssemblyAddr = (pPEAssembly != NULL) ? dac_cast(pPEAssembly) : dac_cast(reflectionModule); // // Look for one we've already created. // - mdImport = m_mdImports.Get(peFileAddr); + mdImport = m_mdImports.Get(peAssemblyAddr); if (mdImport != NULL) { return mdImport; } - if (peFile != NULL) + if (pPEAssembly != NULL) { // Get the metadata size - mdBaseTarget = ((PEFile*)peFile)->GetLoadedMetadata(&mdSize); + mdBaseTarget = const_cast(pPEAssembly)->GetLoadedMetadata(&mdSize); } else if (reflectionModule != NULL) { @@ -6862,12 +6857,12 @@ ClrDataAccess::GetMDImport(const PEFile* peFile, const ReflectionModule* reflect } // Try to see if debugger can locate it - if (peFile != NULL && mdBaseHost == NULL && (m_target3 || m_legacyMetaDataLocator)) + if (pPEAssembly != NULL && mdBaseHost == NULL && (m_target3 || m_legacyMetaDataLocator)) { // We couldn't read the metadata from memory. Ask // the target for metadata as it may be able to // provide it from some alternate means. - mdBaseHost = GetMetaDataFromHost(const_cast(peFile), &isAlternate); + mdBaseHost = GetMetaDataFromHost(const_cast(pPEAssembly), &isAlternate); } if (mdBaseHost == NULL) @@ -6902,7 +6897,7 @@ ClrDataAccess::GetMDImport(const PEFile* peFile, const ReflectionModule* reflect // The m_mdImports list does get cleaned up by calls to ClrDataAccess::Flush, // i.e. every time the process changes state. - if (m_mdImports.Add(peFileAddr, mdImport, isAlternate) == NULL) + if (m_mdImports.Add(peAssemblyAddr, mdImport, isAlternate) == NULL) { mdImport->Release(); DacError(E_OUTOFMEMORY); @@ -6970,9 +6965,9 @@ HRESULT ClrDataAccess::VerifyDlls() } // Read the debug directory timestamp from the target mscorwks image using DAC - // Note that we don't use the PE timestamp because the PE file might be changed in ways + // Note that we don't use the PE timestamp because the PE pPEAssembly might be changed in ways // that don't effect the PDB (and therefore don't effect DAC). Specifically, we rebase - // our DLLs at the end of a build, that changes the PE file, but not the PDB. + // our DLLs at the end of a build, that changes the PE pPEAssembly, but not the PDB. // Note that if we wanted to be extra careful, we could read the CV contents (which includes // the GUID signature) and verify it matches. Using the timestamp is useful for helpful error // messages, and should be sufficient in any real scenario. diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index 20bb5ff3e0847..c6af447d1b13a 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -272,7 +272,7 @@ DacDbiInterfaceImpl::DacDbiInterfaceImpl( ) : ClrDataAccess(pTarget), m_pAllocator(pAllocator), m_pMetaDataLookup(pMetaDataLookup), - m_pCachedPEFile(VMPTR_PEFile::NullPtr()), + m_pCachedPEAssembly(VMPTR_PEAssembly::NullPtr()), m_pCachedImporter(NULL), m_isCachedHijackFunctionValid(FALSE) { @@ -307,7 +307,7 @@ DacDbiInterfaceImpl::~DacDbiInterfaceImpl() // Called from DAC-ized code to get a IMDInternalImport // // Arguments: -// pPEFile - PE file for which to get importer for +// pPEAssembly - PE file for which to get importer for // fThrowEx - if true, throw instead of returning NULL. // // Returns: @@ -324,7 +324,7 @@ DacDbiInterfaceImpl::~DacDbiInterfaceImpl() // This is an Internal importer, not a public Metadata importer. // interface IMDInternalImport* DacDbiInterfaceImpl::GetMDImport( - const PEFile* pPEFile, + const PEAssembly* pPEAssembly, const ReflectionModule * pReflectionModule, bool fThrowEx) { @@ -335,23 +335,23 @@ interface IMDInternalImport* DacDbiInterfaceImpl::GetMDImport( IDacDbiInterface::IMetaDataLookup * pLookup = m_pMetaDataLookup; _ASSERTE(pLookup != NULL); - VMPTR_PEFile vmPEFile = VMPTR_PEFile::NullPtr(); + VMPTR_PEAssembly vmPEAssembly = VMPTR_PEAssembly::NullPtr(); - if (pPEFile != NULL) + if (pPEAssembly != NULL) { - vmPEFile.SetHostPtr(pPEFile); + vmPEAssembly.SetHostPtr(pPEAssembly); } else if (pReflectionModule != NULL) { // SOS and ClrDataAccess rely on special logic to find the metadata for methods in dynamic modules. // We don't need to. The RS has already taken care of the special logic for us. - // So here we just grab the PEFile off of the ReflectionModule and continue down the normal + // So here we just grab the PEAssembly off of the ReflectionModule and continue down the normal // code path. See code:ClrDataAccess::GetMDImport for comparison. - vmPEFile.SetHostPtr(pReflectionModule->GetFile()); + vmPEAssembly.SetHostPtr(pReflectionModule->GetPEAssembly()); } // Optimize for the case where the VM queries the same Importer many times in a row. - if (m_pCachedPEFile == vmPEFile) + if (m_pCachedPEAssembly == vmPEAssembly) { return m_pCachedImporter; } @@ -370,7 +370,7 @@ interface IMDInternalImport* DacDbiInterfaceImpl::GetMDImport( // To get the old codepath that uses the v2 metadata lookup methods, // you'd have to load DAC only and then you'll get ClrDataAccess's implementation // of this function. - pInternal = pLookup->LookupMetaData(vmPEFile, isILMetaDataForNI); + pInternal = pLookup->LookupMetaData(vmPEAssembly, isILMetaDataForNI); } EX_CATCH { @@ -397,7 +397,7 @@ interface IMDInternalImport* DacDbiInterfaceImpl::GetMDImport( else { // Cache it such that it we look for the exact same Importer again, we'll return it. - m_pCachedPEFile = vmPEFile; + m_pCachedPEAssembly = vmPEAssembly; m_pCachedImporter = pInternal; } @@ -445,7 +445,7 @@ HRESULT DacDbiInterfaceImpl::FlushCache() // That would remove host DAC instances while they're being used. DD_NON_REENTRANT_MAY_THROW; - m_pCachedPEFile = VMPTR_PEFile::NullPtr(); + m_pCachedPEAssembly = VMPTR_PEAssembly::NullPtr(); m_pCachedImporter = NULL; m_isCachedHijackFunctionValid = FALSE; @@ -1227,7 +1227,7 @@ mdSignature DacDbiInterfaceImpl::GetILCodeAndSigHelper(Module * pModule, } -bool DacDbiInterfaceImpl::GetMetaDataFileInfoFromPEFile(VMPTR_PEFile vmPEFile, +bool DacDbiInterfaceImpl::GetMetaDataFileInfoFromPEFile(VMPTR_PEAssembly vmPEAssembly, DWORD &dwTimeStamp, DWORD &dwSize, bool &isNGEN, @@ -1237,14 +1237,14 @@ bool DacDbiInterfaceImpl::GetMetaDataFileInfoFromPEFile(VMPTR_PEFile vmPEFile, DWORD dwDataSize; DWORD dwRvaHint; - PEFile * pPEFile = vmPEFile.GetDacPtr(); - _ASSERTE(pPEFile != NULL); - if (pPEFile == NULL) + PEAssembly * pPEAssembly = vmPEAssembly.GetDacPtr(); + _ASSERTE(pPEAssembly != NULL); + if (pPEAssembly == NULL) return false; WCHAR wszFilePath[MAX_LONGPATH] = {0}; DWORD cchFilePath = MAX_LONGPATH; - bool ret = ClrDataAccess::GetMetaDataFileInfoFromPEFile(pPEFile, + bool ret = ClrDataAccess::GetMetaDataFileInfoFromPEFile(pPEAssembly, dwTimeStamp, dwSize, dwDataSize, @@ -1258,7 +1258,7 @@ bool DacDbiInterfaceImpl::GetMetaDataFileInfoFromPEFile(VMPTR_PEFile vmPEFile, } -bool DacDbiInterfaceImpl::GetILImageInfoFromNgenPEFile(VMPTR_PEFile vmPEFile, +bool DacDbiInterfaceImpl::GetILImageInfoFromNgenPEFile(VMPTR_PEAssembly vmPEAssembly, DWORD &dwTimeStamp, DWORD &dwSize, IStringHolder* pStrFilename) @@ -4137,16 +4137,16 @@ BOOL DacDbiInterfaceImpl::GetModulePath(VMPTR_Module vmModule, DD_ENTER_MAY_THROW; Module * pModule = vmModule.GetDacPtr(); - PEFile * pFile = pModule->GetFile(); - if (pFile != NULL) + PEAssembly * pPEAssembly = pModule->GetPEAssembly(); + if (pPEAssembly != NULL) { - if( !pFile->GetPath().IsEmpty() ) + if( !pPEAssembly->GetPath().IsEmpty() ) { // Module has an on-disk path - const WCHAR * szPath = pFile->GetPath().DacGetRawUnicode(); + const WCHAR * szPath = pPEAssembly->GetPath().DacGetRawUnicode(); if (szPath == NULL) { - szPath = pFile->GetModuleFileNameHint().DacGetRawUnicode(); + szPath = pPEAssembly->GetModuleFileNameHint().DacGetRawUnicode(); if (szPath == NULL) { goto NoFileName; @@ -4198,12 +4198,12 @@ HRESULT DacDbiInterfaceImpl::IsModuleMapped(VMPTR_Module pModule, OUT BOOL *isMo EX_TRY { - PTR_PEFile pPEFile = pTargetModule->GetFile(); - _ASSERTE(pPEFile != NULL); + PTR_PEAssembly pPEAssembly = pTargetModule->GetPEAssembly(); + _ASSERTE(pPEAssembly != NULL); - if (pPEFile->HasLoadedIL()) + if (pPEAssembly->HasLoadedPEImage()) { - *isModuleMapped = pPEFile->GetLoadedIL()->IsMapped(); + *isModuleMapped = pPEAssembly->GetLoadedLayout()->IsMapped(); hr = S_OK; } } @@ -4296,11 +4296,11 @@ void DacDbiInterfaceImpl::GetMetadata(VMPTR_Module vmModule, TargetBuffer * pTar } else { - PEFile * pFile = pModule->GetFile(); + PEAssembly * pPEAssembly = pModule->GetPEAssembly(); // For non-dynamic modules, metadata is in the pe-image. COUNT_T size; - CORDB_ADDRESS address = PTR_TO_CORDB_ADDRESS(dac_cast(pFile->GetLoadedMetadata(&size))); + CORDB_ADDRESS address = PTR_TO_CORDB_ADDRESS(dac_cast(pPEAssembly->GetLoadedMetadata(&size))); pTargetBuffer->Init(address, (ULONG) size); } @@ -4386,9 +4386,9 @@ void DacDbiInterfaceImpl::GetModuleData(VMPTR_Module vmModule, ModuleInfo * pDat ZeroMemory(pData, sizeof(*pData)); Module * pModule = vmModule.GetDacPtr(); - PEFile * pFile = pModule->GetFile(); + PEAssembly * pPEAssembly = pModule->GetPEAssembly(); - pData->vmPEFile.SetHostPtr(pFile); + pData->vmPEAssembly.SetHostPtr(pPEAssembly); pData->vmAssembly.SetHostPtr(pModule->GetAssembly()); // Is it dynamic? @@ -4403,15 +4403,15 @@ void DacDbiInterfaceImpl::GetModuleData(VMPTR_Module vmModule, ModuleInfo * pDat if (!fIsDynamic) { COUNT_T size = 0; - pData->pPEBaseAddress = PTR_TO_TADDR(pFile->GetDebuggerContents(&size)); + pData->pPEBaseAddress = PTR_TO_TADDR(pPEAssembly->GetDebuggerContents(&size)); pData->nPESize = (ULONG) size; } // In-memory is determined by whether the module has a filename. pData->fInMemory = FALSE; - if (pFile != NULL) + if (pPEAssembly != NULL) { - pData->fInMemory = pFile->GetPath().IsEmpty(); + pData->fInMemory = pPEAssembly->GetPath().IsEmpty(); } } @@ -7318,13 +7318,13 @@ void DacDbiInterfaceImpl::GetGCHeapInformation(COR_HEAPINFO * pHeapInfo) } -HRESULT DacDbiInterfaceImpl::GetPEFileMDInternalRW(VMPTR_PEFile vmPEFile, OUT TADDR* pAddrMDInternalRW) +HRESULT DacDbiInterfaceImpl::GetPEFileMDInternalRW(VMPTR_PEAssembly vmPEAssembly, OUT TADDR* pAddrMDInternalRW) { DD_ENTER_MAY_THROW; if (pAddrMDInternalRW == NULL) return E_INVALIDARG; - PEFile * pPEFile = vmPEFile.GetDacPtr(); - *pAddrMDInternalRW = pPEFile->GetMDInternalRWAddress(); + PEAssembly * pPEAssembly = vmPEAssembly.GetDacPtr(); + *pAddrMDInternalRW = pPEAssembly->GetMDInternalRWAddress(); return S_OK; } diff --git a/src/coreclr/debug/daccess/dacdbiimpl.h b/src/coreclr/debug/daccess/dacdbiimpl.h index 3088ed007a717..e484a28008b0c 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.h +++ b/src/coreclr/debug/daccess/dacdbiimpl.h @@ -53,7 +53,7 @@ class DacDbiInterfaceImpl : // Overridden from ClrDataAccess. Gets an internal metadata importer for the file. virtual IMDInternalImport* GetMDImport( - const PEFile* pPEFile, + const PEAssembly* pPEAssembly, const ReflectionModule * pReflectionModule, bool fThrowEx); @@ -149,7 +149,7 @@ class DacDbiInterfaceImpl : HRESULT GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT *pLayout); HRESULT GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT *pLayout); void GetGCHeapInformation(COR_HEAPINFO * pHeapInfo); - HRESULT GetPEFileMDInternalRW(VMPTR_PEFile vmPEFile, OUT TADDR* pAddrMDInternalRW); + HRESULT GetPEFileMDInternalRW(VMPTR_PEAssembly vmPEAssembly, OUT TADDR* pAddrMDInternalRW); HRESULT GetReJitInfo(VMPTR_Module vmModule, mdMethodDef methodTk, OUT VMPTR_ReJitInfo* pReJitInfo); HRESULT GetActiveRejitILCodeVersionNode(VMPTR_Module vmModule, mdMethodDef methodTk, OUT VMPTR_ILCodeVersionNode* pVmILCodeVersionNode); HRESULT GetReJitInfo(VMPTR_MethodDesc vmMethod, CORDB_ADDRESS codeStartAddress, OUT VMPTR_ReJitInfo* pReJitInfo); @@ -952,15 +952,15 @@ class DacDbiInterfaceImpl : IMetaDataLookup * m_pMetaDataLookup; - // Metadata lookups is just a property on the PEFile in the normal builds, + // Metadata lookups is just a property on the PEAssembly in the normal builds, // and so VM code tends to access the same metadata importer many times in a row. // Cache the most-recently used to avoid excessive redundant lookups. - // PEFile of Cached Importer. Invalidated between Flush calls. If this is Non-null, + // PEAssembly of Cached Importer. Invalidated between Flush calls. If this is Non-null, // then the importer is m_pCachedImporter, and we can avoid using IMetaDataLookup - VMPTR_PEFile m_pCachedPEFile; + VMPTR_PEAssembly m_pCachedPEAssembly; - // Value of cached importer, corresponds with m_pCachedPEFile. + // Value of cached importer, corresponds with m_pCachedPEAssembly. IMDInternalImport * m_pCachedImporter; // Value of cached hijack function list, corresponds to g_pDebugger->m_rgHijackFunction @@ -1104,13 +1104,13 @@ class DacDbiInterfaceImpl : public: // APIs for picking up the info needed for a debugger to look up an ngen image or IL image // from it's search path. - bool GetMetaDataFileInfoFromPEFile(VMPTR_PEFile vmPEFile, + bool GetMetaDataFileInfoFromPEFile(VMPTR_PEAssembly vmPEAssembly, DWORD &dwTimeStamp, DWORD &dwSize, bool &isNGEN, IStringHolder* pStrFilename); - bool GetILImageInfoFromNgenPEFile(VMPTR_PEFile vmPEFile, + bool GetILImageInfoFromNgenPEFile(VMPTR_PEAssembly vmPEAssembly, DWORD &dwTimeStamp, DWORD &dwSize, IStringHolder* pStrFilename); diff --git a/src/coreclr/debug/daccess/dacfn.cpp b/src/coreclr/debug/daccess/dacfn.cpp index c8ac208d6352c..e1b83aba17e20 100644 --- a/src/coreclr/debug/daccess/dacfn.cpp +++ b/src/coreclr/debug/daccess/dacfn.cpp @@ -1304,7 +1304,7 @@ DacSetMethodDescEnumerated(LPCVOID pMD) // This gets called from DAC-ized code in the VM. IMDInternalImport* -DacGetMDImport(const PEFile* peFile, bool throwEx) +DacGetMDImport(const PEAssembly* pPEAssembly, bool throwEx) { if (!g_dacImpl) { @@ -1312,7 +1312,7 @@ DacGetMDImport(const PEFile* peFile, bool throwEx) UNREACHABLE(); } - return g_dacImpl->GetMDImport(peFile, throwEx); + return g_dacImpl->GetMDImport(pPEAssembly, throwEx); } IMDInternalImport* diff --git a/src/coreclr/debug/daccess/dacimpl.h b/src/coreclr/debug/daccess/dacimpl.h index 62d99ec574929..84d560e73ec03 100644 --- a/src/coreclr/debug/daccess/dacimpl.h +++ b/src/coreclr/debug/daccess/dacimpl.h @@ -132,7 +132,7 @@ class ReflectionModule; struct DAC_MD_IMPORT { DAC_MD_IMPORT* next; // list link field - TADDR peFile; // a TADDR for a PEFile* or a ReflectionModule* + TADDR peFile; // a TADDR for a PEAssembly* or a ReflectionModule* IMDInternalImport* impl; // Associated metadata interface bool isAlternate; // for NGEN images set to true if the metadata corresponds to the IL image @@ -151,7 +151,7 @@ struct DAC_MD_IMPORT // This class maintains a cache of IMDInternalImport* and their corresponding -// source (a PEFile* or a ReflectionModule*), as a singly-linked list of +// source (a PEAssembly* or a ReflectionModule*), as a singly-linked list of // DAC_MD_IMPORT nodes. The cache is flushed whenever the process state changes // by calling its Flush() member function. class MDImportsCache @@ -1352,18 +1352,18 @@ class ClrDataAccess JITNotification* GetHostJitNotificationTable(); GcNotification* GetHostGcNotificationTable(); - void* GetMetaDataFromHost(PEFile* peFile, + void* GetMetaDataFromHost(PEAssembly* pPEAssembly, bool* isAlternate); virtual - interface IMDInternalImport* GetMDImport(const PEFile* peFile, + interface IMDInternalImport* GetMDImport(const PEAssembly* pPEAssembly, const ReflectionModule* reflectionModule, bool throwEx); - interface IMDInternalImport* GetMDImport(const PEFile* peFile, + interface IMDInternalImport* GetMDImport(const PEAssembly* pPEAssembly, bool throwEx) { - return GetMDImport(peFile, NULL, throwEx); + return GetMDImport(pPEAssembly, NULL, throwEx); } interface IMDInternalImport* GetMDImport(const ReflectionModule* reflectionModule, @@ -1501,7 +1501,7 @@ class ClrDataAccess public: // APIs for picking up the info needed for a debugger to look up an ngen image or IL image // from it's search path. - static bool GetMetaDataFileInfoFromPEFile(PEFile *pPEFile, + static bool GetMetaDataFileInfoFromPEFile(PEAssembly *pPEAssembly, DWORD &dwImageTimestamp, DWORD &dwImageSize, DWORD &dwDataSize, @@ -1510,7 +1510,7 @@ class ClrDataAccess __out_ecount(cchFilePath) LPWSTR wszFilePath, DWORD cchFilePath); - static bool GetILImageInfoFromNgenPEFile(PEFile *peFile, + static bool GetILImageInfoFromNgenPEFile(PEAssembly *pPEAssembly, DWORD &dwTimeStamp, DWORD &dwSize, __out_ecount(cchPath) LPWSTR wszPath, diff --git a/src/coreclr/debug/daccess/enummem.cpp b/src/coreclr/debug/daccess/enummem.cpp index f956151f7ce8e..712f0b35c73f0 100644 --- a/src/coreclr/debug/daccess/enummem.cpp +++ b/src/coreclr/debug/daccess/enummem.cpp @@ -67,7 +67,7 @@ HRESULT ClrDataAccess::EnumMemCollectImages() ProcessModIter modIter; Module* modDef = NULL; HRESULT status = S_OK; - PEFile *file; + PEAssembly *assembly; TADDR pStartAddr = 0; ULONG32 ulSize = 0; ULONG32 ulSizeBlock; @@ -84,7 +84,7 @@ HRESULT ClrDataAccess::EnumMemCollectImages() EX_TRY { ulSize = 0; - file = modDef->GetFile(); + assembly = modDef->GetPEAssembly(); // We want to save any in-memory images. These show up like mapped files // and so would not be in a heap dump by default. Technically it's not clear we @@ -92,13 +92,11 @@ HRESULT ClrDataAccess::EnumMemCollectImages() // after-the-fact. But in-memory modules may be harder to track down at debug time // and people may have come to rely on this - so we'll include them for now. if ( - file->GetPath().IsEmpty() && // is in-memory - file->HasMetadata() && // skip resource assemblies - file->IsLoaded(FALSE) && // skip files not yet loaded - !file->IsDynamic()) // skip dynamic (GetLoadedIL asserts anyway) + assembly->GetPath().IsEmpty() && // is in-memory + assembly->HasLoadedPEImage()) // skip files not yet loaded or Dynamic { - pStartAddr = PTR_TO_TADDR(file->GetLoadedIL()->GetBase()); - ulSize = file->GetLoadedIL()->GetSize(); + pStartAddr = PTR_TO_TADDR(assembly->GetLoadedLayout()->GetBase()); + ulSize = assembly->GetLoadedLayout()->GetSize(); } // memory are mapped in in GetOsPageSize() size. @@ -609,7 +607,7 @@ HRESULT ClrDataAccess::EnumMemDumpModuleList(CLRDataEnumMemoryFlags flags) Module* modDef; TADDR base; ULONG32 length; - PEFile *file; + PEAssembly* assembly; TSIZE_T cbMemoryReported = m_cbMemoryReported; // @@ -635,8 +633,8 @@ HRESULT ClrDataAccess::EnumMemDumpModuleList(CLRDataEnumMemoryFlags flags) // To enable a debugger to check on whether a module is an NI or IL image, they need // the DOS header, PE headers, and IMAGE_COR20_HEADER for the Flags member. // We expose no API today to find this out. - PTR_PEFile pPEFile = modDef->GetFile(); - PEImage * pILImage = pPEFile->GetILimage(); + PTR_PEAssembly pPEAssembly = modDef->GetPEAssembly(); + PEImage * pILImage = pPEAssembly->GetPEImage(); // Implicitly gets the COR header. if ((pILImage) && (pILImage->HasLoadedLayout())) @@ -649,9 +647,9 @@ HRESULT ClrDataAccess::EnumMemDumpModuleList(CLRDataEnumMemoryFlags flags) EX_TRY { - file = modDef->GetFile(); - base = PTR_TO_TADDR(file->GetLoadedImageContents(&length)); - file->EnumMemoryRegions(flags); + assembly = modDef->GetPEAssembly(); + base = PTR_TO_TADDR(assembly->GetLoadedImageContents(&length)); + assembly->EnumMemoryRegions(flags); } EX_CATCH { @@ -1599,6 +1597,7 @@ HRESULT ClrDataAccess::EnumMemoryRegionsWorkerSkinny(IN CLRDataEnumMemoryFlags f // // collect CLR static CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( status = EnumMemCLRStatic(flags); ) + CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( status = EnumMemCLRHeapCrticalStatic(flags); ); // Dump AppDomain-specific info needed for MiniDumpNormal. CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( status = EnumMemDumpAppDomainInfo(flags); ) diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 0048e43c3d018..8d6ae0b3bb85f 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -1506,8 +1506,8 @@ ClrDataAccess::GetObjectClassName(CLRDATA_ADDRESS obj, unsigned int count, __out { // There is a case where metadata was unloaded and the AppendType call will fail. // This is when an AppDomain has been unloaded but not yet collected. - PEFile *pPEFile = mt->GetModule()->GetFile(); - if (pPEFile->GetILimage() == NULL) + PEAssembly *pPEAssembly = mt->GetModule()->GetPEAssembly(); + if (pPEAssembly->GetPEImage() == NULL) { if (pNeeded) *pNeeded = 16; @@ -1645,14 +1645,14 @@ ClrDataAccess::GetModuleData(CLRDATA_ADDRESS addr, struct DacpModuleData *Module ZeroMemory(ModuleData,sizeof(DacpModuleData)); ModuleData->Address = addr; - ModuleData->File = HOST_CDADDR(pModule->GetFile()); + ModuleData->PEAssembly = HOST_CDADDR(pModule->GetPEAssembly()); COUNT_T metadataSize = 0; - if (!pModule->GetFile()->IsDynamic()) + if (!pModule->GetPEAssembly()->IsDynamic()) { - ModuleData->ilBase = (CLRDATA_ADDRESS)(ULONG_PTR) pModule->GetFile()->GetIJWBase(); + ModuleData->ilBase = (CLRDATA_ADDRESS)(ULONG_PTR) pModule->GetPEAssembly()->GetIJWBase(); } - ModuleData->metadataStart = (CLRDATA_ADDRESS)dac_cast(pModule->GetFile()->GetLoadedMetadata(&metadataSize)); + ModuleData->metadataStart = (CLRDATA_ADDRESS)dac_cast(pModule->GetPEAssembly()->GetLoadedMetadata(&metadataSize)); ModuleData->metadataSize = (SIZE_T) metadataSize; ModuleData->bIsReflection = pModule->IsReflection(); @@ -1770,8 +1770,8 @@ ClrDataAccess::GetMethodTableName(CLRDATA_ADDRESS mt, unsigned int count, __out_ { // There is a case where metadata was unloaded and the AppendType call will fail. // This is when an AppDomain has been unloaded but not yet collected. - PEFile *pPEFile = pMT->GetModule()->GetFile(); - if (pPEFile->GetILimage() == NULL) + PEAssembly *pPEAssembly = pMT->GetModule()->GetPEAssembly(); + if (pPEAssembly->GetPEImage() == NULL) { if (pNeeded) *pNeeded = 16; @@ -2053,19 +2053,18 @@ ClrDataAccess::GetPEFileName(CLRDATA_ADDRESS addr, unsigned int count, __out_z _ return E_INVALIDARG; SOSDacEnter(); - PEFile* pPEFile = PTR_PEFile(TO_TADDR(addr)); + PEAssembly* pPEAssembly = PTR_PEAssembly(TO_TADDR(addr)); // Turn from bytes to wide characters - if (!pPEFile->GetPath().IsEmpty()) + if (!pPEAssembly->GetPath().IsEmpty()) { - if (!pPEFile->GetPath().DacGetUnicode(count, fileName, pNeeded)) + if (!pPEAssembly->GetPath().DacGetUnicode(count, fileName, pNeeded)) hr = E_FAIL; } - else if (!pPEFile->IsDynamic()) + else if (!pPEAssembly->IsDynamic()) { - PEAssembly *pAssembly = pPEFile->GetAssembly(); StackSString displayName; - pAssembly->GetDisplayName(displayName, 0); + pPEAssembly->GetDisplayName(displayName, 0); if (displayName.IsEmpty()) { @@ -2112,11 +2111,11 @@ ClrDataAccess::GetPEFileBase(CLRDATA_ADDRESS addr, CLRDATA_ADDRESS *base) SOSDacEnter(); - PEFile* pPEFile = PTR_PEFile(TO_TADDR(addr)); + PEAssembly* pPEAssembly = PTR_PEAssembly(TO_TADDR(addr)); // More fields later? - if (!pPEFile->IsDynamic()) - *base = TO_CDADDR(pPEFile->GetIJWBase()); + if (!pPEAssembly->IsDynamic()) + *base = TO_CDADDR(pPEAssembly->GetIJWBase()); else *base = NULL; @@ -4768,8 +4767,8 @@ HRESULT ClrDataAccess::GetAssemblyLoadContext(CLRDATA_ADDRESS methodTable, CLRDA PTR_MethodTable pMT = PTR_MethodTable(CLRDATA_ADDRESS_TO_TADDR(methodTable)); PTR_Module pModule = pMT->GetModule(); - PTR_PEFile pPEFile = pModule->GetFile(); - PTR_AssemblyBinder pBinder = pPEFile->GetAssemblyBinder(); + PTR_PEAssembly pPEAssembly = pModule->GetPEAssembly(); + PTR_AssemblyBinder pBinder = pPEAssembly->GetAssemblyBinder(); INT_PTR managedAssemblyLoadContextHandle = pBinder->GetManagedAssemblyLoadContext(); diff --git a/src/coreclr/debug/daccess/request_svr.cpp b/src/coreclr/debug/daccess/request_svr.cpp index 4528afe27dab1..b2c09a92c625e 100644 --- a/src/coreclr/debug/daccess/request_svr.cpp +++ b/src/coreclr/debug/daccess/request_svr.cpp @@ -122,8 +122,11 @@ ClrDataAccess::ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr, DacpGcHeapDetails * detailsData->lowest_address = PTR_CDADDR(g_lowest_address); detailsData->highest_address = PTR_CDADDR(g_highest_address); - detailsData->current_c_gc_state = (CLRDATA_ADDRESS)*g_gcDacGlobals->current_c_gc_state; - + detailsData->current_c_gc_state = c_gc_state_free; + if (g_gcDacGlobals->current_c_gc_state != NULL) + { + detailsData->current_c_gc_state = (CLRDATA_ADDRESS)*g_gcDacGlobals->current_c_gc_state; + } // now get information specific to this heap (server mode gives us several heaps; we're getting // information about only one of them. detailsData->alloc_allocated = (CLRDATA_ADDRESS)pHeap->alloc_allocated; diff --git a/src/coreclr/debug/daccess/task.cpp b/src/coreclr/debug/daccess/task.cpp index 8989977880e2e..5c8c3d0152dcf 100644 --- a/src/coreclr/debug/daccess/task.cpp +++ b/src/coreclr/debug/daccess/task.cpp @@ -2414,12 +2414,12 @@ ClrDataModule::GetFileName( { COUNT_T _nameLen; - // Try to get the file name through GetPath. - // If the returned name is empty, then try to get the guessed module file name. - // The guessed file name is propogated from metadata's module name. + // Try to get the assembly name through GetPath. + // If the returned name is empty, then try to get the guessed module assembly name. + // The guessed assembly name is propogated from metadata's module name. // - if ((m_module->GetFile()->GetPath().DacGetUnicode(bufLen, name, &_nameLen) && name[0])|| - (m_module->GetFile()->GetModuleFileNameHint().DacGetUnicode(bufLen, name, &_nameLen) && name[0])) + if ((m_module->GetPEAssembly()->GetPath().DacGetUnicode(bufLen, name, &_nameLen) && name[0])|| + (m_module->GetPEAssembly()->GetModuleFileNameHint().DacGetUnicode(bufLen, name, &_nameLen) && name[0])) { if (nameLen) { @@ -2455,19 +2455,11 @@ ClrDataModule::GetVersionId( EX_TRY { - if (!m_module->GetFile()->HasMetadata()) + GUID mdVid; + status = m_module->GetMDImport()->GetScopeProps(NULL, &mdVid); + if (SUCCEEDED(status)) { - status = E_NOINTERFACE; - } - else - { - GUID mdVid; - - status = m_module->GetMDImport()->GetScopeProps(NULL, &mdVid); - if (SUCCEEDED(status)) - { - *vid = mdVid; - } + *vid = mdVid; } } EX_CATCH @@ -2499,10 +2491,7 @@ ClrDataModule::GetFlags( { (*flags) |= CLRDATA_MODULE_IS_DYNAMIC; } - if (m_module->IsIStream()) - { - (*flags) |= CLRDATA_MODULE_IS_MEMORY_STREAM; - } + PTR_Assembly pAssembly = m_module->GetAssembly(); PTR_BaseDomain pBaseDomain = pAssembly->GetDomain(); if (pBaseDomain->IsAppDomain()) @@ -2568,8 +2557,8 @@ ClrDataModule::StartEnumExtents( { if (!m_setExtents) { - PEFile* file = m_module->GetFile(); - if (!file) + PEAssembly* assembly = m_module->GetPEAssembly(); + if (!assembly) { *handle = 0; status = E_INVALIDARG; @@ -2578,10 +2567,10 @@ ClrDataModule::StartEnumExtents( CLRDATA_MODULE_EXTENT* extent = m_extents; - if (file->GetLoadedImageContents() != NULL) + if (assembly->GetLoadedImageContents() != NULL) { extent->base = - TO_CDADDR( PTR_TO_TADDR(file->GetLoadedImageContents(&extent->length)) ); + TO_CDADDR( PTR_TO_TADDR(assembly->GetLoadedImageContents(&extent->length)) ); extent->type = CLRDATA_MODULE_PE_FILE; extent++; } @@ -2723,23 +2712,23 @@ ClrDataModule::RequestGetModuleData( ZeroMemory(outGMD, sizeof(DacpGetModuleData)); Module* pModule = GetModule(); - PEFile *pPEFile = pModule->GetFile(); + PEAssembly *pPEAssembly = pModule->GetPEAssembly(); - outGMD->PEFile = TO_CDADDR(PTR_HOST_TO_TADDR(pPEFile)); + outGMD->PEAssembly = TO_CDADDR(PTR_HOST_TO_TADDR(pPEAssembly)); outGMD->IsDynamic = pModule->IsReflection(); - if (pPEFile != NULL) + if (pPEAssembly != NULL) { - outGMD->IsInMemory = pPEFile->GetPath().IsEmpty(); + outGMD->IsInMemory = pPEAssembly->GetPath().IsEmpty(); COUNT_T peSize; - outGMD->LoadedPEAddress = TO_CDADDR(PTR_TO_TADDR(pPEFile->GetLoadedImageContents(&peSize))); + outGMD->LoadedPEAddress = TO_CDADDR(PTR_TO_TADDR(pPEAssembly->GetLoadedImageContents(&peSize))); outGMD->LoadedPESize = (ULONG64)peSize; - // Can not get the file layout for a dynamic module + // Can not get the assembly layout for a dynamic module if (!outGMD->IsDynamic) { - outGMD->IsFileLayout = pPEFile->GetLoaded()->IsFlat(); + outGMD->IsFileLayout = pPEAssembly->GetLoadedLayout()->IsFlat(); } } @@ -2876,17 +2865,10 @@ ClrDataModule::GetMdInterface(PVOID* retIface) { if (m_mdImport == NULL) { - if (!m_module->GetFile()->HasMetadata()) - { - status = E_NOINTERFACE; - goto Exit; - } - // // Make sure internal MD is in RW format. // IMDInternalImport* rwMd; - status = ConvertMDInternalImport(m_module->GetMDImport(), &rwMd); if (FAILED(status)) { diff --git a/src/coreclr/debug/di/module.cpp b/src/coreclr/debug/di/module.cpp index e662f8cb86e24..b48e12afc96be 100644 --- a/src/coreclr/debug/di/module.cpp +++ b/src/coreclr/debug/di/module.cpp @@ -82,7 +82,7 @@ CordbModule::CordbModule( m_fDynamic = modInfo.fIsDynamic; m_fInMemory = modInfo.fInMemory; - m_vmPEFile = modInfo.vmPEFile; + m_vmPEFile = modInfo.vmPEAssembly; if (!vmDomainFile.IsNull()) { @@ -268,13 +268,13 @@ IDacDbiInterface::SymbolFormat CordbModule::GetInMemorySymbolStream(IStream ** p // Accessor for PE file. // // Returns: -// VMPTR_PEFile for this module. Should always be non-null +// VMPTR_PEAssembly for this module. Should always be non-null // // Notes: // A main usage of this is to find the proper internal MetaData importer. -// DACized code needs to map from PEFile --> IMDInternalImport. +// DACized code needs to map from PEAssembly --> IMDInternalImport. // -VMPTR_PEFile CordbModule::GetPEFile() +VMPTR_PEAssembly CordbModule::GetPEFile() { return m_vmPEFile; } diff --git a/src/coreclr/debug/di/process.cpp b/src/coreclr/debug/di/process.cpp index 134e3dbab4c96..c6c16d0700a85 100644 --- a/src/coreclr/debug/di/process.cpp +++ b/src/coreclr/debug/di/process.cpp @@ -290,10 +290,10 @@ static inline DWORD CordbGetWaitTimeout() //---------------------------------------------------------------------------- // Implementation of IDacDbiInterface::IMetaDataLookup. -// lookup Internal Metadata Importer keyed by PEFile +// lookup Internal Metadata Importer keyed by PEAssembly // isILMetaDataForNGENImage is true iff the IMDInternalImport returned represents a pointer to // metadata from an IL image when the module was an ngen'ed image. -IMDInternalImport * CordbProcess::LookupMetaData(VMPTR_PEFile vmPEFile, bool &isILMetaDataForNGENImage) +IMDInternalImport * CordbProcess::LookupMetaData(VMPTR_PEAssembly vmPEAssembly, bool &isILMetaDataForNGENImage) { INTERNAL_DAC_CALLBACK(this); @@ -312,7 +312,7 @@ IMDInternalImport * CordbProcess::LookupMetaData(VMPTR_PEFile vmPEFile, bool &is pModule != NULL; pModule = pAppDomain->m_modules.FindNext(&hashFindModule)) { - if (pModule->GetPEFile() == vmPEFile) + if (pModule->GetPEFile() == vmPEAssembly) { pMDII = NULL; ALLOW_DATATARGET_MISSING_MEMORY( @@ -341,7 +341,7 @@ IMDInternalImport * CordbProcess::LookupMetaData(VMPTR_PEFile vmPEFile, bool &is pModule != NULL; pModule = pAppDomain->m_modules.FindNext(&hashFindModule)) { - if (pModule->GetPEFile() == vmPEFile) + if (pModule->GetPEFile() == vmPEAssembly) { pMDII = NULL; ALLOW_DATATARGET_MISSING_MEMORY( @@ -354,7 +354,7 @@ IMDInternalImport * CordbProcess::LookupMetaData(VMPTR_PEFile vmPEFile, bool &is // debugger if it can find the metadata elsewhere. // If this was live debugging, we should have just gotten the memory contents. // Thus this code is for dump debugging, when you don't have the metadata in the dump. - pMDII = LookupMetaDataFromDebugger(vmPEFile, isILMetaDataForNGENImage, pModule); + pMDII = LookupMetaDataFromDebugger(vmPEAssembly, isILMetaDataForNGENImage, pModule); } return pMDII; } @@ -366,7 +366,7 @@ IMDInternalImport * CordbProcess::LookupMetaData(VMPTR_PEFile vmPEFile, bool &is IMDInternalImport * CordbProcess::LookupMetaDataFromDebugger( - VMPTR_PEFile vmPEFile, + VMPTR_PEAssembly vmPEAssembly, bool &isILMetaDataForNGENImage, CordbModule * pModule) { @@ -377,7 +377,7 @@ IMDInternalImport * CordbProcess::LookupMetaDataFromDebugger( IMDInternalImport * pMDII = NULL; // First, see if the debugger can locate the exact metadata we want. - if (this->GetDAC()->GetMetaDataFileInfoFromPEFile(vmPEFile, dwImageTimeStamp, dwImageSize, isNGEN, &filePath)) + if (this->GetDAC()->GetMetaDataFileInfoFromPEFile(vmPEAssembly, dwImageTimeStamp, dwImageSize, isNGEN, &filePath)) { _ASSERTE(filePath.IsSet()); @@ -408,7 +408,7 @@ IMDInternalImport * CordbProcess::LookupMetaDataFromDebugger( filePath.Clear(); if ((pMDII == NULL) && (isNGEN) && - (this->GetDAC()->GetILImageInfoFromNgenPEFile(vmPEFile, dwImageTimeStamp, dwImageSize, &filePath))) + (this->GetDAC()->GetILImageInfoFromNgenPEFile(vmPEAssembly, dwImageTimeStamp, dwImageSize, &filePath))) { _ASSERTE(filePath.IsSet()); @@ -496,7 +496,7 @@ IMDInternalImport * CordbProcess::LookupMetaDataFromDebuggerForSingleFile( if (SUCCEEDED(hr)) { // While we're successfully returning a metadata reader, remember that there's - // absolutely no guarantee this metadata is an exact match for the vmPEFile. + // absolutely no guarantee this metadata is an exact match for the vmPEAssembly. // The debugger could literally send us back a path to any managed file with // metadata content that is readable and we'll 'succeed'. // For now, this is by-design. A debugger should be allowed to decide if it wants diff --git a/src/coreclr/debug/di/rspriv.h b/src/coreclr/debug/di/rspriv.h index 7d257f6556e52..1baa6a9f24afd 100644 --- a/src/coreclr/debug/di/rspriv.h +++ b/src/coreclr/debug/di/rspriv.h @@ -2975,10 +2975,10 @@ class CordbProcess : //----------------------------------------------------------- // IMetaDataLookup // ----------------------------------------------------------- - IMDInternalImport * LookupMetaData(VMPTR_PEFile vmPEFile, bool &isILMetaDataForNGENImage); + IMDInternalImport * LookupMetaData(VMPTR_PEAssembly vmPEAssembly, bool &isILMetaDataForNGENImage); // Helper functions for LookupMetaData implementation - IMDInternalImport * LookupMetaDataFromDebugger(VMPTR_PEFile vmPEFile, + IMDInternalImport * LookupMetaDataFromDebugger(VMPTR_PEAssembly vmPEAssembly, bool &isILMetaDataForNGENImage, CordbModule * pModule); @@ -4368,7 +4368,7 @@ class CordbModule : public CordbBase, IDacDbiInterface::SymbolFormat GetInMemorySymbolStream(IStream ** ppStream); // accessor for PE file - VMPTR_PEFile GetPEFile(); + VMPTR_PEAssembly GetPEFile(); IMetaDataImport * GetMetaDataImporter(); @@ -4419,9 +4419,9 @@ class CordbModule : public CordbBase, // "Global" class for this module. Global functions + vars exist in this class. RSSmartPtr m_pClass; - // Handle to PEFile, useful for metadata lookups. + // Handle to PEAssembly, useful for metadata lookups. // this should always be non-null. - VMPTR_PEFile m_vmPEFile; + VMPTR_PEAssembly m_vmPEFile; // Public metadata importer. This is lazily initialized and accessed from code:GetMetaDataImporter diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp index 2a8f565d686eb..0f61f8d36c78e 100644 --- a/src/coreclr/debug/ee/debugger.cpp +++ b/src/coreclr/debug/ee/debugger.cpp @@ -9537,21 +9537,6 @@ void Debugger::LoadModule(Module* pRuntimeModule, SENDIPCEVENT_END; - // need to update pdb stream for SQL passed in pdb stream - // regardless attach or not. - // - if (pRuntimeModule->IsIStream()) - { - // Just ignore failures. Caller was just sending a debug event and we don't - // want that to interop non-debugging functionality. - HRESULT hr = S_OK; - EX_TRY - { - SendUpdateModuleSymsEventAndBlock(pRuntimeModule, pAppDomain); - } - EX_CATCH_HRESULT(hr); - } - // Now that we're done with the load module event, can no longer change Jit flags. module->SetCanChangeJitFlags(false); } @@ -9710,7 +9695,7 @@ void Debugger::UnloadModule(Module* pRuntimeModule, STRESS_LOG6(LF_CORDB, LL_INFO10000, "D::UM: Unloading RTMod:%#08x (DomFile: %#08x, IsISStream:%#08x); DMod:%#08x(RTMod:%#08x DomFile: %#08x)\n", - pRuntimeModule, pRuntimeModule->GetDomainFile(), pRuntimeModule->IsIStream(), + pRuntimeModule, pRuntimeModule->GetDomainFile(), false, module, module->GetRuntimeModule(), module->GetDomainFile()); // Note: the appdomain the module was loaded in must match the appdomain we're unloading it from. If it doesn't, diff --git a/src/coreclr/debug/inc/dacdbiinterface.h b/src/coreclr/debug/inc/dacdbiinterface.h index 6696da0cbbbb0..0bda865bd0f59 100644 --- a/src/coreclr/debug/inc/dacdbiinterface.h +++ b/src/coreclr/debug/inc/dacdbiinterface.h @@ -521,7 +521,7 @@ class IDacDbiInterface // // For dynamic modules, the CLR will eagerly serialize the metadata at "debuggable" points. This // could be after each type is loaded; or after a bulk update. - // For non-dynamic modules (both in-memory and file-based), the metadata exists in the PEFile's image. + // For non-dynamic modules (both in-memory and file-based), the metadata exists in the PEAssembly's image. // // Failure cases: // This should succeed in normal, live-debugging scenarios. However, common failure paths here would be: @@ -2379,14 +2379,14 @@ class IDacDbiInterface CLR_DEBUGGING_PROCESS_FLAGS GetAttachStateFlags() = 0; virtual - bool GetMetaDataFileInfoFromPEFile(VMPTR_PEFile vmPEFile, + bool GetMetaDataFileInfoFromPEFile(VMPTR_PEAssembly vmPEAssembly, DWORD & dwTimeStamp, DWORD & dwImageSize, bool & isNGEN, IStringHolder* pStrFilename) = 0; virtual - bool GetILImageInfoFromNgenPEFile(VMPTR_PEFile vmPEFile, + bool GetILImageInfoFromNgenPEFile(VMPTR_PEAssembly vmPEAssembly, DWORD & dwTimeStamp, DWORD & dwSize, IStringHolder* pStrFilename) = 0; @@ -2512,17 +2512,17 @@ class IDacDbiInterface virtual void GetGCHeapInformation(OUT COR_HEAPINFO * pHeapInfo) = 0; - // If a PEFile has an RW capable IMDInternalImport, this returns the address of the MDInternalRW + // If a PEAssembly has an RW capable IMDInternalImport, this returns the address of the MDInternalRW // object which implements it. // // // Arguments: - // vmPEFile - target PEFile to get metadata MDInternalRW for. - // pAddrMDInternalRW - If a PEFile has an RW capable IMDInternalImport, this will be set to the address + // vmPEAssembly - target PEAssembly to get metadata MDInternalRW for. + // pAddrMDInternalRW - If a PEAssembly has an RW capable IMDInternalImport, this will be set to the address // of the MDInternalRW object which implements it. Otherwise it will be NULL. // virtual - HRESULT GetPEFileMDInternalRW(VMPTR_PEFile vmPEFile, OUT TADDR* pAddrMDInternalRW) = 0; + HRESULT GetPEFileMDInternalRW(VMPTR_PEAssembly vmPEAssembly, OUT TADDR* pAddrMDInternalRW) = 0; // DEPRECATED - use GetActiveRejitILCodeVersionNode // Retrieves the active ReJitInfo for a given module/methodDef, if it exists. @@ -2814,7 +2814,7 @@ class IDacDbiInterface { public: // - // Lookup a metadata importer via PEFile. + // Lookup a metadata importer via PEAssembly. // // Returns: // A IMDInternalImport used by dac-ized VM code. The object is NOT addref-ed. See lifespan notes below. @@ -2822,7 +2822,7 @@ class IDacDbiInterface // Throws on exceptional circumstances (eg, detects the debuggee is corrupted). // // Notes: - // IMDInternalImport is a property of PEFile. The DAC-ized code uses it as a weak reference, + // IMDInternalImport is a property of PEAssembly. The DAC-ized code uses it as a weak reference, // and so we avoid doing an AddRef() here because that would mean we need to add Release() calls // in DAC-only paths. // The metadata importers are not DAC-ized, and thus we have a local copy in the host. @@ -2837,7 +2837,7 @@ class IDacDbiInterface // - the reference count of the returned object is not adjusted. // virtual - IMDInternalImport * LookupMetaData(VMPTR_PEFile addressPEFile, bool &isILMetaDataForNGENImage) = 0; + IMDInternalImport * LookupMetaData(VMPTR_PEAssembly addressPEAssembly, bool &isILMetaDataForNGENImage) = 0; }; }; // end IDacDbiInterface diff --git a/src/coreclr/debug/inc/dacdbistructures.h b/src/coreclr/debug/inc/dacdbistructures.h index 19c788edb297f..5e02a68a792c9 100644 --- a/src/coreclr/debug/inc/dacdbistructures.h +++ b/src/coreclr/debug/inc/dacdbistructures.h @@ -186,10 +186,10 @@ struct MSLAYOUT ModuleInfo // (such as for a dynamic module that's not persisted to disk). CORDB_ADDRESS pPEBaseAddress; - // The PEFile associated with the module. Every module (even non-file-based ones) has a PEFile. + // The PEAssembly associated with the module. Every module (even non-file-based ones) has a PEAssembly. // This is critical because DAC may ask for a metadata importer via PE-file. - // a PEFile may have 1 or more PEImage child objects (1 for IL, 1 for native image, etc) - VMPTR_PEFile vmPEFile; + // a PEAssembly may have 1 or more PEImage child objects (1 for IL, 1 for native image, etc) + VMPTR_PEAssembly vmPEAssembly; // The PE Base address and size of the module. These may be 0 if there is no image // (such as for a dynamic module that's not persisted to disk). diff --git a/src/coreclr/debug/inc/dbgipcevents.h b/src/coreclr/debug/inc/dbgipcevents.h index da097631b2f8c..db4a00fca1c86 100644 --- a/src/coreclr/debug/inc/dbgipcevents.h +++ b/src/coreclr/debug/inc/dbgipcevents.h @@ -858,7 +858,7 @@ DEFINE_VMPTR(class Module, PTR_Module, VMPTR_Module); DEFINE_VMPTR(class DomainAssembly, PTR_DomainAssembly, VMPTR_DomainAssembly); DEFINE_VMPTR(class Assembly, PTR_Assembly, VMPTR_Assembly); -DEFINE_VMPTR(class PEFile, PTR_PEFile, VMPTR_PEFile); +DEFINE_VMPTR(class PEAssembly, PTR_PEAssembly, VMPTR_PEAssembly); DEFINE_VMPTR(class MethodDesc, PTR_MethodDesc, VMPTR_MethodDesc); DEFINE_VMPTR(class FieldDesc, PTR_FieldDesc, VMPTR_FieldDesc); diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index d041ea52d64d1..221d2dc2be631 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -24,6 +24,10 @@ #define USE_INTROSORT #endif +#ifdef DACCESS_COMPILE +#error this source file should not be compiled with DACCESS_COMPILE! +#endif //DACCESS_COMPILE + // We just needed a simple random number generator for testing. class gc_rand { @@ -398,6 +402,7 @@ VOLATILE(bgc_state) gc_heap::current_bgc_state = bgc_not_in_process; int gc_heap::gchist_index_per_heap = 0; gc_heap::gc_history gc_heap::gchist_per_heap[max_history_count]; #endif //MULTIPLE_HEAPS +#endif //BACKGROUND_GC void gc_heap::add_to_history_per_heap() { @@ -444,8 +449,6 @@ void gc_heap::add_to_history() #endif //GC_HISTORY && BACKGROUND_GC } -#endif //BACKGROUND_GC - #ifdef TRACE_GC BOOL gc_log_on = TRUE; FILE* gc_log = NULL; @@ -1242,7 +1245,6 @@ class exclusive_sync void uoh_alloc_done (uint8_t* obj) { -#ifdef BACKGROUND_GC if (!gc_heap::cm_in_progress) { return; @@ -1256,7 +1258,6 @@ class exclusive_sync return; } } -#endif //BACKGROUND_GC } }; @@ -2973,7 +2974,11 @@ void gc_heap::fire_pevents() uint32_t count_time_info = (settings.concurrent ? max_bgc_time_type : (settings.compaction ? max_compact_time_type : max_sweep_time_type)); +#ifdef BACKGROUND_GC uint64_t* time_info = (settings.concurrent ? bgc_time_info : gc_time_info); +#else + uint64_t* time_info = gc_time_info; +#endif //BACKGROUND_GC // We don't want to have to fire the time info as 64-bit integers as there's no need to // so compress them down to 32-bit ones. uint32_t* time_info_32 = (uint32_t*)time_info; @@ -8369,13 +8374,8 @@ void gc_heap::clear_mark_array (uint8_t* from, uint8_t* end, BOOL check_only/*=T } assert (end == align_on_mark_word (end)); -#ifdef BACKGROUND_GC uint8_t* current_lowest_address = background_saved_lowest_address; uint8_t* current_highest_address = background_saved_highest_address; -#else - uint8_t* current_lowest_address = lowest_address; - uint8_t* current_highest_address = highest_address; -#endif //BACKGROUND_GC //there is a possibility of the addresses to be //outside of the covered range because of a newly allocated @@ -8518,12 +8518,12 @@ void gc_heap::get_card_table_element_sizes (uint8_t* start, uint8_t* end, size_t sizes[card_bundle_table_element] = size_card_bundle_of (start, end); } #endif //CARD_BUNDLE -#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP +#if defined(FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP) && defined (BACKGROUND_GC) if (gc_can_use_concurrent) { sizes[software_write_watch_table_element] = SoftwareWriteWatch::GetTableByteSize(start, end); } -#endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP +#endif //FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP && BACKGROUND_GC sizes[seg_mapping_table_element] = size_seg_mapping_table_of (start, end); #ifdef BACKGROUND_GC if (gc_can_use_concurrent) @@ -8819,12 +8819,12 @@ uint32_t* gc_heap::make_card_table (uint8_t* start, uint8_t* end) #endif #endif //CARD_BUNDLE -#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP +#if defined(FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP) && defined (BACKGROUND_GC) if (gc_can_use_concurrent) { SoftwareWriteWatch::InitializeUntranslatedTable(mem + card_table_element_layout[software_write_watch_table_element], start); } -#endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP +#endif //FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP && BACKGROUND_GC seg_mapping_table = (seg_mapping*)(mem + card_table_element_layout[seg_mapping_table_element]); seg_mapping_table = (seg_mapping*)((uint8_t*)seg_mapping_table - @@ -9047,7 +9047,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, } #endif //BACKGROUND_GC -#ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP +#if defined(FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP) && defined(BACKGROUND_GC) if (gc_can_use_concurrent) { // The current design of software write watch requires that the runtime is suspended during resize. Suspending @@ -9097,7 +9097,7 @@ int gc_heap::grow_brick_card_tables (uint8_t* start, } } else -#endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP +#endif //FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP && BACKGROUND_GC { g_gc_card_table = translated_ct; @@ -9182,6 +9182,7 @@ void gc_heap::copy_brick_card_range (uint8_t* la, uint32_t* old_card_table, uint32_t* old_ct = &old_card_table[card_word (card_of (la))]; +#ifdef BACKGROUND_GC if (gc_heap::background_running_p()) { uint32_t* old_mark_array = card_table_mark_array (old_ct); @@ -9210,6 +9211,7 @@ void gc_heap::copy_brick_card_range (uint8_t* la, uint32_t* old_card_table, assert (old_brick_table == 0); } } +#endif //BACKGROUND_GC // n way merge with all of the card table ever used in between uint32_t* ct = card_table_next (&card_table[card_word (card_of(lowest_address))]); @@ -9349,7 +9351,10 @@ BOOL gc_heap::insert_ro_segment (heap_segment* seg) enter_spin_lock (&gc_heap::gc_lock); if (!gc_heap::seg_table->ensure_space_for_insert () - || (is_bgc_in_progress() && !commit_mark_array_new_seg(__this, seg))) +#ifdef BACKGROUND_GC + || (is_bgc_in_progress() && !commit_mark_array_new_seg(__this, seg)) +#endif //BACKGROUND_GC + ) { leave_spin_lock(&gc_heap::gc_lock); return FALSE; @@ -12158,7 +12163,10 @@ void gc_heap::distribute_free_regions() // if so, put the highest free regions on the decommit list total_num_free_regions[kind] += num_regions_to_decommit[kind]; - if (background_running_p() || + if ( +#ifdef BACKGROUND_GC + background_running_p() || +#endif ((total_num_free_regions[kind] + num_huge_region_units_to_consider[kind]) < total_budget_in_region_units[kind])) { dprintf (REGIONS_LOG, ("distributing the %Id %s regions deficit", @@ -12386,6 +12394,7 @@ void gc_heap::update_card_table_bundle() } #endif //CARD_BUNDLE +#ifdef BACKGROUND_GC // static void gc_heap::reset_write_watch_for_gc_heap(void* base_address, size_t region_size) { @@ -12506,6 +12515,7 @@ void gc_heap::reset_write_watch (BOOL concurrent_p) } } } +#endif //BACKGROUND_GC #endif //WRITE_WATCH @@ -12924,9 +12934,11 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size, if (!g_promoted) return E_OUTOFMEMORY; #endif //!USE_REGIONS || _DEBUG +#ifdef BACKGROUND_GC g_bpromoted = new (nothrow) size_t [number_of_heaps*16]; if (!g_bpromoted) return E_OUTOFMEMORY; +#endif #ifdef MH_SC_MARK g_mark_stack_busy = new (nothrow) int[(number_of_heaps+2)*HS_CACHE_LINE_SIZE/sizeof(int)]; @@ -27284,11 +27296,13 @@ uint8_t* gc_heap::find_next_marked (uint8_t* x, uint8_t* end, #endif //MULTIPLE_HEAPS ) x = *mark_list_next; +#ifdef BACKGROUND_GC if (current_c_gc_state == c_gc_state_marking) { assert(gc_heap::background_running_p()); bgc_clear_batch_mark_array_bits (old_x, x); } +#endif //BACKGROUND_GC } else { @@ -28615,8 +28629,11 @@ void gc_heap::plan_phase (int condemned_gen_number) } } - if (maxgen_size_inc_p && provisional_mode_triggered && - !is_bgc_in_progress()) + if (maxgen_size_inc_p && provisional_mode_triggered +#ifdef BACKGROUND_GC + && !is_bgc_in_progress() +#endif //BACKGROUND_GC + ) { pm_trigger_full_gc = true; dprintf (GTC_LOG, ("in PM: maxgen size inc, doing a sweeping gen1 and trigger NGC2")); @@ -28741,8 +28758,11 @@ void gc_heap::plan_phase (int condemned_gen_number) rearrange_uoh_segments (); } - if (maxgen_size_inc_p && provisional_mode_triggered && - !is_bgc_in_progress()) + if (maxgen_size_inc_p && provisional_mode_triggered +#ifdef BACKGROUND_GC + && !is_bgc_in_progress() +#endif //BACKGROUND_GC + ) { pm_trigger_full_gc = true; dprintf (GTC_LOG, ("in PM: maxgen size inc, doing a sweeping gen1 and trigger NGC2")); @@ -28790,8 +28810,11 @@ void gc_heap::plan_phase (int condemned_gen_number) if (!pm_trigger_full_gc && pm_stress_on && provisional_mode_triggered) { if ((settings.condemned_generation == (max_generation - 1)) && - ((settings.gc_index % 5) == 0) && - !is_bgc_in_progress()) + ((settings.gc_index % 5) == 0) +#ifdef BACKGROUND_GC + && !is_bgc_in_progress() +#endif //BACKGROUND_GC + ) { pm_trigger_full_gc = true; } @@ -38061,9 +38084,13 @@ void gc_heap::init_static_data() #ifdef MULTIPLE_HEAPS max (6*1024*1024, min ( Align(soh_segment_size/2), 200*1024*1024)); #else //MULTIPLE_HEAPS - (gc_can_use_concurrent ? + ( +#ifdef BACKGROUND_GC + gc_can_use_concurrent ? 6*1024*1024 : - max (6*1024*1024, min ( Align(soh_segment_size/2), 200*1024*1024))); +#endif //BACKGROUND_GC + max (6*1024*1024, min ( Align(soh_segment_size/2), 200*1024*1024)) + ); #endif //MULTIPLE_HEAPS gen0_max_size = max (gen0_min_size, gen0_max_size); @@ -38094,9 +38121,13 @@ void gc_heap::init_static_data() #ifdef MULTIPLE_HEAPS max (6*1024*1024, Align(soh_segment_size/2)); #else //MULTIPLE_HEAPS - (gc_can_use_concurrent ? + ( +#ifdef BACKGROUND_GC + gc_can_use_concurrent ? 6*1024*1024 : - max (6*1024*1024, Align(soh_segment_size/2))); +#endif //BACKGROUND_GC + max (6*1024*1024, Align(soh_segment_size/2)) + ); #endif //MULTIPLE_HEAPS size_t gen1_max_size_config = (size_t)GCConfig::GetGCGen1MaxBudget(); @@ -38748,7 +38779,7 @@ void gc_heap::decommit_ephemeral_segment_pages() dynamic_data* dd0 = dynamic_data_of (0); - ptrdiff_t desired_allocation = estimate_gen_growth (soh_gen0) + + ptrdiff_t desired_allocation = dd_new_allocation (dd0) + estimate_gen_growth (soh_gen1) + loh_size_threshold; @@ -43340,6 +43371,7 @@ unsigned int GCHeap::GetGenerationWithRange (Object* object, uint8_t** ppStart, } if (generation == -1) { + generation = max_generation; *ppStart = heap_segment_mem (hs); *ppAllocated = *ppReserved = generation_allocation_start (hp->generation_of (max_generation - 1)); } @@ -44592,6 +44624,8 @@ bool gc_heap::is_pm_ratio_exceeded() void gc_heap::update_recorded_gen_data (last_recorded_gc_info* gc_info) { + memset (gc_info->gen_info, 0, sizeof (gc_info->gen_info)); + #ifdef MULTIPLE_HEAPS for (int i = 0; i < gc_heap::n_heaps; i++) { @@ -44685,12 +44719,14 @@ void gc_heap::do_post_gc() // Now record the gc info. last_recorded_gc_info* last_gc_info = 0; +#ifdef BACKGROUND_GC if (settings.concurrent) { last_gc_info = &last_bgc_info[last_bgc_info_index]; assert (last_gc_info->index == settings.gc_index); } else +#endif //BACKGROUND_GC { last_gc_info = ((settings.condemned_generation == max_generation) ? &last_full_blocking_gc_info : &last_ephemeral_gc_info); @@ -44710,10 +44746,12 @@ void gc_heap::do_post_gc() uint64_t gc_start_ts = dd_time_clock (dd); size_t pause_duration = (size_t)(end_gc_time - dd_time_clock (dd)); +#ifdef BACKGROUND_GC if ((hp->current_bgc_state != bgc_initialized) && (settings.reason != reason_pm_full_gc)) { pause_duration += (size_t)(gc_start_ts - suspended_start_time); } +#endif //BACKGROUND_GC last_gc_info->pause_durations[0] = pause_duration; total_suspended_time += pause_duration; @@ -45072,9 +45110,15 @@ size_t GCHeap::ApproxTotalBytesInUse(BOOL small_heap_only) // Get small block heap size info totsize = (pGenGCHeap->alloc_allocated - heap_segment_mem (eph_seg)); heap_segment* seg1 = generation_start_segment (pGenGCHeap->generation_of (max_generation)); - while ((seg1 != eph_seg) && (seg1 != nullptr) && (seg1 != pGenGCHeap->freeable_soh_segment)) + while ((seg1 != eph_seg) && (seg1 != nullptr) +#ifdef BACKGROUND_GC + && (seg1 != pGenGCHeap->freeable_soh_segment) +#endif //BACKGROUND_GC + ) { +#ifdef BACKGROUND_GC if (!heap_segment_decommitted_p (seg1)) +#endif //BACKGROUND_GC { totsize += heap_segment_allocated (seg1) - heap_segment_mem (seg1); @@ -46349,7 +46393,11 @@ void GCHeap::DiagGetGCSettings(EtwGCSettingsInfo* etw_settings) etw_settings->gen0_min_budget_from_config = gc_heap::gen0_min_budget_from_config; etw_settings->gen0_max_budget_from_config = gc_heap::gen0_max_budget_from_config; etw_settings->high_mem_percent_from_config = gc_heap::high_mem_percent_from_config; +#ifdef BACKGROUND_GC etw_settings->concurrent_gc_p = gc_heap::gc_can_use_concurrent; +#else + etw_settings->concurrent_gc_p = false; +#endif //BACKGROUND_GC etw_settings->use_large_pages_p = gc_heap::use_large_pages_p; etw_settings->use_frozen_segments_p = gc_heap::use_frozen_segments_p; etw_settings->hard_limit_config_p = gc_heap::hard_limit_config_p; @@ -46662,10 +46710,18 @@ void PopulateDacVars(GcDacVars *gcDacVars) gcDacVars->generation_size = sizeof(generation); gcDacVars->total_generation_count = total_generation_count; gcDacVars->max_gen = &g_max_generation; +#ifdef BACKGROUND_GC gcDacVars->current_c_gc_state = const_cast(&gc_heap::current_c_gc_state); +#else //BACKGROUND_GC + gcDacVars->current_c_gc_state = 0; +#endif //BACKGROUND_GC #ifndef MULTIPLE_HEAPS - gcDacVars->mark_array = &gc_heap::mark_array; gcDacVars->ephemeral_heap_segment = reinterpret_cast(&gc_heap::ephemeral_heap_segment); +#ifdef BACKGROUND_GC + gcDacVars->mark_array = &gc_heap::mark_array; + gcDacVars->background_saved_lowest_address = &gc_heap::background_saved_lowest_address; + gcDacVars->background_saved_highest_address = &gc_heap::background_saved_highest_address; + gcDacVars->next_sweep_obj = &gc_heap::next_sweep_obj; #ifdef USE_REGIONS gcDacVars->saved_sweep_ephemeral_seg = 0; gcDacVars->saved_sweep_ephemeral_start = 0; @@ -46673,10 +46729,15 @@ void PopulateDacVars(GcDacVars *gcDacVars) gcDacVars->saved_sweep_ephemeral_seg = reinterpret_cast(&gc_heap::saved_sweep_ephemeral_seg); gcDacVars->saved_sweep_ephemeral_start = &gc_heap::saved_sweep_ephemeral_start; #endif //USE_REGIONS - gcDacVars->background_saved_lowest_address = &gc_heap::background_saved_lowest_address; - gcDacVars->background_saved_highest_address = &gc_heap::background_saved_highest_address; +#else //BACKGROUND_GC + gcDacVars->mark_array = 0; + gcDacVars->background_saved_lowest_address = 0; + gcDacVars->background_saved_highest_address = 0; + gcDacVars->next_sweep_obj = 0; + gcDacVars->saved_sweep_ephemeral_seg = 0; + gcDacVars->saved_sweep_ephemeral_start = 0; +#endif //BACKGROUND_GC gcDacVars->alloc_allocated = &gc_heap::alloc_allocated; - gcDacVars->next_sweep_obj = &gc_heap::next_sweep_obj; gcDacVars->oom_info = &gc_heap::oom_info; gcDacVars->finalize_queue = reinterpret_cast(&gc_heap::finalize_queue); gcDacVars->generation_table = reinterpret_cast(&gc_heap::generation_table); diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 1fd5f0421daa8..051dd99301490 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -85,8 +85,10 @@ inline void FATAL_GC_ERROR() #define FEATURE_PREMORTEM_FINALIZATION #define GC_HISTORY +#define BACKGROUND_GC //concurrent background GC (requires WRITE_WATCH) + // We need the lower 3 bits in the MT to do our bookkeeping so doubly linked free list is only for 64-bit -#ifdef HOST_64BIT +#if defined(BACKGROUND_GC) && defined(HOST_64BIT) #define DOUBLY_LINKED_FL #endif //HOST_64BIT @@ -99,8 +101,6 @@ inline void FATAL_GC_ERROR() #define initial_internal_roots (1024*16) #endif // HEAP_ANALYZE -#define BACKGROUND_GC //concurrent background GC (requires WRITE_WATCH) - #ifdef SERVER_GC #define MH_SC_MARK //scalable marking //#define SNOOP_STATS //diagnostic @@ -2038,11 +2038,11 @@ class gc_heap #endif //!USE_REGIONS PER_HEAP_ISOLATED void distribute_free_regions(); +#ifdef BACKGROUND_GC PER_HEAP_ISOLATED void reset_write_watch_for_gc_heap(void* base_address, size_t region_size); PER_HEAP_ISOLATED void get_write_watch_for_gc_heap(bool reset, void *base_address, size_t region_size, void** dirty_pages, uintptr_t* dirty_page_count_ref, bool is_runtime_suspended); - PER_HEAP void switch_one_quantum(); PER_HEAP @@ -2051,6 +2051,7 @@ class gc_heap void switch_on_reset (BOOL concurrent_p, size_t* current_total_reset_size, size_t last_reset_size); PER_HEAP void reset_write_watch (BOOL concurrent_p); +#endif //BACKGROUND_GC PER_HEAP void adjust_ephemeral_limits(); PER_HEAP @@ -5918,14 +5919,7 @@ inline gc_oh_num heap_segment_oh (heap_segment * inst) } } -#ifdef BACKGROUND_GC #ifdef USE_REGIONS -inline -bool heap_segment_overflow_p (heap_segment* inst) -{ - return ((inst->flags & heap_segment_flags_overflow) != 0); -} - inline region_free_list*& heap_segment_containing_free_list (heap_segment* inst) { @@ -5939,6 +5933,15 @@ PTR_heap_segment& heap_segment_prev_free_region (heap_segment* inst) } #endif //USE_REGIONS +#ifdef BACKGROUND_GC +#ifdef USE_REGIONS +inline +bool heap_segment_overflow_p (heap_segment* inst) +{ + return ((inst->flags & heap_segment_flags_overflow) != 0); +} +#endif //USE_REGIONS + inline BOOL heap_segment_decommitted_p (heap_segment * inst) { diff --git a/src/coreclr/inc/clr_std/vector b/src/coreclr/inc/clr_std/vector index 0bed04182a4ee..c10ecf6ba5a92 100644 --- a/src/coreclr/inc/clr_std/vector +++ b/src/coreclr/inc/clr_std/vector @@ -373,6 +373,11 @@ namespace std m_size -= elements; return iterator(m_pelements + (position - begin())); } + + T* data() + { + return m_pelements; + } const T* data() const { diff --git a/src/coreclr/inc/corhdr.h b/src/coreclr/inc/corhdr.h index 58cb0aa7f9ca8..f9d4b5abf3b8b 100644 --- a/src/coreclr/inc/corhdr.h +++ b/src/coreclr/inc/corhdr.h @@ -227,7 +227,7 @@ typedef struct IMAGE_COR20_HEADER }; // This is the blob of managed resources. Fetched using code:AssemblyNative.GetResource and - // code:PEFile.GetResource and accessible from managed code from + // code:PEAssembly.GetResource and accessible from managed code from // System.Assembly.GetManifestResourceStream. The meta data has a table that maps names to offsets into // this blob, so logically the blob is a set of resources. IMAGE_DATA_DIRECTORY Resources; diff --git a/src/coreclr/inc/daccess.h b/src/coreclr/inc/daccess.h index 82009b77890e2..b769fcec22b4b 100644 --- a/src/coreclr/inc/daccess.h +++ b/src/coreclr/inc/daccess.h @@ -769,7 +769,7 @@ HRESULT DacReplacePatchesInHostMemory(MemoryRange range, PVOID pBuffer); #ifdef __cplusplus } class ReflectionModule; -interface IMDInternalImport* DacGetMDImport(const class PEFile* peFile, +interface IMDInternalImport* DacGetMDImport(const class PEAssembly* pPEAssembly, bool throwEx); interface IMDInternalImport* DacGetMDImport(const ReflectionModule* reflectionModule, bool throwEx); diff --git a/src/coreclr/inc/dacprivate.h b/src/coreclr/inc/dacprivate.h index 99419667a9635..45a4eda3cc140 100644 --- a/src/coreclr/inc/dacprivate.h +++ b/src/coreclr/inc/dacprivate.h @@ -230,8 +230,8 @@ struct MSLAYOUT DacpThreadLocalModuleData struct MSLAYOUT DacpModuleData { CLRDATA_ADDRESS Address = 0; - CLRDATA_ADDRESS File = 0; // A PEFile addr - CLRDATA_ADDRESS ilBase = 0; + CLRDATA_ADDRESS PEAssembly = 0; // A PEAssembly addr + CLRDATA_ADDRESS ilBase = 0; CLRDATA_ADDRESS metadataStart = 0; ULONG64 metadataSize = 0; CLRDATA_ADDRESS Assembly = 0; // Assembly pointer @@ -981,7 +981,7 @@ struct MSLAYOUT DacpGetModuleData BOOL IsDynamic = FALSE; BOOL IsInMemory = FALSE; BOOL IsFileLayout = FALSE; - CLRDATA_ADDRESS PEFile = 0; + CLRDATA_ADDRESS PEAssembly = 0; CLRDATA_ADDRESS LoadedPEAddress = 0; ULONG64 LoadedPESize = 0; CLRDATA_ADDRESS InMemoryPdbAddress = 0; diff --git a/src/coreclr/inc/vptr_list.h b/src/coreclr/inc/vptr_list.h index 4ea50d9fe4f44..4f8baccd5cd68 100644 --- a/src/coreclr/inc/vptr_list.h +++ b/src/coreclr/inc/vptr_list.h @@ -39,7 +39,6 @@ VPTR_CLASS(DelegateInvokeStubManager) VPTR_CLASS(TailCallStubManager) #endif VPTR_CLASS(CallCountingStubManager) -VPTR_CLASS(PEFile) VPTR_CLASS(PEAssembly) VPTR_CLASS(PEImageLayout) VPTR_CLASS(RawImageLayout) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index d0395283eb384..ef779db9fcf56 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -118,6 +118,59 @@ bool IntegralRange::Contains(int64_t value) const } } +//------------------------------------------------------------------------ +// ForNode: Compute the integral range for a node. +// +// Arguments: +// node - the node, of an integral type, in question +// compiler - the Compiler, used to retrieve additional info +// +// Return Value: +// The integral range this node produces. +// +/* static */ IntegralRange IntegralRange::ForNode(GenTree* node, Compiler* compiler) +{ + assert(varTypeIsIntegral(node)); + + var_types rangeType = node->TypeGet(); + + switch (node->OperGet()) + { + case GT_EQ: + case GT_NE: + case GT_LT: + case GT_LE: + case GT_GE: + case GT_GT: + return {SymbolicIntegerValue::Zero, SymbolicIntegerValue::One}; + + case GT_ARR_LENGTH: + return {SymbolicIntegerValue::Zero, SymbolicIntegerValue::IntMax}; + + case GT_CALL: + if (node->AsCall()->NormalizesSmallTypesOnReturn()) + { + rangeType = static_cast(node->AsCall()->gtReturnType); + } + break; + + case GT_LCL_VAR: + if (compiler->lvaGetDesc(node->AsLclVar())->lvNormalizeOnStore()) + { + rangeType = compiler->lvaGetDesc(node->AsLclVar())->TypeGet(); + } + break; + + case GT_CAST: + return ForCastOutput(node->AsCast()); + + default: + break; + } + + return ForType(rangeType); +} + //------------------------------------------------------------------------ // ForCastInput: Get the non-overflowing input range for a cast. // @@ -214,7 +267,14 @@ bool IntegralRange::Contains(int64_t value) const // CAST_OVF(long <- ulong) - [0..LONG_MAX] // CAST_OVF(long <- long) - [LONG_MIN..LONG_MAX] case TYP_LONG: - lowerBound = fromUnsigned ? SymbolicIntegerValue::Zero : LowerBoundForType(fromType); + if (fromUnsigned && (fromType == TYP_LONG)) + { + lowerBound = SymbolicIntegerValue::Zero; + } + else + { + lowerBound = LowerBoundForType(fromType); + } upperBound = UpperBoundForType(fromType); break; @@ -1545,12 +1605,17 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, } // Try and see if we can make a subrange assertion. - if (((assertionKind == OAK_SUBRANGE) || (assertionKind == OAK_EQUAL))) + if (((assertionKind == OAK_SUBRANGE) || (assertionKind == OAK_EQUAL)) && varTypeIsIntegral(op2)) { - if (optTryExtractSubrangeAssertion(op2, &assertion.op2.u2)) + IntegralRange nodeRange = IntegralRange::ForNode(op2, this); + IntegralRange typeRange = IntegralRange::ForType(genActualType(op2)); + assert(typeRange.Contains(nodeRange)); + + if (!typeRange.Equals(nodeRange)) { assertion.op2.kind = O2K_SUBRANGE; assertion.assertionKind = OAK_SUBRANGE; + assertion.op2.u2 = nodeRange; } } } @@ -1689,73 +1754,6 @@ AssertionIndex Compiler::optFinalizeCreatingAssertion(AssertionDsc* assertion) return optAddAssertion(assertion); } -//------------------------------------------------------------------------ -// optTryExtractSubrangeAssertion: Extract the bounds of the value a tree produces. -// -// Generates [0..1] ranges for relops, [T_MIN..T_MAX] for small-typed indirections -// and casts to small types. Generates various ranges for casts to and from "large" -// types - see "IntegralRange::ForCastOutput". -// -// Arguments: -// source - tree producing the value -// pRange - [out] parameter for the range -// -// Return Value: -// "true" if the "source" computes a value that could be used for a subrange -// assertion, i. e. narrower than the range of the node's type. -// -// Notes: -// The "pRange" parameter is only written to if the function returns "true". -// -bool Compiler::optTryExtractSubrangeAssertion(GenTree* source, IntegralRange* pRange) -{ - var_types sourceType = TYP_UNDEF; - - switch (source->OperGet()) - { - case GT_EQ: - case GT_NE: - case GT_LT: - case GT_LE: - case GT_GT: - case GT_GE: - *pRange = {SymbolicIntegerValue::Zero, SymbolicIntegerValue::One}; - return true; - - case GT_CLS_VAR: - case GT_LCL_FLD: - case GT_IND: - sourceType = source->TypeGet(); - break; - - case GT_CAST: - if (varTypeIsIntegral(source)) - { - IntegralRange castRange = IntegralRange::ForCastOutput(source->AsCast()); - IntegralRange nodeRange = IntegralRange::ForType(source->TypeGet()); - assert(nodeRange.Contains(castRange)); - - if (!castRange.Equals(nodeRange)) - { - *pRange = castRange; - return true; - } - } - return false; - - default: - return false; - } - - if (varTypeIsSmall(sourceType)) - { - *pRange = IntegralRange::ForType(sourceType); - return true; - } - - return false; -} - /***************************************************************************** * * If tree is a constant node holding an integral value, retrieve the value in @@ -5412,7 +5410,14 @@ GenTree* Compiler::optExtractSideEffListFromConst(GenTree* tree) { // Do a sanity check to ensure persistent side effects aren't discarded and // tell gtExtractSideEffList to ignore the root of the tree. - assert(!gtNodeHasSideEffects(tree, GTF_PERSISTENT_SIDE_EFFECTS)); + // We are relying here on an invariant that VN will only fold non-throwing expressions. + const bool ignoreExceptions = true; + const bool ignoreCctors = false; + // We have to check "AsCall()->HasSideEffects()" here separately because "gtNodeHasSideEffects" + // also checks for side effects that arguments introduce (incosistently so, it otherwise only + // checks for the side effects the node itself has). TODO-Cleanup: change it to not do that? + assert(!gtNodeHasSideEffects(tree, GTF_PERSISTENT_SIDE_EFFECTS) || + (tree->IsCall() && !tree->AsCall()->HasSideEffects(this, ignoreExceptions, ignoreCctors))); // Exception side effects may be ignored because the root is known to be a constant // (e.g. VN may evaluate a DIV/MOD node to a constant and the node may still @@ -5612,6 +5617,13 @@ Compiler::fgWalkResult Compiler::optVNConstantPropCurStmt(BasicBlock* block, Sta } break; + case GT_CALL: + if (!tree->AsCall()->IsPure(this)) + { + return WALK_CONTINUE; + } + break; + default: // Unknown node, continue to walk. return WALK_CONTINUE; diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index 7fb88ab2b5806..59894b1b46056 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -1145,10 +1145,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void genConsumeHWIntrinsicOperands(GenTreeHWIntrinsic* tree); #endif // FEATURE_HW_INTRINSICS void genEmitGSCookieCheck(bool pushReg); - void genSetRegToIcon(regNumber reg, - ssize_t val, - var_types type = TYP_INT, - insFlags flags = INS_FLAGS_DONT_CARE DEBUGARG(GenTreeFlags gtFlags = GTF_EMPTY)); void genCodeForShift(GenTree* tree); #if defined(TARGET_X86) || defined(TARGET_ARM) @@ -1259,6 +1255,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX instruction genGetInsForOper(genTreeOps oper, var_types type); bool genEmitOptimizedGCWriteBarrier(GCInfo::WriteBarrierForm writeBarrierForm, GenTree* addr, GenTree* data); GenTree* getCallTarget(const GenTreeCall* call, CORINFO_METHOD_HANDLE* methHnd); + regNumber getCallIndirectionCellReg(const GenTreeCall* call); void genCall(GenTreeCall* call); void genCallInstruction(GenTreeCall* call X86_ARG(target_ssize_t stackArgBytes)); void genJmpMethod(GenTree* jmp); diff --git a/src/coreclr/jit/codegenarm.cpp b/src/coreclr/jit/codegenarm.cpp index 0ae592f0bdbc2..861eac8963611 100644 --- a/src/coreclr/jit/codegenarm.cpp +++ b/src/coreclr/jit/codegenarm.cpp @@ -236,15 +236,20 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre GenTreeIntConCommon* con = tree->AsIntConCommon(); ssize_t cnsVal = con->IconValue(); - if (con->ImmedValNeedsReloc(compiler)) + emitAttr attr = emitActualTypeSize(targetType); + + if (con->IsIconHandle()) { - instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, targetReg, cnsVal); - regSet.verifyRegUsed(targetReg); + attr = EA_SET_FLG(attr, EA_CNS_RELOC_FLG); } - else + + if (targetType == TYP_BYREF) { - genSetRegToIcon(targetReg, cnsVal, targetType); + attr = EA_SET_FLG(attr, EA_BYREF_FLG); } + + instGen_Set_Reg_To_Imm(attr, targetReg, cnsVal); + regSet.verifyRegUsed(targetReg); } break; @@ -259,7 +264,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre regNumber tmpReg = tree->GetSingleTempReg(); float f = forceCastToFloat(constValue); - genSetRegToIcon(tmpReg, *((int*)(&f))); + instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg, *((int*)(&f))); GetEmitter()->emitIns_Mov(INS_vmov_i2f, EA_4BYTE, targetReg, tmpReg, /* canSkip */ false); } else @@ -272,8 +277,8 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre regNumber tmpReg1 = tree->ExtractTempReg(); regNumber tmpReg2 = tree->GetSingleTempReg(); - genSetRegToIcon(tmpReg1, cv[0]); - genSetRegToIcon(tmpReg2, cv[1]); + instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg1, cv[0]); + instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg2, cv[1]); GetEmitter()->emitIns_R_R_R(INS_vmov_i2d, EA_8BYTE, targetReg, tmpReg1, tmpReg2); } @@ -460,7 +465,7 @@ void CodeGen::genLclHeap(GenTree* tree) } // regCnt will be the total number of bytes to locAlloc - genSetRegToIcon(regCnt, amount, TYP_INT); + instGen_Set_Reg_To_Imm(EA_4BYTE, regCnt, amount); } else { @@ -1883,4 +1888,36 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni #endif // USING_SCOPE_INFO } +//----------------------------------------------------------------------------------- +// instGen_MemoryBarrier: Emit a MemoryBarrier instruction +// +// Arguments: +// barrierKind - kind of barrier to emit (ignored on arm32) +// +// Notes: +// All MemoryBarriers instructions can be removed by DOTNET_JitNoMemoryBarriers=1 +// barrierKind argument is ignored on arm32 and a full memory barrier is emitted +// +void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) +{ +#ifdef DEBUG + if (JitConfig.JitNoMemoryBarriers() == 1) + { + return; + } +#endif // DEBUG + + // Avoid emitting redundant memory barriers on arm32 if they belong to the same IG + // and there were no memory accesses in-between them + if ((GetEmitter()->emitLastMemBarrier != nullptr) && compiler->opts.OptimizationEnabled()) + { + assert(GetEmitter()->emitLastMemBarrier->idSmallCns() == INS_BARRIER_SY); + } + else + { + // ARM has only full barriers, so all barriers need to be emitted as full. + GetEmitter()->emitIns_I(INS_dmb, EA_4BYTE, INS_BARRIER_SY); + } +} + #endif // TARGET_ARM diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index 0d4d9e9da2c20..c23a705096caf 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -1697,17 +1697,21 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre GenTreeIntConCommon* con = tree->AsIntConCommon(); ssize_t cnsVal = con->IconValue(); - if (con->ImmedValNeedsReloc(compiler)) + emitAttr attr = emitActualTypeSize(targetType); + if (con->IsIconHandle()) { - instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, targetReg, cnsVal, - INS_FLAGS_DONT_CARE DEBUGARG(tree->AsIntCon()->gtTargetHandle) - DEBUGARG(tree->AsIntCon()->gtFlags)); - regSet.verifyRegUsed(targetReg); + attr = EA_SET_FLG(attr, EA_CNS_RELOC_FLG); } - else + + if (targetType == TYP_BYREF) { - genSetRegToIcon(targetReg, cnsVal, targetType); + attr = EA_SET_FLG(attr, EA_BYREF_FLG); } + + instGen_Set_Reg_To_Imm(attr, targetReg, cnsVal, + INS_FLAGS_DONT_CARE DEBUGARG(tree->AsIntCon()->gtTargetHandle) + DEBUGARG(tree->AsIntCon()->gtFlags)); + regSet.verifyRegUsed(targetReg); } break; @@ -2279,7 +2283,7 @@ void CodeGen::genLclHeap(GenTree* tree) { regCnt = tree->ExtractTempReg(); } - genSetRegToIcon(regCnt, amount, ((unsigned int)amount == amount) ? TYP_INT : TYP_LONG); + instGen_Set_Reg_To_Imm(((unsigned int)amount == amount) ? EA_4BYTE : EA_8BYTE, regCnt, amount); } if (compiler->info.compInitMem) @@ -4623,7 +4627,7 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) } else { - genSetRegToIcon(REG_PROFILER_ENTER_ARG_FUNC_ID, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL); + instGen_Set_Reg_To_Imm(EA_PTRSIZE, REG_PROFILER_ENTER_ARG_FUNC_ID, (ssize_t)compiler->compProfilerMethHnd); } int callerSPOffset = compiler->lvaToCallerSPRelativeOffset(0, isFramePointerUsed()); @@ -4667,7 +4671,7 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper) } else { - genSetRegToIcon(REG_PROFILER_LEAVE_ARG_FUNC_ID, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL); + instGen_Set_Reg_To_Imm(EA_PTRSIZE, REG_PROFILER_LEAVE_ARG_FUNC_ID, (ssize_t)compiler->compProfilerMethHnd); } gcInfo.gcMarkRegSetNpt(RBM_PROFILER_LEAVE_ARG_FUNC_ID); @@ -9510,4 +9514,54 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni } } +//----------------------------------------------------------------------------------- +// instGen_MemoryBarrier: Emit a MemoryBarrier instruction +// +// Arguments: +// barrierKind - kind of barrier to emit (Full or Load-Only). +// +// Notes: +// All MemoryBarriers instructions can be removed by DOTNET_JitNoMemoryBarriers=1 +// +void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) +{ +#ifdef DEBUG + if (JitConfig.JitNoMemoryBarriers() == 1) + { + return; + } +#endif // DEBUG + + // Avoid emitting redundant memory barriers on arm64 if they belong to the same IG + // and there were no memory accesses in-between them + emitter::instrDesc* lastMemBarrier = GetEmitter()->emitLastMemBarrier; + if ((lastMemBarrier != nullptr) && compiler->opts.OptimizationEnabled()) + { + BarrierKind prevBarrierKind = BARRIER_FULL; + if (lastMemBarrier->idSmallCns() == INS_BARRIER_ISHLD) + { + prevBarrierKind = BARRIER_LOAD_ONLY; + } + else + { + // Currently we only emit two kinds of barriers on arm64: + // ISH - Full (inner shareable domain) + // ISHLD - LoadOnly (inner shareable domain) + assert(lastMemBarrier->idSmallCns() == INS_BARRIER_ISH); + } + + if ((prevBarrierKind == BARRIER_LOAD_ONLY) && (barrierKind == BARRIER_FULL)) + { + // Previous memory barrier: load-only, current: full + // Upgrade the previous one to full + assert((prevBarrierKind == BARRIER_LOAD_ONLY) && (barrierKind == BARRIER_FULL)); + lastMemBarrier->idSmallCns(INS_BARRIER_ISH); + } + } + else + { + GetEmitter()->emitIns_BARR(INS_dmb, barrierKind == BARRIER_LOAD_ONLY ? INS_BARRIER_ISHLD : INS_BARRIER_ISH); + } +} + #endif // TARGET_ARM64 diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 68453abaaf7cd..31d7ef94e3afd 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -553,22 +553,6 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) } } -//------------------------------------------------------------------------ -// genSetRegToIcon: Generate code that will set the given register to the integer constant. -// -void CodeGen::genSetRegToIcon(regNumber reg, ssize_t val, var_types type, insFlags flags DEBUGARG(GenTreeFlags gtFlags)) -{ - // Reg cannot be a FP reg - assert(!genIsValidFloatReg(reg)); - - // The only TYP_REF constant that can come this path is a managed 'null' since it is not - // relocatable. Other ref type constants (e.g. string objects) go through a different - // code path. - noway_assert(type != TYP_REF || val == 0); - - instGen_Set_Reg_To_Imm(emitActualTypeSize(type), reg, val, flags); -} - //--------------------------------------------------------------------- // genSetGSSecurityCookie: Set the "GS" security cookie in the prolog. // @@ -593,7 +577,7 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) { noway_assert(compiler->gsGlobalSecurityCookieVal != 0); // initReg = #GlobalSecurityCookieVal; [frame.GSSecurityCookie] = initReg - genSetRegToIcon(initReg, compiler->gsGlobalSecurityCookieVal, TYP_I_IMPL); + instGen_Set_Reg_To_Imm(EA_PTRSIZE, initReg, compiler->gsGlobalSecurityCookieVal); GetEmitter()->emitIns_S_R(INS_str, EA_PTRSIZE, initReg, compiler->lvaGSSecurityCookie, 0); } else @@ -1817,7 +1801,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) else // we have to load the element size and use a MADD (multiply-add) instruction { // tmpReg = element size - CodeGen::genSetRegToIcon(tmpReg, (ssize_t)node->gtElemSize, TYP_INT); + instGen_Set_Reg_To_Imm(EA_4BYTE, tmpReg, (ssize_t)node->gtElemSize); // dest = index * tmpReg + base GetEmitter()->emitIns_R_R_R_R(INS_MULADD, emitActualTypeSize(node), node->GetRegNum(), index->GetRegNum(), @@ -2565,109 +2549,109 @@ void CodeGen::genCallInstruction(GenTreeCall* call) call->IsFastTailCall()); // clang-format on } - else if (call->IsR2ROrVirtualStubRelativeIndir()) - { - // Generate a indirect call to a virtual user defined function or helper method - assert(call->gtCallType == CT_HELPER || call->gtCallType == CT_USER_FUNC); -#ifdef FEATURE_READYTORUN - assert(((call->IsR2RRelativeIndir()) && (call->gtEntryPoint.accessType == IAT_PVALUE)) || - ((call->IsVirtualStubRelativeIndir()) && (call->gtEntryPoint.accessType == IAT_VALUE))); -#endif // FEATURE_READYTORUN - assert(call->gtControlExpr == nullptr); - - regNumber tmpReg = call->GetSingleTempReg(); - // For fast tailcalls we have already loaded the call target when processing the call node. - if (!call->IsFastTailCall()) - { - regNumber callAddrReg = - call->IsVirtualStubRelativeIndir() ? compiler->virtualStubParamInfo->GetReg() : REG_R2R_INDIRECT_PARAM; - GetEmitter()->emitIns_R_R(ins_Load(TYP_I_IMPL), emitActualTypeSize(TYP_I_IMPL), tmpReg, callAddrReg); - } - else - { - // Register where we save call address in should not be overridden by epilog. - assert((tmpReg & (RBM_INT_CALLEE_TRASH & ~RBM_LR)) == tmpReg); - } - - // We have now generated code for gtControlExpr evaluating it into `tmpReg`. - // We just need to emit "call tmpReg" in this case. - // - assert(genIsValidIntReg(tmpReg)); - - // clang-format off - genEmitCall(emitter::EC_INDIR_R, - methHnd, - INDEBUG_LDISASM_COMMA(sigInfo) - nullptr, // addr - retSize - MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), - ilOffset, - tmpReg, - call->IsFastTailCall()); - // clang-format on - } else { - // Generate a direct call to a non-virtual user defined or helper method - assert(call->gtCallType == CT_HELPER || call->gtCallType == CT_USER_FUNC); - - void* addr = nullptr; -#ifdef FEATURE_READYTORUN - if (call->gtEntryPoint.addr != NULL) - { - assert(call->gtEntryPoint.accessType == IAT_VALUE); - addr = call->gtEntryPoint.addr; - } - else -#endif // FEATURE_READYTORUN - if (call->gtCallType == CT_HELPER) - { - CorInfoHelpFunc helperNum = compiler->eeGetHelperNum(methHnd); - noway_assert(helperNum != CORINFO_HELP_UNDEF); - - void* pAddr = nullptr; - addr = compiler->compGetHelperFtn(helperNum, (void**)&pAddr); - assert(pAddr == nullptr); - } - else + // If we have no target and this is a call with indirection cell + // then we do an optimization where we load the call address directly + // from the indirection cell instead of duplicating the tree. + // In BuildCall we ensure that get an extra register for the purpose. + regNumber indirCellReg = getCallIndirectionCellReg(call); + if (indirCellReg != REG_NA) { - // Direct call to a non-virtual user function. - addr = call->gtDirectCallAddress; - } + assert(call->IsR2ROrVirtualStubRelativeIndir()); + regNumber targetAddrReg = call->GetSingleTempReg(); + // For fast tailcalls we have already loaded the call target when processing the call node. + if (!call->IsFastTailCall()) + { + GetEmitter()->emitIns_R_R(ins_Load(TYP_I_IMPL), emitActualTypeSize(TYP_I_IMPL), targetAddrReg, + indirCellReg); + } + else + { + // Register where we save call address in should not be overridden by epilog. + assert((targetAddrReg & (RBM_INT_CALLEE_TRASH & ~RBM_LR)) == targetAddrReg); + } - assert(addr != nullptr); + // We have now generated code loading the target address from the indirection cell into `targetAddrReg`. + // We just need to emit "bl targetAddrReg" in this case. + // + assert(genIsValidIntReg(targetAddrReg)); -// Non-virtual direct call to known addresses -#ifdef TARGET_ARM - if (!arm_Valid_Imm_For_BL((ssize_t)addr)) - { - regNumber tmpReg = call->GetSingleTempReg(); - instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, tmpReg, (ssize_t)addr); // clang-format off genEmitCall(emitter::EC_INDIR_R, methHnd, INDEBUG_LDISASM_COMMA(sigInfo) - NULL, - retSize, + nullptr, // addr + retSize + MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), ilOffset, - tmpReg, + targetAddrReg, call->IsFastTailCall()); // clang-format on } else -#endif // TARGET_ARM { - // clang-format off - genEmitCall(emitter::EC_FUNC_TOKEN, - methHnd, - INDEBUG_LDISASM_COMMA(sigInfo) - addr, - retSize - MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), - ilOffset, - REG_NA, - call->IsFastTailCall()); - // clang-format on + // Generate a direct call to a non-virtual user defined or helper method + assert(call->gtCallType == CT_HELPER || call->gtCallType == CT_USER_FUNC); + + void* addr = nullptr; +#ifdef FEATURE_READYTORUN + if (call->gtEntryPoint.addr != NULL) + { + assert(call->gtEntryPoint.accessType == IAT_VALUE); + addr = call->gtEntryPoint.addr; + } + else +#endif // FEATURE_READYTORUN + if (call->gtCallType == CT_HELPER) + { + CorInfoHelpFunc helperNum = compiler->eeGetHelperNum(methHnd); + noway_assert(helperNum != CORINFO_HELP_UNDEF); + + void* pAddr = nullptr; + addr = compiler->compGetHelperFtn(helperNum, (void**)&pAddr); + assert(pAddr == nullptr); + } + else + { + // Direct call to a non-virtual user function. + addr = call->gtDirectCallAddress; + } + + assert(addr != nullptr); + +// Non-virtual direct call to known addresses +#ifdef TARGET_ARM + if (!arm_Valid_Imm_For_BL((ssize_t)addr)) + { + regNumber tmpReg = call->GetSingleTempReg(); + instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, tmpReg, (ssize_t)addr); + // clang-format off + genEmitCall(emitter::EC_INDIR_R, + methHnd, + INDEBUG_LDISASM_COMMA(sigInfo) + NULL, + retSize, + ilOffset, + tmpReg, + call->IsFastTailCall()); + // clang-format on + } + else +#endif // TARGET_ARM + { + // clang-format off + genEmitCall(emitter::EC_FUNC_TOKEN, + methHnd, + INDEBUG_LDISASM_COMMA(sigInfo) + addr, + retSize + MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), + ilOffset, + REG_NA, + call->IsFastTailCall()); + // clang-format on + } } } } diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 15fac8b26ae0f..38a134cbe67a4 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -1794,7 +1794,7 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) { // load the GS cookie constant into a reg // - genSetRegToIcon(regGSConst, compiler->gsGlobalSecurityCookieVal, TYP_I_IMPL); + instGen_Set_Reg_To_Imm(EA_PTRSIZE, regGSConst, compiler->gsGlobalSecurityCookieVal); } else { @@ -7802,6 +7802,55 @@ GenTree* CodeGen::getCallTarget(const GenTreeCall* call, CORINFO_METHOD_HANDLE* return call->gtControlExpr; } +//------------------------------------------------------------------------ +// getCallIndirectionCellReg - Get the register containing the indirection cell for a call +// +// Arguments: +// call - the node +// +// Returns: +// The register containing the indirection cell, or REG_NA if this call does not use an indirection cell argument. +// +// Notes: +// We currently use indirection cells for VSD on all platforms and for R2R calls on ARM architectures. +// +regNumber CodeGen::getCallIndirectionCellReg(const GenTreeCall* call) +{ + regNumber result = REG_NA; + switch (call->GetIndirectionCellArgKind()) + { + case NonStandardArgKind::None: + break; + case NonStandardArgKind::R2RIndirectionCell: + result = REG_R2R_INDIRECT_PARAM; + break; + case NonStandardArgKind::VirtualStubCell: + result = compiler->virtualStubParamInfo->GetReg(); + break; + default: + unreached(); + } + +#ifdef DEBUG + regNumber foundReg = REG_NA; + unsigned argCount = call->fgArgInfo->ArgCount(); + fgArgTabEntry** argTable = call->fgArgInfo->ArgTable(); + for (unsigned i = 0; i < argCount; i++) + { + NonStandardArgKind kind = argTable[i]->nonStandardArgKind; + if ((kind == NonStandardArgKind::R2RIndirectionCell) || (kind == NonStandardArgKind::VirtualStubCell)) + { + foundReg = argTable[i]->GetRegNum(); + break; + } + } + + assert(foundReg == result); +#endif + + return result; +} + /***************************************************************************** * * Generates code for a function epilog. @@ -12565,9 +12614,9 @@ void CodeGen::genPoisonFrame(regMaskTP regLiveIn) if (!hasPoisonImm) { #ifdef TARGET_64BIT - genSetRegToIcon(REG_SCRATCH, (ssize_t)0xcdcdcdcdcdcdcdcd, TYP_LONG); + instGen_Set_Reg_To_Imm(EA_8BYTE, REG_SCRATCH, (ssize_t)0xcdcdcdcdcdcdcdcd); #else - genSetRegToIcon(REG_SCRATCH, (ssize_t)0xcdcdcdcd, TYP_INT); + instGen_Set_Reg_To_Imm(EA_4BYTE, REG_SCRATCH, (ssize_t)0xcdcdcdcd); #endif hasPoisonImm = true; } diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index 7b9be941ab4e8..c9251065ce5b9 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -1898,7 +1898,7 @@ void CodeGen::genSetBlockSize(GenTreeBlk* blkNode, regNumber sizeReg) if (!blkNode->OperIs(GT_STORE_DYN_BLK)) { assert((blkNode->gtRsvdRegs & genRegMask(sizeReg)) != 0); - genSetRegToIcon(sizeReg, blockSize); + instGen_Set_Reg_To_Imm(EA_4BYTE, sizeReg, blockSize); } else { diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 9c280d6e63977..df37565b4242a 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -23,32 +23,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "gcinfoencoder.h" #include "patchpointinfo.h" -/***************************************************************************** - * - * Generate code that will set the given register to the integer constant. - */ - -void CodeGen::genSetRegToIcon(regNumber reg, ssize_t val, var_types type, insFlags flags DEBUGARG(GenTreeFlags gtFlags)) -{ - // Reg cannot be a FP reg - assert(!genIsValidFloatReg(reg)); - - // The only TYP_REF constant that can come this path is a managed 'null' since it is not - // relocatable. Other ref type constants (e.g. string objects) go through a different - // code path. - noway_assert(type != TYP_REF || val == 0); - - if (val == 0) - { - instGen_Set_Reg_To_Zero(emitActualTypeSize(type), reg, flags); - } - else - { - // TODO-XArch-CQ: needs all the optimized cases - GetEmitter()->emitIns_R_I(INS_mov, emitActualTypeSize(type), reg, val DEBUGARG(gtFlags)); - } -} - //--------------------------------------------------------------------- // genSetGSSecurityCookie: Set the "GS" security cookie in the prolog. // @@ -82,7 +56,7 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) if ((size_t)(int)compiler->gsGlobalSecurityCookieVal != compiler->gsGlobalSecurityCookieVal) { // initReg = #GlobalSecurityCookieVal64; [frame.GSSecurityCookie] = initReg - genSetRegToIcon(initReg, compiler->gsGlobalSecurityCookieVal, TYP_I_IMPL); + instGen_Set_Reg_To_Imm(EA_PTRSIZE, initReg, compiler->gsGlobalSecurityCookieVal); GetEmitter()->emitIns_S_R(INS_mov, EA_PTRSIZE, initReg, compiler->lvaGSSecurityCookie, 0); *pInitRegZeroed = false; } @@ -230,7 +204,7 @@ void CodeGen::genEmitGSCookieCheck(bool pushReg) // Otherwise, load the value into a reg and use 'cmp mem64, reg64'. if ((int)compiler->gsGlobalSecurityCookieVal != (ssize_t)compiler->gsGlobalSecurityCookieVal) { - genSetRegToIcon(regGSCheck, compiler->gsGlobalSecurityCookieVal, TYP_I_IMPL); + instGen_Set_Reg_To_Imm(EA_PTRSIZE, regGSCheck, compiler->gsGlobalSecurityCookieVal); GetEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, regGSCheck, compiler->lvaGSSecurityCookie, 0); } else @@ -445,9 +419,11 @@ void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, // reg cannot be a FP register assert(!genIsValidFloatReg(reg)); + emitAttr origAttr = size; if (!compiler->opts.compReloc) { - size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs + // Strip any reloc flags from size if we aren't doing relocs + size = EA_REMOVE_FLG(size, EA_CNS_RELOC_FLG | EA_DSP_RELOC_FLG); } if ((imm == 0) && !EA_IS_RELOC(size)) @@ -456,19 +432,17 @@ void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, } else { - if (genDataIndirAddrCanBeEncodedAsPCRelOffset(imm)) + // Only use lea if the original was relocatable. Otherwise we can get spurious + // instruction selection due to different memory placement at runtime. + if (EA_IS_RELOC(origAttr) && genDataIndirAddrCanBeEncodedAsPCRelOffset(imm)) { - emitAttr newSize = EA_PTR_DSP_RELOC; - if (EA_IS_BYREF(size)) - { - newSize = EA_SET_FLG(newSize, EA_BYREF_FLG); - } - - GetEmitter()->emitIns_R_AI(INS_lea, newSize, reg, imm); + // We will use lea so displacement and not immediate will be relocatable + size = EA_SET_FLG(EA_REMOVE_FLG(size, EA_CNS_RELOC_FLG), EA_DSP_RELOC_FLG); + GetEmitter()->emitIns_R_AI(INS_lea, size, reg, imm); } else { - GetEmitter()->emitIns_R_I(INS_mov, size, reg, imm); + GetEmitter()->emitIns_R_I(INS_mov, size, reg, imm DEBUGARG(gtFlags)); } } regSet.verifyRegUsed(reg); @@ -491,22 +465,19 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre GenTreeIntConCommon* con = tree->AsIntConCommon(); ssize_t cnsVal = con->IconValue(); - if (con->ImmedValNeedsReloc(compiler)) + emitAttr attr = emitActualTypeSize(targetType); + if (con->IsIconHandle()) { - emitAttr size = EA_HANDLE_CNS_RELOC; - - if (targetType == TYP_BYREF) - { - size = EA_SET_FLG(size, EA_BYREF_FLG); - } - - instGen_Set_Reg_To_Imm(size, targetReg, cnsVal); - regSet.verifyRegUsed(targetReg); + attr = EA_SET_FLG(attr, EA_CNS_RELOC_FLG); } - else + + if (targetType == TYP_BYREF) { - genSetRegToIcon(targetReg, cnsVal, targetType, INS_FLAGS_DONT_CARE DEBUGARG(tree->gtFlags)); + attr = EA_SET_FLG(attr, EA_BYREF_FLG); } + + instGen_Set_Reg_To_Imm(attr, targetReg, cnsVal, INS_FLAGS_DONT_CARE DEBUGARG(0) DEBUGARG(tree->gtFlags)); + regSet.verifyRegUsed(targetReg); } break; @@ -2515,7 +2486,7 @@ void CodeGen::genLclHeap(GenTree* tree) amount /= STACK_ALIGN; } - genSetRegToIcon(regCnt, amount, ((size_t)(int)amount == amount) ? TYP_INT : TYP_LONG); + instGen_Set_Reg_To_Imm(((size_t)(int)amount == amount) ? EA_4BYTE : EA_8BYTE, regCnt, amount); } if (compiler->info.compInitMem) @@ -5696,15 +5667,18 @@ void CodeGen::genCallInstruction(GenTreeCall* call X86_ARG(target_ssize_t stackA // clang-format on } } -#ifdef FEATURE_READYTORUN - else if (call->gtEntryPoint.addr != nullptr) + else { - emitter::EmitCallType type = - (call->gtEntryPoint.accessType == IAT_VALUE) ? emitter::EC_FUNC_TOKEN : emitter::EC_FUNC_TOKEN_INDIR; - if (call->IsFastTailCall() && (type == emitter::EC_FUNC_TOKEN_INDIR)) + // If we have no target and this is a call with indirection cell + // then emit call through that indir cell. This means we generate e.g. + // lea r11, [addr of cell] + // call [r11] + // which is more efficent than + // lea r11, [addr of cell] + // call [addr of cell] + regNumber indirCellReg = getCallIndirectionCellReg(call); + if (indirCellReg != REG_NA) { - // For fast tailcall with func token indir we already have the indirection cell in REG_R2R_INDIRECT_PARAM, - // so get it from there. // clang-format off GetEmitter()->emitIns_Call( emitter::EC_INDIR_ARD, @@ -5717,11 +5691,15 @@ void CodeGen::genCallInstruction(GenTreeCall* call X86_ARG(target_ssize_t stackA gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur, - ilOffset, REG_R2R_INDIRECT_PARAM, REG_NA, 0, 0, true); + ilOffset, indirCellReg, REG_NA, 0, 0, + call->IsFastTailCall()); // clang-format on } - else +#ifdef FEATURE_READYTORUN + else if (call->gtEntryPoint.addr != nullptr) { + emitter::EmitCallType type = + (call->gtEntryPoint.accessType == IAT_VALUE) ? emitter::EC_FUNC_TOKEN : emitter::EC_FUNC_TOKEN_INDIR; // clang-format off genEmitCall(type, methHnd, @@ -5735,46 +5713,46 @@ void CodeGen::genCallInstruction(GenTreeCall* call X86_ARG(target_ssize_t stackA call->IsFastTailCall()); // clang-format on } - } #endif - else - { - // Generate a direct call to a non-virtual user defined or helper method - assert(call->gtCallType == CT_HELPER || call->gtCallType == CT_USER_FUNC); - - void* addr = nullptr; - if (call->gtCallType == CT_HELPER) - { - // Direct call to a helper method. - CorInfoHelpFunc helperNum = compiler->eeGetHelperNum(methHnd); - noway_assert(helperNum != CORINFO_HELP_UNDEF); - - void* pAddr = nullptr; - addr = compiler->compGetHelperFtn(helperNum, (void**)&pAddr); - assert(pAddr == nullptr); - } else { - // Direct call to a non-virtual user function. - addr = call->gtDirectCallAddress; - } + // Generate a direct call to a non-virtual user defined or helper method + assert(call->gtCallType == CT_HELPER || call->gtCallType == CT_USER_FUNC); - assert(addr != nullptr); + void* addr = nullptr; + if (call->gtCallType == CT_HELPER) + { + // Direct call to a helper method. + CorInfoHelpFunc helperNum = compiler->eeGetHelperNum(methHnd); + noway_assert(helperNum != CORINFO_HELP_UNDEF); - // Non-virtual direct calls to known addresses + void* pAddr = nullptr; + addr = compiler->compGetHelperFtn(helperNum, (void**)&pAddr); + assert(pAddr == nullptr); + } + else + { + // Direct call to a non-virtual user function. + addr = call->gtDirectCallAddress; + } - // clang-format off - genEmitCall(emitter::EC_FUNC_TOKEN, - methHnd, - INDEBUG_LDISASM_COMMA(sigInfo) - addr - X86_ARG(argSizeForEmitter), - retSize - MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), - ilOffset, - REG_NA, - call->IsFastTailCall()); - // clang-format on + assert(addr != nullptr); + + // Non-virtual direct calls to known addresses + + // clang-format off + genEmitCall(emitter::EC_FUNC_TOKEN, + methHnd, + INDEBUG_LDISASM_COMMA(sigInfo) + addr + X86_ARG(argSizeForEmitter), + retSize + MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize), + ilOffset, + REG_NA, + call->IsFastTailCall()); + // clang-format on + } } } @@ -8443,7 +8421,7 @@ void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize, #endif callTarget = callTargetReg; - CodeGen::genSetRegToIcon(callTarget, (ssize_t)pAddr, TYP_I_IMPL); + instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, callTarget, (ssize_t)pAddr); callType = emitter::EC_INDIR_ARD; } } @@ -8818,16 +8796,7 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) } else { - // No need to record relocations, if we are generating ELT hooks under the influence - // of COMPlus_JitELTHookEnabled=1 - if (compiler->opts.compJitELTHookEnabled) - { - genSetRegToIcon(REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL); - } - else - { - instGen_Set_Reg_To_Imm(EA_8BYTE, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd); - } + instGen_Set_Reg_To_Imm(EA_8BYTE, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd); } // RDX = caller's SP @@ -8902,16 +8871,7 @@ void CodeGen::genProfilingEnterCallback(regNumber initReg, bool* pInitRegZeroed) } else { - // No need to record relocations, if we are generating ELT hooks under the influence - // of COMPlus_JitELTHookEnabled=1 - if (compiler->opts.compJitELTHookEnabled) - { - genSetRegToIcon(REG_PROFILER_ENTER_ARG_0, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL); - } - else - { - instGen_Set_Reg_To_Imm(EA_8BYTE, REG_PROFILER_ENTER_ARG_0, (ssize_t)compiler->compProfilerMethHnd); - } + instGen_Set_Reg_To_Imm(EA_PTRSIZE, REG_PROFILER_ENTER_ARG_0, (ssize_t)compiler->compProfilerMethHnd); } // R15 = caller's SP @@ -8990,16 +8950,7 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper) } else { - // Don't record relocations, if we are generating ELT hooks under the influence - // of COMPlus_JitELTHookEnabled=1 - if (compiler->opts.compJitELTHookEnabled) - { - genSetRegToIcon(REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL); - } - else - { - instGen_Set_Reg_To_Imm(EA_8BYTE, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd); - } + instGen_Set_Reg_To_Imm(EA_PTRSIZE, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd); } // RDX = caller's SP @@ -9040,14 +8991,7 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper) } else { - if (compiler->opts.compJitELTHookEnabled) - { - genSetRegToIcon(REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd, TYP_I_IMPL); - } - else - { - instGen_Set_Reg_To_Imm(EA_8BYTE, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd); - } + instGen_Set_Reg_To_Imm(EA_PTRSIZE, REG_ARG_0, (ssize_t)compiler->compProfilerMethHnd); } // RSI = caller's SP @@ -9135,4 +9079,30 @@ void CodeGen::genPushCalleeSavedRegisters() } } +//----------------------------------------------------------------------------------- +// instGen_MemoryBarrier: Emit a MemoryBarrier instruction +// +// Arguments: +// barrierKind - kind of barrier to emit (Load-only is no-op on xarch) +// +// Notes: +// All MemoryBarriers instructions can be removed by DOTNET_JitNoMemoryBarriers=1 +// +void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) +{ +#ifdef DEBUG + if (JitConfig.JitNoMemoryBarriers() == 1) + { + return; + } +#endif // DEBUG + + // only full barrier needs to be emitted on Xarch + if (barrierKind == BARRIER_FULL) + { + instGen(INS_lock); + GetEmitter()->emitIns_I_AR(INS_or, EA_4BYTE, 0, REG_SPBASE, 0); + } +} + #endif // TARGET_XARCH diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 7019714bed642..e2f2eb513cb48 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -1216,6 +1216,11 @@ class IntegralRange return (m_lowerBound <= other.m_lowerBound) && (other.m_upperBound <= m_upperBound); } + bool IsPositive() + { + return m_lowerBound >= SymbolicIntegerValue::Zero; + } + bool Equals(IntegralRange other) const { return (m_lowerBound == other.m_lowerBound) && (m_upperBound == other.m_upperBound); @@ -1230,6 +1235,7 @@ class IntegralRange return {LowerBoundForType(type), UpperBoundForType(type)}; } + static IntegralRange ForNode(GenTree* node, Compiler* compiler); static IntegralRange ForCastInput(GenTreeCast* cast); static IntegralRange ForCastOutput(GenTreeCast* cast); @@ -1633,26 +1639,6 @@ struct FuncInfoDsc // that isn't shared between the main function body and funclets. }; -enum class NonStandardArgKind : unsigned -{ - None, - PInvokeFrame, - PInvokeTarget, - PInvokeCookie, - WrapperDelegateCell, - ShiftLow, - ShiftHigh, - FixedRetBuffer, - VirtualStubCell, - R2RIndirectionCell, - - // If changing this enum also change getNonStandardArgKindName and isNonStandardArgAddedLate below -}; - -#ifdef DEBUG -const char* getNonStandardArgKindName(NonStandardArgKind kind); -#endif - struct fgArgTabEntry { GenTreeCall::Use* use; // Points to the argument's GenTreeCall::Use in gtCallArgs or gtCallThisArg. @@ -5498,6 +5484,9 @@ class Compiler // Does value-numbering for a call. We interpret some helper calls. void fgValueNumberCall(GenTreeCall* call); + // Does value-numbering for a helper representing a cast operation. + void fgValueNumberCastHelper(GenTreeCall* call); + // Does value-numbering for a helper "call" that has a VN function symbol "vnf". void fgValueNumberHelperCallFunc(GenTreeCall* call, VNFunc vnf, ValueNumPair vnpExc); @@ -6363,7 +6352,7 @@ class Compiler GenTree* fgMorphCopyBlock(GenTree* tree); GenTree* fgMorphForRegisterFP(GenTree* tree); GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac = nullptr); - GenTree* fgOptimizeCast(GenTree* tree); + GenTree* fgOptimizeCast(GenTreeCast* cast); GenTree* fgOptimizeEqualityComparisonWithConst(GenTreeOp* cmp); GenTree* fgOptimizeRelationalComparisonWithConst(GenTreeOp* cmp); GenTree* fgPropagateCommaThrow(GenTree* parent, GenTreeOp* commaThrow, GenTreeFlags precedingSideEffects); @@ -6376,6 +6365,7 @@ class Compiler GenTreeLclVar* fgMorphTryFoldObjAsLclVar(GenTreeObj* obj); GenTree* fgMorphCommutative(GenTreeOp* tree); + GenTree* fgMorphCastedBitwiseOp(GenTreeOp* tree); public: GenTree* fgMorphTree(GenTree* tree, MorphAddrContext* mac = nullptr); diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index 8bf8e586f34e1..3708f5123a942 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -703,6 +703,11 @@ insGroup* emitter::emitSavIG(bool emitAdd) ig = emitCurIG; assert(ig); +#ifdef TARGET_ARMARCH + // Reset emitLastMemBarrier for new IG + emitLastMemBarrier = nullptr; +#endif + // Compute how much code we've generated sz = emitCurIGfreeNext - emitCurIGfreeBase; @@ -1140,6 +1145,10 @@ void emitter::emitBegFN(bool hasFramePtr emitLastIns = nullptr; +#ifdef TARGET_ARMARCH + emitLastMemBarrier = nullptr; +#endif + ig->igNext = nullptr; #ifdef DEBUG @@ -1303,6 +1312,17 @@ void emitter::dispIns(instrDesc* id) void emitter::appendToCurIG(instrDesc* id) { +#ifdef TARGET_ARMARCH + if (id->idIns() == INS_dmb) + { + emitLastMemBarrier = id; + } + else if (emitInsIsLoadOrStore(id->idIns())) + { + // A memory access - reset saved memory barrier + emitLastMemBarrier = nullptr; + } +#endif emitCurIGsize += id->idCodeSize(); } diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index d84ede9ed63e8..23d5e0327db57 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -1884,6 +1884,10 @@ class emitter instrDesc* emitLastIns; +#ifdef TARGET_ARMARCH + instrDesc* emitLastMemBarrier; +#endif + #ifdef DEBUG void emitCheckIGoffsets(); #endif diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index dda2f217a7f7b..788034227f3c4 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -8846,7 +8846,12 @@ void emitter::emitDispIns( } else { - printf("%s", sstr); + // GC ref bit is for the return value for calls, do not print it before the address mode + if ((ins != INS_call) && (ins != INS_tail_i_jmp)) + { + printf("%s", sstr); + } + emitDispAddrMode(id, isNew); emitDispShift(ins); } @@ -10292,7 +10297,7 @@ BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc) noway_assert((int)dsp == dsp); // This requires, specifying a SIB byte after ModRM byte. - if (EncodedBySSE38orSSE3A(ins)) + if (EncodedBySSE38orSSE3A(ins) || (ins == INS_crc32)) { dst += emitOutputByte(dst, code | 0x04); } diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 800a09399012d..d58f0f202ab0d 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -15908,7 +15908,7 @@ void Compiler::gtExtractSideEffList(GenTree* expr, { if (m_compiler->gtNodeHasSideEffects(node, m_flags)) { - m_sideEffects.Push(node); + PushSideEffects(node); if (node->OperIsBlk() && !node->OperIsStoreBlk()) { JITDUMP("Replace an unused OBJ/BLK node [%06d] with a NULLCHECK\n", dspTreeID(node)); @@ -15925,7 +15925,7 @@ void Compiler::gtExtractSideEffList(GenTree* expr, // gtNodeHasSideEffects and make this check unconditionally. if (node->OperIsAtomicOp()) { - m_sideEffects.Push(node); + PushSideEffects(node); return Compiler::WALK_SKIP_SUBTREES; } @@ -15936,7 +15936,7 @@ void Compiler::gtExtractSideEffList(GenTree* expr, (node->gtGetOp1()->TypeGet() == TYP_STRUCT)) { JITDUMP("Keep the GT_ADDR and GT_IND together:\n"); - m_sideEffects.Push(node); + PushSideEffects(node); return Compiler::WALK_SKIP_SUBTREES; } } @@ -15953,7 +15953,7 @@ void Compiler::gtExtractSideEffList(GenTree* expr, // those need to be extracted as if they're side effects. if (!UnmarkCSE(node)) { - m_sideEffects.Push(node); + PushSideEffects(node); return Compiler::WALK_SKIP_SUBTREES; } @@ -15989,6 +15989,16 @@ void Compiler::gtExtractSideEffList(GenTree* expr, return false; } } + + void PushSideEffects(GenTree* node) + { + // The extracted side effect will no longer be an argument, so unmark it. + // This is safe to do because the side effects will be visited in pre-order, + // aborting as soon as any tree is extracted. Thus if an argument for a call + // is being extracted, it is guaranteed that the call itself will not be. + node->gtFlags &= ~GTF_LATE_ARG; + m_sideEffects.Push(node); + } }; SideEffectExtractor extractor(this, flags); diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index db7c56072130e..1741b2257f3bc 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -4101,6 +4101,26 @@ class TailCallSiteInfo class fgArgInfo; +enum class NonStandardArgKind : unsigned +{ + None, + PInvokeFrame, + PInvokeTarget, + PInvokeCookie, + WrapperDelegateCell, + ShiftLow, + ShiftHigh, + FixedRetBuffer, + VirtualStubCell, + R2RIndirectionCell, + + // If changing this enum also change getNonStandardArgKindName and isNonStandardArgAddedLate in fgArgInfo +}; + +#ifdef DEBUG +const char* getNonStandardArgKindName(NonStandardArgKind kind); +#endif + struct GenTreeCall final : public GenTree { class Use @@ -4472,12 +4492,14 @@ struct GenTreeCall final : public GenTree bool IsR2ROrVirtualStubRelativeIndir() { -#if defined(FEATURE_READYTORUN) && defined(TARGET_ARMARCH) - bool isVirtualStub = (gtFlags & GTF_CALL_VIRT_KIND_MASK) == GTF_CALL_VIRT_STUB; - return ((IsR2RRelativeIndir()) || (isVirtualStub && (IsVirtualStubRelativeIndir()))); -#else - return false; -#endif // FEATURE_READYTORUN && TARGET_ARMARCH +#if defined(FEATURE_READYTORUN) + if (IsR2RRelativeIndir()) + { + return true; + } +#endif + + return IsVirtualStubRelativeIndir(); } bool HasNonStandardAddedArgs(Compiler* compiler) const; @@ -4636,6 +4658,11 @@ struct GenTreeCall final : public GenTree } #endif // !FEATURE_TAILCALL_OPT + bool NormalizesSmallTypesOnReturn() + { + return GetUnmanagedCallConv() == CorInfoCallConvExtension::Managed; + } + bool IsSameThis() const { return (gtCallMoreFlags & GTF_CALL_M_NONVIRT_SAME_THIS) != 0; @@ -4646,7 +4673,7 @@ struct GenTreeCall final : public GenTree } bool IsVirtualStubRelativeIndir() const { - return (gtCallMoreFlags & GTF_CALL_M_VIRTSTUB_REL_INDIRECT) != 0; + return IsVirtualStub() && (gtCallMoreFlags & GTF_CALL_M_VIRTSTUB_REL_INDIRECT) != 0; } bool IsR2RRelativeIndir() const @@ -4767,14 +4794,46 @@ struct GenTreeCall final : public GenTree return (gtCallMoreFlags & GTF_CALL_M_EXPANDED_EARLY) != 0; } - void ResetArgInfo(); + //----------------------------------------------------------------------------------------- + // GetIndirectionCellArgKind: Get the kind of indirection cell used by this call. + // + // Arguments: + // None + // + // Return Value: + // The kind (either R2RIndirectionCell or VirtualStubCell), + // or NonStandardArgKind::None if this call does not have an indirection cell. + // + NonStandardArgKind GetIndirectionCellArgKind() const + { + if (IsVirtualStub()) + { + return NonStandardArgKind::VirtualStubCell; + } - GenTreeCallFlags gtCallMoreFlags; // in addition to gtFlags +#if defined(TARGET_ARMARCH) + // For ARM architectures, we always use an indirection cell for R2R calls. + if (IsR2RRelativeIndir()) + { + return NonStandardArgKind::R2RIndirectionCell; + } +#elif defined(TARGET_XARCH) + // On XARCH we disassemble it from callsite except for tailcalls that need indirection cell. + if (IsR2RRelativeIndir() && IsFastTailCall()) + { + return NonStandardArgKind::R2RIndirectionCell; + } +#endif + + return NonStandardArgKind::None; + } - unsigned char gtCallType : 3; // value from the gtCallTypes enumeration - unsigned char gtReturnType : 5; // exact return type + void ResetArgInfo(); - CORINFO_CLASS_HANDLE gtRetClsHnd; // The return type handle of the call if it is a struct; always available + GenTreeCallFlags gtCallMoreFlags; // in addition to gtFlags + gtCallTypes gtCallType : 3; // value from the gtCallTypes enumeration + var_types gtReturnType : 5; // exact return type + CORINFO_CLASS_HANDLE gtRetClsHnd; // The return type handle of the call if it is a struct; always available union { // only used for CALLI unmanaged calls (CT_INDIRECT) diff --git a/src/coreclr/jit/instr.cpp b/src/coreclr/jit/instr.cpp index d15a17118f9a1..39f885d925fdf 100644 --- a/src/coreclr/jit/instr.cpp +++ b/src/coreclr/jit/instr.cpp @@ -2386,41 +2386,6 @@ void CodeGen::instGen_Return(unsigned stkArgSize) #endif } -/***************************************************************************** - * - * Emit a MemoryBarrier instruction - * - * Note: all MemoryBarriers instructions can be removed by - * SET COMPlus_JitNoMemoryBarriers=1 - */ -void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind) -{ -#ifdef DEBUG - if (JitConfig.JitNoMemoryBarriers() == 1) - { - return; - } -#endif // DEBUG - -#if defined(TARGET_XARCH) - // only full barrier needs to be emitted on Xarch - if (barrierKind != BARRIER_FULL) - { - return; - } - - instGen(INS_lock); - GetEmitter()->emitIns_I_AR(INS_or, EA_4BYTE, 0, REG_SPBASE, 0); -#elif defined(TARGET_ARM) - // ARM has only full barriers, so all barriers need to be emitted as full. - GetEmitter()->emitIns_I(INS_dmb, EA_4BYTE, 0xf); -#elif defined(TARGET_ARM64) - GetEmitter()->emitIns_BARR(INS_dmb, barrierKind == BARRIER_LOAD_ONLY ? INS_BARRIER_ISHLD : INS_BARRIER_ISH); -#else -#error "Unknown TARGET" -#endif -} - /***************************************************************************** * * Machine independent way to move a Zero value into a register diff --git a/src/coreclr/jit/instr.h b/src/coreclr/jit/instr.h index d9e2b9319ee4c..7999d043b6fc6 100644 --- a/src/coreclr/jit/instr.h +++ b/src/coreclr/jit/instr.h @@ -161,6 +161,10 @@ enum insOpts: unsigned INS_OPTS_ASR, INS_OPTS_ROR }; +enum insBarrier : unsigned +{ + INS_BARRIER_SY = 15 +}; #elif defined(TARGET_ARM64) enum insOpts : unsigned { @@ -306,8 +310,8 @@ enum emitAttr : unsigned EA_GCREF = EA_GCREF_FLG | EA_PTRSIZE, /* size == -1 */ EA_BYREF_FLG = 0x100, EA_BYREF = EA_BYREF_FLG | EA_PTRSIZE, /* size == -2 */ - EA_DSP_RELOC_FLG = 0x200, - EA_CNS_RELOC_FLG = 0x400, + EA_DSP_RELOC_FLG = 0x200, // Is the displacement of the instruction relocatable? + EA_CNS_RELOC_FLG = 0x400, // Is the immediate of the instruction relocatable? }; #define EA_ATTR(x) ((emitAttr)(x)) @@ -315,6 +319,7 @@ enum emitAttr : unsigned #define EA_SIZE_IN_BYTES(x) ((UNATIVE_OFFSET)(EA_SIZE(x))) #define EA_SET_SIZE(x, sz) ((emitAttr)((((unsigned)(x)) & ~EA_SIZE_MASK) | (sz))) #define EA_SET_FLG(x, flg) ((emitAttr)(((unsigned)(x)) | (flg))) +#define EA_REMOVE_FLG(x, flg) ((emitAttr)(((unsigned)(x)) & ~(flg))) #define EA_4BYTE_DSP_RELOC (EA_SET_FLG(EA_4BYTE, EA_DSP_RELOC_FLG)) #define EA_PTR_DSP_RELOC (EA_SET_FLG(EA_PTRSIZE, EA_DSP_RELOC_FLG)) #define EA_HANDLE_CNS_RELOC (EA_SET_FLG(EA_PTRSIZE, EA_CNS_RELOC_FLG)) diff --git a/src/coreclr/jit/jit.h b/src/coreclr/jit/jit.h index e212226851c7c..218871e154fc5 100644 --- a/src/coreclr/jit/jit.h +++ b/src/coreclr/jit/jit.h @@ -529,6 +529,9 @@ const bool dspGCtbls = true; if (JitTls::GetCompiler()->verbose) \ JitTls::GetCompiler()->fgTableDispBasicBlock(b); #define VERBOSE JitTls::GetCompiler()->verbose +// Development-time only macros, simplify guards for specified IL methods one wants to debug/add log messages for +#define ISMETHOD(name) (strcmp(JitTls::GetCompiler()->impInlineRoot()->info.compMethodName, name) == 0) +#define ISMETHODHASH(hash) (JitTls::GetCompiler()->impInlineRoot()->info.compMethodHash() == hash) #else // !DEBUG #define JITDUMP(...) #define JITDUMPEXEC(x) diff --git a/src/coreclr/jit/loopcloning.cpp b/src/coreclr/jit/loopcloning.cpp index 06c408395087f..83b9fe3aa01eb 100644 --- a/src/coreclr/jit/loopcloning.cpp +++ b/src/coreclr/jit/loopcloning.cpp @@ -534,7 +534,6 @@ void LoopCloneContext::EvaluateConditions(unsigned loopNum, bool* pAllTrue, bool // Since this will force us to abort loop cloning, there is no need compute an accurate `allTrue`, // so we can break out of the loop now. - // REVIEW: it appears we never hit this condition in any test. break; } } @@ -1009,7 +1008,7 @@ LC_Deref* LC_Deref::Find(JitExpandArrayStack* children, unsigned lcl) // Operation: // Inspect the loop cloning optimization candidates and populate the conditions necessary // for each optimization candidate. Checks if the loop stride is "> 0" if the loop -// condition is "less than". If the initializer is "var" init then adds condition +// condition is `<` or `<=`. If the initializer is "var" init then adds condition // "var >= 0", and if the loop is var limit then, "var >= 0" and "var <= a.len" // are added to "context". These conditions are checked in the pre-header block // and the cloning choice is made. @@ -1026,7 +1025,7 @@ bool Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext LoopDsc* loop = &optLoopTable[loopNum]; JitExpandArrayStack* optInfos = context->GetLoopOptInfo(loopNum); - if (loop->lpTestOper() == GT_LT) + if (GenTree::StaticOperIs(loop->lpTestOper(), GT_LT, GT_LE)) { // Stride conditions if (loop->lpIterConst() <= 0) @@ -1112,6 +1111,21 @@ bool Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext return false; } + // GT_LT loop test: limit <= arrLen + // GT_LE loop test: limit < arrLen + genTreeOps opLimitCondition; + switch (loop->lpTestOper()) + { + case GT_LT: + opLimitCondition = GT_LE; + break; + case GT_LE: + opLimitCondition = GT_LT; + break; + default: + unreached(); + } + for (unsigned i = 0; i < optInfos->Size(); ++i) { LcOptInfo* optInfo = optInfos->Get(i); @@ -1119,11 +1133,10 @@ bool Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext { case LcOptInfo::LcJaggedArray: { - // limit <= arrLen LcJaggedArrayOptInfo* arrIndexInfo = optInfo->AsLcJaggedArrayOptInfo(); LC_Array arrLen(LC_Array::Jagged, &arrIndexInfo->arrIndex, arrIndexInfo->dim, LC_Array::ArrLen); LC_Ident arrLenIdent = LC_Ident(arrLen); - LC_Condition cond(GT_LE, LC_Expr(ident), LC_Expr(arrLenIdent)); + LC_Condition cond(opLimitCondition, LC_Expr(ident), LC_Expr(arrLenIdent)); context->EnsureConditions(loopNum)->Push(cond); // Ensure that this array must be dereference-able, before executing the actual condition. @@ -1133,13 +1146,15 @@ bool Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext break; case LcOptInfo::LcMdArray: { - // limit <= mdArrLen LcMdArrayOptInfo* mdArrInfo = optInfo->AsLcMdArrayOptInfo(); - LC_Condition cond(GT_LE, LC_Expr(ident), - LC_Expr(LC_Ident(LC_Array(LC_Array::MdArray, mdArrInfo->GetArrIndexForDim( - getAllocator(CMK_LoopClone)), - mdArrInfo->dim, LC_Array::None)))); + LC_Array arrLen(LC_Array(LC_Array::MdArray, + mdArrInfo->GetArrIndexForDim(getAllocator(CMK_LoopClone)), mdArrInfo->dim, + LC_Array::None)); + LC_Ident arrLenIdent = LC_Ident(arrLen); + LC_Condition cond(opLimitCondition, LC_Expr(ident), LC_Expr(arrLenIdent)); context->EnsureConditions(loopNum)->Push(cond); + + // TODO: ensure array is dereference-able? } break; @@ -1148,11 +1163,14 @@ bool Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext return false; } } + JITDUMP("Conditions: "); DBEXEC(verbose, context->PrintConditions(loopNum)); JITDUMP("\n"); + return true; } + return false; } @@ -1398,6 +1416,7 @@ void Compiler::optDebugLogLoopCloning(BasicBlock* block, Statement* insertBefore void Compiler::optPerformStaticOptimizations(unsigned loopNum, LoopCloneContext* context DEBUGARG(bool dynamicPath)) { JitExpandArrayStack* optInfos = context->GetLoopOptInfo(loopNum); + assert(optInfos != nullptr); for (unsigned i = 0; i < optInfos->Size(); ++i) { LcOptInfo* optInfo = optInfos->Get(i); @@ -2547,7 +2566,7 @@ PhaseStatus Compiler::optCloneLoops() { context.CancelLoopOptInfo(i); } - if (allTrue) + else if (allTrue) { // Perform static optimizations on the fast path since we always // have to take the cloned path. diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index b588899670d7a..4c06ed0749de1 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -3721,17 +3721,10 @@ GenTree* Lowering::LowerDirectCall(GenTreeCall* call) case IAT_PVALUE: { - bool hasIndirectionCell = false; -#if defined(TARGET_ARMARCH) - // Skip inserting the indirection node to load the address that is already - // computed in REG_R2R_INDIRECT_PARAM as a hidden parameter. Instead during the - // codegen, just load the call target from REG_R2R_INDIRECT_PARAM. - hasIndirectionCell = call->IsR2RRelativeIndir(); -#elif defined(TARGET_XARCH) - // For xarch we usually get the indirection cell from the return address, - // except for fast tailcalls where we do the same as ARM. - hasIndirectionCell = call->IsR2RRelativeIndir() && call->IsFastTailCall(); -#endif + // If we are using an indirection cell for a direct call then apply + // an optimization that loads the call target directly from the + // indirection cell, instead of duplicating the tree. + bool hasIndirectionCell = call->GetIndirectionCellArgKind() != NonStandardArgKind::None; if (!hasIndirectionCell) { @@ -4801,12 +4794,12 @@ GenTree* Lowering::LowerVirtualStubCall(GenTreeCall* call) else { bool shouldOptimizeVirtualStubCall = false; -#if defined(FEATURE_READYTORUN) && defined(TARGET_ARMARCH) +#if defined(TARGET_ARMARCH) || defined(TARGET_AMD64) // Skip inserting the indirection node to load the address that is already - // computed in REG_R2R_INDIRECT_PARAM as a hidden parameter. Instead during the - // codegen, just load the call target from REG_R2R_INDIRECT_PARAM. + // computed in the VSD stub arg register as a hidden parameter. Instead during the + // codegen, just load the call target from there. shouldOptimizeVirtualStubCall = true; -#endif // FEATURE_READYTORUN && TARGET_ARMARCH +#endif if (!shouldOptimizeVirtualStubCall) { diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index e8b1353a24de0..8e1d5c0147c1e 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -4588,19 +4588,7 @@ void Lowering::ContainCheckIndir(GenTreeIndir* node) else if (addr->IsCnsIntOrI() && addr->AsIntConCommon()->FitsInAddrBase(comp)) { // Amd64: - // We can mark any pc-relative 32-bit addr as containable, except for a direct VSD call address. - // (i.e. those VSD calls for which stub addr is known during JIT compilation time). In this case, - // VM requires us to pass stub addr in VirtualStubParam.reg - see LowerVirtualStubCall(). For - // that reason we cannot mark such an addr as contained. Note that this is not an issue for - // indirect VSD calls since morphArgs() is explicitly materializing hidden param as a non-standard - // argument. - // - // Workaround: - // Note that LowerVirtualStubCall() sets addr->GetRegNum() to VirtualStubParam.reg and Lowering::doPhase() - // sets destination candidates on such nodes and resets addr->GetRegNum() to REG_NA. - // Ideally we should set a flag on addr nodes that shouldn't be marked as contained - // (in LowerVirtualStubCall()), but we don't have any GTF_* flags left for that purpose. As a workaround - // an explicit check is made here. + // We can mark any pc-relative 32-bit addr as containable. // // On x86, direct VSD is done via a relative branch, and in fact it MUST be contained. MakeSrcContained(node, addr); diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index a9a78198cb288..55ea93a8fba3a 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -62,9 +62,9 @@ GenTree* Compiler::fgMorphIntoHelperCall(GenTree* tree, int helper, GenTreeCall: // The helper call ought to be semantically equivalent to the original node, so preserve its VN. tree->ChangeOper(GT_CALL, GenTree::PRESERVE_VN); - GenTreeCall* call = tree->AsCall(); - + GenTreeCall* call = tree->AsCall(); call->gtCallType = CT_HELPER; + call->gtReturnType = tree->TypeGet(); call->gtCallMethHnd = eeFindHelper(helper); call->gtCallThisArg = nullptr; call->gtCallArgs = args; @@ -10872,6 +10872,72 @@ GenTree* Compiler::fgMorphCommutative(GenTreeOp* tree) return op1; } +//------------------------------------------------------------------------------ +// fgMorphCastedBitwiseOp : Try to simplify "(T)x op (T)y" to "(T)(x op y)". +// +// Arguments: +// tree - node to fold +// +// Return Value: +// A folded GenTree* instance, or nullptr if it couldn't be folded +GenTree* Compiler::fgMorphCastedBitwiseOp(GenTreeOp* tree) +{ + assert(varTypeIsIntegralOrI(tree)); + assert(tree->OperIs(GT_OR, GT_AND, GT_XOR)); + + GenTree* op1 = tree->gtGetOp1(); + GenTree* op2 = tree->gtGetOp2(); + genTreeOps oper = tree->OperGet(); + + // see whether both ops are casts, with matching to and from types. + if (op1->OperIs(GT_CAST) && op2->OperIs(GT_CAST)) + { + // bail if either operand is a checked cast + if (op1->gtOverflow() || op2->gtOverflow()) + { + return nullptr; + } + + var_types fromType = op1->AsCast()->CastOp()->TypeGet(); + var_types toType = op1->AsCast()->CastToType(); + bool isUnsigned = op1->IsUnsigned(); + + if ((op2->CastFromType() != fromType) || (op2->CastToType() != toType) || (op2->IsUnsigned() != isUnsigned)) + { + return nullptr; + } + + /* + // Reuse gentree nodes: + // + // tree op1 + // / \ | + // op1 op2 ==> tree + // | | / \. + // x y x y + // + // (op2 becomes garbage) + */ + + tree->gtOp1 = op1->AsCast()->CastOp(); + tree->gtOp2 = op2->AsCast()->CastOp(); + tree->gtType = fromType; + + op1->gtType = genActualType(toType); + op1->AsCast()->gtOp1 = tree; + op1->AsCast()->CastToType() = toType; + op1->SetAllEffectsFlags(tree); + // no need to update isUnsigned + + DEBUG_DESTROY_NODE(op2); + INDEBUG(op1->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); + + return op1; + } + + return nullptr; +} + /***************************************************************************** * * Transform the given GTK_SMPOP tree for code generation. @@ -11118,24 +11184,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) return fgMorphSmpOp(tree, mac); } - if (opts.OptimizationEnabled() && !optValnumCSE_phase) - { - // DIV(NEG(a), C) => DIV(a, NEG(C)) - if (op1->OperIs(GT_NEG) && !op1->gtGetOp1()->IsCnsIntOrI() && op2->IsCnsIntOrI() && - !op2->IsIconHandle()) - { - ssize_t op2Value = op2->AsIntCon()->IconValue(); - if (op2Value != 1 && op2Value != -1) // Div must throw exception for int(long).MinValue / -1. - { - tree->AsOp()->gtOp1 = op1->gtGetOp1(); - DEBUG_DESTROY_NODE(op1); - tree->AsOp()->gtOp2 = gtNewIconNode(-op2Value, op2->TypeGet()); - DEBUG_DESTROY_NODE(op2); - return fgMorphSmpOp(tree, mac); - } - } - } - #ifndef TARGET_64BIT if (typ == TYP_LONG) { @@ -11998,7 +12046,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) break; case GT_CAST: - tree = fgOptimizeCast(tree); + tree = fgOptimizeCast(tree->AsCast()); if (!tree->OperIsSimple()) { return tree; @@ -12516,6 +12564,22 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) op2 = tree->AsOp()->gtOp2; } + if (fgGlobalMorph && varTypeIsIntegralOrI(tree) && tree->OperIs(GT_AND, GT_OR, GT_XOR)) + { + GenTree* result = fgMorphCastedBitwiseOp(tree->AsOp()); + if (result != nullptr) + { + assert(result->OperIs(GT_CAST)); + assert(result->AsOp()->gtOp2 == nullptr); + // tree got folded to a unary (cast) op + tree = result; + oper = tree->OperGet(); + typ = tree->TypeGet(); + op1 = tree->AsOp()->gtGetOp1(); + op2 = nullptr; + } + } + if (varTypeIsIntegralOrI(tree->TypeGet()) && tree->OperIs(GT_ADD, GT_MUL, GT_AND, GT_OR, GT_XOR)) { GenTree* foldedTree = fgMorphCommutative(tree->AsOp()); @@ -13251,195 +13315,94 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) // Return Value: // The optimized tree (that can have any shape). // -GenTree* Compiler::fgOptimizeCast(GenTree* tree) +GenTree* Compiler::fgOptimizeCast(GenTreeCast* cast) { - GenTree* oper = tree->AsCast()->CastOp(); - var_types srcType = oper->TypeGet(); - var_types dstType = tree->CastToType(); - unsigned dstSize = genTypeSize(dstType); + GenTree* src = cast->CastOp(); - if (gtIsActiveCSE_Candidate(tree) || gtIsActiveCSE_Candidate(oper)) + if (gtIsActiveCSE_Candidate(cast) || gtIsActiveCSE_Candidate(src)) { - return tree; + return cast; } - /* See if we can discard the cast */ - if (varTypeIsIntegral(srcType) && varTypeIsIntegral(dstType)) + // See if we can discard the cast. + if (varTypeIsIntegral(cast) && varTypeIsIntegral(src)) { - if (tree->IsUnsigned() && !varTypeIsUnsigned(srcType)) + IntegralRange srcRange = IntegralRange::ForNode(src, this); + IntegralRange noOvfRange = IntegralRange::ForCastInput(cast); + + if (noOvfRange.Contains(srcRange)) { - if (varTypeIsSmall(srcType)) + // Casting between same-sized types is a no-op, + // given we have proven this cast cannot overflow. + if (genActualType(cast) == genActualType(src)) { - // Small signed values are automatically sign extended to TYP_INT. If the cast is interpreting the - // resulting TYP_INT value as unsigned then the "sign" bits end up being "value" bits and srcType - // must be TYP_UINT, not the original small signed type. Otherwise "conv.ovf.i2.un(i1(-1))" is - // wrongly treated as a widening conversion from i1 to i2 when in fact it is a narrowing conversion - // from u4 to i2. - srcType = genActualType(srcType); + return src; } - srcType = varTypeToUnsigned(srcType); - } + cast->ClearOverflow(); + cast->SetAllEffectsFlags(src); - if (srcType == dstType) - { // Certainly if they are identical it is pointless - goto REMOVE_CAST; + // Try and see if we can make this cast into a cheaper zero-extending version. + if (genActualTypeIsInt(src) && cast->TypeIs(TYP_LONG) && srcRange.IsPositive()) + { + cast->SetUnsigned(); + } } - if (oper->OperGet() == GT_LCL_VAR && varTypeIsSmall(dstType)) + // For checked casts, we're done. + if (cast->gtOverflow()) { - unsigned varNum = oper->AsLclVarCommon()->GetLclNum(); - LclVarDsc* varDsc = &lvaTable[varNum]; - if (varDsc->TypeGet() == dstType && varDsc->lvNormalizeOnStore()) - { - goto REMOVE_CAST; - } + return cast; } - bool unsignedSrc = varTypeIsUnsigned(srcType); - bool unsignedDst = varTypeIsUnsigned(dstType); - bool signsDiffer = (unsignedSrc != unsignedDst); - unsigned srcSize = genTypeSize(srcType); + var_types castToType = cast->CastToType(); - // For same sized casts with - // the same signs or non-overflow cast we discard them as well - if (srcSize == dstSize) + // For indir-like nodes, we may be able to change their type to satisfy (and discard) the cast. + if (varTypeIsSmall(castToType) && (genTypeSize(castToType) == genTypeSize(src)) && + src->OperIs(GT_IND, GT_CLS_VAR, GT_LCL_FLD)) { - // This should have been handled by "fgMorphExpandCast". - noway_assert(varTypeIsGC(srcType) == varTypeIsGC(dstType)); + // We're changing the type here so we need to update the VN; + // in other cases we discard the cast without modifying src + // so the VN doesn't change. - if (!signsDiffer) - { - goto REMOVE_CAST; - } + src->ChangeType(castToType); + src->SetVNsFromNode(cast); - if (!tree->gtOverflow()) - { - /* For small type casts, when necessary we force - the src operand to the dstType and allow the - implied load from memory to perform the casting */ - if (varTypeIsSmall(srcType)) - { - switch (oper->gtOper) - { - case GT_IND: - case GT_CLS_VAR: - case GT_LCL_FLD: - oper->gtType = dstType; - // We're changing the type here so we need to update the VN; - // in other cases we discard the cast without modifying oper - // so the VN doesn't change. - oper->SetVNsFromNode(tree); - goto REMOVE_CAST; - default: - break; - } - } - else - { - goto REMOVE_CAST; - } - } + return src; } - else if (srcSize < dstSize) // widening cast - { - // Keep any long casts - if (dstSize == sizeof(int)) - { - // Only keep signed to unsigned widening cast with overflow check - if (!tree->gtOverflow() || !unsignedDst || unsignedSrc) - { - goto REMOVE_CAST; - } - } - // Widening casts from unsigned or to signed can never overflow + // Try to narrow the operand of the cast and discard the cast. + if (opts.OptEnabled(CLFLG_TREETRANS) && (genTypeSize(src) > genTypeSize(castToType)) && + optNarrowTree(src, src->TypeGet(), castToType, cast->gtVNPair, false)) + { + optNarrowTree(src, src->TypeGet(), castToType, cast->gtVNPair, true); - if (unsignedSrc || !unsignedDst) + // "optNarrowTree" may leave a dead cast behind. + if (src->OperIs(GT_CAST) && (src->AsCast()->CastToType() == genActualType(src->AsCast()->CastOp()))) { - tree->ClearOverflow(); - if ((oper->gtFlags & GTF_EXCEPT) == GTF_EMPTY) - { - tree->gtFlags &= ~GTF_EXCEPT; - } + src = src->AsCast()->CastOp(); } - } - else // if (srcSize > dstSize) - { - // Try to narrow the operand of the cast and discard the cast - // Note: Do not narrow a cast that is marked as a CSE - // And do not narrow if the oper is marked as a CSE either - // - if (!tree->gtOverflow() && opts.OptEnabled(CLFLG_TREETRANS) && - optNarrowTree(oper, srcType, dstType, tree->gtVNPair, false)) - { - optNarrowTree(oper, srcType, dstType, tree->gtVNPair, true); - /* If oper is changed into a cast to TYP_INT, or to a GT_NOP, we may need to discard it */ - if (oper->gtOper == GT_CAST && oper->CastToType() == genActualType(oper->CastFromType())) - { - oper = oper->AsCast()->CastOp(); - } - goto REMOVE_CAST; - } + return src; } - } - // Check for two consecutive casts into the same dstType. - // Also check for consecutive casts to small types. - if (oper->OperIs(GT_CAST) && !tree->gtOverflow()) - { - var_types dstCastToType = dstType; - var_types srcCastToType = oper->CastToType(); - if (dstCastToType == srcCastToType) - { - goto REMOVE_CAST; - } - // We can take advantage of the implicit zero/sign-extension for - // small integer types and eliminate some casts. - if (opts.OptimizationEnabled() && !oper->gtOverflow() && varTypeIsSmall(dstCastToType) && - varTypeIsSmall(srcCastToType)) + // Check for two consecutive casts, we may be able to discard the intermediate one. + if (opts.OptimizationEnabled() && src->OperIs(GT_CAST) && !src->gtOverflow()) { - // Gather some facts about our casts. - bool srcZeroExtends = varTypeIsUnsigned(srcCastToType); - bool dstZeroExtends = varTypeIsUnsigned(dstCastToType); - unsigned srcCastToSize = genTypeSize(srcCastToType); - unsigned dstCastToSize = genTypeSize(dstCastToType); - - // If the previous cast to a smaller type was zero-extending, - // this cast will also always be zero-extending. Example: - // CAST(ubyte): 000X => CAST(short): Sign-extend(0X) => 000X. - if (srcZeroExtends && (dstCastToSize > srcCastToSize)) - { - dstZeroExtends = true; - } + var_types dstCastToType = castToType; + var_types srcCastToType = src->AsCast()->CastToType(); - // Case #1: cast to a smaller or equal in size type. - // We can discard the intermediate cast. Examples: - // CAST(short): --XX => CAST(ubyte): 000X. - // CAST(ushort): 00XX => CAST(short): --XX. - if (dstCastToSize <= srcCastToSize) - { - tree->AsCast()->CastOp() = oper->AsCast()->CastOp(); - DEBUG_DESTROY_NODE(oper); - } - // Case #2: cast to a larger type with the same effect. - // Here we can eliminate the outer cast. Example: - // CAST(byte): ---X => CAST(short): Sign-extend(-X) => ---X. - // Example of a sequence where this does not hold: - // CAST(byte): ---X => CAST(ushort): Zero-extend(-X) => 00-X. - else if (srcZeroExtends == dstZeroExtends) + // CAST(ubyte <- CAST(short <- X)): CAST(ubyte <- X). + // CAST(ushort <- CAST(short <- X)): CAST(ushort <- X). + if (varTypeIsSmall(srcCastToType) && (genTypeSize(dstCastToType) <= genTypeSize(srcCastToType))) { - goto REMOVE_CAST; + cast->CastOp() = src->AsCast()->CastOp(); + DEBUG_DESTROY_NODE(src); } } } - return tree; - -REMOVE_CAST: - DEBUG_DESTROY_NODE(tree); - return oper; + return cast; } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 71c68cd7d78e7..8143582285386 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -1731,8 +1731,7 @@ ValueNum ValueNumStore::VNForByrefCon(target_size_t cnsVal) return VnForConst(cnsVal, GetByrefCnsMap(), TYP_BYREF); } -ValueNum ValueNumStore::VNForCastOper(var_types castToType, - bool srcIsUnsigned /*=false*/ DEBUGARG(bool printResult /*=true*/)) +ValueNum ValueNumStore::VNForCastOper(var_types castToType, bool srcIsUnsigned) { assert(castToType != TYP_STRUCT); INT32 cnsVal = INT32(castToType) << INT32(VCA_BitCount); @@ -1745,14 +1744,6 @@ ValueNum ValueNumStore::VNForCastOper(var_types castToType, } ValueNum result = VNForIntCon(cnsVal); -#ifdef DEBUG - if (printResult && m_pComp->verbose) - { - printf(" VNForCastOper(%s%s) is " FMT_VN "\n", varTypeName(castToType), srcIsUnsigned ? ", unsignedSrc" : "", - result); - } -#endif - return result; } @@ -1768,7 +1759,7 @@ void ValueNumStore::GetCastOperFromVN(ValueNum vn, var_types* pCastToType, bool* *pSrcIsUnsigned = (value & INT32(VCA_UnsignedSrc)) != 0; *pCastToType = var_types(value >> INT32(VCA_BitCount)); - assert(VNForCastOper(*pCastToType, *pSrcIsUnsigned DEBUGARG(/*printResult*/ false)) == vn); + assert(VNForCastOper(*pCastToType, *pSrcIsUnsigned) == vn); } ValueNum ValueNumStore::VNForHandle(ssize_t cnsVal, GenTreeFlags handleFlags) @@ -5608,6 +5599,10 @@ void ValueNumStore::vnDump(Compiler* comp, ValueNum vn, bool isPtr) vnDumpSimdType(comp, &funcApp); break; #endif // FEATURE_SIMD + case VNF_Cast: + case VNF_CastOvf: + vnDumpCast(comp, vn); + break; default: printf("%s(", VNFuncName(funcApp.m_func)); @@ -5799,6 +5794,36 @@ void ValueNumStore::vnDumpSimdType(Compiler* comp, VNFuncApp* simdType) } #endif // FEATURE_SIMD +void ValueNumStore::vnDumpCast(Compiler* comp, ValueNum castVN) +{ + VNFuncApp cast; + bool castFound = GetVNFunc(castVN, &cast); + assert(castFound && ((cast.m_func == VNF_Cast) || (cast.m_func == VNF_CastOvf))); + + var_types castToType; + bool srcIsUnsigned; + GetCastOperFromVN(cast.m_args[1], &castToType, &srcIsUnsigned); + + var_types castFromType = TypeOfVN(cast.m_args[0]); + var_types resultType = TypeOfVN(castVN); + if (srcIsUnsigned) + { + castFromType = varTypeToUnsigned(castFromType); + } + + comp->vnPrint(cast.m_args[0], 0); + + printf(", "); + if ((resultType != castToType) && (castToType != castFromType)) + { + printf("%s <- %s <- %s", varTypeName(resultType), varTypeName(castToType), varTypeName(castFromType)); + } + else + { + printf("%s <- %s", varTypeName(resultType), varTypeName(castFromType)); + } +} + #endif // DEBUG // Static fields, methods. @@ -9418,38 +9443,41 @@ void Compiler::fgValueNumberCastTree(GenTree* tree) tree->gtVNPair = vnStore->VNPairForCast(srcVNPair, castToType, castFromType, srcIsUnsigned, hasOverflowCheck); } -// Compute the normal ValueNumber for a cast operation with no exceptions +// Compute the ValueNumber for a cast operation ValueNum ValueNumStore::VNForCast(ValueNum srcVN, var_types castToType, var_types castFromType, - bool srcIsUnsigned /* = false */) + bool srcIsUnsigned, /* = false */ + bool hasOverflowCheck) /* = false */ { - // The resulting type after performingthe cast is always widened to a supported IL stack size + // The resulting type after performing the cast is always widened to a supported IL stack size var_types resultType = genActualType(castToType); - // When we're considering actual value returned by a non-checking cast whether or not the source is - // unsigned does *not* matter for non-widening casts. That is, if we cast an int or a uint to short, - // we just extract the first two bytes from the source bit pattern, not worrying about the interpretation. - // The same is true in casting between signed/unsigned types of the same width. Only when we're doing - // a widening cast do we care about whether the source was unsigned,so we know whether to sign or zero extend it. - // - bool srcIsUnsignedNorm = srcIsUnsigned; - if (genTypeSize(castToType) <= genTypeSize(castFromType)) + // For integral unchecked casts, only the "int -> long" upcasts use + // "srcIsUnsigned", to decide whether to use sign or zero extension. + if (!hasOverflowCheck && !varTypeIsFloating(castToType) && (genTypeSize(castToType) <= genTypeSize(castFromType))) { - srcIsUnsignedNorm = false; + srcIsUnsigned = false; } - ValueNum castTypeVN = VNForCastOper(castToType, srcIsUnsigned); - ValueNum resultVN = VNForFunc(resultType, VNF_Cast, srcVN, castTypeVN); + ValueNum srcExcVN; + ValueNum srcNormVN; + VNUnpackExc(srcVN, &srcNormVN, &srcExcVN); -#ifdef DEBUG - if (m_pComp->verbose) + VNFunc castFunc = hasOverflowCheck ? VNF_CastOvf : VNF_Cast; + ValueNum castTypeVN = VNForCastOper(castToType, srcIsUnsigned); + ValueNum resultNormVN = VNForFunc(resultType, castFunc, srcNormVN, castTypeVN); + ValueNum resultExcVN = srcExcVN; + + // Add an exception, except if folding took place. + // We only fold checked casts that do not overflow. + if (hasOverflowCheck && !IsVNConstant(resultNormVN)) { - printf(" VNForCast(" FMT_VN ", " FMT_VN ") returns ", srcVN, castTypeVN); - m_pComp->vnPrint(resultVN, 1); - printf("\n"); + ValueNum ovfChk = VNForFunc(TYP_REF, VNF_ConvOverflowExc, srcNormVN, castTypeVN); + resultExcVN = VNExcSetUnion(VNExcSetSingleton(ovfChk), srcExcVN); } -#endif + + ValueNum resultVN = VNWithExc(resultNormVN, resultExcVN); return resultVN; } @@ -9461,60 +9489,12 @@ ValueNumPair ValueNumStore::VNPairForCast(ValueNumPair srcVNPair, bool srcIsUnsigned, /* = false */ bool hasOverflowCheck) /* = false */ { - // The resulting type after performingthe cast is always widened to a supported IL stack size - var_types resultType = genActualType(castToType); + ValueNum srcLibVN = srcVNPair.GetLiberal(); + ValueNum srcConVN = srcVNPair.GetConservative(); + ValueNum castLibVN = VNForCast(srcLibVN, castToType, castFromType, srcIsUnsigned, hasOverflowCheck); + ValueNum castConVN = VNForCast(srcConVN, castToType, castFromType, srcIsUnsigned, hasOverflowCheck); - ValueNumPair castArgVNP; - ValueNumPair castArgxVNP; - VNPUnpackExc(srcVNPair, &castArgVNP, &castArgxVNP); - - // When we're considering actual value returned by a non-checking cast, (hasOverflowCheck is false) - // whether or not the source is unsigned does *not* matter for non-widening casts. - // That is, if we cast an int or a uint to short, we just extract the first two bytes from the source - // bit pattern, not worrying about the interpretation. The same is true in casting between signed/unsigned - // types of the same width. Only when we're doing a widening cast do we care about whether the source - // was unsigned, so we know whether to sign or zero extend it. - // - // Important: Casts to floating point cannot be optimized in this fashion. (bug 946768) - // - bool srcIsUnsignedNorm = srcIsUnsigned; - if (!hasOverflowCheck && !varTypeIsFloating(castToType) && (genTypeSize(castToType) <= genTypeSize(castFromType))) - { - srcIsUnsignedNorm = false; - } - - VNFunc vnFunc = hasOverflowCheck ? VNF_CastOvf : VNF_Cast; - ValueNum castTypeVN = VNForCastOper(castToType, srcIsUnsignedNorm); - ValueNumPair castTypeVNPair(castTypeVN, castTypeVN); - ValueNumPair castNormRes = VNPairForFunc(resultType, vnFunc, castArgVNP, castTypeVNPair); - - ValueNumPair resultVNP = VNPWithExc(castNormRes, castArgxVNP); - - // If we have a check for overflow, add the exception information. - if (hasOverflowCheck) - { - ValueNumPair excSet = ValueNumStore::VNPForEmptyExcSet(); - - ValueNumKind vnKinds[2] = {VNK_Liberal, VNK_Conservative}; - for (ValueNumKind vnKind : vnKinds) - { - // Do not add exceptions for folded casts. - // We only fold checked casts that do not overflow. - if (IsVNConstant(castNormRes.Get(vnKind))) - { - continue; - } - - ValueNum ovfChk = - VNForFunc(TYP_REF, VNF_ConvOverflowExc, castArgVNP.Get(vnKind), castTypeVNPair.Get(vnKind)); - excSet.Set(vnKind, VNExcSetSingleton(ovfChk)); - } - - excSet = VNPExcSetUnion(excSet, castArgxVNP); - resultVNP = VNPWithExc(castNormRes, excSet); - } - - return resultVNP; + return {castLibVN, castConVN}; } void Compiler::fgValueNumberHelperCallFunc(GenTreeCall* call, VNFunc vnf, ValueNumPair vnpExc) @@ -9789,6 +9769,81 @@ void Compiler::fgValueNumberCall(GenTreeCall* call) } } +void Compiler::fgValueNumberCastHelper(GenTreeCall* call) +{ + CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd); + var_types castToType = TYP_UNDEF; + var_types castFromType = TYP_UNDEF; + bool srcIsUnsigned = false; + bool hasOverflowCheck = false; + + switch (helpFunc) + { + case CORINFO_HELP_LNG2DBL: + castToType = TYP_DOUBLE; + castFromType = TYP_LONG; + break; + + case CORINFO_HELP_ULNG2DBL: + castToType = TYP_DOUBLE; + castFromType = TYP_LONG; + srcIsUnsigned = true; + break; + + case CORINFO_HELP_DBL2INT: + castToType = TYP_INT; + castFromType = TYP_DOUBLE; + break; + + case CORINFO_HELP_DBL2INT_OVF: + castToType = TYP_INT; + castFromType = TYP_DOUBLE; + hasOverflowCheck = true; + break; + + case CORINFO_HELP_DBL2LNG: + castToType = TYP_LONG; + castFromType = TYP_DOUBLE; + break; + + case CORINFO_HELP_DBL2LNG_OVF: + castToType = TYP_LONG; + castFromType = TYP_DOUBLE; + hasOverflowCheck = true; + break; + + case CORINFO_HELP_DBL2UINT: + castToType = TYP_UINT; + castFromType = TYP_DOUBLE; + break; + + case CORINFO_HELP_DBL2UINT_OVF: + castToType = TYP_UINT; + castFromType = TYP_DOUBLE; + hasOverflowCheck = true; + break; + + case CORINFO_HELP_DBL2ULNG: + castToType = TYP_ULONG; + castFromType = TYP_DOUBLE; + break; + + case CORINFO_HELP_DBL2ULNG_OVF: + castToType = TYP_ULONG; + castFromType = TYP_DOUBLE; + hasOverflowCheck = true; + break; + + default: + unreached(); + } + + ValueNumPair argVNP = call->gtCallArgs->GetNode()->gtVNPair; + ValueNumPair castVNP = vnStore->VNPairForCast(argVNP, castToType, castFromType, srcIsUnsigned, hasOverflowCheck); + + call->SetVNs(castVNP); +} + VNFunc Compiler::fgValueNumberJitHelperMethodVNFunc(CorInfoHelpFunc helpFunc) { assert(s_helperCallProperties.IsPure(helpFunc) || s_helperCallProperties.IsAllocator(helpFunc)); @@ -9819,12 +9874,14 @@ VNFunc Compiler::fgValueNumberJitHelperMethodVNFunc(CorInfoHelpFunc helpFunc) vnf = VNFunc(GT_RSZ); break; case CORINFO_HELP_LMUL: - case CORINFO_HELP_LMUL_OVF: vnf = VNFunc(GT_MUL); break; + case CORINFO_HELP_LMUL_OVF: + vnf = VNF_MUL_OVF; + break; case CORINFO_HELP_ULMUL_OVF: - vnf = VNFunc(GT_MUL); - break; // Is this the right thing? + vnf = VNF_MUL_UN_OVF; + break; case CORINFO_HELP_LDIV: vnf = VNFunc(GT_DIV); break; @@ -9837,37 +9894,6 @@ VNFunc Compiler::fgValueNumberJitHelperMethodVNFunc(CorInfoHelpFunc helpFunc) case CORINFO_HELP_ULMOD: vnf = VNFunc(GT_UMOD); break; - - case CORINFO_HELP_LNG2DBL: - vnf = VNF_Lng2Dbl; - break; - case CORINFO_HELP_ULNG2DBL: - vnf = VNF_ULng2Dbl; - break; - case CORINFO_HELP_DBL2INT: - vnf = VNF_Dbl2Int; - break; - case CORINFO_HELP_DBL2INT_OVF: - vnf = VNF_Dbl2IntOvf; - break; - case CORINFO_HELP_DBL2LNG: - vnf = VNF_Dbl2Lng; - break; - case CORINFO_HELP_DBL2LNG_OVF: - vnf = VNF_Dbl2LngOvf; - break; - case CORINFO_HELP_DBL2UINT: - vnf = VNF_Dbl2UInt; - break; - case CORINFO_HELP_DBL2UINT_OVF: - vnf = VNF_Dbl2UIntOvf; - break; - case CORINFO_HELP_DBL2ULNG: - vnf = VNF_Dbl2ULng; - break; - case CORINFO_HELP_DBL2ULNG_OVF: - vnf = VNF_Dbl2ULngOvf; - break; case CORINFO_HELP_FLTREM: vnf = VNFunc(GT_MOD); break; @@ -10072,12 +10098,32 @@ VNFunc Compiler::fgValueNumberJitHelperMethodVNFunc(CorInfoHelpFunc helpFunc) bool Compiler::fgValueNumberHelperCall(GenTreeCall* call) { - CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd); - bool pure = s_helperCallProperties.IsPure(helpFunc); - bool isAlloc = s_helperCallProperties.IsAllocator(helpFunc); - bool modHeap = s_helperCallProperties.MutatesHeap(helpFunc); - bool mayRunCctor = s_helperCallProperties.MayRunCctor(helpFunc); - bool noThrow = s_helperCallProperties.NoThrow(helpFunc); + CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd); + + switch (helpFunc) + { + case CORINFO_HELP_LNG2DBL: + case CORINFO_HELP_ULNG2DBL: + case CORINFO_HELP_DBL2INT: + case CORINFO_HELP_DBL2INT_OVF: + case CORINFO_HELP_DBL2LNG: + case CORINFO_HELP_DBL2LNG_OVF: + case CORINFO_HELP_DBL2UINT: + case CORINFO_HELP_DBL2UINT_OVF: + case CORINFO_HELP_DBL2ULNG: + case CORINFO_HELP_DBL2ULNG_OVF: + fgValueNumberCastHelper(call); + return false; + + default: + break; + } + + bool pure = s_helperCallProperties.IsPure(helpFunc); + bool isAlloc = s_helperCallProperties.IsAllocator(helpFunc); + bool modHeap = s_helperCallProperties.MutatesHeap(helpFunc); + bool mayRunCctor = s_helperCallProperties.MayRunCctor(helpFunc); + bool noThrow = s_helperCallProperties.NoThrow(helpFunc); ValueNumPair vnpExc = ValueNumStore::VNPForEmptyExcSet(); @@ -10843,7 +10889,6 @@ void Compiler::vnpPrint(ValueNumPair vnp, unsigned level) void Compiler::vnPrint(ValueNum vn, unsigned level) { - if (ValueNumStore::isReservedVN(vn)) { printf(ValueNumStore::reservedName(vn)); diff --git a/src/coreclr/jit/valuenum.h b/src/coreclr/jit/valuenum.h index b64d19993fa72..d09bd3197e91c 100644 --- a/src/coreclr/jit/valuenum.h +++ b/src/coreclr/jit/valuenum.h @@ -291,7 +291,7 @@ class ValueNumStore // Packs information about the cast into an integer constant represented by the returned value number, // to be used as the second operand of VNF_Cast & VNF_CastOvf. - ValueNum VNForCastOper(var_types castToType, bool srcIsUnsigned = false DEBUGARG(bool printResult = true)); + ValueNum VNForCastOper(var_types castToType, bool srcIsUnsigned); // Unpacks the information stored by VNForCastOper in the constant represented by the value number. void GetCastOperFromVN(ValueNum vn, var_types* pCastToType, bool* pSrcIsUnsigned); @@ -556,8 +556,12 @@ class ValueNumStore rhs.GetConservative(), indType, block)); } - // Compute the normal ValueNumber for a cast with no exceptions - ValueNum VNForCast(ValueNum srcVN, var_types castToType, var_types castFromType, bool srcIsUnsigned = false); + // Compute the ValueNumber for a cast + ValueNum VNForCast(ValueNum srcVN, + var_types castToType, + var_types castFromType, + bool srcIsUnsigned = false, + bool hasOverflowCheck = false); // Compute the ValueNumberPair for a cast ValueNumPair VNPairForCast(ValueNumPair srcVNPair, @@ -898,6 +902,10 @@ class ValueNumStore void vnDumpSimdType(Compiler* comp, VNFuncApp* simdType); #endif // FEATURE_SIMD + // Requires "castVN" to represent VNF_Cast or VNF_CastOvf. + // Prints the cast's representation mirroring GT_CAST's dump format. + void vnDumpCast(Compiler* comp, ValueNum castVN); + // Returns the string name of "vnf". static const char* VNFuncName(VNFunc vnf); // Used in the implementation of the above. diff --git a/src/coreclr/jit/valuenumfuncs.h b/src/coreclr/jit/valuenumfuncs.h index 448f40e382146..7665770881bcd 100644 --- a/src/coreclr/jit/valuenumfuncs.h +++ b/src/coreclr/jit/valuenumfuncs.h @@ -69,16 +69,6 @@ ValueNumFuncDef(InvalidCastExc, 2, false, false, false) // CastClass check, ValueNumFuncDef(NewArrOverflowExc, 1, false, false, false) // Raises Integer overflow when Arg 0 is negative ValueNumFuncDef(HelperMultipleExc, 0, false, false, false) // Represents one or more different exceptions that could be thrown by a Jit Helper method -ValueNumFuncDef(Lng2Dbl, 1, false, false, false) -ValueNumFuncDef(ULng2Dbl, 1, false, false, false) -ValueNumFuncDef(Dbl2Int, 1, false, false, false) -ValueNumFuncDef(Dbl2UInt, 1, false, false, false) -ValueNumFuncDef(Dbl2Lng, 1, false, false, false) -ValueNumFuncDef(Dbl2ULng, 1, false, false, false) -ValueNumFuncDef(Dbl2IntOvf, 1, false, false, false) -ValueNumFuncDef(Dbl2UIntOvf, 1, false, false, false) -ValueNumFuncDef(Dbl2LngOvf, 1, false, false, false) -ValueNumFuncDef(Dbl2ULngOvf, 1, false, false, false) ValueNumFuncDef(FltRound, 1, false, false, false) ValueNumFuncDef(DblRound, 1, false, false, false) diff --git a/src/coreclr/scripts/antigen_run.py b/src/coreclr/scripts/antigen_run.py index e97196debeedf..96146005906d9 100644 --- a/src/coreclr/scripts/antigen_run.py +++ b/src/coreclr/scripts/antigen_run.py @@ -20,8 +20,7 @@ from os.path import getsize import os from coreclr_arguments import * -from superpmi_setup import run_command -from superpmi import TempDir +from azdo_pipelines_util import run_command, TempDir parser = argparse.ArgumentParser(description="description") @@ -30,6 +29,7 @@ parser.add_argument("-output_directory", help="Path to output directory") parser.add_argument("-partition", help="Partition name") parser.add_argument("-core_root", help="path to CORE_ROOT directory") +parser.add_argument("-run_duration", help="Run duration in minutes") is_windows = platform.system() == "Windows" @@ -71,6 +71,10 @@ def setup_args(args): lambda core_root: os.path.isdir(core_root), "core_root doesn't exist") + coreclr_args.verify(args, + "run_duration", + lambda unused: True, + "Unable to set run_duration") return coreclr_args @@ -164,7 +168,16 @@ def sorter_by_size(pair): except PermissionError as pe_error: print('Ignoring PermissionError: {0}'.format(pe_error)) + src_antigen_log = os.path.join(issues_directory, get_antigen_filename(tag_name)) + dst_antigen_log = os.path.join(upload_directory, get_antigen_filename(tag_name)) + print("Copying {} to {}".format(src_antigen_log, dst_antigen_log)) + try: + shutil.copy2(src_antigen_log, dst_antigen_log) + except PermissionError as pe_error: + print('Ignoring PermissionError: {0}'.format(pe_error)) +def get_antigen_filename(tag_name): + return "Antigen-{}.log".format(tag_name) def main(main_args): """Main entrypoint @@ -179,7 +192,9 @@ def main(main_args): core_root = coreclr_args.core_root tag_name = "{}-{}".format(coreclr_args.run_configuration, coreclr_args.partition) output_directory = coreclr_args.output_directory - run_duration = 120 # Run for 2 hours + run_duration = coreclr_args.run_duration + if not run_duration: + run_duration = 60 path_to_corerun = os.path.join(core_root, "corerun") path_to_tool = os.path.join(antigen_directory, "Antigen") @@ -187,13 +202,17 @@ def main(main_args): path_to_corerun += ".exe" path_to_tool += ".exe" - # Run tool such that issues are placed in a temp folder - with TempDir() as temp_location: - run_command([path_to_tool, "-c", path_to_corerun, "-o", temp_location, "-d", str(run_duration)], _exit_on_fail=True, _long_running= True) - - # Copy issues for upload - print("Copying issues to " + output_directory) - copy_issues(temp_location, output_directory, tag_name) + try: + # Run tool such that issues are placed in a temp folder + with TempDir() as temp_location: + antigen_log = path.join(temp_location, get_antigen_filename(tag_name)) + run_command([path_to_tool, "-c", path_to_corerun, "-o", temp_location, "-d", str(run_duration)], _exit_on_fail=True, _output_file= antigen_log) + + # Copy issues for upload + print("Copying issues to " + output_directory) + copy_issues(temp_location, output_directory, tag_name) + except PermissionError as pe: + print("Got error: %s", pe) if __name__ == "__main__": args = parser.parse_args() diff --git a/src/coreclr/scripts/antigen_setup.py b/src/coreclr/scripts/antigen_setup.py index d82df7d9338a8..8026bcb93a93f 100644 --- a/src/coreclr/scripts/antigen_setup.py +++ b/src/coreclr/scripts/antigen_setup.py @@ -19,8 +19,7 @@ import os from os import listdir from coreclr_arguments import * -from superpmi_setup import run_command, copy_directory, set_pipeline_variable -from superpmi import ChangeDir, TempDir +from azdo_pipelines_util import run_command, copy_directory, set_pipeline_variable, ChangeDir, TempDir import tempfile parser = argparse.ArgumentParser(description="description") @@ -88,7 +87,6 @@ def main(main_args): helix_source_prefix = "official" creator = "" - ci = True # create exploratory directory print('Copying {} -> {}'.format(scripts_src_directory, coreroot_dst_directory)) diff --git a/src/coreclr/scripts/azdo_pipelines_util.py b/src/coreclr/scripts/azdo_pipelines_util.py new file mode 100644 index 0000000000000..cabbcf8e68607 --- /dev/null +++ b/src/coreclr/scripts/azdo_pipelines_util.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python3 +# +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# +# Title : azdo_pipelines_util.py +# +# Notes: +# +# Utility functions used by Python scripts involved with Azure DevOps Pipelines +# setup. +# +################################################################################ +################################################################################ + +import os +import shutil +import subprocess +import sys +import tempfile + + +def run_command(command_to_run, _cwd=None, _exit_on_fail=False, _output_file=None): + """ Runs the command. + + Args: + command_to_run ([string]): Command to run along with arguments. + _cwd (string): Current working directory. + _exit_on_fail (bool): If it should exit on failure. + Returns: + (string, string, int): Returns a tuple of stdout, stderr, and command return code if _output_file= None + Otherwise stdout, stderr are empty. + """ + print("Running: " + " ".join(command_to_run)) + command_stdout = "" + command_stderr = "" + return_code = 1 + + output_type = subprocess.STDOUT if _output_file else subprocess.PIPE + with subprocess.Popen(command_to_run, stdout=subprocess.PIPE, stderr=output_type, cwd=_cwd) as proc: + + # For long running command, continuously print the output + if _output_file: + while True: + with open(_output_file, 'a') as of: + output = proc.stdout.readline() + if proc.poll() is not None: + break + if output: + of.write(output.strip().decode("utf-8") + "\n") + else: + command_stdout, command_stderr = proc.communicate() + if len(command_stdout) > 0: + print(command_stdout.decode("utf-8")) + if len(command_stderr) > 0: + print(command_stderr.decode("utf-8")) + + return_code = proc.returncode + if _exit_on_fail and return_code != 0: + print("Command failed. Exiting.") + sys.exit(1) + return command_stdout, command_stderr, return_code + + +def copy_directory(src_path, dst_path, verbose_output=True, match_func=lambda path: True): + """Copies directory in 'src_path' to 'dst_path' maintaining the directory + structure. https://docs.python.org/3.5/library/shutil.html#shutil.copytree can't + be used in this case because it expects the destination directory should not + exist, however we do call copy_directory() to copy files to same destination directory. + + Args: + src_path (string): Path of source directory that need to be copied. + dst_path (string): Path where directory should be copied. + verbose_output (bool): True to print every copy or skipped file. + match_func (str -> bool) : Criteria function determining if a file is copied. + """ + if not os.path.exists(dst_path): + os.makedirs(dst_path) + for item in os.listdir(src_path): + src_item = os.path.join(src_path, item) + dst_item = os.path.join(dst_path, item) + if os.path.isdir(src_item): + copy_directory(src_item, dst_item, verbose_output, match_func) + else: + try: + if match_func(src_item): + if verbose_output: + print("> copy {0} => {1}".format(src_item, dst_item)) + try: + shutil.copy2(src_item, dst_item) + except PermissionError as pe_error: + print('Ignoring PermissionError: {0}'.format(pe_error)) + else: + if verbose_output: + print("> skipping {0}".format(src_item)) + except UnicodeEncodeError: + if verbose_output: + print("> Got UnicodeEncodeError") + + +def copy_files(src_path, dst_path, file_names): + """Copy files from 'file_names' list from 'src_path' to 'dst_path'. + It retains the original directory structure of src_path. + + Args: + src_path (string): Source directory from where files are copied. + dst_path (string): Destination directory where files to be copied. + file_names ([string]): List of full path file names to be copied. + """ + + print('### Copying below files from {0} to {1}:'.format(src_path, dst_path)) + print('') + print(os.linesep.join(file_names)) + for f in file_names: + # Create same structure in dst so we don't clobber same files names present in different directories + dst_path_of_file = f.replace(src_path, dst_path) + + dst_directory = os.path.dirname(dst_path_of_file) + if not os.path.exists(dst_directory): + os.makedirs(dst_directory) + try: + shutil.copy2(f, dst_path_of_file) + except PermissionError as pe_error: + print('Ignoring PermissionError: {0}'.format(pe_error)) + + +def set_pipeline_variable(name, value): + """ This method sets pipeline variable. + + Args: + name (string): Name of the variable. + value (string): Value of the variable. + """ + define_variable_format = "##vso[task.setvariable variable={0}]{1}" + print("{0} -> {1}".format(name, value)) # logging + print(define_variable_format.format(name, value)) # set variable + + +class TempDir: + """ Class to create a temporary working directory, or use one that is passed as an argument. + + Use with: "with TempDir() as temp_dir" to change to that directory and then automatically + change back to the original working directory afterwards and remove the temporary + directory and its contents (if skip_cleanup is False). + """ + + def __init__(self, path=None, skip_cleanup=False): + self.mydir = tempfile.mkdtemp() if path is None else path + self.cwd = None + self._skip_cleanup = skip_cleanup + + def __enter__(self): + self.cwd = os.getcwd() + os.chdir(self.mydir) + return self.mydir + + def __exit__(self, exc_type, exc_val, exc_tb): + os.chdir(self.cwd) + if not self._skip_cleanup: + shutil.rmtree(self.mydir) + + +class ChangeDir: + """ Class to temporarily change to a given directory. Use with "with". + """ + + def __init__(self, mydir): + self.mydir = mydir + self.cwd = None + + def __enter__(self): + self.cwd = os.getcwd() + os.chdir(self.mydir) + + def __exit__(self, exc_type, exc_val, exc_tb): + os.chdir(self.cwd) \ No newline at end of file diff --git a/src/coreclr/scripts/exploratory.proj b/src/coreclr/scripts/exploratory.proj index 2c347c5a0cbff..8b24de9bdfb52 100644 --- a/src/coreclr/scripts/exploratory.proj +++ b/src/coreclr/scripts/exploratory.proj @@ -28,7 +28,6 @@ false false - 2:30 $(_Creator) $(_HelixAccessToken) $(_HelixBuild) @@ -37,6 +36,16 @@ $(_HelixType) + + + 3:15 + 180 + + + 1:15 + 60 + + @@ -48,7 +57,7 @@ @(HelixPreCommand) @(HelixPostCommand) - $(Python) $(CoreRoot)$(FileSeparatorChar)antigen_run.py -run_configuration $(RunConfiguration) -output_directory $(OutputDirectory) -antigen_directory $(ToolPath) -core_root $(CoreRoot) + $(Python) $(CoreRoot)$(FileSeparatorChar)antigen_run.py -run_configuration $(RunConfiguration) -output_directory $(OutputDirectory) -antigen_directory $(ToolPath) -core_root $(CoreRoot) -run_duration $(RunDuration) @@ -70,7 +79,7 @@ $(WorkItemDirectory) $(WorkItemCommand) -partition %(PartitionName) $(WorkItemTimeout) - AllIssues-$(RunConfiguration)-%(PartitionName).zip;issues-summary-$(RunConfiguration)-%(PartitionName).txt + AllIssues-$(RunConfiguration)-%(PartitionName).zip;issues-summary-$(RunConfiguration)-%(PartitionName).txt;Antigen-$(RunConfiguration)-%(PartitionName).log diff --git a/src/coreclr/scripts/superpmi.proj b/src/coreclr/scripts/superpmi-collect.proj similarity index 100% rename from src/coreclr/scripts/superpmi.proj rename to src/coreclr/scripts/superpmi-collect.proj diff --git a/src/coreclr/scripts/superpmi-replay.proj b/src/coreclr/scripts/superpmi-replay.proj index a44bc0889c255..e76a4a3d810e5 100644 --- a/src/coreclr/scripts/superpmi-replay.proj +++ b/src/coreclr/scripts/superpmi-replay.proj @@ -30,10 +30,19 @@ %HELIX_WORKITEM_UPLOAD_ROOT% $(BUILD_SOURCESDIRECTORY)\artifacts\helixresults - $(Python) $(ProductDirectory)\superpmi-replay.py -jit_directory $(ProductDirectory) + $(Python) $(ProductDirectory)\superpmi_replay.py -jit_directory $(ProductDirectory) + 3:15 + + + false false - 5:00 + $(_Creator) + $(_HelixAccessToken) + $(_HelixBuild) + $(_HelixSource) + $(_HelixTargetQueues) + $(_HelixType) diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py index 4b502f0bffa4f..7618c11480ec0 100755 --- a/src/coreclr/scripts/superpmi.py +++ b/src/coreclr/scripts/superpmi.py @@ -18,6 +18,7 @@ import argparse import asyncio +import csv import datetime import locale import logging @@ -800,6 +801,22 @@ def is_url(path): # If it doesn't look like an URL, treat it like a file, possibly a UNC file. return path.lower().startswith("http:") or path.lower().startswith("https:") +def read_csv_metrics(path): + """ Read a metrics summary file produced by superpmi, and return the single row containing the information as a dictionary. + + Args: + path (str) : path to .csv file + + Returns: + A dictionary with each metric + """ + + with open(path) as csv_file: + reader = csv.DictReader(csv_file) + for row in reader: + return row + + return None ################################################################################ # Helper classes @@ -1800,6 +1817,9 @@ def replay_with_asm_diffs(self): fail_mcl_file = os.path.join(temp_location, os.path.basename(mch_file) + "_fail.mcl") diff_mcl_file = os.path.join(temp_location, os.path.basename(mch_file) + "_diff.mcl") + base_metrics_summary_file = os.path.join(temp_location, os.path.basename(mch_file) + "_base_metrics.csv") + diff_metrics_summary_file = os.path.join(temp_location, os.path.basename(mch_file) + "_diff_metrics.csv") + # If the user passed -temp_dir, we skip the SuperPMI replay process, # and rely on what we find from a previous run. if self.coreclr_args.temp_dir is not None: @@ -1810,7 +1830,9 @@ def replay_with_asm_diffs(self): "-v", "ewmi", # display errors, warnings, missing, jit info "-f", fail_mcl_file, # Failing mc List "-diffMCList", diff_mcl_file, # Create all of the diffs in an mcl file - "-r", os.path.join(temp_location, "repro") # Repro name, create .mc repro files + "-r", os.path.join(temp_location, "repro"), # Repro name, create .mc repro files + "-baseMetricsSummary", base_metrics_summary_file, # Create summary of metrics we can use to get total code size impact + "-diffMetricsSummary", diff_metrics_summary_file, ] flags += altjit_asm_diffs_flags flags += base_option_flags @@ -1839,7 +1861,7 @@ def replay_with_asm_diffs(self): return_code = run_and_log(command) print_superpmi_failure_code(return_code, self.coreclr_args) if return_code == 0: - logging.info("Clean SuperPMI replay") + logging.info("Clean SuperPMI diff") else: result = False # Don't report as replay failure asm diffs (return code 2) or missing data (return code 3). @@ -1961,6 +1983,17 @@ async def create_one_artifact(jit_path: str, location: str, flags) -> str: logging.debug(item) logging.debug("") + base_metrics = read_csv_metrics(base_metrics_summary_file) + diff_metrics = read_csv_metrics(diff_metrics_summary_file) + + if base_metrics is not None and "Code bytes" in base_metrics and diff_metrics is not None and "Code bytes" in diff_metrics: + base_bytes = int(base_metrics["Code bytes"]) + diff_bytes = int(diff_metrics["Code bytes"]) + logging.info("Total Code bytes of base: {}".format(base_bytes)) + logging.info("Total Code bytes of diff: {}".format(diff_bytes)) + delta_bytes = diff_bytes - base_bytes + logging.info("Total Code bytes of delta: {} ({:.2%} of base)".format(delta_bytes, delta_bytes / base_bytes)) + try: current_text_diff = text_differences.get_nowait() except: @@ -1985,6 +2018,9 @@ async def create_one_artifact(jit_path: str, location: str, flags) -> str: command = [ jit_analyze_path, "--md", md_summary_file, "-r", "--base", base_asm_location, "--diff", diff_asm_location ] if self.coreclr_args.metrics: command += [ "--metrics", ",".join(self.coreclr_args.metrics) ] + elif base_bytes is not None and diff_bytes is not None: + command += [ "--override-total-base-metric", str(base_bytes), "--override-total-diff-metric", str(diff_bytes) ] + run_and_log(command, logging.INFO) ran_jit_analyze = True @@ -2015,6 +2051,14 @@ async def create_one_artifact(jit_path: str, location: str, flags) -> str: os.remove(fail_mcl_file) fail_mcl_file = None + if os.path.isfile(base_metrics_summary_file): + os.remove(base_metrics_summary_file) + base_metrics_summary_file = None + + if os.path.isfile(diff_metrics_summary_file): + os.remove(diff_metrics_summary_file) + diff_metrics_summary_file = None + ################################################################################################ end of for mch_file in self.mch_files # Report the overall results summary of the asmdiffs run diff --git a/src/coreclr/scripts/superpmi_benchmarks.py b/src/coreclr/scripts/superpmi_benchmarks.py index 6981fa22cbba0..d96f06b7e9866 100644 --- a/src/coreclr/scripts/superpmi_benchmarks.py +++ b/src/coreclr/scripts/superpmi_benchmarks.py @@ -20,8 +20,7 @@ from os.path import isfile from shutil import copyfile from coreclr_arguments import * -from superpmi import ChangeDir, TempDir -from superpmi_setup import run_command +from azdo_pipelines_util import run_command, ChangeDir, TempDir # Start of parser object creation. is_windows = platform.system() == "Windows" diff --git a/src/coreclr/scripts/superpmi_setup.py b/src/coreclr/scripts/superpmi_collect_setup.py similarity index 75% rename from src/coreclr/scripts/superpmi_setup.py rename to src/coreclr/scripts/superpmi_collect_setup.py index 9ecec3bd9dd23..db49ff5b70d19 100644 --- a/src/coreclr/scripts/superpmi_setup.py +++ b/src/coreclr/scripts/superpmi_collect_setup.py @@ -3,8 +3,7 @@ # Licensed to the .NET Foundation under one or more agreements. # The .NET Foundation licenses this file to you under the MIT license. # -## -# Title : superpmi_setup.py +# Title : superpmi_collect_setup.py # # Notes: # @@ -21,7 +20,7 @@ # `CORE_ROOT` folder and this script will copy `max_size` bytes of those files under `payload/libraries/0/binaries`, # `payload/libraries/1/binaries` and so forth. # 4. Lastly, it sets the pipeline variables. - +# # Below are the helix queues it sets depending on the OS/architecture: # | Arch | windows | Linux | # |-------|----------------------|--------------------------------------------------------------------------------------------------------------------------------------| @@ -29,20 +28,17 @@ # | x64 | Windows.10.Amd64.X86 | Ubuntu.1804.Amd64 | # | arm | - | (Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-bfcd90a-20200121150440 | # | arm64 | Windows.10.Arm64 | (Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20210531091519-97d8652 | +# ################################################################################ ################################################################################ - import argparse -import shutil +import os import stat -import subprocess -import tempfile -from os import linesep, listdir, path, walk -from os.path import isfile, join, getsize from coreclr_arguments import * -from superpmi import ChangeDir +from azdo_pipelines_util import run_command, copy_directory, copy_files, set_pipeline_variable, ChangeDir, TempDir + # Start of parser object creation. @@ -251,7 +247,7 @@ def sorter_by_size(pair): filename_with_size = [] - for file_path, dirs, files in walk(src_directory, topdown=True): + for file_path, dirs, files in os.walk(src_directory, topdown=True): # Credit: https://stackoverflow.com/a/19859907 dirs[:] = [d for d in dirs if d not in exclude_directories] for name in files: @@ -259,14 +255,14 @@ def sorter_by_size(pair): exclude_files_lower = [filename.lower() for filename in exclude_files] if name.lower() in exclude_files_lower: continue - curr_file_path = path.join(file_path, name) + curr_file_path = os.path.join(file_path, name) - if not isfile(curr_file_path): + if not os.path.isfile(curr_file_path): continue if not name.endswith(".dll") and not name.endswith(".exe"): continue - size = getsize(curr_file_path) + size = os.path.getsize(curr_file_path) filename_with_size.append((curr_file_path, size)) return sorter_by_size(filename_with_size) @@ -312,109 +308,6 @@ def first_fit(sorted_by_size, max_size): return partitions -def run_command(command_to_run, _cwd=None, _exit_on_fail=False, _long_running=False): - """ Runs the command. - - Args: - command_to_run ([string]): Command to run along with arguments. - _cwd (string): Current working directory. - _exit_on_fail (bool): If it should exit on failure. - Returns: - (string, string, int): Returns a tuple of stdout, stderr, and command return code if _long_running= False - Otherwise stdout, stderr are empty. - """ - print("Running: " + " ".join(command_to_run)) - command_stdout = "" - command_stderr = "" - return_code = 1 - - output_type = subprocess.STDOUT if _long_running else subprocess.PIPE - with subprocess.Popen(command_to_run, stdout=subprocess.PIPE, stderr=output_type, cwd=_cwd) as proc: - - # For long running command, continuosly print the output - if _long_running: - while True: - output = proc.stdout.readline() - if proc.poll() is not None: - break - if output: - print(output.strip().decode("utf-8")) - else: - command_stdout, command_stderr = proc.communicate() - if len(command_stdout) > 0: - print(command_stdout.decode("utf-8")) - if len(command_stderr) > 0: - print(command_stderr.decode("utf-8")) - - return_code = proc.returncode - if _exit_on_fail and return_code != 0: - print("Command failed. Exiting.") - sys.exit(1) - return command_stdout, command_stderr, return_code - - -def copy_directory(src_path, dst_path, verbose_output=True, match_func=lambda path: True): - """Copies directory in 'src_path' to 'dst_path' maintaining the directory - structure. https://docs.python.org/3.5/library/shutil.html#shutil.copytree can't - be used in this case because it expects the destination directory should not - exist, however we do call copy_directory() to copy files to same destination directory. - - Args: - src_path (string): Path of source directory that need to be copied. - dst_path (string): Path where directory should be copied. - verbose_output (bool): True to print every copy or skipped file. - match_func (str -> bool) : Criteria function determining if a file is copied. - """ - if not os.path.exists(dst_path): - os.makedirs(dst_path) - for item in os.listdir(src_path): - src_item = os.path.join(src_path, item) - dst_item = os.path.join(dst_path, item) - if os.path.isdir(src_item): - copy_directory(src_item, dst_item, verbose_output, match_func) - else: - try: - if match_func(src_item): - if verbose_output: - print("> copy {0} => {1}".format(src_item, dst_item)) - try: - shutil.copy2(src_item, dst_item) - except PermissionError as pe_error: - print('Ignoring PermissionError: {0}'.format(pe_error)) - else: - if verbose_output: - print("> skipping {0}".format(src_item)) - except UnicodeEncodeError: - if verbose_output: - print("> Got UnicodeEncodeError") - - -def copy_files(src_path, dst_path, file_names): - """Copy files from 'file_names' list from 'src_path' to 'dst_path'. - It retains the original directory structure of src_path. - - Args: - src_path (string): Source directory from where files are copied. - dst_path (string): Destination directory where files to be copied. - file_names ([string]): List of full path file names to be copied. - """ - - print('### Copying below files from {0} to {1}:'.format(src_path, dst_path)) - print('') - print(os.linesep.join(file_names)) - for f in file_names: - # Create same structure in dst so we don't clobber same files names present in different directories - dst_path_of_file = f.replace(src_path, dst_path) - - dst_directory = path.dirname(dst_path_of_file) - if not os.path.exists(dst_directory): - os.makedirs(dst_directory) - try: - shutil.copy2(f, dst_path_of_file) - except PermissionError as pe_error: - print('Ignoring PermissionError: {0}'.format(pe_error)) - - def partition_files(src_directory, dst_directory, max_size, exclude_directories=[], exclude_files=native_binaries_to_ignore): """ Copy bucketized files based on size to destination folder. @@ -434,7 +327,7 @@ def partition_files(src_directory, dst_directory, max_size, exclude_directories= index = 0 for p_index in partitions: file_names = [curr_file[0] for curr_file in partitions[p_index]] - curr_dst_path = path.join(dst_directory, str(index), "binaries") + curr_dst_path = os.path.join(dst_directory, str(index), "binaries") copy_files(src_directory, curr_dst_path, file_names) index += 1 @@ -446,7 +339,7 @@ def setup_microbenchmark(workitem_directory, arch): workitem_directory (string): Path to work arch (string): Architecture for which dotnet will be installed """ - performance_directory = path.join(workitem_directory, "performance") + performance_directory = os.path.join(workitem_directory, "performance") run_command( ["git", "clone", "--quiet", "--depth", "1", "https://github.com/dotnet/performance", performance_directory]) @@ -455,7 +348,7 @@ def setup_microbenchmark(workitem_directory, arch): dotnet_directory = os.path.join(performance_directory, "tools", "dotnet", arch) dotnet_install_script = os.path.join(performance_directory, "scripts", "dotnet.py") - if not isfile(dotnet_install_script): + if not os.path.isfile(dotnet_install_script): print("Missing " + dotnet_install_script) return @@ -476,18 +369,6 @@ def get_python_name(): return ["python3"] -def set_pipeline_variable(name, value): - """ This method sets pipeline variable. - - Args: - name (string): Name of the variable. - value (string): Value of the variable. - """ - define_variable_format = "##vso[task.setvariable variable={0}]{1}" - print("{0} -> {1}".format(name, value)) # logging - print(define_variable_format.format(name, value)) # set variable - - def main(main_args): """ Main entrypoint @@ -498,9 +379,9 @@ def main(main_args): source_directory = coreclr_args.source_directory # CorrelationPayload directories - correlation_payload_directory = path.join(coreclr_args.source_directory, "payload") - superpmi_src_directory = path.join(source_directory, 'src', 'coreclr', 'scripts') - superpmi_dst_directory = path.join(correlation_payload_directory, "superpmi") + correlation_payload_directory = os.path.join(coreclr_args.source_directory, "payload") + superpmi_src_directory = os.path.join(source_directory, 'src', 'coreclr', 'scripts') + superpmi_dst_directory = os.path.join(correlation_payload_directory, "superpmi") arch = coreclr_args.arch helix_source_prefix = "official" creator = "" @@ -546,7 +427,7 @@ def make_readable(folder_name): print("Inside make_readable") run_command(["ls", "-l", folder_name]) - for file_path, dirs, files in walk(folder_name, topdown=True): + for file_path, dirs, files in os.walk(folder_name, topdown=True): for d in dirs: os.chmod(os.path.join(file_path, d), # read+write+execute for owner @@ -570,7 +451,7 @@ def make_readable(folder_name): copy_directory(coreclr_args.input_directory, superpmi_dst_directory, match_func=acceptable_copy) # Workitem directories - workitem_directory = path.join(source_directory, "workitem") + workitem_directory = os.path.join(source_directory, "workitem") input_artifacts = "" if coreclr_args.collection_name == "benchmarks": @@ -581,21 +462,21 @@ def make_readable(folder_name): # Clone and build jitutils try: - with tempfile.TemporaryDirectory() as jitutils_directory: + with TempDir() as jitutils_directory: run_command( ["git", "clone", "--quiet", "--depth", "1", "https://github.com/dotnet/jitutils", jitutils_directory]) # Make sure ".dotnet" directory exists, by running the script at least once dotnet_script_name = "dotnet.cmd" if is_windows else "dotnet.sh" - dotnet_script_path = path.join(source_directory, dotnet_script_name) + dotnet_script_path = os.path.join(source_directory, dotnet_script_name) run_command([dotnet_script_path, "--info"], jitutils_directory) - # Set dotnet path to run bootstrap - os.environ["PATH"] = path.join(source_directory, ".dotnet") + os.pathsep + os.environ["PATH"] - bootstrap_file = "bootstrap.cmd" if is_windows else "bootstrap.sh" - run_command([path.join(jitutils_directory, bootstrap_file)], jitutils_directory) + # Set dotnet path to run build + os.environ["PATH"] = os.path.join(source_directory, ".dotnet") + os.pathsep + os.environ["PATH"] + build_file = "build.cmd" if is_windows else "build.sh" + run_command([os.path.join(jitutils_directory, build_file), "-p"], jitutils_directory) - copy_files(path.join(jitutils_directory, "bin"), superpmi_dst_directory, [path.join(jitutils_directory, "bin", "pmi.dll")]) + copy_files(os.path.join(jitutils_directory, "bin"), superpmi_dst_directory, [os.path.join(jitutils_directory, "bin", "pmi.dll")]) except PermissionError as pe_error: # Details: https://bugs.python.org/issue26660 print('Ignoring PermissionError: {0}'.format(pe_error)) @@ -606,14 +487,14 @@ def make_readable(folder_name): # # Copy ".dotnet" to correlation_payload_directory for crossgen2 job; it is needed to invoke crossgen2.dll # if coreclr_args.collection_type == "crossgen2": - # dotnet_src_directory = path.join(source_directory, ".dotnet") - # dotnet_dst_directory = path.join(correlation_payload_directory, ".dotnet") + # dotnet_src_directory = os.path.join(source_directory, ".dotnet") + # dotnet_dst_directory = os.path.join(correlation_payload_directory, ".dotnet") # print('Copying {} -> {}'.format(dotnet_src_directory, dotnet_dst_directory)) # copy_directory(dotnet_src_directory, dotnet_dst_directory, verbose_output=False) # payload - pmiassemblies_directory = path.join(workitem_directory, "pmiAssembliesDirectory") - input_artifacts = path.join(pmiassemblies_directory, coreclr_args.collection_name) + pmiassemblies_directory = os.path.join(workitem_directory, "pmiAssembliesDirectory") + input_artifacts = os.path.join(pmiassemblies_directory, coreclr_args.collection_name) exclude_directory = ['Core_Root'] if coreclr_args.collection_name == "coreclr_tests" else [] exclude_files = native_binaries_to_ignore if coreclr_args.collection_type == "crossgen2": @@ -625,7 +506,7 @@ def make_readable(folder_name): # libraries_tests artifacts contains files from core_root folder. Exclude them. core_root_dir = coreclr_args.core_root_directory exclude_files += [item for item in os.listdir(core_root_dir) - if isfile(join(core_root_dir, item)) and (item.endswith(".dll") or item.endswith(".exe"))] + if os.path.isfile(os.path.join(core_root_dir, item)) and (item.endswith(".dll") or item.endswith(".exe"))] partition_files(coreclr_args.input_directory, input_artifacts, coreclr_args.max_size, exclude_directory, exclude_files) diff --git a/src/coreclr/scripts/superpmi-replay.py b/src/coreclr/scripts/superpmi_replay.py similarity index 78% rename from src/coreclr/scripts/superpmi-replay.py rename to src/coreclr/scripts/superpmi_replay.py index 158c50162340c..a00b80753b2a9 100644 --- a/src/coreclr/scripts/superpmi-replay.py +++ b/src/coreclr/scripts/superpmi_replay.py @@ -3,22 +3,19 @@ # Licensed to the .NET Foundation under one or more agreements. # The .NET Foundation licenses this file to you under the MIT license. # -## -# Title : superpmi_setup.py +# Title : superpmi_replay.py # # Notes: # -# Script to run "superpmi replay" for various collections under various COMPlus_JitStressRegs value. +# Script to run "superpmi replay" for various collections under various COMPlus_JitStressRegs values. +# ################################################################################ ################################################################################ - import argparse -from os import path import os -from os import listdir from coreclr_arguments import * -from superpmi_setup import run_command +from azdo_pipelines_util import run_command parser = argparse.ArgumentParser(description="description") @@ -86,40 +83,47 @@ def main(main_args): python_path = sys.executable cwd = os.path.dirname(os.path.realpath(__file__)) coreclr_args = setup_args(main_args) - spmi_location = path.join(cwd, "artifacts", "spmi") + spmi_location = os.path.join(cwd, "artifacts", "spmi") log_directory = coreclr_args.log_directory platform_name = coreclr_args.platform os_name = "win" if platform_name.lower() == "windows" else "unix" arch_name = coreclr_args.arch host_arch_name = "x64" if arch_name.endswith("64") else "x86" os_name = "universal" if arch_name.startswith("arm") else os_name - jit_path = path.join(coreclr_args.jit_directory, 'clrjit_{}_{}_{}.dll'.format(os_name, arch_name, host_arch_name)) + jit_path = os.path.join(coreclr_args.jit_directory, 'clrjit_{}_{}_{}.dll'.format(os_name, arch_name, host_arch_name)) print("Running superpmi.py download") - run_command([python_path, path.join(cwd, "superpmi.py"), "download", "--no_progress", "-target_os", platform_name, + run_command([python_path, os.path.join(cwd, "superpmi.py"), "download", "--no_progress", "-target_os", platform_name, "-target_arch", arch_name, "-core_root", cwd, "-spmi_location", spmi_location], _exit_on_fail=True) failed_runs = [] for jit_flag in jit_flags: - log_file = path.join(log_directory, 'superpmi_{}.log'.format(jit_flag.replace("=", "_"))) + log_file = os.path.join(log_directory, 'superpmi_{}.log'.format(jit_flag.replace("=", "_"))) print("Running superpmi.py replay for {}".format(jit_flag)) _, _, return_code = run_command([ - python_path, path.join(cwd, "superpmi.py"), "replay", "-core_root", cwd, - "-jitoption", jit_flag, "-jitoption", "TieredCompilation=0", - "-target_os", platform_name, "-target_arch", arch_name, + python_path, + os.path.join(cwd, "superpmi.py"), + "replay", + "-core_root", cwd, + "-jitoption", jit_flag, + "-jitoption", "TieredCompilation=0", + "-target_os", platform_name, + "-target_arch", arch_name, "-arch", host_arch_name, - "-jit_path", jit_path, "-spmi_location", spmi_location, - "-log_level", "debug", "-log_file", log_file]) + "-jit_path", jit_path, + "-spmi_location", spmi_location, + "-log_level", "debug", + "-log_file", log_file]) if return_code != 0: failed_runs.append("Failure in {}".format(log_file)) # Consolidate all superpmi_*.logs in superpmi_platform_architecture.log - final_log_name = path.join(log_directory, "superpmi_{}_{}.log".format(platform_name, arch_name)) + final_log_name = os.path.join(log_directory, "superpmi_{}_{}.log".format(platform_name, arch_name)) print("Consolidating final {}".format(final_log_name)) with open(final_log_name, "a") as final_superpmi_log: - for superpmi_log in listdir(log_directory): + for superpmi_log in os.listdir(log_directory): if not superpmi_log.startswith("superpmi_Jit") or not superpmi_log.endswith(".log"): continue @@ -127,7 +131,7 @@ def main(main_args): final_superpmi_log.write("======================================================={}".format(os.linesep)) final_superpmi_log.write("Contents from {}{}".format(superpmi_log, os.linesep)) final_superpmi_log.write("======================================================={}".format(os.linesep)) - with open(path.join(log_directory, superpmi_log), "r") as current_superpmi_log: + with open(os.path.join(log_directory, superpmi_log), "r") as current_superpmi_log: contents = current_superpmi_log.read() final_superpmi_log.write(contents) diff --git a/src/coreclr/scripts/superpmi_replay_setup.py b/src/coreclr/scripts/superpmi_replay_setup.py index c6c6fcb507f89..73c89eb333556 100644 --- a/src/coreclr/scripts/superpmi_replay_setup.py +++ b/src/coreclr/scripts/superpmi_replay_setup.py @@ -3,27 +3,21 @@ # Licensed to the .NET Foundation under one or more agreements. # The .NET Foundation licenses this file to you under the MIT license. # -## # Title : superpmi_replay_setup.py # # Notes: # # Script to setup directory structure required to perform SuperPMI replay in CI. -# It creates `correlation_payload_directory` that contains clrjit*_x64.dll and clrjit*_x86.dll +# It creates `correlation_payload_directory` that contains clrjit*_x64.dll and clrjit*_x86.dll +# ################################################################################ ################################################################################ import argparse -from os import path, walk import os -import shutil -import stat -import subprocess -import tempfile -from os.path import isfile, join from coreclr_arguments import * -from superpmi_setup import copy_directory, copy_files, set_pipeline_variable, run_command +from azdo_pipelines_util import copy_directory, copy_files, set_pipeline_variable parser = argparse.ArgumentParser(description="description") @@ -63,38 +57,10 @@ def setup_args(args): return coreclr_args -def partition_mch(mch_directory, dst_directory): - from os import listdir - - print("Inside partition_mch") - mch_zip_files = [] - for file_path, dirs, files in walk(mch_directory, topdown=True): - for name in files: - curr_file_path = path.join(file_path, name) - - if not isfile(curr_file_path): - continue - if not name.endswith(".mch.zip"): - continue - - mch_zip_files.append(curr_file_path) - - index = 1 - for mch_file in mch_zip_files: - print("Processing {}".format(mch_file)) - file_names = [] - file_names += [mch_file] - file_names += [mch_file.replace(".mch.zip", ".mch.mct.zip")] - curr_dst_path = path.join(dst_directory, "partitions", str(index)) - copy_files(mch_directory, curr_dst_path, file_names) - index += 1 - - def match_correlation_files(full_path): file_name = os.path.basename(full_path) - if file_name.startswith("clrjit_") and file_name.endswith(".dll") and file_name.find( - "osx") == -1: + if file_name.startswith("clrjit_") and file_name.endswith(".dll") and file_name.find("osx") == -1: return True if file_name == "superpmi.exe" or file_name == "mcs.exe": @@ -116,13 +82,11 @@ def main(main_args): product_directory = coreclr_args.product_directory # CorrelationPayload directories - correlation_payload_directory = path.join(coreclr_args.source_directory, "payload") - superpmi_src_directory = path.join(source_directory, 'src', 'coreclr', 'scripts') + correlation_payload_directory = os.path.join(source_directory, "payload") + superpmi_src_directory = os.path.join(source_directory, 'src', 'coreclr', 'scripts') helix_source_prefix = "official" creator = "" - ci = True - helix_queue = "Windows.10.Amd64.X86" # Copy *.py to CorrelationPayload print('Copying {} -> {}'.format(superpmi_src_directory, correlation_payload_directory)) @@ -130,7 +94,7 @@ def main(main_args): match_func=lambda path: any(path.endswith(extension) for extension in [".py"])) # Copy clrjit*_arch.dll binaries to CorrelationPayload - print('Copying binaries {} -> {}'.format(arch, product_directory, correlation_payload_directory)) + print('Copying binaries {} -> {}'.format(product_directory, correlation_payload_directory)) copy_directory(product_directory, correlation_payload_directory, match_func=match_correlation_files) # Set variables @@ -138,7 +102,6 @@ def main(main_args): set_pipeline_variable("CorrelationPayloadDirectory", correlation_payload_directory) set_pipeline_variable("Architecture", arch) set_pipeline_variable("Creator", creator) - set_pipeline_variable("Queue", helix_queue) set_pipeline_variable("HelixSourcePrefix", helix_source_prefix) diff --git a/src/coreclr/tools/Common/Compiler/Logging/CompilerGeneratedState.cs b/src/coreclr/tools/Common/Compiler/Logging/CompilerGeneratedState.cs index 4a5f482d35048..c2d861e62b2f6 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/CompilerGeneratedState.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/CompilerGeneratedState.cs @@ -1,6 +1,5 @@ // 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.Collections.Generic; diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/CompilerGeneratedState.cs b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/CompilerGeneratedState.cs index 9df15ab508906..34821288b76d9 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/CompilerGeneratedState.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/CompilerGeneratedState.cs @@ -1,6 +1,5 @@ // 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.Collections.Generic; using Mono.Cecil; diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageContainer.cs b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageContainer.cs index 9417723276745..7977343d17d5a 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageContainer.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageContainer.cs @@ -1,6 +1,5 @@ // 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.Diagnostics; diff --git a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageOrigin.cs b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageOrigin.cs index 701f3c0e56cde..364216788ba61 100644 --- a/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageOrigin.cs +++ b/src/coreclr/tools/Common/Compiler/Logging/ReferenceSource/MessageOrigin.cs @@ -1,6 +1,5 @@ // 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.Linq; diff --git a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs index 197e04c33e380..a8962fa2e3c1d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs +++ b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs @@ -877,7 +877,7 @@ private void ParseInstanceMethodEntrypointsCustom(provider, default(TGenericContext), mdReader.MetadataReader, this, (int)curParser.Offset); + var decoder = new R2RSignatureDecoder(provider, default(TGenericContext), mdReader?.MetadataReader, this, (int)curParser.Offset); TMethod customMethod = decoder.ParseMethod(); @@ -887,7 +887,6 @@ private void ParseInstanceMethodEntrypointsCustom + { + public JittedID(long methodID, long reJITID) + { + MethodID = methodID; + ReJITID = reJITID; + } + + public readonly long MethodID; + public readonly long ReJITID; + + public override int GetHashCode() => HashCode.Combine(MethodID, ReJITID); + public override bool Equals([NotNullWhen(true)] object obj) => obj is JittedID id ? Equals(id) : false; + + public bool Equals(JittedID other) + { + if (other.MethodID != MethodID) + return false; + return other.ReJITID == ReJITID; + } + } + public MethodMemoryMap( TraceProcess p, TraceTypeSystemContext tsc, TraceRuntimeDescToTypeSystemDesc idParser, - int clrInstanceID) + int clrInstanceID, + Logger logger) { // Capture the addresses of jitted code List infos = new List(); - Dictionary info = new Dictionary(); + Dictionary info = new Dictionary(); foreach (var e in p.EventsInProcess.ByEventType()) { if (e.ClrInstanceID != clrInstanceID) @@ -47,13 +71,16 @@ public MethodMemoryMap( if (method != null) { - infos.Add(new MemoryRegionInfo + JittedID jittedID = new JittedID(e.MethodID, 0); + if (!info.ContainsKey(jittedID)) { - StartAddress = e.MethodStartAddress, - EndAddress = e.MethodStartAddress + checked((uint)e.MethodSize), - MethodID = e.MethodID, - Method = method, - }); + info.Add(jittedID, new MemoryRegionInfo + { + StartAddress = e.MethodStartAddress, + EndAddress = e.MethodStartAddress + checked((uint)e.MethodSize), + Method = method, + }); + } } } @@ -67,7 +94,7 @@ public MethodMemoryMap( MethodDesc method = null; try { - method = idParser.ResolveMethodID(e.MethodID); + method = idParser.ResolveMethodID(e.MethodID, throwIfNotFound: false); } catch { @@ -75,17 +102,20 @@ public MethodMemoryMap( if (method != null) { - infos.Add(new MemoryRegionInfo + JittedID jittedID = new JittedID(e.MethodID, e.ReJITID); + if (!info.ContainsKey(jittedID)) { - StartAddress = e.MethodStartAddress, - EndAddress = e.MethodStartAddress + checked((uint)e.MethodSize), - MethodID = e.MethodID, - Method = method, - }); + info.Add(jittedID, new MemoryRegionInfo + { + StartAddress = e.MethodStartAddress, + EndAddress = e.MethodStartAddress + checked((uint)e.MethodSize), + Method = method, + }); + } } } - var sigProvider = new R2RSignatureTypeProvider(tsc); + var sigProvider = new R2RSignatureTypeProviderForGlobalTables(tsc); foreach (var module in p.LoadedModules) { if (module.FilePath == "") @@ -120,18 +150,40 @@ public MethodMemoryMap( } } } - catch { } + catch + { + logger.PrintWarning($"Failed to load method entry points from R2R module {module.FilePath}"); + } } - // Can have duplicate events, so pick first for each - var byMethodID = infos.GroupBy(i => i.MethodID).ToDictionary(g => g.Key, g => g.First()); + // Associate NativeToILMap with MethodLoad event found Memory Regions foreach (MethodILToNativeMapTraceData e in p.EventsInProcess.ByEventType()) { - if (byMethodID.TryGetValue(e.MethodID, out MemoryRegionInfo inf)) + if (info.TryGetValue(new JittedID(e.MethodID, e.ReJITID), out MemoryRegionInfo inf)) inf.NativeToILMap = NativeToILMap.FromEvent(e); } - _infos = byMethodID.Values.OrderBy(i => i.StartAddress).ToArray(); + // Sort the R2R data by StartAddress + MemoryRegionInfoStartAddressComparer startAddressComparer = new MemoryRegionInfoStartAddressComparer(); + infos.Sort(startAddressComparer); + + // For each method found via MethodLoad events, check to see if it exists in the infos array, and if it does not, build a list to add + List memoryRegionsToAdd = new List(); + foreach (var methodLoadInfo in info.Values) + { + int searchResult = infos.BinarySearch(methodLoadInfo, startAddressComparer); + if (searchResult < 0) + { + memoryRegionsToAdd.Add(methodLoadInfo); + } + } + + // Add the regions from the MethodLoad events, and keep the overall array sorted + infos.AddRange(memoryRegionsToAdd); + infos.Sort(startAddressComparer); + + _infos = infos.ToArray(); + _infoKeys = _infos.Select(i => i.StartAddress).ToArray(); #if DEBUG @@ -164,13 +216,17 @@ public MemoryRegionInfo GetInfo(ulong ip) } public MethodDesc GetMethod(ulong ip) => GetInfo(ip)?.Method; + + private class MemoryRegionInfoStartAddressComparer : IComparer + { + int IComparer.Compare(MemoryRegionInfo x, MemoryRegionInfo y) => x.StartAddress.CompareTo(y.StartAddress); + } } public class MemoryRegionInfo { public ulong StartAddress { get; set; } public ulong EndAddress { get; set; } - public long MethodID { get; set; } public MethodDesc Method { get; set; } public NativeToILMap NativeToILMap { get; set; } } diff --git a/src/coreclr/tools/dotnet-pgo/ModuleLoadLogger.cs b/src/coreclr/tools/dotnet-pgo/ModuleLoadLogger.cs index fb9afffb517ce..0271bb930b877 100644 --- a/src/coreclr/tools/dotnet-pgo/ModuleLoadLogger.cs +++ b/src/coreclr/tools/dotnet-pgo/ModuleLoadLogger.cs @@ -18,13 +18,28 @@ public ModuleLoadLogger(Logger logger) Logger _logger; + [ThreadStatic] + private static int s_loadFailuresAreErrors = 0; + + public class LoadFailuresAsErrors : IDisposable + { + public LoadFailuresAsErrors() + { + s_loadFailuresAreErrors++; + } + public void Dispose() + { + s_loadFailuresAreErrors--; + } + } + public void LogModuleLoadFailure(string simpleName, string filePath) { if (_simpleNamesReported.Add(simpleName)) { string str = $"Failed to load assembly '{simpleName}' from '{filePath}'"; - if (String.Compare("System.Private.CoreLib", simpleName, StringComparison.OrdinalIgnoreCase) == 0) + if (s_loadFailuresAreErrors != 0 || String.Compare("System.Private.CoreLib", simpleName, StringComparison.OrdinalIgnoreCase) == 0) { _logger.PrintError(str); } @@ -41,7 +56,7 @@ public void LogModuleLoadFailure(string simpleName) { string str = $"Failed to load assembly '{simpleName}'"; - if (String.Compare("System.Private.CoreLib", simpleName, StringComparison.OrdinalIgnoreCase) == 0) + if (s_loadFailuresAreErrors != 0 || String.Compare("System.Private.CoreLib", simpleName, StringComparison.OrdinalIgnoreCase) == 0) { _logger.PrintError(str); } diff --git a/src/coreclr/tools/dotnet-pgo/Program.cs b/src/coreclr/tools/dotnet-pgo/Program.cs index 77113377c478d..4636a4184a509 100644 --- a/src/coreclr/tools/dotnet-pgo/Program.cs +++ b/src/coreclr/tools/dotnet-pgo/Program.cs @@ -948,9 +948,11 @@ static int InnerProcessTraceFileMain(CommandLineOptions commandLineOptions) return -5; } - if (!p.EventsInProcess.ByEventType().Any()) + if (!p.EventsInProcess.ByEventType().Any() && + !p.EventsInProcess.ByEventType().Any() && + !p.EventsInProcess.ByEventType< SampledProfileTraceData>().Any()) { - PrintError($"No managed jit starting data\nWas the trace collected with provider at least \"Microsoft-Windows-DotNETRuntime:0x4000080018:5\"?"); + PrintError($"No data in trace for process\nWas the trace collected with provider at least \"Microsoft-Windows-DotNETRuntime:0x4000080018:5\"?"); return -5; } @@ -1014,7 +1016,9 @@ static int InnerProcessTraceFileMain(CommandLineOptions commandLineOptions) filePathError = true; } else - tsc.GetModuleFromPath(fileReference.FullName); + { + tsc.GetModuleFromPath(fileReference.FullName, throwIfNotLoadable: false); + } } catch (Internal.TypeSystem.TypeSystemException.BadImageFormatException) { @@ -1034,7 +1038,63 @@ static int InnerProcessTraceFileMain(CommandLineOptions commandLineOptions) TraceRuntimeDescToTypeSystemDesc idParser = new TraceRuntimeDescToTypeSystemDesc(p, tsc, clrInstanceId.Value); - SortedDictionary methodsToAttemptToPrepare = new SortedDictionary(); + int mismatchErrors = 0; + foreach (var e in p.EventsInProcess.ByEventType()) + { + ModuleDesc loadedModule = idParser.ResolveModuleID(e.ModuleID, false); + if (loadedModule == null) + { + PrintWarning($"Unable to find loaded module {e.ModuleILFileName} to verify match"); + continue; + } + + EcmaModule ecmaModule = loadedModule as EcmaModule; + if (ecmaModule == null) + { + continue; + } + + bool matched = false; + bool mismatch = false; + foreach (var debugEntry in ecmaModule.PEReader.ReadDebugDirectory()) + { + if (debugEntry.Type == DebugDirectoryEntryType.CodeView) + { + var codeViewData = ecmaModule.PEReader.ReadCodeViewDebugDirectoryData(debugEntry); + if (codeViewData.Path.EndsWith("ni.pdb")) + continue; + if (codeViewData.Guid != e.ManagedPdbSignature) + { + PrintError($"Dll mismatch between assembly located at \"{e.ModuleILPath}\" during trace collection and module \"{tsc.PEReaderToFilePath(ecmaModule.PEReader)}\""); + mismatchErrors++; + mismatch = true; + continue; + } + else + { + matched = true; + } + } + } + + if (!matched && !mismatch) + { + PrintMessage($"Unable to validate match between assembly located at \"{e.ModuleILPath}\" during trace collection and module \"{tsc.PEReaderToFilePath(ecmaModule.PEReader)}\""); + } + + // TODO find some way to match on MVID as only some dlls have managed pdbs, and this won't find issues with embedded pdbs + } + + if (mismatchErrors != 0) + { + PrintError($"{mismatchErrors} mismatch error(s) found"); + return -1; + } + + // Now that the modules are validated run Init to prepare for the rest of execution + idParser.Init(); + + SortedDictionary methodsToAttemptToPrepare = new SortedDictionary(); if (commandLineOptions.ProcessR2REvents) { @@ -1133,7 +1193,8 @@ MethodMemoryMap GetMethodMemMap() p, tsc, idParser, - clrInstanceId.Value); + clrInstanceId.Value, + s_logger); } return methodMemMap; @@ -1155,6 +1216,9 @@ MethodMemoryMap GetMethodMemMap() MethodMemoryMap mmap = GetMethodMemMap(); foreach (var e in p.EventsInProcess.ByEventType()) { + if ((e.TimeStampRelativeMSec < commandLineOptions.ExcludeEventsBefore) && (e.TimeStampRelativeMSec > commandLineOptions.ExcludeEventsAfter)) + continue; + var callstack = e.CallStack(); if (callstack == null) continue; @@ -1191,7 +1255,7 @@ MethodMemoryMap GetMethodMemMap() if (!methodsListedToPrepare.Contains(nextMethod)) { methodsListedToPrepare.Add(nextMethod); - methodsToAttemptToPrepare.Add((int)e.EventIndex, new ProcessedMethodData(e.TimeStampRelativeMSec, nextMethod, "SampleMethodCaller")); + methodsToAttemptToPrepare.Add(0x100000000 + (int)e.EventIndex, new ProcessedMethodData(e.TimeStampRelativeMSec, nextMethod, "SampleMethodCaller")); } if (!callGraph.TryGetValue(nextMethod, out var innerDictionary)) diff --git a/src/coreclr/tools/dotnet-pgo/R2RSignatureTypeProvider.cs b/src/coreclr/tools/dotnet-pgo/R2RSignatureTypeProvider.cs index a640425f209b4..3f68a63e271b3 100644 --- a/src/coreclr/tools/dotnet-pgo/R2RSignatureTypeProvider.cs +++ b/src/coreclr/tools/dotnet-pgo/R2RSignatureTypeProvider.cs @@ -1,7 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Collections.Immutable; +using System.Diagnostics; using System.Linq; using System.Reflection.Metadata; using ILCompiler.Reflection.ReadyToRun; @@ -109,7 +111,7 @@ MethodDesc IR2RSignatureTypeProvider.GetMethodFromMethodDef(MetadataReader reader, MethodDefinitionHandle handle, TypeDesc owningTypeOverride) + protected MethodDesc GetMethodFromMethodDef(MetadataReader reader, MethodDefinitionHandle handle, TypeDesc owningTypeOverride) { var ecmaModule = (EcmaModule)_tsc.GetModuleForSimpleName(reader.GetString(reader.GetAssemblyDefinition().Name)); var method = (MethodDesc)ecmaModule.GetObject(handle, NotFoundBehavior.ReturnNull); @@ -119,11 +121,19 @@ MethodDesc IR2RSignatureTypeProvider.GetMethodFromMethodDef(MetadataReader reader, MethodDefinitionHandle handle, TypeDesc owningTypeOverride) + { + return GetMethodFromMethodDef(reader, handle, owningTypeOverride); + } + MethodDesc IR2RSignatureTypeProvider.GetMethodWithFlags(ReadyToRunMethodSigFlags flags, MethodDesc method) { return method; @@ -237,4 +247,27 @@ TypeDesc ISignatureTypeProvider.GetTypeFromSpec return (TypeDesc)ecmaModule.GetObject(handle, NotFoundBehavior.ReturnNull); } } + + class R2RSignatureTypeProviderForGlobalTables : R2RSignatureTypeProvider, IR2RSignatureTypeProvider + { + public R2RSignatureTypeProviderForGlobalTables(TraceTypeSystemContext tsc) : base(tsc) + { + } + + MethodDesc IR2RSignatureTypeProvider.GetMethodFromMethodDef(MetadataReader reader, MethodDefinitionHandle handle, TypeDesc owningTypeOverride) + { + if (owningTypeOverride != null) + { + reader = ((EcmaModule)((MetadataType)owningTypeOverride.GetTypeDefinition()).Module).MetadataReader; + } + Debug.Assert(reader != null); + return GetMethodFromMethodDef(reader, handle, owningTypeOverride); + } + + MethodDesc IR2RSignatureTypeProvider.GetMethodFromMemberRef(MetadataReader reader, MemberReferenceHandle handle, TypeDesc owningTypeOverride) + { + // Global signature cannot have MemberRef entries in them as such things aren't uniquely identifiable + throw new NotSupportedException(); + } + } } diff --git a/src/coreclr/tools/dotnet-pgo/TraceRuntimeDescToTypeSystemDesc.cs b/src/coreclr/tools/dotnet-pgo/TraceRuntimeDescToTypeSystemDesc.cs index cb1816a26e073..90e4e96c37310 100644 --- a/src/coreclr/tools/dotnet-pgo/TraceRuntimeDescToTypeSystemDesc.cs +++ b/src/coreclr/tools/dotnet-pgo/TraceRuntimeDescToTypeSystemDesc.cs @@ -93,15 +93,15 @@ public override string ToString() class ModuleDescInfo { - public ModuleDescInfo(long id, TraceManagedModule traceManagedModule) + public ModuleDescInfo(long id, string assemblyName) { ID = id; - TraceManagedModule = traceManagedModule; + AssemblyName = assemblyName; } public readonly long ID; public ModuleDesc Module; - public readonly TraceManagedModule TraceManagedModule; + public readonly string AssemblyName; } private readonly Dictionary _methods = new Dictionary(); @@ -222,9 +222,11 @@ public TraceRuntimeDescToTypeSystemDesc(TraceProcess traceProcess, TypeSystemCon } Dictionary assemblyToCLRInstanceIDMap = new Dictionary(); + Dictionary assemblyToFullyQualifiedAssemblyName = new Dictionary(); foreach (var assemblyLoadTrace in _traceProcess.EventsInProcess.ByEventType()) { assemblyToCLRInstanceIDMap[assemblyLoadTrace.AssemblyID] = assemblyLoadTrace.ClrInstanceID; + assemblyToFullyQualifiedAssemblyName[assemblyLoadTrace.AssemblyID] = assemblyLoadTrace.FullyQualifiedAssemblyName; } foreach (var moduleFile in _traceProcess.LoadedModules) @@ -240,20 +242,15 @@ public TraceRuntimeDescToTypeSystemDesc(TraceProcess traceProcess, TypeSystemCon if (clrInstanceIDModule != _clrInstanceID) continue; - if (managedModule.ModuleFile != null) - { - ModuleDescInfo currentInfo; - if (_modules.TryGetValue(managedModule.ModuleID, out currentInfo)) - { - continue; - } - currentInfo = new ModuleDescInfo(managedModule.ModuleID, managedModule); - _modules.Add(managedModule.ModuleID, currentInfo); - } + var currentInfo = new ModuleDescInfo(managedModule.ModuleID, assemblyToFullyQualifiedAssemblyName[managedModule.AssemblyID]); + _modules.Add(managedModule.ModuleID, currentInfo); } } + } - + // Call before any api other than ResolveModuleID will work + public void Init() + { // Fill in all the types foreach (var entry in _types) { @@ -271,14 +268,7 @@ public ModuleDesc ResolveModuleID(long handle, bool throwIfNotFound = true) if (minfo.Module != null) return minfo.Module; - string simpleName = minfo.TraceManagedModule.Name; - - if (!File.Exists(minfo.TraceManagedModule.FilePath) && minfo.TraceManagedModule.FilePath.EndsWith(".il.dll") && simpleName.EndsWith(".il")) - { - simpleName = simpleName.Substring(0, simpleName.Length - 3); - } - - minfo.Module = _context.ResolveAssembly(new AssemblyName(simpleName), throwIfNotFound); + minfo.Module = _context.ResolveAssembly(new AssemblyName(minfo.AssemblyName), throwIfNotFound); return minfo.Module; } else diff --git a/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs b/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs index 3f0155fc5b76c..09e2f52ea053a 100644 --- a/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs +++ b/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs @@ -16,6 +16,7 @@ using Microsoft.Diagnostics.Tracing.Parsers.Clr; using System.Reflection.Metadata; using ILCompiler.Reflection.ReadyToRun; +using System.Runtime.CompilerServices; namespace Microsoft.Diagnostics.Tools.Pgo { @@ -181,9 +182,9 @@ public ModuleDesc GetModuleForSimpleName(string simpleName, bool throwIfNotFound } } - public EcmaModule GetModuleFromPath(string filePath) + public EcmaModule GetModuleFromPath(string filePath, bool throwIfNotLoadable = true) { - return GetOrAddModuleFromPath(filePath, null, true); + return GetOrAddModuleFromPath(filePath, null, true, throwIfNotLoadable: throwIfNotLoadable); } public EcmaModule GetMetadataOnlyModuleFromPath(string filePath) @@ -196,7 +197,7 @@ public EcmaModule GetMetadataOnlyModuleFromMemory(string filePath, byte[] module return GetOrAddModuleFromPath(filePath, moduleData, false); } - private EcmaModule GetOrAddModuleFromPath(string filePath, byte[] moduleData, bool useForBinding) + private EcmaModule GetOrAddModuleFromPath(string filePath, byte[] moduleData, bool useForBinding, bool throwIfNotLoadable = true) { // This method is not expected to be called frequently. Linear search is acceptable. foreach (var entry in ModuleHashtable.Enumerator.Get(_moduleHashtable)) @@ -208,10 +209,13 @@ private EcmaModule GetOrAddModuleFromPath(string filePath, byte[] moduleData, bo bool succeeded = false; try { - EcmaModule returnValue = AddModule(filePath, null, moduleData, useForBinding); - _moduleLoadLogger.LogModuleLoadSuccess(returnValue.Assembly.GetName().Name, filePath); - succeeded = true; - return returnValue; + EcmaModule returnValue = AddModule(filePath, null, moduleData, useForBinding, throwIfNotLoadable: throwIfNotLoadable); + if (returnValue != null) + { + _moduleLoadLogger.LogModuleLoadSuccess(returnValue.Assembly.GetName().Name, filePath); + succeeded = true; + return returnValue; + } } finally { @@ -220,6 +224,20 @@ private EcmaModule GetOrAddModuleFromPath(string filePath, byte[] moduleData, bo _moduleLoadLogger.LogModuleLoadFailure(Path.GetFileNameWithoutExtension(filePath), filePath); } } + return null; + } + + private static ConditionalWeakTable s_peReaderToPath = new ConditionalWeakTable(); + + // Get the file path used to load a PEReader or "Memory" if it wasn't loaded from a file + public string PEReaderToFilePath(PEReader reader) + { + if (!s_peReaderToPath.TryGetValue(reader, out string filepath)) + { + filepath = "Memory"; + } + + return filepath; } public static unsafe PEReader OpenPEFile(string filePath, byte[] moduleBytes, out MemoryMappedViewAccessor mappedViewAccessor) @@ -249,6 +267,7 @@ public static unsafe PEReader OpenPEFile(string filePath, byte[] moduleBytes, ou var safeBuffer = accessor.SafeMemoryMappedViewHandle; var peReader = new PEReader((byte*)safeBuffer.DangerousGetHandle(), (int)safeBuffer.ByteLength); + s_peReaderToPath.Add(peReader, filePath); // MemoryMappedFile does not need to be kept around. MemoryMappedViewAccessor is enough. @@ -268,13 +287,17 @@ public static unsafe PEReader OpenPEFile(string filePath, byte[] moduleBytes, ou } } - private EcmaModule AddModule(string filePath, string expectedSimpleName, byte[] moduleDataBytes, bool useForBinding) + private EcmaModule AddModule(string filePath, string expectedSimpleName, byte[] moduleDataBytes, bool useForBinding, bool throwIfNotLoadable = true) { MemoryMappedViewAccessor mappedViewAccessor = null; PdbSymbolReader pdbReader = null; try { PEReader peReader = OpenPEFile(filePath, moduleDataBytes, out mappedViewAccessor); + if ((!peReader.HasMetadata) && !throwIfNotLoadable) + { + return null; + } pdbReader = OpenAssociatedSymbolFile(filePath, peReader); EcmaModule module = EcmaModule.Create(this, peReader, containingAssembly: null, pdbReader); @@ -316,6 +339,10 @@ private EcmaModule AddModule(string filePath, string expectedSimpleName, byte[] return module; } + catch when (!throwIfNotLoadable) + { + return null; + } finally { if (mappedViewAccessor != null) @@ -375,12 +402,14 @@ public MetadataStringDecoder GetMetadataStringDecoder() IAssemblyMetadata IAssemblyResolver.FindAssembly(MetadataReader metadataReader, AssemblyReferenceHandle assemblyReferenceHandle, string parentFile) { + using var triggerErrors = new ModuleLoadLogger.LoadFailuresAsErrors(); EcmaAssembly ecmaAssembly = (EcmaAssembly)this.GetModuleForSimpleName(metadataReader.GetString(metadataReader.GetAssemblyReference(assemblyReferenceHandle).Name), false); return new StandaloneAssemblyMetadata(ecmaAssembly.PEReader); } IAssemblyMetadata IAssemblyResolver.FindAssembly(string simpleName, string parentFile) { + using var triggerErrors = new ModuleLoadLogger.LoadFailuresAsErrors(); EcmaAssembly ecmaAssembly = (EcmaAssembly)this.GetModuleForSimpleName(simpleName, false); return new StandaloneAssemblyMetadata(ecmaAssembly.PEReader); } diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index da3a36468c06c..a1b164a0af65d 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -106,7 +106,7 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON nativeimage.cpp object.cpp onstackreplacement.cpp - pefile.cpp + peassembly.cpp peimage.cpp perfmap.cpp perfinfo.cpp @@ -207,8 +207,8 @@ set(VM_HEADERS_DAC_AND_WKS_COMMON object.h object.inl onstackreplacement.h - pefile.h - pefile.inl + peassembly.h + peassembly.inl peimage.h peimage.inl peimagelayout.h diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index d76db29301529..61c4c08e24925 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1041,7 +1041,6 @@ void SystemDomain::Attach() // Create the one and only app domain AppDomain::Create(); - AppDomain::GetCurrentDomain()->CreateBinderContext(); // Each domain gets its own ReJitManager, and ReJitManager has its own static // initialization to run @@ -1174,7 +1173,7 @@ void SystemDomain::Init() if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_ZapDisable) != 0) g_fAllowNativeImages = false; - m_pSystemFile = NULL; + m_pSystemPEAssembly = NULL; m_pSystemAssembly = NULL; DWORD size = 0; @@ -1320,12 +1319,11 @@ void SystemDomain::LoadBaseSystemClasses() ETWOnStartup(LdSysBases_V1, LdSysBasesEnd_V1); - { - m_pSystemFile = PEAssembly::OpenSystem(); - } + m_pSystemPEAssembly = PEAssembly::OpenSystem(); + // Only partially load the system assembly. Other parts of the code will want to access // the globals in this function before finishing the load. - m_pSystemAssembly = DefaultDomain()->LoadDomainAssembly(NULL, m_pSystemFile, FILE_LOAD_POST_LOADLIBRARY)->GetCurrentAssembly(); + m_pSystemAssembly = DefaultDomain()->LoadDomainAssembly(NULL, m_pSystemPEAssembly, FILE_LOAD_POST_LOADLIBRARY)->GetCurrentAssembly(); // Set up binder for CoreLib CoreLibBinder::AttachModule(m_pSystemAssembly->GetManifestModule()); @@ -1839,6 +1837,8 @@ void AppDomain::Create() pDomain->InitVSD(); pDomain->SetStage(AppDomain::STAGE_OPEN); + pDomain->CreateDefaultBinder(); + pDomain.SuppressRelease(); m_pTheAppDomain = pDomain; @@ -2251,7 +2251,7 @@ DispIDCache* AppDomain::SetupRefDispIDCache() #endif // FEATURE_COMINTEROP -FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile) +FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEAssembly * pPEAssembly, DomainFile *pDomainFile) { CONTRACTL { @@ -2259,12 +2259,12 @@ FileLoadLock *FileLoadLock::Create(PEFileListLock *pLock, PEFile *pFile, DomainF GC_TRIGGERS; MODE_ANY; PRECONDITION(pLock->HasLock()); - PRECONDITION(pLock->FindFileLock(pFile) == NULL); + PRECONDITION(pLock->FindFileLock(pPEAssembly) == NULL); INJECT_FAULT(COMPlusThrowOM();); } CONTRACTL_END; - NewHolder result(new FileLoadLock(pLock, pFile, pDomainFile)); + NewHolder result(new FileLoadLock(pLock, pPEAssembly, pDomainFile)); pLock->AddElement(result); result->AddRef(); // Add one ref on behalf of the ListLock's reference. The corresponding Release() happens in FileLoadLock::CompleteLoadLevel. @@ -2281,7 +2281,7 @@ FileLoadLock::~FileLoadLock() MODE_ANY; } CONTRACTL_END; - ((PEFile *) m_data)->Release(); + ((PEAssembly *) m_data)->Release(); } DomainFile *FileLoadLock::GetDomainFile() @@ -2476,14 +2476,14 @@ UINT32 FileLoadLock::Release() return count; } -FileLoadLock::FileLoadLock(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile) - : ListLockEntry(pLock, pFile, "File load lock"), +FileLoadLock::FileLoadLock(PEFileListLock *pLock, PEAssembly * pPEAssembly, DomainFile *pDomainFile) + : ListLockEntry(pLock, pPEAssembly, "File load lock"), m_level((FileLoadLevel) (FILE_LOAD_CREATE)), m_pDomainFile(pDomainFile), m_cachedHR(S_OK) { WRAPPER_NO_CONTRACT; - pFile->AddRef(); + pPEAssembly->AddRef(); } void FileLoadLock::HolderLeave(FileLoadLock *pThis) @@ -2531,7 +2531,7 @@ void AppDomain::LoadSystemAssemblies() // // Right now we have only one system assembly. We shouldn't need to add any more. - LoadAssembly(NULL, SystemDomain::System()->SystemFile(), FILE_ACTIVE); + LoadAssembly(NULL, SystemDomain::System()->SystemPEAssembly(), FILE_ACTIVE); } FileLoadLevel AppDomain::GetDomainFileLoadLevel(DomainFile *pFile) @@ -2546,7 +2546,7 @@ FileLoadLevel AppDomain::GetDomainFileLoadLevel(DomainFile *pFile) LoadLockHolder lock(this); - FileLoadLock* pLockEntry = (FileLoadLock *) lock->FindFileLock(pFile->GetFile()); + FileLoadLock* pLockEntry = (FileLoadLock *) lock->FindFileLock(pFile->GetPEAssembly()); if (pLockEntry == NULL) return pFile->GetLoadLevel(); @@ -2576,7 +2576,7 @@ BOOL AppDomain::IsLoading(DomainFile *pFile, FileLoadLevel level) { LoadLockHolder lock(this); - pLock = (FileLoadLock *) lock->FindFileLock(pFile->GetFile()); + pLock = (FileLoadLock *) lock->FindFileLock(pFile->GetPEAssembly()); if (pLock == NULL) { @@ -2613,7 +2613,7 @@ CHECK AppDomain::CheckLoading(DomainFile *pFile, FileLoadLevel level) LoadLockHolder lock(this); - pLock = (FileLoadLock *) lock->FindFileLock(pFile->GetFile()); + pLock = (FileLoadLock *) lock->FindFileLock(pFile->GetPEAssembly()); if (pLock != NULL && pLock->CanAcquire(level)) @@ -2699,7 +2699,7 @@ void AppDomain::LoadDomainFile(DomainFile *pFile, // Load some more if appropriate LoadLockHolder lock(this); - FileLoadLock* pLockEntry = (FileLoadLock *) lock->FindFileLock(pFile->GetFile()); + FileLoadLock* pLockEntry = (FileLoadLock *) lock->FindFileLock(pFile->GetPEAssembly()); if (pLockEntry == NULL) { _ASSERTE (!pFile->IsLoading()); @@ -2731,7 +2731,7 @@ FileLoadLevel AppDomain::GetThreadFileLoadLevel() Assembly *AppDomain::LoadAssembly(AssemblySpec* pIdentity, - PEAssembly *pFile, + PEAssembly * pPEAssembly, FileLoadLevel targetLevel) { CONTRACT(Assembly *) @@ -2739,20 +2739,20 @@ Assembly *AppDomain::LoadAssembly(AssemblySpec* pIdentity, GC_TRIGGERS; THROWS; MODE_ANY; - PRECONDITION(CheckPointer(pFile)); + PRECONDITION(CheckPointer(pPEAssembly)); POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); // May be NULL in recursive load case INJECT_FAULT(COMPlusThrowOM();); } CONTRACT_END; - DomainAssembly *pAssembly = LoadDomainAssembly(pIdentity, pFile, targetLevel); + DomainAssembly *pAssembly = LoadDomainAssembly(pIdentity, pPEAssembly, targetLevel); PREFIX_ASSUME(pAssembly != NULL); RETURN pAssembly->GetAssembly(); } DomainAssembly* AppDomain::LoadDomainAssembly(AssemblySpec* pSpec, - PEAssembly *pFile, + PEAssembly * pPEAssembly, FileLoadLevel targetLevel) { STATIC_CONTRACT_THROWS; @@ -2760,13 +2760,13 @@ DomainAssembly* AppDomain::LoadDomainAssembly(AssemblySpec* pSpec, if (pSpec == nullptr) { // skip caching, since we don't have anything to base it on - return LoadDomainAssemblyInternal(pSpec, pFile, targetLevel); + return LoadDomainAssemblyInternal(pSpec, pPEAssembly, targetLevel); } DomainAssembly* pRetVal = NULL; EX_TRY { - pRetVal = LoadDomainAssemblyInternal(pSpec, pFile, targetLevel); + pRetVal = LoadDomainAssemblyInternal(pSpec, pPEAssembly, targetLevel); } EX_HOOK { @@ -2775,7 +2775,7 @@ DomainAssembly* AppDomain::LoadDomainAssembly(AssemblySpec* pSpec, { // Setup the binder reference in AssemblySpec from the PEAssembly if one is not already set. AssemblyBinder* pCurrentBinder = pSpec->GetBinder(); - AssemblyBinder* pBinderFromPEAssembly = pFile->GetAssemblyBinder(); + AssemblyBinder* pBinderFromPEAssembly = pPEAssembly->GetAssemblyBinder(); if (pCurrentBinder == NULL) { @@ -2811,7 +2811,7 @@ DomainAssembly* AppDomain::LoadDomainAssembly(AssemblySpec* pSpec, DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, - PEAssembly *pFile, + PEAssembly * pPEAssembly, FileLoadLevel targetLevel) { CONTRACT(DomainAssembly *) @@ -2819,8 +2819,8 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, GC_TRIGGERS; THROWS; MODE_ANY; - PRECONDITION(CheckPointer(pFile)); - PRECONDITION(pFile->IsSystem() || ::GetAppDomain()==this); + PRECONDITION(CheckPointer(pPEAssembly)); + PRECONDITION(::GetAppDomain()==this); POSTCONDITION(CheckPointer(RETVAL)); POSTCONDITION(RETVAL->GetLoadLevel() >= GetThreadFileLoadLevel() || RETVAL->GetLoadLevel() >= targetLevel); @@ -2836,16 +2836,16 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, GCX_PREEMP(); // Check for existing fully loaded assembly, or for an assembly which has failed during the loading process. - result = FindAssembly(pFile, FindAssemblyOptions_IncludeFailedToLoad); + result = FindAssembly(pPEAssembly, FindAssemblyOptions_IncludeFailedToLoad); if (result == NULL) { LoaderAllocator *pLoaderAllocator = NULL; - AssemblyBinder *pFileBinder = pFile->GetAssemblyBinder(); + AssemblyBinder *pAssemblyBinder = pPEAssembly->GetAssemblyBinder(); // Assemblies loaded with CustomAssemblyBinder need to use a different LoaderAllocator if // marked as collectible - pLoaderAllocator = pFileBinder->GetLoaderAllocator(); + pLoaderAllocator = pAssemblyBinder->GetLoaderAllocator(); if (pLoaderAllocator == NULL) { pLoaderAllocator = this->GetLoaderAllocator(); @@ -2853,22 +2853,22 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, // Allocate the DomainAssembly a bit early to avoid GC mode problems. We could potentially avoid // a rare redundant allocation by moving this closer to FileLoadLock::Create, but it's not worth it. - NewHolder pDomainAssembly = new DomainAssembly(this, pFile, pLoaderAllocator); + NewHolder pDomainAssembly = new DomainAssembly(this, pPEAssembly, pLoaderAllocator); LoadLockHolder lock(this); // Find the list lock entry - FileLoadLock * fileLock = (FileLoadLock *)lock->FindFileLock(pFile); + FileLoadLock * fileLock = (FileLoadLock *)lock->FindFileLock(pPEAssembly); bool registerNewAssembly = false; if (fileLock == NULL) { // Check again in case we were racing - result = FindAssembly(pFile, FindAssemblyOptions_IncludeFailedToLoad); + result = FindAssembly(pPEAssembly, FindAssemblyOptions_IncludeFailedToLoad); if (result == NULL) { // We are the first one in - create the DomainAssembly registerNewAssembly = true; - fileLock = FileLoadLock::Create(lock, pFile, pDomainAssembly); + fileLock = FileLoadLock::Create(lock, pPEAssembly, pDomainAssembly); pDomainAssembly.SuppressRelease(); if (pDomainAssembly->IsCollectible()) { @@ -2901,7 +2901,7 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, if (registerNewAssembly) { - pFile->GetAssemblyBinder()->AddLoadedAssembly(pDomainAssembly->GetCurrentAssembly()); + pPEAssembly->GetAssemblyBinder()->AddLoadedAssembly(pDomainAssembly->GetCurrentAssembly()); } } else @@ -2915,11 +2915,11 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, ThrowHR(COR_E_ASSEMBLYEXPECTED); } - // Cache result in all cases, since found pFile could be from a different AssemblyRef than pIdentity + // Cache result in all cases, since found pPEAssembly could be from a different AssemblyRef than pIdentity if (pIdentity == NULL) { AssemblySpec spec; - spec.InitializeSpec(result->GetFile()); + spec.InitializeSpec(result->GetPEAssembly()); GetAppDomain()->AddAssemblyToCache(&spec, result); } else @@ -2956,26 +2956,6 @@ DomainFile *AppDomain::LoadDomainFile(FileLoadLock *pLock, FileLoadLevel targetL // Make sure we release the lock on exit FileLoadLockRefHolder lockRef(pLock); - // We need to perform the early steps of loading CoreLib without a domain transition. This is - // important for bootstrapping purposes - we need to get CoreLib at least partially loaded - // into a domain before we can run serialization code to do the transition. - // - // Note that we cannot do this in general for all assemblies, because some of the security computations - // require the managed exposed object, which must be created in the correct app domain. - - if (this != GetAppDomain() - && pFile->GetFile()->IsSystem() - && targetLevel > FILE_LOAD_ALLOCATE) - { - // Re-call the routine with a limited load level. This will cause the first part of the load to - // get performed in the current app domain. - - pLock->AddRef(); - LoadDomainFile(pLock, targetLevel > FILE_LOAD_ALLOCATE ? FILE_LOAD_ALLOCATE : targetLevel); - - // Now continue on to complete the rest of the load, if any. - } - // Do a quick out check for the already loaded case. if (pLock->GetLoadLevel() >= targetLevel) { @@ -3151,7 +3131,7 @@ void AppDomain::TryIncrementalLoad(DomainFile *pFile, FileLoadLevel workLevel, F } if (!EEFileLoadException::CheckType(pEx)) - EEFileLoadException::Throw(pFile->GetFile(), pEx->GetHR(), pEx); + EEFileLoadException::Throw(pFile->GetPEAssembly(), pEx->GetHR(), pEx); } // Otherwise, we simply abort this load, and can retry later on. @@ -3212,7 +3192,7 @@ void AppDomain::SetupSharedStatics() SetObjectReference( pEmptyStringHandle, StringObject::GetEmptyString()); } -DomainAssembly * AppDomain::FindAssembly(PEAssembly * pFile, FindAssemblyOptions options/* = FindAssemblyOptions_None*/) +DomainAssembly * AppDomain::FindAssembly(PEAssembly * pPEAssembly, FindAssemblyOptions options/* = FindAssemblyOptions_None*/) { CONTRACTL { @@ -3225,9 +3205,9 @@ DomainAssembly * AppDomain::FindAssembly(PEAssembly * pFile, FindAssemblyOptions const bool includeFailedToLoad = (options & FindAssemblyOptions_IncludeFailedToLoad) != 0; - if (pFile->HasHostAssembly()) + if (pPEAssembly->HasHostAssembly()) { - DomainAssembly * pDA = FindAssembly(pFile->GetHostAssembly()); + DomainAssembly * pDA = FindAssembly(pPEAssembly->GetHostAssembly()); if (pDA != nullptr && (pDA->IsLoaded() || (includeFailedToLoad && pDA->IsError()))) { return pDA; @@ -3243,10 +3223,9 @@ DomainAssembly * AppDomain::FindAssembly(PEAssembly * pFile, FindAssemblyOptions while (i.Next(pDomainAssembly.This())) { - PEFile * pManifestFile = pDomainAssembly->GetFile(); + PEAssembly * pManifestFile = pDomainAssembly->GetPEAssembly(); if (pManifestFile && - !pManifestFile->IsResource() && - pManifestFile->Equals(pFile)) + pManifestFile->Equals(pPEAssembly)) { // Caller already has PEAssembly, so we can give DomainAssembly away freely without added reference return pDomainAssembly.GetValue(); @@ -3412,7 +3391,7 @@ PVOID AppDomain::GetFriendlyNameNoSet(bool* isUtf8) #ifndef DACCESS_COMPILE -BOOL AppDomain::AddFileToCache(AssemblySpec* pSpec, PEAssembly *pFile, BOOL fAllowFailure) +BOOL AppDomain::AddFileToCache(AssemblySpec* pSpec, PEAssembly * pPEAssembly, BOOL fAllowFailure) { CONTRACTL { @@ -3428,7 +3407,7 @@ BOOL AppDomain::AddFileToCache(AssemblySpec* pSpec, PEAssembly *pFile, BOOL fAll DomainCacheCrstHolderForGCCoop holder(this); // !!! suppress exceptions - if(!m_AssemblyCache.StoreFile(pSpec, pFile) && !fAllowFailure) + if(!m_AssemblyCache.StorePEAssembly(pSpec, pPEAssembly) && !fAllowFailure) { // TODO: Disabling the below assertion as currently we experience // inconsistency on resolving the Microsoft.Office.Interop.MSProject.dll @@ -3538,17 +3517,17 @@ NATIVE_LIBRARY_HANDLE AppDomain::FindUnmanagedImageInCache(LPCWSTR libraryName) RETURN existingEntry->Handle; } -BOOL AppDomain::RemoveFileFromCache(PEAssembly *pFile) +BOOL AppDomain::RemoveFileFromCache(PEAssembly * pPEAssembly) { CONTRACTL { GC_TRIGGERS; - PRECONDITION(CheckPointer(pFile)); + PRECONDITION(CheckPointer(pPEAssembly)); } CONTRACTL_END; LoadLockHolder lock(this); - FileLoadLock *fileLock = (FileLoadLock *)lock->FindFileLock(pFile); + FileLoadLock *fileLock = (FileLoadLock *)lock->FindFileLock(pPEAssembly); if (fileLock == NULL) return FALSE; @@ -3611,9 +3590,9 @@ PEAssembly* AppDomain::FindCachedFile(AssemblySpec* pSpec, BOOL fThrow /*=TRUE*/ if (fThrow && pSpec->IsCoreLib()) { CONSISTENCY_CHECK(SystemDomain::System()->SystemAssembly() != NULL); - PEAssembly *pFile = SystemDomain::System()->SystemFile(); - pFile->AddRef(); - return pFile; + PEAssembly * pPEAssembly = SystemDomain::System()->SystemPEAssembly(); + pPEAssembly->AddRef(); + return pPEAssembly; } return m_AssemblyCache.LookupFile(pSpec, fThrow); @@ -3697,16 +3676,16 @@ PEAssembly * AppDomain::BindAssemblySpec( if (boundAssembly) { - if (SystemDomain::SystemFile() && boundAssembly->GetAssemblyName()->IsCoreLib()) + if (SystemDomain::SystemPEAssembly() && boundAssembly->GetAssemblyName()->IsCoreLib()) { // Avoid rebinding to another copy of CoreLib - result = SystemDomain::SystemFile(); + result = SystemDomain::SystemPEAssembly(); result.SuppressRelease(); // Didn't get a refcount } else { - // IsSystem on the PEFile should be false, even for CoreLib satellites - result = PEAssembly::Open(boundAssembly, FALSE); + // IsSystem on the PEAssembly should be false, even for CoreLib satellites + result = PEAssembly::Open(boundAssembly); } // Setup the reference to the binder, which performed the bind, into the AssemblySpec @@ -3861,9 +3840,9 @@ PEAssembly *AppDomain::TryResolveAssemblyUsingEvent(AssemblySpec *pSpec) Assembly *pAssembly = RaiseAssemblyResolveEvent(pSpec); if (pAssembly != nullptr) { - PEAssembly *pFile = pAssembly->GetManifestFile(); - pFile->AddRef(); - result = pFile; + PEAssembly* pPEAssembly = pAssembly->GetManifestFile(); + pPEAssembly->AddRef(); + result = pPEAssembly; } BinderTracing::ResolutionAttemptedOperation::TraceAppDomainAssemblyResolve(pSpec, result); @@ -3924,7 +3903,7 @@ void AppDomain::RaiseLoadingAssemblyEvent(DomainAssembly *pAssembly) } CONTRACTL_END; - if (pAssembly->GetFile()->IsSystem()) + if (pAssembly->GetPEAssembly()->IsSystem()) { return; } @@ -4040,7 +4019,7 @@ AppDomain::RaiseUnhandledExceptionEvent(OBJECTREF *pThrowable, BOOL isTerminatin } -DefaultAssemblyBinder *AppDomain::CreateBinderContext() +DefaultAssemblyBinder *AppDomain::CreateDefaultBinder() { CONTRACT(DefaultAssemblyBinder *) { @@ -5138,7 +5117,7 @@ HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToB } else { - pLoadedPEAssembly = pDomainAssembly->GetFile(); + pLoadedPEAssembly = pDomainAssembly->GetPEAssembly(); if (!pLoadedPEAssembly->HasHostAssembly()) { // Reflection emitted assemblies will not have a domain assembly. @@ -5300,9 +5279,9 @@ SystemDomain::EnumMemoryRegions(CLRDataEnumMemoryFlags flags, } BaseDomain::EnumMemoryRegions(flags, false); - if (m_pSystemFile.IsValid()) + if (m_pSystemPEAssembly.IsValid()) { - m_pSystemFile->EnumMemoryRegions(flags); + m_pSystemPEAssembly->EnumMemoryRegions(flags); } if (m_pSystemAssembly.IsValid()) { @@ -5372,11 +5351,11 @@ void AppDomain::PublishHostedAssembly( } CONTRACTL_END - if (pDomainAssembly->GetFile()->HasHostAssembly()) + if (pDomainAssembly->GetPEAssembly()->HasHostAssembly()) { // We have to serialize all Add operations CrstHolder lockAdd(&m_crstHostAssemblyMapAdd); - _ASSERTE(m_hostAssemblyMap.Lookup(pDomainAssembly->GetFile()->GetHostAssembly()) == nullptr); + _ASSERTE(m_hostAssemblyMap.Lookup(pDomainAssembly->GetPEAssembly()->GetHostAssembly()) == nullptr); // Wrapper for m_hostAssemblyMap.Add that avoids call out into host HostAssemblyMap::AddPhases addCall; @@ -5401,75 +5380,6 @@ void AppDomain::PublishHostedAssembly( } } -//--------------------------------------------------------------------------------------------------------------------- -void AppDomain::UpdatePublishHostedAssembly( - DomainAssembly * pAssembly, - PTR_PEFile pFile) -{ - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - MODE_ANY; - CAN_TAKE_LOCK; - } - CONTRACTL_END - - if (pAssembly->GetFile()->HasHostAssembly()) - { - // We have to serialize all Add operations - CrstHolder lockAdd(&m_crstHostAssemblyMapAdd); - { - // Wrapper for m_hostAssemblyMap.Add that avoids call out into host - OriginalFileHostAssemblyMap::AddPhases addCall; - bool fAddOrigFile = false; - - // For cases where the pefile is being updated - // 1. Preallocate one element - if (pFile != pAssembly->GetFile()) - { - addCall.PreallocateForAdd(&m_hostAssemblyMapForOrigFile); - fAddOrigFile = true; - } - - { - // We cannot call out into host from ForbidSuspend region (i.e. no allocations/deallocations) - ForbidSuspendThreadHolder suspend; - { - CrstHolder lock(&m_crstHostAssemblyMap); - - // Remove from hash table. - _ASSERTE(m_hostAssemblyMap.Lookup(pAssembly->GetFile()->GetHostAssembly()) != nullptr); - m_hostAssemblyMap.Remove(pAssembly->GetFile()->GetHostAssembly()); - - // Update PEFile on DomainAssembly. (This may cause the key for the hash to change, which is why we need this function) - pAssembly->UpdatePEFileWorker(pFile); - - _ASSERTE(fAddOrigFile == (pAssembly->GetOriginalFile() != pAssembly->GetFile())); - if (fAddOrigFile) - { - // Add to the orig file hash table if we might be in a case where we've cached the original pefile and not the final pe file (for use during GetAssemblyIfLoaded) - addCall.Add(pAssembly); - } - - // Add back to the hashtable (the call to Remove above guarantees that we will not call into host for table reallocation) - _ASSERTE(m_hostAssemblyMap.Lookup(pAssembly->GetFile()->GetHostAssembly()) == nullptr); - m_hostAssemblyMap.Add(pAssembly); - } - } - - // 4. Cleanup the old memory (if any) - if (fAddOrigFile) - addCall.DeleteOldTable(); - } - } - else - { - - pAssembly->UpdatePEFileWorker(pFile); - } -} - //--------------------------------------------------------------------------------------------------------------------- void AppDomain::UnPublishHostedAssembly( DomainAssembly * pAssembly) @@ -5483,19 +5393,13 @@ void AppDomain::UnPublishHostedAssembly( } CONTRACTL_END - if (pAssembly->GetFile()->HasHostAssembly()) + if (pAssembly->GetPEAssembly()->HasHostAssembly()) { ForbidSuspendThreadHolder suspend; { CrstHolder lock(&m_crstHostAssemblyMap); - _ASSERTE(m_hostAssemblyMap.Lookup(pAssembly->GetFile()->GetHostAssembly()) != nullptr); - m_hostAssemblyMap.Remove(pAssembly->GetFile()->GetHostAssembly()); - - // We also have an entry in m_hostAssemblyMapForOrigFile. Handle that case. - if (pAssembly->GetOriginalFile() != pAssembly->GetFile()) - { - m_hostAssemblyMapForOrigFile.Remove(pAssembly->GetOriginalFile()->GetHostAssembly()); - } + _ASSERTE(m_hostAssemblyMap.Lookup(pAssembly->GetPEAssembly()->GetHostAssembly()) != nullptr); + m_hostAssemblyMap.Remove(pAssembly->GetPEAssembly()->GetHostAssembly()); } } } @@ -5521,18 +5425,7 @@ PTR_DomainAssembly AppDomain::FindAssembly(PTR_BINDER_SPACE_Assembly pHostAssemb ForbidSuspendThreadHolder suspend; { CrstHolder lock(&m_crstHostAssemblyMap); - PTR_DomainAssembly returnValue = m_hostAssemblyMap.Lookup(pHostAssembly); - if (returnValue == NULL) - { - // If not found in the m_hostAssemblyMap, look in the m_hostAssemblyMapForOrigFile - // This is necessary as it may happen during in a second AppDomain that the PEFile - // first discovered in the AppDomain may not be used by the DomainFile, but the CLRPrivBinderFusion - // will in some cases find the pHostAssembly associated with this no longer used PEFile - // instead of the PEFile that was finally decided upon. - returnValue = m_hostAssemblyMapForOrigFile.Lookup(pHostAssembly); - } - - return returnValue; + return m_hostAssemblyMap.Lookup(pHostAssembly); } } } diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index d31dc9af6d8ab..27509c601e4cc 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -700,7 +700,7 @@ class PEFileListLock : public ListLock { public: #ifndef DACCESS_COMPILE - ListLockEntry *FindFileLock(PEFile *pFile) + ListLockEntry *FindFileLock(PEAssembly *pPEAssembly) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; @@ -714,7 +714,7 @@ class PEFileListLock : public ListLock pEntry != NULL; pEntry = pEntry->m_pNext) { - if (((PEFile *)pEntry->m_data)->Equals(pFile)) + if (((PEAssembly *)pEntry->m_data)->Equals(pPEAssembly)) { return pEntry; } @@ -777,7 +777,7 @@ class FileLoadLock : public ListLockEntry HRESULT m_cachedHR; public: - static FileLoadLock *Create(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile); + static FileLoadLock *Create(PEFileListLock *pLock, PEAssembly *pPEAssembly, DomainFile *pDomainFile); ~FileLoadLock(); DomainFile *GetDomainFile(); @@ -807,7 +807,7 @@ class FileLoadLock : public ListLockEntry private: - FileLoadLock(PEFileListLock *pLock, PEFile *pFile, DomainFile *pDomainFile); + FileLoadLock(PEFileListLock *pLock, PEAssembly *pPEAssembly, DomainFile *pDomainFile); static void HolderLeave(FileLoadLock *pThis); @@ -1812,11 +1812,11 @@ class AppDomain : public BaseDomain FindAssemblyOptions_IncludeFailedToLoad = 0x1 }; - DomainAssembly * FindAssembly(PEAssembly * pFile, FindAssemblyOptions options = FindAssemblyOptions_None) DAC_EMPTY_RET(NULL); + DomainAssembly * FindAssembly(PEAssembly* pPEAssembly, FindAssemblyOptions options = FindAssemblyOptions_None) DAC_EMPTY_RET(NULL); Assembly *LoadAssembly(AssemblySpec* pIdentity, - PEAssembly *pFile, + PEAssembly *pPEAssembly, FileLoadLevel targetLevel); // this function does not provide caching, you must use LoadDomainAssembly @@ -1826,11 +1826,11 @@ class AppDomain : public BaseDomain // resulting in multiple DomainAssembly objects that share the same PEAssembly for ngen image //which is violating our internal assumptions DomainAssembly *LoadDomainAssemblyInternal( AssemblySpec* pIdentity, - PEAssembly *pFile, + PEAssembly *pPEAssembly, FileLoadLevel targetLevel); DomainAssembly *LoadDomainAssembly( AssemblySpec* pIdentity, - PEAssembly *pFile, + PEAssembly *pPEAssembly, FileLoadLevel targetLevel); @@ -1859,8 +1859,8 @@ class AppDomain : public BaseDomain BOOL IsCached(AssemblySpec *pSpec); #endif // DACCESS_COMPILE - BOOL AddFileToCache(AssemblySpec* pSpec, PEAssembly *pFile, BOOL fAllowFailure = FALSE); - BOOL RemoveFileFromCache(PEAssembly *pFile); + BOOL AddFileToCache(AssemblySpec* pSpec, PEAssembly *pPEAssembly, BOOL fAllowFailure = FALSE); + BOOL RemoveFileFromCache(PEAssembly *pPEAssembly); BOOL AddAssemblyToCache(AssemblySpec* pSpec, DomainAssembly *pAssembly); BOOL RemoveAssemblyFromCache(DomainAssembly* pAssembly); @@ -1974,7 +1974,7 @@ class AppDomain : public BaseDomain return m_tpIndex; } - DefaultAssemblyBinder *CreateBinderContext(); + DefaultAssemblyBinder *CreateDefaultBinder(); void SetIgnoreUnhandledExceptions() { @@ -2364,7 +2364,7 @@ class AppDomain : public BaseDomain //----------------------------------------------------------- // Static BINDER_SPACE::Assembly -> DomainAssembly mapping functions. // This map does not maintain a reference count to either key or value. - // PEFile maintains a reference count on the BINDER_SPACE::Assembly through its code:PEFile::m_pHostAssembly field. + // PEAssembly maintains a reference count on the BINDER_SPACE::Assembly through its code:PEAssembly::m_pHostAssembly field. // It is removed from this hash table by code:DomainAssembly::~DomainAssembly. struct HostAssemblyHashTraits : public DefaultSHashTraits { @@ -2374,7 +2374,7 @@ class AppDomain : public BaseDomain static key_t GetKey(element_t const & elem) { STATIC_CONTRACT_WRAPPER; - return elem->GetFile()->GetHostAssembly(); + return elem->GetPEAssembly()->GetHostAssembly(); } static BOOL Equals(key_t key1, key_t key2) @@ -2396,20 +2396,8 @@ class AppDomain : public BaseDomain static bool IsDeleted(const element_t & e) { return dac_cast(e) == (TADDR)-1; } }; - struct OriginalFileHostAssemblyHashTraits : public HostAssemblyHashTraits - { - public: - static key_t GetKey(element_t const & elem) - { - STATIC_CONTRACT_WRAPPER; - return elem->GetOriginalFile()->GetHostAssembly(); - } - }; - typedef SHash HostAssemblyMap; - typedef SHash OriginalFileHostAssemblyMap; HostAssemblyMap m_hostAssemblyMap; - OriginalFileHostAssemblyMap m_hostAssemblyMapForOrigFile; CrstExplicitInit m_crstHostAssemblyMap; // Lock to serialize all Add operations (in addition to the "read-lock" above) CrstExplicitInit m_crstHostAssemblyMapAdd; @@ -2427,11 +2415,6 @@ class AppDomain : public BaseDomain void PublishHostedAssembly( DomainAssembly* pAssembly); - // Called from DomainAssembly::UpdatePEFile. - void UpdatePublishHostedAssembly( - DomainAssembly* pAssembly, - PTR_PEFile pFile); - // Called from DomainAssembly::~DomainAssembly void UnPublishHostedAssembly( DomainAssembly* pAssembly); @@ -2512,12 +2495,12 @@ class SystemDomain : public BaseDomain return m_pSystemDomain; } - static PEAssembly* SystemFile() + static PEAssembly* SystemPEAssembly() { WRAPPER_NO_CONTRACT; _ASSERTE(m_pSystemDomain); - return System()->m_pSystemFile; + return System()->m_pSystemPEAssembly; } static Assembly* SystemAssembly() @@ -2708,7 +2691,7 @@ class SystemDomain : public BaseDomain } #endif - PTR_PEAssembly m_pSystemFile; // Single assembly (here for quicker reference); + PTR_PEAssembly m_pSystemPEAssembly;// Single assembly (here for quicker reference); PTR_Assembly m_pSystemAssembly; // Single assembly (here for quicker reference); GlobalLoaderAllocator m_GlobalAllocator; diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index c0fe297fc1ecc..754cf91696ff7 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -62,9 +62,56 @@ #ifndef DACCESS_COMPILE volatile uint32_t g_cAssemblies = 0; - static CrstStatic g_friendAssembliesCrst; +namespace +{ + void DefineEmitScope(GUID iid, void** ppEmit) + { + CONTRACT_VOID + { + PRECONDITION(CheckPointer(ppEmit)); + POSTCONDITION(CheckPointer(*ppEmit)); + THROWS; + GC_TRIGGERS; + MODE_ANY; + INJECT_FAULT(COMPlusThrowOM();); + } + CONTRACT_END; + + SafeComHolder pDispenser; + + // Get the Dispenser interface. + MetaDataGetDispenser( + CLSID_CorMetaDataDispenser, + IID_IMetaDataDispenserEx, + (void**)&pDispenser); + if (pDispenser == NULL) + { + ThrowOutOfMemory(); + } + + // Set the option on the dispenser turn on duplicate check for TypeDef and moduleRef + VARIANT varOption; + V_VT(&varOption) = VT_UI4; + V_I4(&varOption) = MDDupDefault | MDDupTypeDef | MDDupModuleRef | MDDupExportedType | MDDupAssemblyRef | MDDupPermission | MDDupFile; + IfFailThrow(pDispenser->SetOption(MetaDataCheckDuplicatesFor, &varOption)); + + // Set minimal MetaData size + V_VT(&varOption) = VT_UI4; + V_I4(&varOption) = MDInitialSizeMinimal; + IfFailThrow(pDispenser->SetOption(MetaDataInitialSize, &varOption)); + + // turn on the thread safety! + V_I4(&varOption) = MDThreadSafetyOn; + IfFailThrow(pDispenser->SetOption(MetaDataThreadSafetyOptions, &varOption)); + + IfFailThrow(pDispenser->DefineScope(CLSID_CorMetaDataRuntime, 0, iid, (IUnknown**)ppEmit)); + + RETURN; + } +} + void Assembly::Initialize() { g_friendAssembliesCrst.Init(CrstLeafLock); @@ -75,12 +122,12 @@ void Assembly::Initialize() // It cannot do any allocations or operations that might fail. Those operations should be done // in Assembly::Init() //---------------------------------------------------------------------------------------------- -Assembly::Assembly(BaseDomain *pDomain, PEAssembly* pFile, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible) : +Assembly::Assembly(BaseDomain *pDomain, PEAssembly* pPEAssembly, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible) : m_pDomain(pDomain), m_pClassLoader(NULL), m_pEntryPoint(NULL), m_pManifest(NULL), - m_pManifestFile(clr::SafeAddRef(pFile)), + m_pManifestFile(clr::SafeAddRef(pPEAssembly)), m_pFriendAssemblyDescriptor(NULL), m_isDynamic(false), #ifdef FEATURE_COLLECTIBLE_TYPES @@ -164,7 +211,7 @@ void Assembly::Init(AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocat if (IsCollectible()) { COUNT_T size; - BYTE *start = (BYTE*)m_pManifest->GetFile()->GetLoadedImageContents(&size); + BYTE *start = (BYTE*)m_pManifest->GetPEAssembly()->GetLoadedImageContents(&size); if (start != NULL) { GCX_COOP(); @@ -381,14 +428,14 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C // Set up the assembly manifest metadata // When we create dynamic assembly, we always use a working copy of IMetaDataAssemblyEmit // to store temporary runtime assembly information. This is to preserve the invariant that - // an assembly must have a PEFile with proper metadata. + // an assembly must have a PEAssembly with proper metadata. // This working copy of IMetaDataAssemblyEmit will store every AssemblyRef as a simple name // reference as we must have an instance of Assembly(can be dynamic assembly) before we can // add such a reference. Also because the referenced assembly if dynamic strong name, it may // not be ready to be hashed! SafeComHolder pAssemblyEmit; - PEFile::DefineEmitScope( + DefineEmitScope( IID_IMetaDataAssemblyEmit, &pAssemblyEmit); @@ -453,7 +500,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C DWORD dwFlags = args->assemblyName->GetFlags(); // Now create a dynamic PE file out of the name & metadata - PEAssemblyHolder pFile; + PEAssemblyHolder pPEAssembly; { GCX_PREEMP(); @@ -462,7 +509,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C IfFailThrow(pAssemblyEmit->DefineAssembly(publicKey, publicKey.GetSize(), ulHashAlgId, name, &assemData, dwFlags, &ma)); - pFile = PEAssembly::Create(pCallerAssembly->GetManifestFile(), pAssemblyEmit); + pPEAssembly = PEAssembly::Create(pCallerAssembly->GetManifestFile(), pAssemblyEmit); AssemblyBinder* pFallbackBinder = pBinder; @@ -477,7 +524,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C // and will have a fallback load context binder associated with it. // There is always a manifest file - wehther working with static or dynamic assemblies. - PEFile* pCallerAssemblyManifestFile = pCallerAssembly->GetManifestFile(); + PEAssembly* pCallerAssemblyManifestFile = pCallerAssembly->GetManifestFile(); _ASSERTE(pCallerAssemblyManifestFile != NULL); if (!pCallerAssemblyManifestFile->IsDynamic()) @@ -503,7 +550,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C _ASSERTE(pFallbackBinder != nullptr); // Set it as the fallback load context binder for the dynamic assembly being created - pFile->SetFallbackBinder(pFallbackBinder); + pPEAssembly->SetFallbackBinder(pFallbackBinder); } NewHolder pDomainAssembly; @@ -551,7 +598,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C } // Create a domain assembly - pDomainAssembly = new DomainAssembly(pDomain, pFile, pLoaderAllocator); + pDomainAssembly = new DomainAssembly(pDomain, pPEAssembly, pLoaderAllocator); if (pDomainAssembly->IsCollectible()) { // We add the assembly to the LoaderAllocator only when we are sure that it can be added @@ -569,7 +616,7 @@ Assembly *Assembly::CreateDynamic(AppDomain *pDomain, AssemblyBinder* pBinder, C { GCX_PREEMP(); // Assembly::Create will call SuppressRelease on the NewHolder that holds the LoaderAllocator when it transfers ownership - pAssem = Assembly::Create(pDomain, pFile, pDomainAssembly->GetDebuggerInfoBits(), pLoaderAllocator->IsCollectible(), pamTracker, pLoaderAllocator); + pAssem = Assembly::Create(pDomain, pPEAssembly, pDomainAssembly->GetDebuggerInfoBits(), pLoaderAllocator->IsCollectible(), pamTracker, pLoaderAllocator); ReflectionModule* pModule = (ReflectionModule*) pAssem->GetManifestModule(); pModule->SetCreatingAssembly( pCallerAssembly ); @@ -817,7 +864,7 @@ Module *Assembly::FindModuleByExportedType(mdExportedType mdType, // Note that we don't want to attempt a LoadModule if a GetModuleIfLoaded will // succeed, because it has a stronger contract. - Module *pModule = GetManifestModule()->GetModuleIfLoaded(mdLinkRef, TRUE, FALSE); + Module *pModule = GetManifestModule()->GetModuleIfLoaded(mdLinkRef); #ifdef DACCESS_COMPILE return pModule; #else @@ -830,7 +877,11 @@ Module *Assembly::FindModuleByExportedType(mdExportedType mdType, // We should never get here in the GC case - the above should have succeeded. CONSISTENCY_CHECK(!FORBIDGC_LOADER_USE_ENABLED()); - DomainFile * pDomainModule = GetManifestModule()->LoadModule(::GetAppDomain(), mdLinkRef, FALSE, loadFlag!=Loader::Load); + DomainFile* pDomainModule = NULL; + if (loadFlag == Loader::Load) + { + pDomainModule = GetManifestModule()->LoadModule(::GetAppDomain(), mdLinkRef); + } if (pDomainModule == NULL) RETURN NULL; @@ -953,18 +1004,18 @@ Module * Assembly::FindModuleByTypeRef( // Either we're not supposed to load, or we're doing a GC or stackwalk // in which case we shouldn't need to load. So just look up the module // and return what we find. - RETURN(pModule->LookupModule(tkType,FALSE)); + RETURN(pModule->LookupModule(tkType)); } #ifndef DACCESS_COMPILE - DomainFile * pActualDomainFile = pModule->LoadModule(::GetAppDomain(), tkType, FALSE, loadFlag!=Loader::Load); - if (pActualDomainFile == NULL) + if (loadFlag == Loader::Load) { - RETURN NULL; + DomainFile* pActualDomainFile = pModule->LoadModule(::GetAppDomain(), tkType); + RETURN(pActualDomainFile->GetModule()); } else { - RETURN(pActualDomainFile->GetModule()); + RETURN NULL; } #else //DACCESS_COMPILE @@ -1056,7 +1107,7 @@ Module *Assembly::FindModuleByName(LPCSTR pszModuleName) ThrowHR(COR_E_UNAUTHORIZEDACCESS); if (this == SystemDomain::SystemAssembly()) - RETURN m_pManifest->GetModuleIfLoaded(kFile, TRUE, TRUE); + RETURN m_pManifest->GetModuleIfLoaded(kFile); else RETURN m_pManifest->LoadModule(::GetAppDomain(), kFile)->GetModule(); } @@ -1124,7 +1175,7 @@ void Assembly::PrepareModuleForAssembly(Module* module, AllocMemTracker *pamTrac module->SetDebuggerInfoBits(GetDebuggerInfoBits()); LOG((LF_CORDB, LL_INFO10, "Module %s: bits=0x%x\n", - module->GetFile()->GetSimpleName(), + module->GetPEAssembly()->GetSimpleName(), module->GetDebuggerInfoBits())); #endif // DEBUGGING_SUPPORTED @@ -1648,7 +1699,7 @@ MethodDesc* Assembly::GetEntryPoint() Module *pModule = NULL; switch(TypeFromToken(mdEntry)) { case mdtFile: - pModule = m_pManifest->LoadModule(::GetAppDomain(), mdEntry, FALSE)->GetModule(); + pModule = m_pManifest->LoadModule(::GetAppDomain(), mdEntry)->GetModule(); mdEntry = pModule->GetEntryPointToken(); if ( (TypeFromToken(mdEntry) != mdtMethodDef) || @@ -1657,7 +1708,7 @@ MethodDesc* Assembly::GetEntryPoint() break; case mdtMethodDef: - if (m_pManifestFile->GetPersistentMDImport()->IsValidToken(mdEntry)) + if (m_pManifestFile->GetMDImport()->IsValidToken(mdEntry)) pModule = m_pManifest; break; } @@ -2240,7 +2291,7 @@ ReleaseHolder FriendAssemblyDescriptor::CreateFriendAs ReleaseHolder pFriendAssemblies = new FriendAssemblyDescriptor; // We're going to do this twice, once for InternalsVisibleTo and once for IgnoresAccessChecks - ReleaseHolder pImport(pAssembly->GetMDImportWithRef()); + IMDInternalImport* pImport = pAssembly->GetMDImport(); for(int count = 0 ; count < 2 ; ++count) { _ASSERTE(pImport != NULL); diff --git a/src/coreclr/vm/assembly.hpp b/src/coreclr/vm/assembly.hpp index db972f0ccf149..f8de5c162e752 100644 --- a/src/coreclr/vm/assembly.hpp +++ b/src/coreclr/vm/assembly.hpp @@ -79,13 +79,13 @@ class Assembly friend class ClrDataAccess; public: - Assembly(BaseDomain *pDomain, PEAssembly *pFile, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible); + Assembly(BaseDomain *pDomain, PEAssembly *pPEAssembly, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible); void Init(AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocator); void StartUnload(); void Terminate( BOOL signalProfiler = TRUE ); - static Assembly *Create(BaseDomain *pDomain, PEAssembly *pFile, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible, AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocator); + static Assembly *Create(BaseDomain *pDomain, PEAssembly *pPEAssembly, DebuggerAssemblyControlFlags debuggerFlags, BOOL fIsCollectible, AllocMemTracker *pamTracker, LoaderAllocator *pLoaderAllocator); static void Initialize(); BOOL IsSystem() { WRAPPER_NO_CONTRACT; return m_pManifestFile->IsSystem(); } @@ -299,7 +299,7 @@ class Assembly { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - return m_pManifestFile->GetPersistentMDImport(); + return m_pManifestFile->GetMDImport(); } HRESULT GetCustomAttribute(mdToken parentToken, @@ -312,14 +312,6 @@ class Assembly return GetManifestModule()->GetCustomAttribute(parentToken, attribute, ppData, pcbData); } -#ifndef DACCESS_COMPILE - IMetaDataAssemblyImport* GetManifestAssemblyImporter() - { - WRAPPER_NO_CONTRACT; - return m_pManifestFile->GetAssemblyImporter(); - } -#endif // DACCESS_COMPILE - mdAssembly GetManifestToken() { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/assemblybinder.cpp b/src/coreclr/vm/assemblybinder.cpp index 1ce6d2e93beb1..2e231741efbd3 100644 --- a/src/coreclr/vm/assemblybinder.cpp +++ b/src/coreclr/vm/assemblybinder.cpp @@ -32,7 +32,7 @@ NativeImage* AssemblyBinder::LoadNativeImage(Module* componentModule, LPCUTF8 na STANDARD_VM_CONTRACT; BaseDomain::LoadLockHolder lock(AppDomain::GetCurrentDomain()); - AssemblyBinder* binder = componentModule->GetFile()->GetAssemblyBinder(); + AssemblyBinder* binder = componentModule->GetPEAssembly()->GetAssemblyBinder(); PTR_LoaderAllocator moduleLoaderAllocator = componentModule->GetLoaderAllocator(); bool isNewNativeImage; diff --git a/src/coreclr/vm/assemblyname.cpp b/src/coreclr/vm/assemblyname.cpp index 0983c80715fae..c04a01408bbf8 100644 --- a/src/coreclr/vm/assemblyname.cpp +++ b/src/coreclr/vm/assemblyname.cpp @@ -56,7 +56,7 @@ FCIMPL1(Object*, AssemblyNameNative::GetFileInformation, StringObject* filenameU // waiting for it to happen during HasNTHeaders. This allows us to // get the assembly name for images that contain native code for a // non-native platform. - PEImageLayoutHolder pLayout(pImage->GetLayout(PEImageLayout::LAYOUT_FLAT, PEImage::LAYOUT_CREATEIFNEEDED)); + PEImageLayout* pLayout = pImage->GetOrCreateLayout(PEImageLayout::LAYOUT_FLAT); pImage->VerifyIsAssembly(); diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 37d27fb1a9c25..a67c9e5c4c0b6 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -108,7 +108,7 @@ void QCALLTYPE AssemblyNative::InternalLoad(QCall::ObjectHandleOnStack assemblyN { // If the requesting assembly has Fallback LoadContext binder available, // then set it up in the AssemblySpec. - PEFile *pRefAssemblyManifestFile = pRefAssembly->GetManifestFile(); + PEAssembly *pRefAssemblyManifestFile = pRefAssembly->GetManifestFile(); spec.SetFallbackBinderForRequestingAssembly(pRefAssemblyManifestFile->GetFallbackBinder()); } @@ -157,7 +157,7 @@ Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pIma // Set the caller's assembly to be CoreLib DomainAssembly *pCallersAssembly = SystemDomain::System()->SystemAssembly()->GetDomainAssembly(); - PEAssembly *pParentAssembly = pCallersAssembly->GetFile(); + PEAssembly *pParentAssembly = pCallersAssembly->GetPEAssembly(); // Initialize the AssemblySpec AssemblySpec spec; @@ -289,7 +289,7 @@ void QCALLTYPE AssemblyNative::LoadFromStream(INT_PTR ptrNativeAssemblyBinder, I // we created above. We need pointer comparison instead of pe image equivalence // to avoid mixed binaries/PDB pairs of other images. // This applies to both Desktop CLR and CoreCLR, with or without fusion. - BOOL fIsSameAssembly = (pLoadedAssembly->GetManifestFile()->GetILimage() == pILImage); + BOOL fIsSameAssembly = (pLoadedAssembly->GetManifestFile()->GetPEImage() == pILImage); // Setting the PDB info is only applicable for our original assembly. // This applies to both Desktop CLR and CoreCLR, with or without fusion. @@ -351,7 +351,7 @@ void QCALLTYPE AssemblyNative::GetLocation(QCall::AssemblyHandle pAssembly, QCal BEGIN_QCALL; { - retString.Set(pAssembly->GetFile()->GetPath()); + retString.Set(pAssembly->GetPEAssembly()->GetPath()); } END_QCALL; @@ -449,7 +449,7 @@ FCIMPL1(FC_BOOL_RET, AssemblyNative::IsDynamic, AssemblyBaseObject* pAssemblyUNS if (refAssembly == NULL) FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); - FC_RETURN_BOOL(refAssembly->GetDomainAssembly()->GetFile()->IsDynamic()); + FC_RETURN_BOOL(refAssembly->GetDomainAssembly()->GetPEAssembly()->IsDynamic()); } FCIMPLEND @@ -461,7 +461,7 @@ void QCALLTYPE AssemblyNative::GetVersion(QCall::AssemblyHandle pAssembly, INT32 UINT16 major=0xffff, minor=0xffff, build=0xffff, revision=0xffff; - pAssembly->GetFile()->GetVersion(&major, &minor, &build, &revision); + pAssembly->GetPEAssembly()->GetVersion(&major, &minor, &build, &revision); *pMajorVersion = major; *pMinorVersion = minor; @@ -478,7 +478,7 @@ void QCALLTYPE AssemblyNative::GetPublicKey(QCall::AssemblyHandle pAssembly, QCa BEGIN_QCALL; DWORD cbPublicKey = 0; - const void *pbPublicKey = pAssembly->GetFile()->GetPublicKey(&cbPublicKey); + const void *pbPublicKey = pAssembly->GetPEAssembly()->GetPublicKey(&cbPublicKey); retPublicKey.SetByteArray((BYTE *)pbPublicKey, cbPublicKey); END_QCALL; @@ -499,7 +499,7 @@ void QCALLTYPE AssemblyNative::GetLocale(QCall::AssemblyHandle pAssembly, QCall: BEGIN_QCALL; - LPCUTF8 pLocale = pAssembly->GetFile()->GetLocale(); + LPCUTF8 pLocale = pAssembly->GetPEAssembly()->GetLocale(); if(pLocale) { retString.Set(pLocale); @@ -519,7 +519,7 @@ BOOL QCALLTYPE AssemblyNative::GetCodeBase(QCall::AssemblyHandle pAssembly, QCal StackSString codebase; { - ret = pAssembly->GetFile()->GetCodeBase(codebase); + ret = pAssembly->GetPEAssembly()->GetCodeBase(codebase); } retString.Set(codebase); @@ -534,7 +534,7 @@ INT32 QCALLTYPE AssemblyNative::GetHashAlgorithm(QCall::AssemblyHandle pAssembly INT32 retVal=0; BEGIN_QCALL; - retVal = pAssembly->GetFile()->GetHashAlgId(); + retVal = pAssembly->GetPEAssembly()->GetHashAlgId(); END_QCALL; return retVal; } @@ -545,7 +545,7 @@ INT32 QCALLTYPE AssemblyNative::GetFlags(QCall::AssemblyHandle pAssembly) INT32 retVal=0; BEGIN_QCALL; - retVal = pAssembly->GetFile()->GetFlags(); + retVal = pAssembly->GetPEAssembly()->GetFlags(); END_QCALL; return retVal; } @@ -639,9 +639,9 @@ void QCALLTYPE AssemblyNative::GetModules(QCall::AssemblyHandle pAssembly, BOOL mdFile mdFile; while (pAssembly->GetMDImport()->EnumNext(&phEnum, &mdFile)) { - DomainFile *pModule = pAssembly->GetModule()->LoadModule(GetAppDomain(), mdFile, fGetResourceModules, !fLoadIfNotFound); - - if (pModule) { + if (fLoadIfNotFound) + { + DomainFile* pModule = pAssembly->GetModule()->LoadModule(GetAppDomain(), mdFile); modules.Append(pModule); } } @@ -1065,7 +1065,7 @@ void QCALLTYPE AssemblyNative::GetFullName(QCall::AssemblyHandle pAssembly, QCal BEGIN_QCALL; StackSString name; - pAssembly->GetFile()->GetDisplayName(name); + pAssembly->GetPEAssembly()->GetDisplayName(name); retString.Set(name); END_QCALL; @@ -1135,12 +1135,12 @@ void QCALLTYPE AssemblyNative::GetImageRuntimeVersion(QCall::AssemblyHandle pAss BEGIN_QCALL; - // Retrieve the PEFile from the assembly. - PEFile* pPEFile = pAssembly->GetFile(); - PREFIX_ASSUME(pPEFile!=NULL); + // Retrieve the PEAssembly from the assembly. + PEAssembly* pPEAssembly = pAssembly->GetPEAssembly(); + PREFIX_ASSUME(pPEAssembly!=NULL); LPCSTR pszVersion = NULL; - IfFailThrow(pPEFile->GetMDImport()->GetVersionString(&pszVersion)); + IfFailThrow(pPEAssembly->GetMDImport()->GetVersionString(&pszVersion)); SString version(SString::Utf8, pszVersion); @@ -1253,7 +1253,7 @@ INT_PTR QCALLTYPE AssemblyNative::GetLoadContextForAssembly(QCall::AssemblyHandl _ASSERTE(pAssembly != NULL); - AssemblyBinder* pAssemblyBinder = pAssembly->GetFile()->GetAssemblyBinder(); + AssemblyBinder* pAssemblyBinder = pAssembly->GetPEAssembly()->GetAssemblyBinder(); if (!pAssemblyBinder->IsDefault()) { @@ -1284,7 +1284,7 @@ BOOL QCALLTYPE AssemblyNative::InternalTryGetRawMetadata( _ASSERTE(lengthRef != nullptr); static_assert_no_msg(sizeof(*lengthRef) == sizeof(COUNT_T)); - metadata = assembly->GetFile()->GetLoadedMetadata(reinterpret_cast(lengthRef)); + metadata = assembly->GetPEAssembly()->GetLoadedMetadata(reinterpret_cast(lengthRef)); *blobRef = reinterpret_cast(const_cast(metadata)); _ASSERTE(*lengthRef >= 0); diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index a4ecc62da9a32..6270e5072612e 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -108,7 +108,7 @@ class AssemblyNative static FCDECL0(uint32_t, GetAssemblyCount); // - // PEFile QCalls + // PEAssembly QCalls // static INT_PTR QCALLTYPE InitializeAssemblyLoadContext(INT_PTR ptrManagedAssemblyLoadContext, BOOL fRepresentsTPALoadContext, BOOL fIsCollectible); diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index af5862a9ac5ff..dfbee7152df19 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -231,7 +231,7 @@ void AssemblySpec::InitializeSpec(PEAssembly * pFile) INJECT_FAULT(COMPlusThrowOM();); } CONTRACTL_END; - ReleaseHolder pImport(pFile->GetMDImportWithRef()); + IMDInternalImport* pImport = pFile->GetMDImport(); mdAssembly a; IfFailThrow(pImport->GetAssemblyFromScope(&a)); @@ -690,7 +690,7 @@ AssemblyBinder* AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) if(pParentDomainAssembly != NULL) { // Get the PEAssembly associated with the parent's domain assembly - PEAssembly *pParentPEAssembly = pParentDomainAssembly->GetFile(); + PEAssembly *pParentPEAssembly = pParentDomainAssembly->GetPEAssembly(); pParentAssemblyBinder = pParentPEAssembly->GetAssemblyBinder(); } @@ -754,7 +754,7 @@ DomainAssembly *AssemblySpec::LoadDomainAssembly(FileLoadLevel targetLevel, if (pAssembly) { BinderTracing::AssemblyBindOperation bindOperation(this); - bindOperation.SetResult(pAssembly->GetFile(), true /*cached*/); + bindOperation.SetResult(pAssembly->GetPEAssembly(), true /*cached*/); pDomain->LoadDomainFile(pAssembly, targetLevel); RETURN pAssembly; @@ -1219,7 +1219,7 @@ BOOL AssemblySpecBindingCache::StoreAssembly(AssemblySpec *pSpec, DomainAssembly UPTR key = (UPTR)pSpec->Hash(); - AssemblyBinder* pBinderContextForLookup = pAssembly->GetFile()->GetAssemblyBinder(); + AssemblyBinder* pBinderContextForLookup = pAssembly->GetPEAssembly()->GetAssemblyBinder(); key = key ^ (UPTR)pBinderContextForLookup; if (!pSpec->GetBinder()) @@ -1240,13 +1240,13 @@ BOOL AssemblySpecBindingCache::StoreAssembly(AssemblySpec *pSpec, DomainAssembly } entry = abHolder.CreateAssemblyBinding(pHeap); - entry->Init(pSpec,pAssembly->GetFile(),pAssembly,NULL,pHeap, abHolder.GetPamTracker()); + entry->Init(pSpec,pAssembly->GetPEAssembly(),pAssembly,NULL,pHeap, abHolder.GetPamTracker()); m_map.InsertValue(key, entry); abHolder.SuppressRelease(); - STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StoreFile (StoreAssembly): Add cached entry (%p) with PEFile %p",entry,pAssembly->GetFile()); + STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly (StoreAssembly): Add cached entry (%p) with PEAssembly %p",entry,pAssembly->GetPEAssembly()); RETURN TRUE; } else @@ -1263,7 +1263,7 @@ BOOL AssemblySpecBindingCache::StoreAssembly(AssemblySpec *pSpec, DomainAssembly { // OK if we have have a matching PEAssembly if (entry->GetFile() != NULL - && pAssembly->GetFile()->Equals(entry->GetFile())) + && pAssembly->GetPEAssembly()->Equals(entry->GetFile())) { entry->SetAssembly(pAssembly); RETURN TRUE; @@ -1280,7 +1280,7 @@ BOOL AssemblySpecBindingCache::StoreAssembly(AssemblySpec *pSpec, DomainAssembly // Returns TRUE if add was successful - if FALSE is returned, caller should honor current // cached value to ensure consistency. -BOOL AssemblySpecBindingCache::StoreFile(AssemblySpec *pSpec, PEAssembly *pFile) +BOOL AssemblySpecBindingCache::StorePEAssembly(AssemblySpec *pSpec, PEAssembly *pPEAssembly) { CONTRACT(BOOL) { @@ -1288,14 +1288,14 @@ BOOL AssemblySpecBindingCache::StoreFile(AssemblySpec *pSpec, PEAssembly *pFile) THROWS; GC_TRIGGERS; MODE_ANY; - POSTCONDITION((!RETVAL) || (UnsafeContains(this, pSpec) && UnsafeVerifyLookupFile(this, pSpec, pFile))); + POSTCONDITION((!RETVAL) || (UnsafeContains(this, pSpec) && UnsafeVerifyLookupFile(this, pSpec, pPEAssembly))); INJECT_FAULT(COMPlusThrowOM();); } CONTRACT_END; UPTR key = (UPTR)pSpec->Hash(); - AssemblyBinder* pBinderContextForLookup = pFile->GetAssemblyBinder(); + AssemblyBinder* pBinderContextForLookup = pPEAssembly->GetAssemblyBinder(); key = key ^ (UPTR)pBinderContextForLookup; if (!pSpec->GetBinder()) @@ -1325,12 +1325,12 @@ BOOL AssemblySpecBindingCache::StoreFile(AssemblySpec *pSpec, PEAssembly *pFile) entry = abHolder.CreateAssemblyBinding(pHeap); - entry->Init(pSpec,pFile,NULL,NULL,pHeap, abHolder.GetPamTracker()); + entry->Init(pSpec, pPEAssembly,NULL,NULL,pHeap, abHolder.GetPamTracker()); m_map.InsertValue(key, entry); abHolder.SuppressRelease(); - STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StoreFile: Add cached entry (%p) with PEFile %p\n", entry, pFile); + STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly: Add cached entry (%p) with PEAssembly %p\n", entry, pPEAssembly); RETURN TRUE; } @@ -1340,7 +1340,7 @@ BOOL AssemblySpecBindingCache::StoreFile(AssemblySpec *pSpec, PEAssembly *pFile) { // OK if this is a duplicate if (entry->GetFile() != NULL - && pFile->Equals(entry->GetFile())) + && pPEAssembly->Equals(entry->GetFile())) RETURN TRUE; } else @@ -1350,7 +1350,7 @@ BOOL AssemblySpecBindingCache::StoreFile(AssemblySpec *pSpec, PEAssembly *pFile) entry->ThrowIfError(); } - STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"Incompatible cached entry found (%p) when adding PEFile %p\n", entry, pFile); + STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"Incompatible cached entry found (%p) when adding PEAssembly %p\n", entry, pPEAssembly); // Invalid cache transition (see above note about state transitions) RETURN FALSE; } @@ -1396,7 +1396,7 @@ BOOL AssemblySpecBindingCache::StoreException(AssemblySpec *pSpec, Exception* pE m_map.InsertValue(key, entry); abHolder.SuppressRelease(); - STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StoreFile (StoreException): Add cached entry (%p) with exception %p",entry,pEx); + STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly (StoreException): Add cached entry (%p) with exception %p",entry,pEx); RETURN TRUE; } else diff --git a/src/coreclr/vm/assemblyspec.hpp b/src/coreclr/vm/assemblyspec.hpp index 63ffac82f6e7a..5d09b5b75a664 100644 --- a/src/coreclr/vm/assemblyspec.hpp +++ b/src/coreclr/vm/assemblyspec.hpp @@ -102,7 +102,7 @@ class AssemblySpec : public BaseAssemblySpec }; - void InitializeSpec(PEAssembly *pFile); + void InitializeSpec(PEAssembly* pPEAssembly); HRESULT InitializeSpec(StackingAllocator* alloc, ASSEMBLYNAMEREF* pName, BOOL fParse = TRUE); @@ -332,8 +332,8 @@ class AssemblySpecBindingCache { WRAPPER_NO_CONTRACT; - if (m_pFile != NULL) - m_pFile->Release(); + if (m_pPEAssembly != NULL) + m_pPEAssembly->Release(); if (m_exceptionType==EXTYPE_EE) delete m_pException; @@ -341,7 +341,7 @@ class AssemblySpecBindingCache inline DomainAssembly* GetAssembly(){ LIMITED_METHOD_CONTRACT; return m_pAssembly;}; inline void SetAssembly(DomainAssembly* pAssembly){ LIMITED_METHOD_CONTRACT; m_pAssembly=pAssembly;}; - inline PEAssembly* GetFile(){ LIMITED_METHOD_CONTRACT; return m_pFile;}; + inline PEAssembly* GetFile(){ LIMITED_METHOD_CONTRACT; return m_pPEAssembly;}; inline BOOL IsError(){ LIMITED_METHOD_CONTRACT; return (m_exceptionType!=EXTYPE_NONE);}; // bound to the file, but failed later @@ -365,7 +365,7 @@ class AssemblySpecBindingCache default: _ASSERTE(!"Unexpected exception type"); } }; - inline void Init(AssemblySpec* pSpec, PEAssembly* pFile, DomainAssembly* pAssembly, Exception* pEx, LoaderHeap *pHeap, AllocMemTracker *pamTracker) + inline void Init(AssemblySpec* pSpec, PEAssembly* pPEAssembly, DomainAssembly* pAssembly, Exception* pEx, LoaderHeap *pHeap, AllocMemTracker *pamTracker) { CONTRACTL { @@ -375,7 +375,7 @@ class AssemblySpecBindingCache } CONTRACTL_END; - InitInternal(pSpec,pFile,pAssembly); + InitInternal(pSpec,pPEAssembly,pAssembly); if (pHeap != NULL) { m_spec.CloneFieldsToLoaderHeap(AssemblySpec::ALL_OWNED,pHeap, pamTracker); @@ -444,19 +444,19 @@ class AssemblySpecBindingCache }; protected: - inline void InitInternal(AssemblySpec* pSpec, PEAssembly* pFile, DomainAssembly* pAssembly ) + inline void InitInternal(AssemblySpec* pSpec, PEAssembly* pPEAssembly, DomainAssembly* pAssembly ) { WRAPPER_NO_CONTRACT; m_spec.CopyFrom(pSpec); - m_pFile = pFile; - if (m_pFile) - m_pFile->AddRef(); + m_pPEAssembly = pPEAssembly; + if (m_pPEAssembly) + m_pPEAssembly->AddRef(); m_pAssembly = pAssembly; m_exceptionType=EXTYPE_NONE; } AssemblySpec m_spec; - PEAssembly *m_pFile; + PEAssembly *m_pPEAssembly; DomainAssembly *m_pAssembly; enum{ EXTYPE_NONE = 0x00000000, @@ -490,7 +490,7 @@ class AssemblySpecBindingCache PEAssembly *LookupFile(AssemblySpec *pSpec, BOOL fThrow = TRUE); BOOL StoreAssembly(AssemblySpec *pSpec, DomainAssembly *pAssembly); - BOOL StoreFile(AssemblySpec *pSpec, PEAssembly *pFile); + BOOL StorePEAssembly(AssemblySpec *pSpec, PEAssembly *pPEAssembly); BOOL StoreException(AssemblySpec *pSpec, Exception* pEx); diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index 3ffb9a83b1511..02374e18df61c 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -214,7 +214,7 @@ void Module::UpdateNewlyAddedTypes() // R2R pre-computes an export table and tries to avoid populating a class hash at runtime. However the profiler can // still add new types on the fly by calling here. If that occurs we fallback to the slower path of creating the // in memory hashtable as usual. - if (!IsResource() && GetAvailableClassHash() == NULL) + if (GetAvailableClassHash() == NULL) { // This call will populate the hash tables with anything that is in metadata already. GetClassLoader()->LazyPopulateCaseSensitiveHashTablesDontHaveLock(); @@ -266,12 +266,9 @@ void Module::NotifyProfilerLoadFinished(HRESULT hr) if (SetTransientFlagInterlocked(IS_PROFILER_NOTIFIED)) { // Record how many types are already present - if (!IsResource()) - { - m_dwTypeCount = GetMDImport()->GetCountWithTokenKind(mdtTypeDef); - m_dwExportedTypeCount = GetMDImport()->GetCountWithTokenKind(mdtExportedType); - m_dwCustomAttributeCount = GetMDImport()->GetCountWithTokenKind(mdtCustomAttribute); - } + m_dwTypeCount = GetMDImport()->GetCountWithTokenKind(mdtTypeDef); + m_dwExportedTypeCount = GetMDImport()->GetCountWithTokenKind(mdtExportedType); + m_dwCustomAttributeCount = GetMDImport()->GetCountWithTokenKind(mdtCustomAttribute); BOOL profilerCallbackHappened = FALSE; // Notify the profiler, this may cause metadata to be updated @@ -294,7 +291,7 @@ void Module::NotifyProfilerLoadFinished(HRESULT hr) // If there are more types than before, add these new types to the // assembly - if (profilerCallbackHappened && !IsResource()) + if (profilerCallbackHappened) { UpdateNewlyAddedTypes(); } @@ -337,7 +334,7 @@ void Module::NotifyEtwLoadFinished(HRESULT hr) // The constructor phase initializes just enough so that Destruct() can be safely called. // It cannot throw or fail. // -Module::Module(Assembly *pAssembly, mdFile moduleRef, PEFile *file) +Module::Module(Assembly *pAssembly, mdFile moduleRef, PEAssembly *pPEAssembly) { CONTRACTL { @@ -351,13 +348,13 @@ Module::Module(Assembly *pAssembly, mdFile moduleRef, PEFile *file) m_pAssembly = pAssembly; m_moduleRef = moduleRef; - m_file = file; + m_pPEAssembly = pPEAssembly; m_dwTransientFlags = CLASSES_FREED; // Memory allocated on LoaderHeap is zero-filled. Spot-check it here. _ASSERTE(m_pBinder == NULL); - file->AddRef(); + pPEAssembly->AddRef(); } void Module::InitializeForProfiling() @@ -457,7 +454,7 @@ void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName) } CONTRACTL_END; - m_pSimpleName = m_file->GetSimpleName(); + m_pSimpleName = m_pPEAssembly->GetSimpleName(); m_Crst.Init(CrstModule); m_LookupTableCrst.Init(CrstModuleLookupTable, CrstFlags(CRST_UNSAFE_ANYMODE | CRST_DEBUGGER_THREAD)); @@ -486,62 +483,56 @@ void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName) #ifdef FEATURE_READYTORUN m_pNativeImage = NULL; - if (!IsResource()) + if ((m_pReadyToRunInfo = ReadyToRunInfo::Initialize(this, pamTracker)) != NULL) { - if ((m_pReadyToRunInfo = ReadyToRunInfo::Initialize(this, pamTracker)) != NULL) + m_pNativeImage = m_pReadyToRunInfo->GetNativeImage(); + if (m_pNativeImage != NULL) { - m_pNativeImage = m_pReadyToRunInfo->GetNativeImage(); - if (m_pNativeImage != NULL) - { - m_NativeMetadataAssemblyRefMap = m_pNativeImage->GetManifestMetadataAssemblyRefMap(); - } - else + m_NativeMetadataAssemblyRefMap = m_pNativeImage->GetManifestMetadataAssemblyRefMap(); + } + else + { + // For composite images, manifest metadata gets loaded as part of the native image + COUNT_T cMeta = 0; + if (GetPEAssembly()->GetPEImage()->GetNativeManifestMetadata(&cMeta) != NULL) { - // For composite images, manifest metadata gets loaded as part of the native image - COUNT_T cMeta = 0; - if (GetFile()->GetOpenedILimage()->GetNativeManifestMetadata(&cMeta) != NULL) - { - // Load the native assembly import - GetNativeAssemblyImport(TRUE /* loadAllowed */); - } + // Load the native assembly import + GetNativeAssemblyImport(TRUE /* loadAllowed */); } } } #endif - // Initialize the instance fields that we need for all non-Resource Modules - if (!IsResource()) + // Initialize the instance fields that we need for all Modules + if (m_pAvailableClasses == NULL && !IsReadyToRun()) { - if (m_pAvailableClasses == NULL && !IsReadyToRun()) - { - m_pAvailableClasses = EEClassHashTable::Create(this, - GetAssembly()->IsCollectible() ? AVAILABLE_CLASSES_HASH_BUCKETS_COLLECTIBLE : AVAILABLE_CLASSES_HASH_BUCKETS, - FALSE /* bCaseInsensitive */, pamTracker); - } + m_pAvailableClasses = EEClassHashTable::Create(this, + GetAssembly()->IsCollectible() ? AVAILABLE_CLASSES_HASH_BUCKETS_COLLECTIBLE : AVAILABLE_CLASSES_HASH_BUCKETS, + FALSE /* bCaseInsensitive */, pamTracker); + } - if (m_pAvailableParamTypes == NULL) - { - m_pAvailableParamTypes = EETypeHashTable::Create(GetLoaderAllocator(), this, PARAMTYPES_HASH_BUCKETS, pamTracker); - } + if (m_pAvailableParamTypes == NULL) + { + m_pAvailableParamTypes = EETypeHashTable::Create(GetLoaderAllocator(), this, PARAMTYPES_HASH_BUCKETS, pamTracker); + } - if (m_pInstMethodHashTable == NULL) + if (m_pInstMethodHashTable == NULL) + { + m_pInstMethodHashTable = InstMethodHashTable::Create(GetLoaderAllocator(), this, PARAMMETHODS_HASH_BUCKETS, pamTracker); + } + + if (m_pMemberRefToDescHashTable == NULL) + { + if (IsReflection()) { - m_pInstMethodHashTable = InstMethodHashTable::Create(GetLoaderAllocator(), this, PARAMMETHODS_HASH_BUCKETS, pamTracker); + m_pMemberRefToDescHashTable = MemberRefToDescHashTable::Create(this, MEMBERREF_MAP_INITIAL_SIZE, pamTracker); } - - if(m_pMemberRefToDescHashTable == NULL) + else { - if (IsReflection()) - { - m_pMemberRefToDescHashTable = MemberRefToDescHashTable::Create(this, MEMBERREF_MAP_INITIAL_SIZE, pamTracker); - } - else - { - IMDInternalImport * pImport = GetMDImport(); + IMDInternalImport* pImport = GetMDImport(); - // Get #MemberRefs and create memberrefToDesc hash table - m_pMemberRefToDescHashTable = MemberRefToDescHashTable::Create(this, pImport->GetCountWithTokenKind(mdtMemberRef)+1, pamTracker); - } + // Get #MemberRefs and create memberrefToDesc hash table + m_pMemberRefToDescHashTable = MemberRefToDescHashTable::Create(this, pImport->GetCountWithTokenKind(mdtMemberRef) + 1, pamTracker); } } @@ -563,7 +554,7 @@ void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName) InitializeForProfiling(); } - if (!IsResource() && (m_AssemblyRefByNameTable == NULL)) + if (m_AssemblyRefByNameTable == NULL) { Module::CreateAssemblyRefByNameTable(pamTracker); } @@ -744,16 +735,15 @@ void Module::SetDebuggerInfoBits(DebuggerAssemblyControlFlags newBits) #ifndef DACCESS_COMPILE /* static */ -Module *Module::Create(Assembly *pAssembly, mdFile moduleRef, PEFile *file, AllocMemTracker *pamTracker) +Module *Module::Create(Assembly *pAssembly, mdFile moduleRef, PEAssembly *pPEAssembly, AllocMemTracker *pamTracker) { CONTRACT(Module *) { STANDARD_VM_CHECK; PRECONDITION(CheckPointer(pAssembly)); - PRECONDITION(CheckPointer(file)); - PRECONDITION(!IsNilToken(moduleRef) || file->IsAssembly()); + PRECONDITION(CheckPointer(pPEAssembly)); POSTCONDITION(CheckPointer(RETVAL)); - POSTCONDITION(RETVAL->GetFile() == file); + POSTCONDITION(RETVAL->GetPEAssembly() == pPEAssembly); } CONTRACT_END; @@ -764,19 +754,19 @@ Module *Module::Create(Assembly *pAssembly, mdFile moduleRef, PEFile *file, Allo // Create the module #ifdef EnC_SUPPORTED - if (IsEditAndContinueCapable(pAssembly, file)) + if (IsEditAndContinueCapable(pAssembly, pPEAssembly)) { // if file is EnCCapable, always create an EnC-module, but EnC won't necessarily be enabled. // Debugger enables this by calling SetJITCompilerFlags on LoadModule callback. void* pMemory = pamTracker->Track(pAssembly->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(EditAndContinueModule)))); - pModule = new (pMemory) EditAndContinueModule(pAssembly, moduleRef, file); + pModule = new (pMemory) EditAndContinueModule(pAssembly, moduleRef, pPEAssembly); } else #endif // EnC_SUPPORTED { void* pMemory = pamTracker->Track(pAssembly->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(Module)))); - pModule = new (pMemory) Module(pAssembly, moduleRef, file); + pModule = new (pMemory) Module(pAssembly, moduleRef, pPEAssembly); } PREFIX_ASSUME(pModule != NULL); @@ -802,10 +792,7 @@ void Module::ApplyMetaData() ULONG ulCount; #if defined(PROFILING_SUPPORTED) || defined(EnC_SUPPORTED) - if (!IsResource()) - { - UpdateNewlyAddedTypes(); - } + UpdateNewlyAddedTypes(); #endif // PROFILING_SUPPORTED || EnC_SUPPORTED // Ensure for TypeRef @@ -953,7 +940,7 @@ void Module::Destruct() delete m_debuggerSpecificData.m_pILOffsetMappingTable; } - m_file->Release(); + m_pPEAssembly->Release(); // If this module was loaded as domain-specific, then // we must free its ModuleIndex so that it can be reused @@ -972,7 +959,7 @@ bool Module::NeedsGlobalMethodTable() CONTRACTL_END; IMDInternalImport * pImport = GetMDImport(); - if (!IsResource() && pImport->IsValidToken(COR_GLOBAL_PARENT_TOKEN)) + if (pImport->IsValidToken(COR_GLOBAL_PARENT_TOKEN)) { { HENUMInternalHolder funcEnum(pImport); @@ -1032,7 +1019,7 @@ MethodTable *Module::GetGlobalMethodTable() #endif // !DACCESS_COMPILE /*static*/ -BOOL Module::IsEditAndContinueCapable(Assembly *pAssembly, PEFile *file) +BOOL Module::IsEditAndContinueCapable(Assembly *pAssembly, PEAssembly *pPEAssembly) { CONTRACTL { @@ -1043,13 +1030,12 @@ BOOL Module::IsEditAndContinueCapable(Assembly *pAssembly, PEFile *file) } CONTRACTL_END; - _ASSERTE(pAssembly != NULL && file != NULL); + _ASSERTE(pAssembly != NULL && pPEAssembly != NULL); // Some modules are never EnC-capable return ! (pAssembly->GetDebuggerInfoBits() & DACF_ALLOW_JIT_OPTS || - file->IsSystem() || - file->IsResource() || - file->IsDynamic()); + pPEAssembly->IsSystem() || + pPEAssembly->IsDynamic()); } BOOL Module::IsManifest() @@ -1975,17 +1961,6 @@ void Module::AllocateStatics(AllocMemTracker *pamTracker) { STANDARD_VM_CONTRACT; - if (IsResource()) - { - m_dwRegularStaticsBlockSize = DomainLocalModule::OffsetOfDataBlob(); - m_dwThreadStaticsBlockSize = ThreadLocalModule::OffsetOfDataBlob(); - - // If it has no code, we don't have to allocate anything - LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Resource module %s. No statics needed\n", GetSimpleName())); - _ASSERTE(m_maxTypeRidStaticsAllocated == 0); - return; - } - LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Allocating statics for module %s\n", GetSimpleName())); // Build the offset table, which will tell us what the offsets for the statics of each class are (one offset for gc handles, one offset @@ -2114,9 +2089,6 @@ void Module::AllocateMaps() PTR_TADDR pTable = NULL; - if (IsResource()) - return; - if (IsReflection()) { // For dynamic modules, it is essential that we at least have a TypeDefToMethodTable @@ -2402,7 +2374,7 @@ BOOL Module::IsInSameVersionBubble(Module *target) { // Check if the current module's image has native manifest metadata, otherwise the current->GetNativeAssemblyImport() asserts. COUNT_T cMeta=0; - const void* pMeta = GetFile()->GetOpenedILimage()->GetNativeManifestMetadata(&cMeta); + const void* pMeta = GetPEAssembly()->GetPEImage()->GetNativeManifestMetadata(&cMeta); if (pMeta == NULL) { return FALSE; @@ -2529,10 +2501,6 @@ ISymUnmanagedReader *Module::GetISymUnmanagedReader(void) } CONTRACT_END; - // No symbols for resource modules - if (IsResource()) - RETURN NULL; - if (g_fEEShutDown) RETURN NULL; @@ -2565,16 +2533,15 @@ ISymUnmanagedReader *Module::GetISymUnmanagedReader(void) // There are 4 main cases here: // 1. Assembly is on disk and we'll get the symbols from a file next to the assembly - // 2. Assembly is provided by the host and we'll get the symbols from the host - // 3. Assembly was loaded in-memory (by byte array or ref-emit), and symbols were + // 2. Assembly was loaded in-memory (by byte array or ref-emit), and symbols were // provided along with it. - // 4. Assembly was loaded in-memory but no symbols were provided. + // 3. Assembly was loaded in-memory but no symbols were provided. - // Determine whether we should be looking in memory for the symbols (cases 2 & 3) - bool fInMemorySymbols = ( m_file->IsIStream() || GetInMemorySymbolStream() ); - if( !fInMemorySymbols && m_file->GetPath().IsEmpty() ) + // Determine whether we should be looking in memory for the symbols (case 2) + bool fInMemorySymbols = GetInMemorySymbolStream(); + if( !fInMemorySymbols && m_pPEAssembly->GetPath().IsEmpty() ) { - // Case 4. We don't have a module path, an IStream or an in memory symbol stream, + // Case 3. We don't have a module path or an in memory symbol stream, // so there is no-where to try and get symbols from. RETURN (NULL); } @@ -2657,7 +2624,7 @@ ISymUnmanagedReader *Module::GetISymUnmanagedReader(void) else { // The assembly is on disk, so try and load symbols based on the path to the assembly (case 1) - const SString &path = m_file->GetPath(); + const SString &path = m_pPEAssembly->GetPath(); // Call Fusion to ensure that any PDB's are shadow copied before // trying to get a symbol reader. This has to be done once per @@ -2856,7 +2823,6 @@ void Module::AddClass(mdTypeDef classdef) THROWS; GC_TRIGGERS; MODE_PREEMPTIVE; - PRECONDITION(!IsResource()); } CONTRACTL_END; @@ -2913,8 +2879,8 @@ void Module::BuildClassForModule() // Returns true iff the debugger should be notified about this module // // Notes: -// Debugger doesn't need to be notified about modules that can't be executed, -// like inspection and resource only. These are just pure data. +// Debugger doesn't need to be notified about modules that can't be executed. +// (we do not have such cases at the moment) // // This should be immutable for an instance of a module. That ensures that the debugger gets consistent // notifications about it. It this value mutates, than the debugger may miss relevant notifications. @@ -2923,11 +2889,6 @@ BOOL Module::IsVisibleToDebugger() WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - if (IsResource()) - { - return FALSE; - } - return TRUE; } @@ -2987,7 +2948,7 @@ TADDR Module::GetIL(DWORD target) if (target == 0) return NULL; - return m_file->GetIL(target); + return m_pPEAssembly->GetIL(target); } PTR_VOID Module::GetRvaField(DWORD rva) @@ -2995,7 +2956,7 @@ PTR_VOID Module::GetRvaField(DWORD rva) WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - return m_file->GetRvaField(rva); + return m_pPEAssembly->GetRvaField(rva); } #ifndef DACCESS_COMPILE @@ -3004,7 +2965,7 @@ CHECK Module::CheckRvaField(RVA field) { WRAPPER_NO_CONTRACT; if (!IsReflection()) - CHECK(m_file->CheckRvaField(field)); + CHECK(m_pPEAssembly->CheckRvaField(field)); CHECK_OK; } @@ -3018,7 +2979,7 @@ CHECK Module::CheckRvaField(RVA field, COUNT_T size) CONTRACTL_END; if (!IsReflection()) - CHECK(m_file->CheckRvaField(field, size)); + CHECK(m_pPEAssembly->CheckRvaField(field, size)); CHECK_OK; } @@ -3028,28 +2989,28 @@ BOOL Module::HasTls() { WRAPPER_NO_CONTRACT; - return m_file->HasTls(); + return m_pPEAssembly->HasTls(); } BOOL Module::IsRvaFieldTls(DWORD rva) { WRAPPER_NO_CONTRACT; - return m_file->IsRvaFieldTls(rva); + return m_pPEAssembly->IsRvaFieldTls(rva); } UINT32 Module::GetFieldTlsOffset(DWORD rva) { WRAPPER_NO_CONTRACT; - return m_file->GetFieldTlsOffset(rva); + return m_pPEAssembly->GetFieldTlsOffset(rva); } UINT32 Module::GetTlsIndex() { WRAPPER_NO_CONTRACT; - return m_file->GetTlsIndex(); + return m_pPEAssembly->GetTlsIndex(); } @@ -3077,7 +3038,7 @@ BOOL Module::IsSigInIL(PCCOR_SIGNATURE signature) } CONTRACTL_END; - return m_file->IsPtrInILImage(signature); + return m_pPEAssembly->IsPtrInPEImage(signature); } void Module::InitializeStringData(DWORD token, EEStringData *pstrData, CQuickBytes *pqb) @@ -3182,7 +3143,7 @@ mdToken Module::GetEntryPointToken() { WRAPPER_NO_CONTRACT; - return m_file->GetEntryPointToken(); + return m_pPEAssembly->GetEntryPointToken(); } BYTE *Module::GetProfilerBase() @@ -3195,13 +3156,13 @@ BYTE *Module::GetProfilerBase() } CONTRACT_END; - if (m_file == NULL) // I'd rather assert this is not the case... + if (m_pPEAssembly == NULL) // I'd rather assert this is not the case... { RETURN NULL; } - else if (m_file->IsLoaded()) + else if (m_pPEAssembly->HasLoadedPEImage()) { - RETURN (BYTE*)(m_file->GetLoadedIL()->GetBase()); + RETURN (BYTE*)(m_pPEAssembly->GetLoadedLayout()->GetBase()); } else { @@ -3413,20 +3374,18 @@ DomainAssembly * Module::LoadAssembly(mdAssemblyRef kAssemblyRef) } { - PEAssemblyHolder pFile = GetDomainAssembly()->GetFile()->LoadAssembly( - kAssemblyRef, - NULL); + PEAssemblyHolder pPEAssembly = GetDomainAssembly()->GetPEAssembly()->LoadAssembly(kAssemblyRef); AssemblySpec spec; spec.InitializeSpec(kAssemblyRef, GetMDImport(), GetDomainAssembly()); // Set the binding context in the AssemblySpec if one is available. This can happen if the LoadAssembly ended up // invoking the custom AssemblyLoadContext implementation that returned a reference to an assembly bound to a different // AssemblyLoadContext implementation. - AssemblyBinder *pBinder = pFile->GetAssemblyBinder(); + AssemblyBinder *pBinder = pPEAssembly->GetAssemblyBinder(); if (pBinder != NULL) { spec.SetBinder(pBinder); } - pDomainAssembly = GetAppDomain()->LoadDomainAssembly(&spec, pFile, FILE_LOADED); + pDomainAssembly = GetAppDomain()->LoadDomainAssembly(&spec, pPEAssembly, FILE_LOADED); } if (pDomainAssembly != NULL) @@ -3434,7 +3393,7 @@ DomainAssembly * Module::LoadAssembly(mdAssemblyRef kAssemblyRef) _ASSERTE( pDomainAssembly->IsSystem() || // GetAssemblyIfLoaded will not find CoreLib (see AppDomain::FindCachedFile) !pDomainAssembly->IsLoaded() || // GetAssemblyIfLoaded will not find not-yet-loaded assemblies - GetAssemblyIfLoaded(kAssemblyRef, NULL, FALSE, pDomainAssembly->GetFile()->GetHostAssembly()->GetBinder()) != NULL); // GetAssemblyIfLoaded should find all remaining cases + GetAssemblyIfLoaded(kAssemblyRef, NULL, FALSE, pDomainAssembly->GetPEAssembly()->GetHostAssembly()->GetBinder()) != NULL); // GetAssemblyIfLoaded should find all remaining cases if (pDomainAssembly->GetCurrentAssembly() != NULL) { @@ -3447,7 +3406,7 @@ DomainAssembly * Module::LoadAssembly(mdAssemblyRef kAssemblyRef) #endif // !DACCESS_COMPILE -Module *Module::GetModuleIfLoaded(mdFile kFile, BOOL onlyLoadedInAppDomain, BOOL permitResources) +Module *Module::GetModuleIfLoaded(mdFile kFile) { CONTRACT(Module *) { @@ -3479,7 +3438,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile, BOOL onlyLoadedInAppDomain, BOOL if (kFile == mdTokenNil) RETURN NULL; - RETURN GetAssembly()->GetManifestModule()->GetModuleIfLoaded(kFile, onlyLoadedInAppDomain, permitResources); + RETURN GetAssembly()->GetManifestModule()->GetModuleIfLoaded(kFile); } Module *pModule = LookupFile(kFile); @@ -3519,10 +3478,6 @@ Module *Module::GetModuleIfLoaded(mdFile kFile, BOOL onlyLoadedInAppDomain, BOOL #endif } - // We may not want to return a resource module - if (!permitResources && pModule && pModule->IsResource()) - pModule = NULL; - #ifndef DACCESS_COMPILE #endif // !DACCESS_COMPILE RETURN pModule; @@ -3530,8 +3485,7 @@ Module *Module::GetModuleIfLoaded(mdFile kFile, BOOL onlyLoadedInAppDomain, BOOL #ifndef DACCESS_COMPILE -DomainFile *Module::LoadModule(AppDomain *pDomain, mdFile kFile, - BOOL permitResources/*=TRUE*/, BOOL bindOnly/*=FALSE*/) +DomainFile *Module::LoadModule(AppDomain *pDomain, mdFile kFile) { CONTRACT(DomainFile *) { @@ -3541,38 +3495,32 @@ DomainFile *Module::LoadModule(AppDomain *pDomain, mdFile kFile, MODE_ANY; PRECONDITION(TypeFromToken(kFile) == mdtFile || TypeFromToken(kFile) == mdtModuleRef); - POSTCONDITION(CheckPointer(RETVAL, !permitResources || bindOnly ? NULL_OK : NULL_NOT_OK)); } CONTRACT_END; - if (bindOnly) + LPCSTR psModuleName=NULL; + if (TypeFromToken(kFile) == mdtModuleRef) { - RETURN NULL; + // This is a moduleRef + IfFailThrow(GetMDImport()->GetModuleRefProps(kFile, &psModuleName)); } else { - LPCSTR psModuleName=NULL; - if (TypeFromToken(kFile) == mdtModuleRef) - { - // This is a moduleRef - IfFailThrow(GetMDImport()->GetModuleRefProps(kFile, &psModuleName)); - } - else - { - // This is mdtFile - IfFailThrow(GetAssembly()->GetManifestImport()->GetFileProps(kFile, - &psModuleName, - NULL, - NULL, - NULL)); - } - SString name(SString::Utf8, psModuleName); - EEFileLoadException::Throw(name, COR_E_MULTIMODULEASSEMBLIESDIALLOWED, NULL); + // This is mdtFile + IfFailThrow(GetAssembly()->GetManifestImport()->GetFileProps(kFile, + &psModuleName, + NULL, + NULL, + NULL)); } + + SString name(SString::Utf8, psModuleName); + EEFileLoadException::Throw(name, COR_E_MULTIMODULEASSEMBLIESDIALLOWED, NULL); + RETURN NULL; } #endif // !DACCESS_COMPILE -PTR_Module Module::LookupModule(mdToken kFile,BOOL permitResources/*=TRUE*/) +PTR_Module Module::LookupModule(mdToken kFile) { CONTRACT(PTR_Module) { @@ -3598,7 +3546,7 @@ PTR_Module Module::LookupModule(mdToken kFile,BOOL permitResources/*=TRUE*/) if (kFileLocal == mdTokenNil) COMPlusThrowHR(COR_E_BADIMAGEFORMAT); - RETURN GetAssembly()->GetManifestModule()->LookupModule(kFileLocal, permitResources); + RETURN GetAssembly()->GetManifestModule()->LookupModule(kFileLocal); } PTR_Module pModule = LookupFile(kFile); @@ -4111,8 +4059,8 @@ BOOL Module::NotifyDebuggerLoad(AppDomain *pDomain, DomainFile * pDomainFile, in if (flags & ATTACH_MODULE_LOAD) { g_pDebugInterface->LoadModule(this, - m_file->GetPath(), - m_file->GetPath().GetCount(), + m_pPEAssembly->GetPath(), + m_pPEAssembly->GetPath().GetCount(), GetAssembly(), pDomain, pDomainFile, @@ -4168,9 +4116,9 @@ using GetTokenForVTableEntry_t = mdToken(STDMETHODCALLTYPE*)(HMODULE module, BYT static HMODULE GetIJWHostForModule(Module* module) { #if !defined(TARGET_UNIX) - PEDecoder* pe = module->GetFile()->GetLoadedIL(); + PEDecoder* pe = module->GetPEAssembly()->GetLoadedLayout(); - BYTE* baseAddress = (BYTE*)module->GetFile()->GetIJWBase(); + BYTE* baseAddress = (BYTE*)module->GetPEAssembly()->GetIJWBase(); IMAGE_IMPORT_DESCRIPTOR* importDescriptor = (IMAGE_IMPORT_DESCRIPTOR*)pe->GetDirectoryData(pe->GetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_IMPORT)); @@ -4286,7 +4234,7 @@ void Module::FixupVTables() // If we've already fixed up, or this is not an IJW module, just return. // NOTE: This relies on ILOnly files not having fixups. If this changes, // we need to change this conditional. - if (IsIJWFixedUp() || m_file->IsILOnly()) { + if (IsIJWFixedUp() || m_pPEAssembly->IsILOnly()) { return; } @@ -4302,11 +4250,11 @@ void Module::FixupVTables() GetTokenForVTableEntryCallback = GetTokenForVTableEntry; } - HINSTANCE hInstThis = GetFile()->GetIJWBase(); + HINSTANCE hInstThis = GetPEAssembly()->GetIJWBase(); // Get vtable fixup data COUNT_T cFixupRecords; - IMAGE_COR_VTABLEFIXUP *pFixupTable = m_file->GetVTableFixups(&cFixupRecords); + IMAGE_COR_VTABLEFIXUP *pFixupTable = m_pPEAssembly->GetVTableFixups(&cFixupRecords); // No records then return if (cFixupRecords == 0) { @@ -4314,7 +4262,7 @@ void Module::FixupVTables() } // Now, we need to take a lock to serialize fixup. - PEImage::IJWFixupData *pData = PEImage::GetIJWData(m_file->GetIJWBase()); + PEImage::IJWFixupData *pData = PEImage::GetIJWData(m_pPEAssembly->GetIJWBase()); // If it's already been fixed (in some other appdomain), record the fact and return if (pData->IsFixedUp()) { @@ -4381,7 +4329,7 @@ void Module::FixupVTables() (pFixupTable[iFixup].Type == (COR_VTABLE_PTRSIZED | COR_VTABLE_FROM_UNMANAGED)) || (pFixupTable[iFixup].Type == (COR_VTABLE_PTRSIZED | COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN))) { - const BYTE** pPointers = (const BYTE **)m_file->GetVTable(pFixupTable[iFixup].RVA); + const BYTE** pPointers = (const BYTE **)m_pPEAssembly->GetVTable(pFixupTable[iFixup].RVA); for (int iMethod = 0; iMethod < pFixupTable[iFixup].Count; iMethod++) { if (pData->IsMethodFixedUp(iFixup, iMethod)) @@ -4465,7 +4413,7 @@ void Module::FixupVTables() continue; const BYTE** pPointers = (const BYTE **) - m_file->GetVTable(pFixupTable[iFixup].RVA); + m_pPEAssembly->GetVTable(pFixupTable[iFixup].RVA); // Vtables can be 32 or 64 bit. if (pFixupTable[iFixup].Type == COR_VTABLE_PTRSIZED) @@ -4556,7 +4504,7 @@ LoaderHeap *Module::GetDllThunkHeap() MODE_ANY; } CONTRACTL_END; - return PEImage::GetDllThunkHeap(GetFile()->GetIJWBase()); + return PEImage::GetDllThunkHeap(GetPEAssembly()->GetIJWBase()); } @@ -4661,7 +4609,7 @@ IMDInternalImport* Module::GetNativeAssemblyImport(BOOL loadAllowed) } CONTRACT_END; - RETURN GetFile()->GetOpenedILimage()->GetNativeMDImport(loadAllowed); + RETURN GetPEAssembly()->GetPEImage()->GetNativeMDImport(loadAllowed); } BYTE* Module::GetNativeFixupBlobData(RVA rva) @@ -4930,7 +4878,7 @@ HANDLE Module::OpenMethodProfileDataLogFile(GUID mvid) HANDLE profileDataFile = INVALID_HANDLE_VALUE; SString path; - LPCWSTR assemblyPath = m_file->GetPath(); + LPCWSTR assemblyPath = m_pPEAssembly->GetPath(); LPCWSTR ibcDir = g_pConfig->GetZapBBInstrDir(); // should we put the ibc data into a particular directory? if (ibcDir == 0) { path.Set(assemblyPath); // no, then put it beside the IL dll @@ -6402,9 +6350,6 @@ HRESULT Module::WriteMethodProfileDataLogFile(bool cleanup) HRESULT hr = S_OK; - if (IsResource()) - return S_OK; - EX_TRY { if (GetAssembly()->IsInstrumented() && (m_pProfilingBlobTable != NULL) && (m_tokenProfileData != NULL)) @@ -6990,14 +6935,14 @@ idMethodSpec Module::LogInstantiatedMethod(const MethodDesc * md, ULONG flagNum) // =========================================================================== /* static */ -ReflectionModule *ReflectionModule::Create(Assembly *pAssembly, PEFile *pFile, AllocMemTracker *pamTracker, LPCWSTR szName) +ReflectionModule *ReflectionModule::Create(Assembly *pAssembly, PEAssembly *pPEAssembly, AllocMemTracker *pamTracker, LPCWSTR szName) { CONTRACT(ReflectionModule *) { STANDARD_VM_CHECK; PRECONDITION(CheckPointer(pAssembly)); - PRECONDITION(CheckPointer(pFile)); - PRECONDITION(pFile->IsDynamic()); + PRECONDITION(CheckPointer(pPEAssembly)); + PRECONDITION(pPEAssembly->IsDynamic()); POSTCONDITION(CheckPointer(RETVAL)); } CONTRACT_END; @@ -7005,14 +6950,13 @@ ReflectionModule *ReflectionModule::Create(Assembly *pAssembly, PEFile *pFile, A // Hoist CONTRACT into separate routine because of EX incompatibility mdFile token; - _ASSERTE(pFile->IsAssembly()); token = mdFileNil; // Initial memory block for Modules must be zero-initialized (to make it harder // to introduce Destruct crashes arising from OOM's during initialization.) void* pMemory = pamTracker->Track(pAssembly->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(ReflectionModule)))); - ReflectionModuleHolder pModule(new (pMemory) ReflectionModule(pAssembly, token, pFile)); + ReflectionModuleHolder pModule(new (pMemory) ReflectionModule(pAssembly, token, pPEAssembly)); pModule->DoInit(pamTracker, szName); @@ -7025,8 +6969,8 @@ ReflectionModule *ReflectionModule::Create(Assembly *pAssembly, PEFile *pFile, A // The constructor phase initializes just enough so that Destruct() can be safely called. // It cannot throw or fail. // -ReflectionModule::ReflectionModule(Assembly *pAssembly, mdFile token, PEFile *pFile) - : Module(pAssembly, token, pFile) +ReflectionModule::ReflectionModule(Assembly *pAssembly, mdFile token, PEAssembly *pPEAssembly) + : Module(pAssembly, token, pPEAssembly) { CONTRACTL { @@ -7569,9 +7513,9 @@ void Module::EnumMemoryRegions(CLRDataEnumMemoryFlags flags, m_ModuleID->EnumMemoryRegions(flags); } - if (m_file.IsValid()) + if (m_pPEAssembly.IsValid()) { - m_file->EnumMemoryRegions(flags); + m_pPEAssembly->EnumMemoryRegions(flags); } if (m_pAssembly.IsValid()) { @@ -7724,11 +7668,11 @@ LPCWSTR Module::GetPathForErrorMessages() } CONTRACTL_END - PEFile *pFile = GetFile(); + PEAssembly *pPEAssembly = GetPEAssembly(); - if (pFile) + if (pPEAssembly) { - return pFile->GetPathForErrorMessages(); + return pPEAssembly->GetPathForErrorMessages(); } else { diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index 2e3b474ef298a..e7dd5629a2c84 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -19,7 +19,7 @@ #include "corsym.h" #include "typehandle.h" #include "arraylist.h" -#include "pefile.h" +#include "peassembly.h" #include "typehash.h" #include "contractimpl.h" #include "bitmask.h" @@ -43,7 +43,6 @@ #include "ilinstrumentation.h" -class PELoader; class Stub; class MethodDesc; class FieldDesc; @@ -736,7 +735,7 @@ struct ThreadLocalModule; // Native code (NGEN module). A module live in a code:Assembly // // Some important fields are -// * code:Module.m_file - this points at a code:PEFile that understands the layout of a PE file. The most +// * code:Module.m_pPEAssembly - this points at a code:PEAssembly that understands the layout of a PE assembly. The most // important part is getting at the code:Module (see file:..\inc\corhdr.h#ManagedHeader) from there // you can get at the Meta-data and IL) // * code:Module.m_pAvailableClasses - this is a table that lets you look up the types (the code:EEClass) @@ -758,7 +757,7 @@ class Module private: PTR_CUTF8 m_pSimpleName; // Cached simple name for better performance and easier diagnostics - PTR_PEFile m_file; + PTR_PEAssembly m_pPEAssembly; enum { // These are the values set in m_dwTransientFlags. @@ -1079,10 +1078,10 @@ class Module #endif // _DEBUG public: - static Module *Create(Assembly *pAssembly, mdFile kFile, PEFile *pFile, AllocMemTracker *pamTracker); + static Module *Create(Assembly *pAssembly, mdFile kFile, PEAssembly *pPEAssembly, AllocMemTracker *pamTracker); protected: - Module(Assembly *pAssembly, mdFile moduleRef, PEFile *file); + Module(Assembly *pAssembly, mdFile moduleRef, PEAssembly *file); public: @@ -1092,9 +1091,7 @@ class Module PTR_LoaderAllocator GetLoaderAllocator(); - PTR_PEFile GetFile() const { LIMITED_METHOD_DAC_CONTRACT; return m_file; } - - static size_t GetFileOffset() { LIMITED_METHOD_CONTRACT; return offsetof(Module, m_file); } + PTR_PEAssembly GetPEAssembly() const { LIMITED_METHOD_DAC_CONTRACT; return m_pPEAssembly; } BOOL IsManifest(); @@ -1153,10 +1150,8 @@ class Module return m_moduleRef; } - BOOL IsResource() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return GetFile()->IsResource(); } - BOOL IsPEFile() const { WRAPPER_NO_CONTRACT; return !GetFile()->IsDynamic(); } - BOOL IsReflection() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return GetFile()->IsDynamic(); } - BOOL IsIbcOptimized() const { WRAPPER_NO_CONTRACT; return GetFile()->IsIbcOptimized(); } + BOOL IsPEFile() const { WRAPPER_NO_CONTRACT; return !GetPEAssembly()->IsDynamic(); } + BOOL IsReflection() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return GetPEAssembly()->IsDynamic(); } // Returns true iff the debugger can see this module. BOOL IsVisibleToDebugger(); @@ -1170,11 +1165,9 @@ class Module virtual BOOL IsEditAndContinueCapable() const { return FALSE; } - BOOL IsIStream() { LIMITED_METHOD_CONTRACT; return GetFile()->IsIStream(); } - - BOOL IsSystem() { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return m_file->IsSystem(); } + BOOL IsSystem() { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return m_pPEAssembly->IsSystem(); } - static BOOL IsEditAndContinueCapable(Assembly *pAssembly, PEFile *file); + static BOOL IsEditAndContinueCapable(Assembly *pAssembly, PEAssembly *file); void EnableEditAndContinue() { @@ -1265,7 +1258,7 @@ class Module return DacGetMDImport(GetReflectionModule(), true); } #endif // DACCESS_COMPILE - return m_file->GetPersistentMDImport(); + return m_pPEAssembly->GetMDImport(); } #ifndef DACCESS_COMPILE @@ -1273,21 +1266,14 @@ class Module { WRAPPER_NO_CONTRACT; - return m_file->GetEmitter(); + return m_pPEAssembly->GetEmitter(); } IMetaDataImport2 *GetRWImporter() { WRAPPER_NO_CONTRACT; - return m_file->GetRWImporter(); - } - - IMetaDataAssemblyImport *GetAssemblyImporter() - { - WRAPPER_NO_CONTRACT; - - return m_file->GetAssemblyImporter(); + return m_pPEAssembly->GetRWImporter(); } HRESULT GetReadablePublicMetaDataInterface(DWORD dwOpenFlags, REFIID riid, LPVOID * ppvInterface); @@ -1379,54 +1365,26 @@ class Module { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; - { - // IsResource() may lock when accessing metadata, but this is only in debug, - // for the assert below - CONTRACT_VIOLATION(TakesLockViolation); - - _ASSERTE(!IsResource()); - } return m_pAvailableClasses; } #ifndef DACCESS_COMPILE void SetAvailableClassHash(EEClassHashTable *pAvailableClasses) { - LIMITED_METHOD_CONTRACT; - { - // IsResource() may lock when accessing metadata, but this is only in debug, - // for the assert below - CONTRACT_VIOLATION(TakesLockViolation); - _ASSERTE(!IsResource()); - } m_pAvailableClasses = pAvailableClasses; } #endif // !DACCESS_COMPILE PTR_EEClassHashTable GetAvailableClassCaseInsHash() { LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - { - // IsResource() may lock when accessing metadata, but this is only in debug, - // for the assert below - CONTRACT_VIOLATION(TakesLockViolation); - _ASSERTE(!IsResource()); - } return m_pAvailableClassesCaseIns; } #ifndef DACCESS_COMPILE void SetAvailableClassCaseInsHash(EEClassHashTable *pAvailableClassesCaseIns) { - LIMITED_METHOD_CONTRACT; - { - // IsResource() may lock when accessing metadata, but this is only in debug, - // for the assert below - CONTRACT_VIOLATION(TakesLockViolation); - _ASSERTE(!IsResource()); - } m_pAvailableClassesCaseIns = pAvailableClassesCaseIns; } #endif // !DACCESS_COMPILE @@ -1436,26 +1394,14 @@ class Module { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; - { - // IsResource() may lock when accessing metadata, but this is only in debug, - // for the assert below - CONTRACT_VIOLATION(TakesLockViolation); - _ASSERTE(!IsResource()); - } return m_pAvailableParamTypes; } InstMethodHashTable *GetInstMethodHashTable() { LIMITED_METHOD_CONTRACT; - { - // IsResource() may lock when accessing metadata, but this is only in debug, - // for the assert below - CONTRACT_VIOLATION(TakesLockViolation); - _ASSERTE(!IsResource()); - } return m_pInstMethodHashTable; } @@ -1484,9 +1430,9 @@ class Module public: DomainAssembly * LoadAssembly(mdAssemblyRef kAssemblyRef); - Module *GetModuleIfLoaded(mdFile kFile, BOOL onlyLoadedInAppDomain, BOOL loadAllowed); - DomainFile *LoadModule(AppDomain *pDomain, mdFile kFile, BOOL loadResources = TRUE, BOOL bindOnly = FALSE); - PTR_Module LookupModule(mdToken kFile, BOOL loadResources = TRUE); //wrapper over GetModuleIfLoaded, takes modulerefs as well + Module *GetModuleIfLoaded(mdFile kFile); + DomainFile *LoadModule(AppDomain *pDomain, mdFile kFile); + PTR_Module LookupModule(mdToken kFile); //wrapper over GetModuleIfLoaded, takes modulerefs as well DWORD GetAssemblyRefFlags(mdAssemblyRef tkAssemblyRef); // RID maps @@ -1806,8 +1752,8 @@ class Module public: #ifndef DACCESS_COMPILE - BOOL Equals(Module *pModule) { WRAPPER_NO_CONTRACT; return m_file->Equals(pModule->m_file); } - BOOL Equals(PEFile *pFile) { WRAPPER_NO_CONTRACT; return m_file->Equals(pFile); } + BOOL Equals(Module *pModule) { WRAPPER_NO_CONTRACT; return m_pPEAssembly->Equals(pModule->m_pPEAssembly); } + BOOL Equals(PEAssembly *pPEAssembly) { WRAPPER_NO_CONTRACT; return m_pPEAssembly->Equals(pPEAssembly); } #endif // !DACCESS_COMPILE LPCUTF8 GetSimpleName() @@ -1817,11 +1763,11 @@ class Module return m_pSimpleName; } - HRESULT GetScopeName(LPCUTF8 * pszName) { WRAPPER_NO_CONTRACT; return m_file->GetScopeName(pszName); } - const SString &GetPath() { WRAPPER_NO_CONTRACT; return m_file->GetPath(); } + HRESULT GetScopeName(LPCUTF8 * pszName) { WRAPPER_NO_CONTRACT; return m_pPEAssembly->GetScopeName(pszName); } + const SString &GetPath() { WRAPPER_NO_CONTRACT; return m_pPEAssembly->GetPath(); } #ifdef LOGGING - LPCWSTR GetDebugName() { WRAPPER_NO_CONTRACT; return m_file->GetDebugName(); } + LPCWSTR GetDebugName() { WRAPPER_NO_CONTRACT; return m_pPEAssembly->GetDebugName(); } #endif PEImageLayout * GetReadyToRunImage(); @@ -1837,7 +1783,7 @@ class Module CHECK CheckRvaField(RVA field, COUNT_T size); const void *GetInternalPInvokeTarget(RVA target) - { WRAPPER_NO_CONTRACT; return m_file->GetInternalPInvokeTarget(target); } + { WRAPPER_NO_CONTRACT; return m_pPEAssembly->GetInternalPInvokeTarget(target); } BOOL HasTls(); BOOL IsRvaFieldTls(DWORD field); @@ -2268,7 +2214,7 @@ class ReflectionModule : public Module bool m_fSuppressMetadataCapture; #if !defined DACCESS_COMPILE - ReflectionModule(Assembly *pAssembly, mdFile token, PEFile *pFile); + ReflectionModule(Assembly *pAssembly, mdFile token, PEAssembly *pPEAssembly); #endif // !DACCESS_COMPILE public: @@ -2279,7 +2225,7 @@ class ReflectionModule : public Module #endif #if !defined DACCESS_COMPILE - static ReflectionModule *Create(Assembly *pAssembly, PEFile *pFile, AllocMemTracker *pamTracker, LPCWSTR szName); + static ReflectionModule *Create(Assembly *pAssembly, PEAssembly *pPEAssembly, AllocMemTracker *pamTracker, LPCWSTR szName); void Initialize(AllocMemTracker *pamTracker, LPCWSTR szName); void Destruct(); #endif // !DACCESS_COMPILE diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index 9c68686b31d6e..8f347255d4e0d 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -848,7 +848,6 @@ void EEStartupHelper() // Setup the domains. Threads are started in a default domain. // Static initialization - PEAssembly::Attach(); BaseDomain::Attach(); SystemDomain::Attach(); diff --git a/src/coreclr/vm/clrex.cpp b/src/coreclr/vm/clrex.cpp index b4959ad479237..a1fe3e4c8985d 100644 --- a/src/coreclr/vm/clrex.cpp +++ b/src/coreclr/vm/clrex.cpp @@ -1733,7 +1733,7 @@ void DECLSPEC_NORETURN EEFileLoadException::Throw(AssemblySpec *pSpec, HRESULT } /* static */ -void DECLSPEC_NORETURN EEFileLoadException::Throw(PEFile *pFile, HRESULT hr, Exception *pInnerException /* = NULL*/) +void DECLSPEC_NORETURN EEFileLoadException::Throw(PEAssembly *pPEAssembly, HRESULT hr, Exception *pInnerException /* = NULL*/) { CONTRACTL { @@ -1749,11 +1749,8 @@ void DECLSPEC_NORETURN EEFileLoadException::Throw(PEFile *pFile, HRESULT hr, Exc COMPlusThrowOM(); StackSString name; + pPEAssembly->GetDisplayName(name); - if (pFile->IsAssembly()) - ((PEAssembly*)pFile)->GetDisplayName(name); - else - name = StackSString(SString::Utf8, pFile->GetSimpleName()); EX_THROW_WITH_INNER(EEFileLoadException, (name, hr), pInnerException); } diff --git a/src/coreclr/vm/clrex.h b/src/coreclr/vm/clrex.h index 569e8442854cd..cf7d458f90ff3 100644 --- a/src/coreclr/vm/clrex.h +++ b/src/coreclr/vm/clrex.h @@ -18,7 +18,6 @@ class BaseBind; class AssemblySpec; -class PEFile; class PEAssembly; enum StackTraceElementFlags @@ -678,7 +677,7 @@ class EEFileLoadException : public EEException static RuntimeExceptionKind GetFileLoadKind(HRESULT hr); static void DECLSPEC_NORETURN Throw(AssemblySpec *pSpec, HRESULT hr, Exception *pInnerException = NULL); - static void DECLSPEC_NORETURN Throw(PEFile *pFile, HRESULT hr, Exception *pInnerException = NULL); + static void DECLSPEC_NORETURN Throw(PEAssembly *pPEAssembly, HRESULT hr, Exception *pInnerException = NULL); static void DECLSPEC_NORETURN Throw(LPCWSTR path, HRESULT hr, Exception *pInnerException = NULL); static void DECLSPEC_NORETURN Throw(PEAssembly *parent, const void *memory, COUNT_T size, HRESULT hr, Exception *pInnerException = NULL); static BOOL CheckType(Exception* ex); // typeof(EEFileLoadException) diff --git a/src/coreclr/vm/clsload.cpp b/src/coreclr/vm/clsload.cpp index 8b53e019d39aa..9392f6c11d93e 100644 --- a/src/coreclr/vm/clsload.cpp +++ b/src/coreclr/vm/clsload.cpp @@ -654,8 +654,6 @@ void ClassLoader::GetClassValue(NameHandleTable nhTable, Module * pCurrentClsModule = i.GetModule(); PREFIX_ASSUME(pCurrentClsModule != NULL); - if (pCurrentClsModule->IsResource()) - continue; if (pLookInThisModuleOnly && (pCurrentClsModule != pLookInThisModuleOnly)) continue; @@ -844,7 +842,7 @@ void ClassLoader::LazyPopulateCaseSensitiveHashTables() { Module *pModule = i.GetModule(); PREFIX_ASSUME(pModule != NULL); - if (pModule->IsResource() || pModule->GetAvailableClassHash() != NULL) + if (pModule->GetAvailableClassHash() != NULL) continue; // Lazy construction of the case-sensitive hashtable of types is *only* a scenario for ReadyToRun images @@ -858,16 +856,13 @@ void ClassLoader::LazyPopulateCaseSensitiveHashTables() } // Add exported types of the manifest module to the hashtable - if (!GetAssembly()->GetManifestModule()->IsResource()) - { - IMDInternalImport * pManifestImport = GetAssembly()->GetManifestImport(); - HENUMInternalHolder phEnum(pManifestImport); - phEnum.EnumInit(mdtExportedType, mdTokenNil); + IMDInternalImport * pManifestImport = GetAssembly()->GetManifestImport(); + HENUMInternalHolder phEnum(pManifestImport); + phEnum.EnumInit(mdtExportedType, mdTokenNil); - mdToken mdExportedType; - while (pManifestImport->EnumNext(&phEnum, &mdExportedType)) - AddExportedTypeHaveLock(GetAssembly()->GetManifestModule(), mdExportedType, &amTracker); - } + mdToken mdExportedType; + while (pManifestImport->EnumNext(&phEnum, &mdExportedType)) + AddExportedTypeHaveLock(GetAssembly()->GetManifestModule(), mdExportedType, &amTracker); amTracker.SuppressRelease(); } @@ -884,7 +879,7 @@ void ClassLoader::LazyPopulateCaseInsensitiveHashTables() } CONTRACTL_END; - if (!GetAssembly()->GetManifestModule()->IsResource() && GetAssembly()->GetManifestModule()->GetAvailableClassHash() == NULL) + if (GetAssembly()->GetManifestModule()->GetAvailableClassHash() == NULL) { // This is a R2R assembly, and a case insensitive type lookup was triggered. // Construct the case-sensitive table first, since the case-insensitive table @@ -900,9 +895,6 @@ void ClassLoader::LazyPopulateCaseInsensitiveHashTables() while (i.Next()) { Module *pModule = i.GetModule(); - if (pModule->IsResource()) - continue; - if (pModule->GetAvailableClassCaseInsHash() == NULL) { EEClassHashTable *pNewClassCaseInsHash = pModule->GetAvailableClassHash()->MakeCaseInsensitiveTable(pModule, &amTracker); diff --git a/src/coreclr/vm/commodule.cpp b/src/coreclr/vm/commodule.cpp index 99b4982329f04..c00a08336a7c2 100644 --- a/src/coreclr/vm/commodule.cpp +++ b/src/coreclr/vm/commodule.cpp @@ -651,26 +651,13 @@ void QCALLTYPE COMModule::GetScopeName(QCall::ModuleHandle pModule, QCall::Strin BEGIN_QCALL; - LPCSTR szName = NULL; - - if (pModule->IsResource()) - { - IfFailThrow(pModule->GetAssembly()->GetManifestImport()->GetFileProps( - pModule->GetModuleRef(), - &szName, - NULL, - NULL, - NULL)); - } - else + if (!pModule->GetMDImport()->IsValidToken(pModule->GetMDImport()->GetModuleFromScope())) { - if (!pModule->GetMDImport()->IsValidToken(pModule->GetMDImport()->GetModuleFromScope())) - { - ThrowHR(COR_E_BADIMAGEFORMAT); - } - IfFailThrow(pModule->GetMDImport()->GetScopeProps(&szName, 0)); + ThrowHR(COR_E_BADIMAGEFORMAT); } + LPCSTR szName = NULL; + IfFailThrow(pModule->GetMDImport()->GetScopeProps(&szName, 0)); retString.Set(szName); END_QCALL; @@ -734,10 +721,10 @@ HINSTANCE QCALLTYPE COMModule::GetHINSTANCE(QCall::ModuleHandle pModule) // This returns the base address // Other modules should have zero base - PEFile *pPEFile = pModule->GetFile(); - if (!pPEFile->IsDynamic() && !pPEFile->IsResource()) + PEAssembly *pPEAssembly = pModule->GetPEAssembly(); + if (!pPEAssembly->IsDynamic()) { - hMod = (HMODULE) pModule->GetFile()->GetManagedFileContents(); + hMod = (HMODULE) pModule->GetPEAssembly()->GetManagedFileContents(); } //If we don't have an hMod, set it to -1 so that they know that there's none @@ -801,12 +788,6 @@ Object* GetTypesInner(Module* pModule) int AllocSize = 0; MethodTable* pMT = NULL; - if (pModule->IsResource()) - { - refArrClasses = (PTRARRAYREF) AllocateObjectArray(0, CoreLibBinder::GetClass(CLASS__CLASS)); - RETURN(OBJECTREFToObject(refArrClasses)); - } - GCPROTECT_BEGIN(refArrClasses); GCPROTECT_BEGIN(xcept); @@ -890,15 +871,3 @@ Object* GetTypesInner(Module* pModule) RETURN(OBJECTREFToObject(refArrClasses)); } - - -FCIMPL1(FC_BOOL_RET, COMModule::IsResource, ReflectModuleBaseObject* pModuleUNSAFE) -{ - FCALL_CONTRACT; - - if (pModuleUNSAFE == NULL) - FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); - - FC_RETURN_BOOL(pModuleUNSAFE->GetModule()->IsResource()); -} -FCIMPLEND diff --git a/src/coreclr/vm/commodule.h b/src/coreclr/vm/commodule.h index c995ec80dfd82..4453214c473a5 100644 --- a/src/coreclr/vm/commodule.h +++ b/src/coreclr/vm/commodule.h @@ -90,8 +90,6 @@ class COMModule static void QCALLTYPE SetModuleName(QCall::ModuleHandle pModule, LPCWSTR wszModuleName); - static FCDECL1(FC_BOOL_RET, IsResource, ReflectModuleBaseObject* pModuleUNSAFE); - static FCDECL1(Object*, GetMethods, ReflectModuleBaseObject* refThisUNSAFE); static diff --git a/src/coreclr/vm/common.h b/src/coreclr/vm/common.h index 7d2f3532219a3..bcd9af84555c6 100644 --- a/src/coreclr/vm/common.h +++ b/src/coreclr/vm/common.h @@ -345,7 +345,7 @@ inline void ClrRestoreNonvolatileContext(PCONTEXT ContextRecord) #include "specialstatics.h" #include "object.h" // We should not really need to put this so early... #include "gchelpers.h" -#include "pefile.h" +#include "peassembly.h" #include "clrex.h" #include "clsload.hpp" // We should not really need to put this so early... #include "siginfo.hpp" @@ -362,7 +362,7 @@ inline void ClrRestoreNonvolatileContext(PCONTEXT ContextRecord) #include "appdomain.hpp" #include "appdomain.inl" #include "assembly.hpp" -#include "pefile.inl" +#include "peassembly.inl" #include "excep.h" #include "method.hpp" #include "field.h" diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index 9d1547cda8edd..eaaddafdbe9c6 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -116,7 +116,7 @@ STDAPI BinderAcquirePEImage(LPCWSTR wszAssemblyPath, { PEImageHolder pImage = PEImage::OpenImage(wszAssemblyPath, MDInternalImport_Default, bundleFileLocation); - // Make sure that the IL image can be opened if the native image is not available. + // Make sure that the IL image can be opened. hr=pImage->TryOpenFile(); if (FAILED(hr)) { @@ -144,7 +144,7 @@ STDAPI BinderAcquireImport(PEImage *pPEImage, EX_TRY { - PEImageLayoutHolder pLayout(pPEImage->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED)); + PEImageLayout* pLayout = pPEImage->GetOrCreateLayout(PEImageLayout::LAYOUT_ANY); // CheckCorHeader includes check of NT headers too if (!pLayout->CheckCorHeader()) diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index a4b2bfa74a876..861ec15be77a8 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -612,8 +612,6 @@ HRESULT CorHost2::CreateAppDomainWithManager( if (dwFlags & APPDOMAIN_FORCE_TRIVIAL_WAIT_OPERATIONS) pDomain->SetForceTrivialWaitOperations(); - pDomain->CreateBinderContext(); - { GCX_COOP(); diff --git a/src/coreclr/vm/debugdebugger.cpp b/src/coreclr/vm/debugdebugger.cpp index e21939990405c..e6313d9c20be9 100644 --- a/src/coreclr/vm/debugdebugger.cpp +++ b/src/coreclr/vm/debugdebugger.cpp @@ -713,11 +713,11 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, I4 *pMethodToken = (I4 *)((I4ARRAYREF)pStackFrameHelper->rgiMethodToken)->GetDirectPointerToNonObjectElements(); pMethodToken[iNumValidFrames] = pMethod->GetMemberDef(); - PEFile *pPEFile = pModule->GetFile(); + PEAssembly *pPEAssembly = pModule->GetPEAssembly(); // Get the address and size of the loaded PE image COUNT_T peSize; - PTR_CVOID peAddress = pPEFile->GetLoadedImageContents(&peSize); + PTR_CVOID peAddress = pPEAssembly->GetLoadedImageContents(&peSize); // Save the PE address and size PTR_CVOID *pLoadedPeAddress = (PTR_CVOID *)pStackFrameHelper->rgLoadedPeAddress->GetDataPtr(); @@ -727,11 +727,11 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, pLoadedPeSize[iNumValidFrames] = (I4)peSize; // Set flag indicating PE file in memory has the on disk layout - if (!pPEFile->IsDynamic()) + if (!pPEAssembly->IsDynamic()) { // This flag is only available for non-dynamic assemblies. U1 *pIsFileLayout = (U1 *)((BOOLARRAYREF)pStackFrameHelper->rgiIsFileLayout)->GetDirectPointerToNonObjectElements(); - pIsFileLayout[iNumValidFrames] = (U1) pPEFile->GetLoaded()->IsFlat(); + pIsFileLayout[iNumValidFrames] = (U1) pPEAssembly->GetLoadedLayout()->IsFlat(); } // If there is a in memory symbol stream @@ -750,7 +750,7 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, else { // Set the pdb path (assembly file name) - SString assemblyPath = pPEFile->GetIdentityPath(); + SString assemblyPath = pPEAssembly->GetIdentityPath(); if (!assemblyPath.IsEmpty()) { OBJECTREF obj = (OBJECTREF)StringObject::NewString(assemblyPath); diff --git a/src/coreclr/vm/domainfile.cpp b/src/coreclr/vm/domainfile.cpp index 70f03913f1879..ca9ea6565d3f7 100644 --- a/src/coreclr/vm/domainfile.cpp +++ b/src/coreclr/vm/domainfile.cpp @@ -30,10 +30,9 @@ #endif // FEATURE_PERFMAP #ifndef DACCESS_COMPILE -DomainFile::DomainFile(AppDomain *pDomain, PEFile *pFile) +DomainFile::DomainFile(AppDomain *pDomain, PEAssembly *pPEAssembly) : m_pDomain(pDomain), - m_pFile(pFile), - m_pOriginalFile(NULL), + m_pPEAssembly(pPEAssembly), m_pModule(NULL), m_level(FILE_LOAD_CREATE), m_pError(NULL), @@ -54,7 +53,7 @@ DomainFile::DomainFile(AppDomain *pDomain, PEFile *pFile) CONTRACTL_END; m_hExposedModuleObject = NULL; - pFile->AddRef(); + pPEAssembly->AddRef(); } DomainFile::~DomainFile() @@ -68,9 +67,7 @@ DomainFile::~DomainFile() } CONTRACTL_END; - m_pFile->Release(); - if(m_pOriginalFile) - m_pOriginalFile->Release(); + m_pPEAssembly->Release(); if (m_pDynamicMethodTable) m_pDynamicMethodTable->Destroy(); delete m_pError; @@ -282,10 +279,10 @@ CHECK DomainFile::CheckLoaded() // assemblies for bootstrapping purposes. This is because it has no // dependencies, security checks, and doesn't rely on loader notifications. - if (GetFile()->IsSystem()) + if (GetPEAssembly()->IsSystem()) CHECK_OK; - CHECK_MSG(GetFile()->CheckLoaded(), "PEFile has not been loaded"); + CHECK_MSG(GetPEAssembly()->IsLoaded(), "PEAssembly has not been loaded"); CHECK_OK; } @@ -310,10 +307,10 @@ CHECK DomainFile::CheckActivated() // assemblies for bootstrapping purposes. This is because it has no // dependencies, security checks, and doesn't rely on loader notifications. - if (GetFile()->IsSystem()) + if (GetPEAssembly()->IsSystem()) CHECK_OK; - CHECK_MSG(GetFile()->CheckLoaded(), "PEFile has not been loaded"); + CHECK_MSG(GetPEAssembly()->IsLoaded(), "PEAssembly has not been loaded"); CHECK_MSG(IsLoaded(), "DomainFile has not been fully loaded"); CHECK_MSG(m_bDisableActivationCheck || CheckLoadLevel(FILE_ACTIVE), "File has not had execution verified"); @@ -392,7 +389,7 @@ OBJECTREF DomainFile::GetExposedModuleObject() GCPROTECT_BEGIN(refClass); - if (GetFile()->IsDynamic()) + if (GetPEAssembly()->IsDynamic()) { refClass = (REFLECTMODULEBASEREF) AllocateObject(CoreLibBinder::GetClass(CLASS__MODULE_BUILDER)); } @@ -528,7 +525,7 @@ void DomainFile::LoadLibrary() } CONTRACTL_END; - GetFile()->LoadLibrary(); + GetPEAssembly()->EnsureLoaded(); } void DomainFile::PostLoadLibrary() @@ -536,8 +533,8 @@ void DomainFile::PostLoadLibrary() CONTRACTL { INSTANCE_CHECK; - // Note that GetFile()->LoadLibrary must be called before this OUTSIDE OF THE LOCKS - PRECONDITION(GetFile()->CheckLoaded()); + // Note that GetPEAssembly()->EnsureLoaded must be called before this OUTSIDE OF THE LOCKS + PRECONDITION(GetPEAssembly()->IsLoaded()); STANDARD_VM_CHECK; } CONTRACTL_END; @@ -597,8 +594,7 @@ void DomainFile::VtableFixups() { WRAPPER_NO_CONTRACT; - if (!GetCurrentModule()->IsResource()) - GetCurrentModule()->FixupVTables(); + GetCurrentModule()->FixupVTables(); } void DomainFile::FinishLoad() @@ -622,7 +618,7 @@ void DomainFile::FinishLoad() #ifdef FEATURE_PERFMAP // Notify the perfmap of the IL image load. - PerfMap::LogImageLoad(m_pFile); + PerfMap::LogImageLoad(m_pPEAssembly); #endif } @@ -682,8 +678,8 @@ void DomainFile::Activate() // DomainAssembly //-------------------------------------------------------------------------------- -DomainAssembly::DomainAssembly(AppDomain *pDomain, PEFile *pFile, LoaderAllocator *pLoaderAllocator) - : DomainFile(pDomain, pFile), +DomainAssembly::DomainAssembly(AppDomain *pDomain, PEAssembly *pPEAssembly, LoaderAllocator *pLoaderAllocator) + : DomainFile(pDomain, pPEAssembly), m_pAssembly(NULL), m_debuggerFlags(DACF_NONE), m_fDebuggerUnloadStarted(FALSE), @@ -700,7 +696,7 @@ DomainAssembly::DomainAssembly(AppDomain *pDomain, PEFile *pFile, LoaderAllocato } CONTRACTL_END; - pFile->ValidateForExecution(); + pPEAssembly->ValidateForExecution(); // !!! backout @@ -747,8 +743,9 @@ void DomainAssembly::SetAssembly(Assembly* pAssembly) { STANDARD_VM_CONTRACT; - UpdatePEFile(pAssembly->GetManifestFile()); - _ASSERTE(pAssembly->GetManifestModule()->GetFile()==m_pFile); + _ASSERTE(pAssembly->GetManifestModule()->GetPEAssembly()==m_pPEAssembly); + _ASSERTE(m_pAssembly == NULL); + m_pAssembly = pAssembly; m_pModule = pAssembly->GetManifestModule(); @@ -793,7 +790,7 @@ OBJECTREF DomainAssembly::GetExposedAssemblyObject() { ASSEMBLYREF assemblyObj = NULL; MethodTable * pMT; - if (GetFile()->IsDynamic()) + if (GetPEAssembly()->IsDynamic()) { // This is unnecessary because the managed InternalAssemblyBuilder object // should have already been created at the time of DefineDynamicAssembly @@ -879,18 +876,11 @@ void DomainAssembly::Allocate() { //! If you decide to remove "if" do not remove this brace: order is important here - in the case of an exception, //! the Assembly holder must destruct before the AllocMemTracker declared above. - - // We can now rely on the fact that our MDImport will not change so we can stop refcounting it. - GetFile()->MakeMDImportPersistent(); - NewHolder assemblyHolder(NULL); - assemblyHolder = pAssembly = Assembly::Create(m_pDomain, GetFile(), GetDebuggerInfoBits(), this->IsCollectible(), pamTracker, this->IsCollectible() ? this->GetLoaderAllocator() : NULL); + assemblyHolder = pAssembly = Assembly::Create(m_pDomain, GetPEAssembly(), GetDebuggerInfoBits(), this->IsCollectible(), pamTracker, this->IsCollectible() ? this->GetLoaderAllocator() : NULL); assemblyHolder->SetIsTenured(); - //@todo! This is too early to be calling SuppressRelease. The right place to call it is below after - // the CANNOTTHROWCOMPLUSEXCEPTION. Right now, we have to do this to unblock OOM injection testing quickly - // as doing the right thing is nontrivial. pamTracker->SuppressRelease(); assemblyHolder.SuppressRelease(); } @@ -973,7 +963,7 @@ BOOL DomainAssembly::GetResource(LPCSTR szName, DWORD *cbResource, } CONTRACTL_END; - return GetFile()->GetResource( szName, + return GetPEAssembly()->GetResource( szName, cbResource, pbInMemoryResource, pAssemblyRef, @@ -1048,7 +1038,7 @@ HRESULT DomainAssembly::GetDebuggingCustomAttributes(DWORD *pdwFlags) ULONG size; BYTE *blob; mdModule mdMod; - ReleaseHolder mdImport(GetFile()->GetMDImportWithRef()); + IMDInternalImport* mdImport = GetPEAssembly()->GetMDImport(); mdMod = mdImport->GetModuleFromScope(); mdAssembly asTK = TokenFromRid(mdtAssembly, 1); @@ -1202,9 +1192,9 @@ DomainFile::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) // so we don't need to duplicate effort; thus we do noting with m_pModule. // For MiniDumpNormal, we only want the file name. - if (m_pFile.IsValid()) + if (m_pPEAssembly.IsValid()) { - m_pFile->EnumMemoryRegions(flags); + m_pPEAssembly->EnumMemoryRegions(flags); } if (flags != CLRDATA_ENUM_MEM_MINI && flags != CLRDATA_ENUM_MEM_TRIAGE diff --git a/src/coreclr/vm/domainfile.h b/src/coreclr/vm/domainfile.h index 4396ad6c8d990..49a8344b21e84 100644 --- a/src/coreclr/vm/domainfile.h +++ b/src/coreclr/vm/domainfile.h @@ -87,23 +87,16 @@ class DomainFile return m_pDomain; } - PEFile *GetFile() + PEAssembly *GetPEAssembly() { LIMITED_METHOD_DAC_CONTRACT; - return m_pFile; + return PTR_PEAssembly(m_pPEAssembly); } - PEFile *GetOriginalFile() - { - LIMITED_METHOD_DAC_CONTRACT; - return m_pOriginalFile!= NULL ? m_pOriginalFile : m_pFile; - } - - IMDInternalImport *GetMDImport() { WRAPPER_NO_CONTRACT; - return m_pFile->GetPersistentMDImport(); + return m_pPEAssembly->GetMDImport(); } OBJECTREF GetExposedModuleObjectIfExists() @@ -120,20 +113,20 @@ class DomainFile BOOL IsSystem() { WRAPPER_NO_CONTRACT; - return GetFile()->IsSystem(); + return GetPEAssembly()->IsSystem(); } LPCUTF8 GetSimpleName() { WRAPPER_NO_CONTRACT; - return GetFile()->GetSimpleName(); + return GetPEAssembly()->GetSimpleName(); } #ifdef LOGGING LPCWSTR GetDebugName() { WRAPPER_NO_CONTRACT; - return GetFile()->GetDebugName(); + return GetPEAssembly()->GetDebugName(); } #endif @@ -252,8 +245,8 @@ class DomainFile // ------------------------------------------------------------ #ifndef DACCESS_COMPILE - BOOL Equals(DomainFile *pFile) { WRAPPER_NO_CONTRACT; return GetFile()->Equals(pFile->GetFile()); } - BOOL Equals(PEFile *pFile) { WRAPPER_NO_CONTRACT; return GetFile()->Equals(pFile); } + BOOL Equals(DomainFile *pFile) { WRAPPER_NO_CONTRACT; return GetPEAssembly()->Equals(pFile->GetPEAssembly()); } + BOOL Equals(PEAssembly *pPEAssembly) { WRAPPER_NO_CONTRACT; return GetPEAssembly()->Equals(pPEAssembly); } #endif // DACCESS_COMPILE Module* GetCurrentModule(); @@ -279,7 +272,7 @@ class DomainFile friend class Module; friend class FileLoadLock; - DomainFile(AppDomain *pDomain, PEFile *pFile); + DomainFile(AppDomain *pDomain, PEAssembly *pPEAssembly); BOOL DoIncrementalLoad(FileLoadLevel targetLevel); void ClearLoading() { LIMITED_METHOD_CONTRACT; m_loading = FALSE; } @@ -306,17 +299,13 @@ class DomainFile void SetProfilerNotified() { LIMITED_METHOD_CONTRACT; m_notifyflags|= PROFILER_NOTIFIED; } void SetDebuggerNotified() { LIMITED_METHOD_CONTRACT; m_notifyflags|=DEBUGGER_NOTIFIED; } void SetShouldNotifyDebugger() { LIMITED_METHOD_CONTRACT; m_notifyflags|=DEBUGGER_NEEDNOTIFICATION; } -#ifndef DACCESS_COMPILE - void UpdatePEFileWorker(PTR_PEFile pFile); -#endif // ------------------------------------------------------------ // Instance data // ------------------------------------------------------------ PTR_AppDomain m_pDomain; - PTR_PEFile m_pFile; - PTR_PEFile m_pOriginalFile; // keep file alive just in case someone is sitill using it. If this is not NULL then m_pFile contains reused file from the shared assembly + PTR_PEAssembly m_pPEAssembly; PTR_Module m_pModule; FileLoadLevel m_level; LOADERHANDLE m_hExposedModuleObject; @@ -425,12 +414,6 @@ class DomainAssembly : public DomainFile // Public API // ------------------------------------------------------------ - PEAssembly *GetFile() - { - LIMITED_METHOD_CONTRACT; - return PTR_PEAssembly(m_pFile); - } - LoaderAllocator *GetLoaderAllocator() { LIMITED_METHOD_CONTRACT; @@ -592,7 +575,7 @@ class DomainAssembly : public DomainFile public: ~DomainAssembly(); private: - DomainAssembly(AppDomain *pDomain, PEFile *pFile, LoaderAllocator *pLoaderAllocator); + DomainAssembly(AppDomain *pDomain, PEAssembly *pPEAssembly, LoaderAllocator *pLoaderAllocator); #endif // ------------------------------------------------------------ @@ -606,10 +589,6 @@ class DomainAssembly : public DomainFile void DeliverAsyncEvents(); #endif - void UpdatePEFile(PTR_PEFile pFile); - - BOOL IsInstrumented(); - public: ULONG HashIdentity(); diff --git a/src/coreclr/vm/domainfile.inl b/src/coreclr/vm/domainfile.inl index 91ed0ae4a1ff3..a87d9aaef1309 100644 --- a/src/coreclr/vm/domainfile.inl +++ b/src/coreclr/vm/domainfile.inl @@ -58,39 +58,10 @@ inline Assembly* DomainAssembly::GetAssembly() return m_pAssembly; } -#ifndef DACCESS_COMPILE -inline void DomainFile::UpdatePEFileWorker(PTR_PEFile pFile) -{ - LIMITED_METHOD_CONTRACT; - CONSISTENCY_CHECK(CheckPointer(pFile)); - if (pFile==m_pFile) - return; - _ASSERTE(m_pOriginalFile==NULL); - m_pOriginalFile=m_pFile; - pFile->AddRef(); - m_pFile=pFile; -} - -inline void DomainAssembly::UpdatePEFile(PTR_PEFile pFile) -{ - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - MODE_ANY; - CAN_TAKE_LOCK; - } - CONTRACTL_END; - - GetAppDomain()->UpdatePublishHostedAssembly(this, pFile); -} - -#endif // DACCESS_COMPILE - inline ULONG DomainAssembly::HashIdentity() { WRAPPER_NO_CONTRACT; - return GetFile()->HashIdentity(); + return GetPEAssembly()->HashIdentity(); } inline BOOL DomainAssembly::IsCollectible() diff --git a/src/coreclr/vm/dwbucketmanager.hpp b/src/coreclr/vm/dwbucketmanager.hpp index cf360ac7322a5..21267b8f36070 100644 --- a/src/coreclr/vm/dwbucketmanager.hpp +++ b/src/coreclr/vm/dwbucketmanager.hpp @@ -701,14 +701,14 @@ void BaseBucketParamsManager::GetModuleTimeStamp(__out_ecount(maxLength) WCHAR* { // We only store the IL timestamp in the native image for the // manifest module. We should consider fixing this for Orcas. - PTR_PEFile pFile = pModule->GetAssembly()->GetManifestModule()->GetFile(); + PTR_PEAssembly pFile = pModule->GetAssembly()->GetManifestModule()->GetPEAssembly(); // for dynamic modules use 0 as the time stamp ULONG ulTimeStamp = 0; if (!pFile->IsDynamic()) { - ulTimeStamp = pFile->GetILImageTimeDateStamp(); + ulTimeStamp = pFile->GetPEImageTimeDateStamp(); _ASSERTE(ulTimeStamp != 0); } @@ -957,13 +957,13 @@ bool BaseBucketParamsManager::GetFileVersionInfoForModule(Module* pModule, USHOR bool succeeded = false; - PEFile* pFile = pModule->GetFile(); - if (pFile) + PEAssembly* pPEAssembly = pModule->GetPEAssembly(); + if (pPEAssembly) { // if we failed to get the version info from the native image then fall back to the IL image. if (!succeeded) { - LPCWSTR modulePath = pFile->GetPath().GetUnicode(); + LPCWSTR modulePath = pPEAssembly->GetPath().GetUnicode(); if (modulePath != NULL && modulePath != SString::Empty() && SUCCEEDED(DwGetFileVersionInfo(modulePath, major, minor, build, revision))) { succeeded = true; diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index a93343b112a41..5abf6c7d87c9a 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -314,7 +314,6 @@ FCFuncStart(gCOMModuleFuncs) QCFuncElement("GetScopeName", COMModule::GetScopeName) FCFuncElement("GetTypes", COMModule::GetTypes) QCFuncElement("GetFullyQualifiedName", COMModule::GetFullyQualifiedName) - FCFuncElement("IsResource", COMModule::IsResource) FCFuncEnd() FCFuncStart(gCOMModuleBuilderFuncs) diff --git a/src/coreclr/vm/eedbginterfaceimpl.h b/src/coreclr/vm/eedbginterfaceimpl.h index d4d790c9e886f..72594c336794c 100644 --- a/src/coreclr/vm/eedbginterfaceimpl.h +++ b/src/coreclr/vm/eedbginterfaceimpl.h @@ -26,7 +26,7 @@ #include "debugdebugger.h" #include "eeconfig.h" -#include "pefile.h" +#include "peassembly.h" class EEDbgInterfaceImpl : public EEDebugInterface { diff --git a/src/coreclr/vm/encee.cpp b/src/coreclr/vm/encee.cpp index b11e2d8437068..3f745d299427c 100644 --- a/src/coreclr/vm/encee.cpp +++ b/src/coreclr/vm/encee.cpp @@ -35,8 +35,8 @@ static int g_BreakOnEnCResolveField = -1; // The constructor phase initializes just enough so that Destruct() can be safely called. // It cannot throw or fail. // -EditAndContinueModule::EditAndContinueModule(Assembly *pAssembly, mdToken moduleRef, PEFile *file) - : Module(pAssembly, moduleRef, file) +EditAndContinueModule::EditAndContinueModule(Assembly *pAssembly, mdToken moduleRef, PEAssembly *pPEAssembly) + : Module(pAssembly, moduleRef, pPEAssembly) { CONTRACTL { @@ -175,7 +175,7 @@ HRESULT EditAndContinueModule::ApplyEditAndContinue( { // ConvertMDInternalToReadWrite should only ever be called on EnC capable files. _ASSERTE(IsEditAndContinueCapable()); // this also checks that the file is EnC capable - GetFile()->ConvertMDInternalToReadWrite(); + GetPEAssembly()->ConvertMDInternalToReadWrite(); } EX_CATCH_HRESULT(hr); diff --git a/src/coreclr/vm/encee.h b/src/coreclr/vm/encee.h index 2c7a834f32803..bd20a4057651a 100644 --- a/src/coreclr/vm/encee.h +++ b/src/coreclr/vm/encee.h @@ -202,13 +202,13 @@ class EditAndContinueModule : public Module // Return the minimum permissable address for new IL to be stored at // This can't be less than the current load address because then we'd // have negative RVAs. - BYTE *GetEnCBase() { return (BYTE *) GetFile()->GetManagedFileContents(); } + BYTE *GetEnCBase() { return (BYTE *) GetPEAssembly()->GetManagedFileContents(); } #endif // DACCESS_COMPILE private: // Constructor is invoked only by Module::Create - friend Module *Module::Create(Assembly *pAssembly, mdToken moduleRef, PEFile *file, AllocMemTracker *pamTracker); - EditAndContinueModule(Assembly *pAssembly, mdToken moduleRef, PEFile *file); + friend Module *Module::Create(Assembly *pAssembly, mdToken moduleRef, PEAssembly *pPEAssembly, AllocMemTracker *pamTracker); + EditAndContinueModule(Assembly *pAssembly, mdToken moduleRef, PEAssembly *pPEAssembly); protected: #ifndef DACCESS_COMPILE diff --git a/src/coreclr/vm/eventtrace.cpp b/src/coreclr/vm/eventtrace.cpp index dd36960e257e5..c549018584d70 100644 --- a/src/coreclr/vm/eventtrace.cpp +++ b/src/coreclr/vm/eventtrace.cpp @@ -6135,13 +6135,13 @@ static void GetCodeViewInfo(Module * pModule, CV_INFO_PDB70 * pCvInfoIL, CV_INFO ZeroMemory(pCvInfoIL, sizeof(*pCvInfoIL)); ZeroMemory(pCvInfoNative, sizeof(*pCvInfoNative)); - PTR_PEFile pPEFile = pModule->GetFile(); - _ASSERTE(pPEFile != NULL); + PTR_PEAssembly pPEAssembly = pModule->GetPEAssembly(); + _ASSERTE(pPEAssembly != NULL); PTR_PEImageLayout pLayout = NULL; - if (pPEFile->HasOpenedILimage()) + if (pPEAssembly->HasPEImage()) { - pLayout = pPEFile->GetLoadedIL(); + pLayout = pPEAssembly->GetLoadedLayout(); } if (pLayout == NULL) @@ -6338,7 +6338,7 @@ VOID ETW::LoaderLog::SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL if(!bIsDynamicAssembly) { - ModuleILPath = (PWCHAR)pModule->GetAssembly()->GetManifestFile()->GetILimage()->GetPath().GetUnicode(); + ModuleILPath = (PWCHAR)pModule->GetAssembly()->GetManifestFile()->GetPEImage()->GetPath().GetUnicode(); ModuleNativePath = (PWCHAR)pEmptyString; } diff --git a/src/coreclr/vm/exceptmacros.h b/src/coreclr/vm/exceptmacros.h index 1eba8ca9c47fc..70e1fe0871e0d 100644 --- a/src/coreclr/vm/exceptmacros.h +++ b/src/coreclr/vm/exceptmacros.h @@ -520,7 +520,7 @@ VOID ThrowBadFormatWorkerT(UINT resID, T * pImgObj DEBUGARG(__in_z const char *c // Worker macro for throwing BadImageFormat exceptions. // // resID: resource ID in mscorrc.rc. Message may not have substitutions. resID is permitted (but not encouraged) to be 0. -// imgObj: one of Module* or PEFile* or PEImage* (must support GetPathForErrorMessages method.) +// imgObj: one of Module* or PEAssembly* or PEImage* (must support GetPathForErrorMessages method.) // #define IfFailThrowBF(hresult, resID, imgObj) \ do \ diff --git a/src/coreclr/vm/inlinetracking.cpp b/src/coreclr/vm/inlinetracking.cpp index bfd420850c1bd..86d73ea0a7657 100644 --- a/src/coreclr/vm/inlinetracking.cpp +++ b/src/coreclr/vm/inlinetracking.cpp @@ -45,7 +45,7 @@ bool MethodInModule::operator <(const MethodInModule& other) const } else { - m_module->GetFile()->GetMVID(&thisGuid); + m_module->GetPEAssembly()->GetMVID(&thisGuid); } if (other.m_module == NULL) @@ -54,7 +54,7 @@ bool MethodInModule::operator <(const MethodInModule& other) const } else { - other.m_module->GetFile()->GetMVID(&otherGuid); + other.m_module->GetPEAssembly()->GetMVID(&otherGuid); } return memcmp(&thisGuid, &otherGuid, sizeof(GUID)) < 0; diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 9b6023b4d98d0..3ffb87896fa96 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -984,7 +984,7 @@ void CEEInfo::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken ThrowBadTokenException(pResolvedToken); { - DomainFile *pTargetModule = pModule->LoadModule(GetAppDomain(), metaTOK, FALSE /* loadResources */); + DomainFile *pTargetModule = pModule->LoadModule(GetAppDomain(), metaTOK); if (pTargetModule == NULL) COMPlusThrowHR(COR_E_BADIMAGEFORMAT); th = TypeHandle(pTargetModule->GetModule()->GetGlobalMethodTable()); @@ -7798,14 +7798,14 @@ void CEEInfo::reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd, if (LoggingOn(LF_JIT, LL_INFO100000)) { SString currentMethodName; - currentMethodName.AppendUTF8(m_pMethodBeingCompiled->GetModule_NoLogging()->GetFile()->GetSimpleName()); + currentMethodName.AppendUTF8(m_pMethodBeingCompiled->GetModule_NoLogging()->GetPEAssembly()->GetSimpleName()); currentMethodName.Append(L'/'); TypeString::AppendMethodInternal(currentMethodName, m_pMethodBeingCompiled, TypeString::FormatBasic); SString inlineeMethodName; if (GetMethod(inlineeHnd)) { - inlineeMethodName.AppendUTF8(GetMethod(inlineeHnd)->GetModule_NoLogging()->GetFile()->GetSimpleName()); + inlineeMethodName.AppendUTF8(GetMethod(inlineeHnd)->GetModule_NoLogging()->GetPEAssembly()->GetSimpleName()); inlineeMethodName.Append(L'/'); TypeString::AppendMethodInternal(inlineeMethodName, GetMethod(inlineeHnd), TypeString::FormatBasic); } @@ -7817,7 +7817,7 @@ void CEEInfo::reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd, SString inlinerMethodName; if (GetMethod(inlinerHnd)) { - inlinerMethodName.AppendUTF8(GetMethod(inlinerHnd)->GetModule_NoLogging()->GetFile()->GetSimpleName()); + inlinerMethodName.AppendUTF8(GetMethod(inlinerHnd)->GetModule_NoLogging()->GetPEAssembly()->GetSimpleName()); inlinerMethodName.Append(L'/'); TypeString::AppendMethodInternal(inlinerMethodName, GetMethod(inlinerHnd), TypeString::FormatBasic); } @@ -12815,7 +12815,7 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, LARGE_INTEGER methodJitTimeStop; QueryPerformanceCounter(&methodJitTimeStop); SString codeBase; - ftn->GetModule()->GetDomainFile()->GetFile()->GetCodeBaseOrName(codeBase); + ftn->GetModule()->GetDomainFile()->GetPEAssembly()->GetPathOrCodeBase(codeBase); codeBase.AppendPrintf(W(",0x%x,%d,%d\n"), //(const WCHAR *)codeBase, //module name ftn->GetMemberDef(), //method token diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index f30f3f83daecd..d92fba38536e5 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -481,9 +481,9 @@ LoaderAllocator * LoaderAllocator::GCLoaderAllocators_RemoveAssemblies(AppDomain if (!domainAssemblyToRemove->GetAssembly()->IsDynamic()) { - pAppDomain->RemoveFileFromCache(domainAssemblyToRemove->GetFile()); + pAppDomain->RemoveFileFromCache(domainAssemblyToRemove->GetPEAssembly()); AssemblySpec spec; - spec.InitializeSpec(domainAssemblyToRemove->GetFile()); + spec.InitializeSpec(domainAssemblyToRemove->GetPEAssembly()); VERIFY(pAppDomain->RemoveAssemblyFromCache(domainAssemblyToRemove)); } diff --git a/src/coreclr/vm/memberload.cpp b/src/coreclr/vm/memberload.cpp index ce53bf22589f8..78fdb518a1618 100644 --- a/src/coreclr/vm/memberload.cpp +++ b/src/coreclr/vm/memberload.cpp @@ -277,7 +277,7 @@ void MemberLoader::GetDescFromMemberRef(Module * pModule, { case mdtModuleRef: { - DomainFile *pTargetModule = pModule->LoadModule(GetAppDomain(), parent, FALSE /* loadResources */); + DomainFile *pTargetModule = pModule->LoadModule(GetAppDomain(), parent); if (pTargetModule == NULL) COMPlusThrowHR(COR_E_BADIMAGEFORMAT); typeHnd = TypeHandle(pTargetModule->GetModule()->GetGlobalMethodTable()); diff --git a/src/coreclr/vm/methoditer.cpp b/src/coreclr/vm/methoditer.cpp index 5bd7e81f5de2d..841b3214d2e2d 100644 --- a/src/coreclr/vm/methoditer.cpp +++ b/src/coreclr/vm/methoditer.cpp @@ -83,9 +83,6 @@ BOOL LoadedMethodDescIterator::Next( if (!m_moduleIterator.Next()) goto ADVANCE_ASSEMBLY; - if (GetCurrentModule()->IsResource()) - goto ADVANCE_MODULE; - if (m_mainMD->HasClassInstantiation()) { m_typeIterator.Reset(); diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 8751224545933..90f451a1dfde1 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -4337,9 +4337,8 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList, DWORD rva; IfFailThrow(pInternalImport->GetFieldRVA(pFD->GetMemberDef(), &rva)); - // Ensure that the IL image is loaded. Note that this assembly may - // have an ngen image, but this type may have failed to load during ngen. - GetModule()->GetFile()->LoadLibrary(FALSE); + // Ensure that the IL image is loaded. + GetModule()->GetPEAssembly()->EnsureLoaded(); DWORD fldSize; if (FieldDescElementType == ELEMENT_TYPE_VALUETYPE) @@ -11216,7 +11215,7 @@ BOOL MethodTableBuilder::NeedsAlignedBaseOffset() // Always use the ReadyToRun field layout algorithm if the source IL image was ReadyToRun, independent on // whether ReadyToRun is actually enabled for the module. It is required to allow mixing and matching // ReadyToRun images with and without input bubble enabled. - if (!GetModule()->GetFile()->IsReadyToRun()) + if (!GetModule()->GetPEAssembly()->IsReadyToRun()) { // Always use ReadyToRun field layout algorithm to produce ReadyToRun images return FALSE; diff --git a/src/coreclr/vm/multicorejit.cpp b/src/coreclr/vm/multicorejit.cpp index b94be184959d7..e66e6e39d8f49 100644 --- a/src/coreclr/vm/multicorejit.cpp +++ b/src/coreclr/vm/multicorejit.cpp @@ -255,25 +255,20 @@ bool ModuleVersion::GetModuleVersion(Module * pModule) // GetMVID can throw exception EX_TRY { - PEFile * pFile = pModule->GetFile(); + PEAssembly * pAsm = pModule->GetPEAssembly(); - if (pFile != NULL) + if (pAsm != NULL) { - PEAssembly * pAsm = pFile->GetAssembly(); + // CorAssemblyFlags, only 16-bit used + versionFlags = pAsm->GetFlags(); - if (pAsm != NULL) - { - // CorAssemblyFlags, only 16-bit used - versionFlags = pAsm->GetFlags(); - - _ASSERTE((versionFlags & 0x80000000) == 0); + _ASSERTE((versionFlags & 0x80000000) == 0); - pAsm->GetVersion(& major, & minor, & build, & revision); + pAsm->GetVersion(&major, &minor, &build, &revision); - pAsm->GetMVID(& mvid); + pAsm->GetMVID(&mvid); - hr = S_OK; - } + hr = S_OK; } // If the load context is LOADFROM, store it in the flags. diff --git a/src/coreclr/vm/multicorejitplayer.cpp b/src/coreclr/vm/multicorejitplayer.cpp index d84ed388c9c44..7aae1dadaf873 100644 --- a/src/coreclr/vm/multicorejitplayer.cpp +++ b/src/coreclr/vm/multicorejitplayer.cpp @@ -396,11 +396,6 @@ bool MulticoreJitManager::ModuleHasNoCode(Module * pModule) { LIMITED_METHOD_CONTRACT; - if (pModule->IsResource()) - { - return true; - } - IMDInternalImport * pImport = pModule->GetMDImport(); if (pImport != NULL) @@ -434,15 +429,15 @@ bool MulticoreJitManager::IsSupportedModule(Module * pModule, bool fMethodJit) return false; } - PEFile * pFile = pModule->GetFile(); + PEAssembly * pPEAssembly = pModule->GetPEAssembly(); // dynamic module. - if (pFile->IsDynamic()) // Ignore dynamic modules + if (pPEAssembly->IsDynamic()) // Ignore dynamic modules { return false; } - if (pFile->GetPath().IsEmpty()) // Ignore in-memory modules + if (pPEAssembly->GetPath().IsEmpty()) // Ignore in-memory modules { return false; } diff --git a/src/coreclr/vm/nativeimage.cpp b/src/coreclr/vm/nativeimage.cpp index 13a39a2d4666e..b081091f1b94e 100644 --- a/src/coreclr/vm/nativeimage.cpp +++ b/src/coreclr/vm/nativeimage.cpp @@ -146,8 +146,9 @@ NativeImage *NativeImage::Open( BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(fullPath, /*pathIsBundleRelative */ true); if (bundleFileLocation.IsValid()) { - PEImageHolder pImage = PEImage::OpenImage(fullPath, MDInternalImport_NoCache, bundleFileLocation); - peLoadedImage = pImage->GetLayout(PEImageLayout::LAYOUT_MAPPED, PEImage::LAYOUT_CREATEIFNEEDED); + PEImageHolder pImage = PEImage::OpenImage(fullPath, MDInternalImport_Default, bundleFileLocation); + peLoadedImage = pImage->GetOrCreateLayout(PEImageLayout::LAYOUT_MAPPED); + peLoadedImage.SuppressRelease(); } if (peLoadedImage.IsNull()) diff --git a/src/coreclr/vm/nativeimage.h b/src/coreclr/vm/nativeimage.h index bf3f7b6272edf..4774365197f2b 100644 --- a/src/coreclr/vm/nativeimage.h +++ b/src/coreclr/vm/nativeimage.h @@ -57,7 +57,7 @@ class NativeImageIndexTraits : public NoRemoveSHashTraitsGetManifestFile(); + PEAssembly *pManifestFile = pAssembly->GetManifestFile(); PTR_AssemblyBinder pBinder = pManifestFile->GetAssemblyBinder(); //Step 0: Check if the assembly was bound using TPA. diff --git a/src/coreclr/vm/pefile.cpp b/src/coreclr/vm/peassembly.cpp similarity index 67% rename from src/coreclr/vm/pefile.cpp rename to src/coreclr/vm/peassembly.cpp index 8e7d70732a27f..956512a3dbe06 100644 --- a/src/coreclr/vm/pefile.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -1,14 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // -------------------------------------------------------------------------------- -// PEFile.cpp +// PEAssembly.cpp // // -------------------------------------------------------------------------------- #include "common.h" -#include "pefile.h" +#include "peassembly.h" #include "eecontract.h" #include "eeconfig.h" #include "eventtrace.h" @@ -28,127 +28,19 @@ #ifndef DACCESS_COMPILE -// ================================================================================ -// PEFile class - this is an abstract base class for PEAssembly -// ================================================================================ - -PEFile::PEFile(PEImage *identity) : -#if _DEBUG - m_pDebugName(NULL), -#endif - m_identity(NULL), - m_openedILimage(NULL), - m_MDImportIsRW_Debugger_Use_Only(FALSE), - m_bHasPersistentMDImport(FALSE), - m_pMDImport(NULL), - m_pImporter(NULL), - m_pEmitter(NULL), - m_pMetadataLock(::new SimpleRWLock(PREEMPTIVE, LOCK_TYPE_DEFAULT)), - m_refCount(1), - m_flags(0), - m_pHostAssembly(nullptr), - m_pFallbackBinder(nullptr) -{ - CONTRACTL - { - CONSTRUCTOR_CHECK; - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - if (identity) - { - identity->AddRef(); - m_identity = identity; - - if(identity->IsOpened()) - { - //already opened, prepopulate - identity->AddRef(); - m_openedILimage = identity; - } - } - - -} - - - -PEFile::~PEFile() -{ - CONTRACTL - { - DESTRUCTOR_CHECK; - NOTHROW; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - ReleaseMetadataInterfaces(TRUE); - - - if (m_openedILimage != NULL) - m_openedILimage->Release(); - if (m_identity != NULL) - m_identity->Release(); - if (m_pMetadataLock) - delete m_pMetadataLock; - - if (m_pHostAssembly != NULL) - { - m_pHostAssembly->Release(); - } -} - -/* static */ -PEFile *PEFile::Open(PEImage *image) -{ - CONTRACT(PEFile *) - { - PRECONDITION(image != NULL); - PRECONDITION(image->CheckFormat()); - POSTCONDITION(RETVAL != NULL); - POSTCONDITION(!RETVAL->IsAssembly()); - THROWS; - GC_TRIGGERS; - MODE_ANY; - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACT_END; - - PEFile *pFile = new PEFile(image); - - if (image->HasNTHeaders() && image->HasCorHeader()) - pFile->OpenMDImport_Unsafe(); //no one else can see the object yet - -#if _DEBUG - pFile->m_debugName = image->GetPath(); - pFile->m_debugName.Normalize(); - pFile->m_pDebugName = pFile->m_debugName; -#endif - - RETURN pFile; -} - //----------------------------------------------------------------------------------------------------- // Catch attempts to load x64 assemblies on x86, etc. //----------------------------------------------------------------------------------------------------- -static void ValidatePEFileMachineType(PEFile *peFile) +static void ValidatePEFileMachineType(PEAssembly *pPEAssembly) { STANDARD_VM_CONTRACT; - if (peFile->IsDynamic()) + if (pPEAssembly->IsDynamic()) return; // PEFiles for ReflectionEmit assemblies don't cache the machine type. - if (peFile->IsResource()) - return; // PEFiles for resource assemblies don't cache the machine type. - DWORD peKind; DWORD actualMachineType; - peFile->GetPEKindAndMachine(&peKind, &actualMachineType); + pPEAssembly->GetPEKindAndMachine(&peKind, &actualMachineType); if (actualMachineType == IMAGE_FILE_MACHINE_I386 && ((peKind & (peILonly | pe32BitRequired)) == peILonly)) return; // Image is marked CPU-agnostic. @@ -167,10 +59,7 @@ static void ValidatePEFileMachineType(PEFile *peFile) // Image has required machine that doesn't match the CLR. StackSString name; - if (peFile->IsAssembly()) - ((PEAssembly*)peFile)->GetDisplayName(name); - else - name = StackSString(SString::Utf8, peFile->GetSimpleName()); + pPEAssembly->GetDisplayName(name); COMPlusThrow(kBadImageFormatException, IDS_CLASSLOAD_WRONGCPU, name.GetUnicode()); } @@ -178,12 +67,12 @@ static void ValidatePEFileMachineType(PEFile *peFile) return; // If we got here, all is good. } -void PEFile::LoadLibrary(BOOL allowNativeSkip/*=TRUE*/) // if allowNativeSkip==FALSE force IL image load +void PEAssembly::EnsureLoaded() { CONTRACT_VOID { INSTANCE_CHECK; - POSTCONDITION(CheckLoaded()); + POSTCONDITION(IsLoaded()); STANDARD_VM_CHECK; } CONTRACT_END; @@ -191,142 +80,64 @@ void PEFile::LoadLibrary(BOOL allowNativeSkip/*=TRUE*/) // if allowNativeSkip==F // Catch attempts to load x64 assemblies on x86, etc. ValidatePEFileMachineType(this); - // See if we've already loaded it. - if (CheckLoaded(allowNativeSkip)) + // See if we do not have anything to load or have already loaded it. + if (IsLoaded()) { RETURN; } // Note that we may be racing other threads here, in the case of domain neutral files - // Resource images are always flat. - if (IsResource()) - { - GetILimage()->LoadNoMetaData(); - RETURN; - } - #if !defined(TARGET_64BIT) - if (!GetILimage()->Has32BitNTHeaders()) + if (!GetPEImage()->Has32BitNTHeaders()) { // Tried to load 64-bit assembly on 32-bit platform. EEFileLoadException::Throw(this, COR_E_BADIMAGEFORMAT, NULL); } #endif - // We need contents now - EnsureImageOpened(); - // Since we couldn't call LoadLibrary, we must be an IL only image // or the image may still contain unfixed up stuff - if (!GetILimage()->IsILOnly()) + if (!GetPEImage()->IsILOnly()) { - if (!GetILimage()->HasV1Metadata()) + if (!GetPEImage()->HasV1Metadata()) ThrowHR(COR_E_FIXUPSINEXE); // @todo: better error } - if (GetILimage()->IsFile()) + if (GetPEImage()->IsFile()) { #ifdef TARGET_UNIX - bool loadILImage = GetILimage()->IsILOnly(); + bool loadILImage = GetPEImage()->IsILOnly(); #else // TARGET_UNIX - bool loadILImage = GetILimage()->IsILOnly() && GetILimage()->IsInBundle(); + bool loadILImage = GetPEImage()->IsILOnly() && GetPEImage()->IsInBundle(); #endif // TARGET_UNIX if (loadILImage) { - GetILimage()->Load(); + GetPEImage()->Load(); } else { - GetILimage()->LoadFromMapped(); + GetPEImage()->LoadFromMapped(); } } else { - GetILimage()->LoadNoFile(); - } - - RETURN; -} - -void PEFile::SetLoadedHMODULE(HMODULE hMod) -{ - CONTRACT_VOID - { - INSTANCE_CHECK; - PRECONDITION(CheckPointer(hMod)); - POSTCONDITION(CheckLoaded()); - THROWS; - GC_TRIGGERS; - MODE_ANY; - INJECT_FAULT(COMPlusThrowOM();); + GetPEImage()->LoadNoFile(); } - CONTRACT_END; - - // See if the image is an internal PEImage. - GetILimage()->SetLoadedHMODULE(hMod); RETURN; } -/* static */ -void PEFile::DefineEmitScope( - GUID iid, - void **ppEmit) -{ - CONTRACT_VOID - { - PRECONDITION(CheckPointer(ppEmit)); - POSTCONDITION(CheckPointer(*ppEmit)); - THROWS; - GC_TRIGGERS; - MODE_ANY; - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACT_END; - - SafeComHolder pDispenser; - - // Get the Dispenser interface. - MetaDataGetDispenser( - CLSID_CorMetaDataDispenser, - IID_IMetaDataDispenserEx, - (void **)&pDispenser); - if (pDispenser == NULL) - { - ThrowOutOfMemory(); - } - - // Set the option on the dispenser turn on duplicate check for TypeDef and moduleRef - VARIANT varOption; - V_VT(&varOption) = VT_UI4; - V_I4(&varOption) = MDDupDefault | MDDupTypeDef | MDDupModuleRef | MDDupExportedType | MDDupAssemblyRef | MDDupPermission | MDDupFile; - IfFailThrow(pDispenser->SetOption(MetaDataCheckDuplicatesFor, &varOption)); - - // Set minimal MetaData size - V_VT(&varOption) = VT_UI4; - V_I4(&varOption) = MDInitialSizeMinimal; - IfFailThrow(pDispenser->SetOption(MetaDataInitialSize, &varOption)); - - // turn on the thread safety! - V_I4(&varOption) = MDThreadSafetyOn; - IfFailThrow(pDispenser->SetOption(MetaDataThreadSafetyOptions, &varOption)); - - IfFailThrow(pDispenser->DefineScope(CLSID_CorMetaDataRuntime, 0, iid, (IUnknown **)ppEmit)); - - RETURN; -} // PEFile::DefineEmitScope - // ------------------------------------------------------------ // Identity // ------------------------------------------------------------ -BOOL PEFile::Equals(PEFile *pFile) +BOOL PEAssembly::Equals(PEAssembly *pPEAssembly) { CONTRACTL { INSTANCE_CHECK; - PRECONDITION(CheckPointer(pFile)); + PRECONDITION(CheckPointer(pPEAssembly)); GC_NOTRIGGER; NOTHROW; CANNOT_TAKE_LOCK; @@ -335,36 +146,31 @@ BOOL PEFile::Equals(PEFile *pFile) CONTRACTL_END; // Same object is equal - if (pFile == this) + if (pPEAssembly == this) return TRUE; // Different host assemblies cannot be equal unless they are associated with the same host binder // It's ok if only one has a host binder because multiple threads can race to load the same assembly // and that may cause temporary candidate PEAssembly objects that never get bound to a host assembly // because another thread beats it; the losing thread will pick up the PEAssembly in the cache. - if (pFile->HasHostAssembly() && this->HasHostAssembly()) + if (pPEAssembly->HasHostAssembly() && this->HasHostAssembly()) { - AssemblyBinder* fileBinder = pFile->GetHostAssembly()->GetBinder(); + AssemblyBinder* otherBinder = pPEAssembly->GetHostAssembly()->GetBinder(); AssemblyBinder* thisBinder = this->GetHostAssembly()->GetBinder(); - if (fileBinder != thisBinder || fileBinder == NULL) + if (otherBinder != thisBinder || otherBinder == NULL) return FALSE; } - // Same identity is equal - if (m_identity != NULL && pFile->m_identity != NULL - && m_identity->Equals(pFile->m_identity)) - return TRUE; - // Same image is equal - if (m_openedILimage != NULL && pFile->m_openedILimage != NULL - && m_openedILimage->Equals(pFile->m_openedILimage)) + if (m_PEImage != NULL && pPEAssembly->m_PEImage != NULL + && m_PEImage->Equals(pPEAssembly->m_PEImage)) return TRUE; return FALSE; } -BOOL PEFile::Equals(PEImage *pImage) +BOOL PEAssembly::Equals(PEImage *pImage) { CONTRACTL { @@ -376,21 +182,15 @@ BOOL PEFile::Equals(PEImage *pImage) } CONTRACTL_END; - // Same object is equal - if (pImage == m_identity || pImage == m_openedILimage) + // Same image ==> equal + if (pImage == m_PEImage) return TRUE; - // Same identity is equal - if (m_identity != NULL - && m_identity->Equals(pImage)) + // Equal image ==> equal + if (m_PEImage != NULL + && m_PEImage->Equals(pImage)) return TRUE; - // Same image is equal - if (m_openedILimage != NULL - && m_openedILimage->Equals(pImage)) - return TRUE; - - return FALSE; } @@ -398,7 +198,7 @@ BOOL PEFile::Equals(PEImage *pImage) // Descriptive strings // ------------------------------------------------------------ -void PEFile::GetCodeBaseOrName(SString &result) +void PEAssembly::GetPathOrCodeBase(SString &result) { CONTRACTL { @@ -410,47 +210,21 @@ void PEFile::GetCodeBaseOrName(SString &result) } CONTRACTL_END; - if (m_identity != NULL && !m_identity->GetPath().IsEmpty()) - { - result.Set(m_identity->GetPath()); - } - else if (IsAssembly()) + if (m_PEImage != NULL && !m_PEImage->GetPath().IsEmpty()) { - ((PEAssembly*)this)->GetCodeBase(result); + result.Set(m_PEImage->GetPath()); } else - result.SetUTF8(GetSimpleName()); -} - - -// ------------------------------------------------------------ -// Checks -// ------------------------------------------------------------ - - - -CHECK PEFile::CheckLoaded(BOOL bAllowNativeSkip/*=TRUE*/) -{ - CONTRACT_CHECK { - INSTANCE_CHECK; - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; + GetCodeBase(result); } - CONTRACT_CHECK_END; - - CHECK(IsLoaded(bAllowNativeSkip)); - - CHECK_OK; } - // ------------------------------------------------------------ // Metadata access // ------------------------------------------------------------ -PTR_CVOID PEFile::GetMetadata(COUNT_T *pSize) +PTR_CVOID PEAssembly::GetMetadata(COUNT_T *pSize) { CONTRACT(PTR_CVOID) { @@ -465,8 +239,8 @@ PTR_CVOID PEFile::GetMetadata(COUNT_T *pSize) CONTRACT_END; if (IsDynamic() - || !GetILimage()->HasNTHeaders() - || !GetILimage()->HasCorHeader()) + || !GetPEImage()->HasNTHeaders() + || !GetPEImage()->HasCorHeader()) { if (pSize != NULL) *pSize = 0; @@ -474,12 +248,12 @@ PTR_CVOID PEFile::GetMetadata(COUNT_T *pSize) } else { - RETURN GetILimage()->GetMetadata(pSize); + RETURN GetPEImage()->GetMetadata(pSize); } } #endif // #ifndef DACCESS_COMPILE -PTR_CVOID PEFile::GetLoadedMetadata(COUNT_T *pSize) +PTR_CVOID PEAssembly::GetLoadedMetadata(COUNT_T *pSize) { CONTRACT(PTR_CVOID) { @@ -493,9 +267,9 @@ PTR_CVOID PEFile::GetLoadedMetadata(COUNT_T *pSize) } CONTRACT_END; - if (!HasLoadedIL() - || !GetLoadedIL()->HasNTHeaders() - || !GetLoadedIL()->HasCorHeader()) + if (!HasLoadedPEImage() + || !GetLoadedLayout()->HasNTHeaders() + || !GetLoadedLayout()->HasCorHeader()) { if (pSize != NULL) *pSize = 0; @@ -503,20 +277,19 @@ PTR_CVOID PEFile::GetLoadedMetadata(COUNT_T *pSize) } else { - RETURN GetLoadedIL()->GetMetadata(pSize); + RETURN GetLoadedLayout()->GetMetadata(pSize); } } -TADDR PEFile::GetIL(RVA il) +TADDR PEAssembly::GetIL(RVA il) { CONTRACT(TADDR) { INSTANCE_CHECK; PRECONDITION(il != 0); PRECONDITION(!IsDynamic()); - PRECONDITION(!IsResource()); #ifndef DACCESS_COMPILE - PRECONDITION(CheckLoaded()); + PRECONDITION(HasLoadedPEImage()); #endif POSTCONDITION(RETVAL != NULL); THROWS; @@ -527,8 +300,7 @@ TADDR PEFile::GetIL(RVA il) CONTRACT_END; PEImageLayout *image = NULL; - - image = GetLoadedIL(); + image = GetLoadedLayout(); #ifndef DACCESS_COMPILE // Verify that the IL blob is valid before giving it out @@ -541,7 +313,7 @@ TADDR PEFile::GetIL(RVA il) #ifndef DACCESS_COMPILE -void PEFile::OpenImporter() +void PEAssembly::OpenImporter() { CONTRACTL { @@ -557,7 +329,7 @@ void PEFile::OpenImporter() ConvertMDInternalToReadWrite(); IMetaDataImport2 *pIMDImport = NULL; - IfFailThrow(GetMetaDataPublicInterfaceFromInternal((void*)GetPersistentMDImport(), + IfFailThrow(GetMetaDataPublicInterfaceFromInternal((void*)GetMDImport(), IID_IMetaDataImport2, (void **)&pIMDImport)); @@ -566,7 +338,7 @@ void PEFile::OpenImporter() pIMDImport->Release(); } -void PEFile::ConvertMDInternalToReadWrite() +void PEAssembly::ConvertMDInternalToReadWrite() { CONTRACTL { @@ -617,7 +389,6 @@ void PEFile::ConvertMDInternalToReadWrite() // Swap the pointers in a thread safe manner. If the contents of *ppImport // equals pOld then no other thread got here first, and the old contents are // replaced with pNew. The old contents are returned. - _ASSERTE(m_bHasPersistentMDImport); if (FastInterlockCompareExchangePointer(&m_pMDImport, pNew, pOld) == pOld) { //if the debugger queries, it will now see that we have RW metadata @@ -634,7 +405,7 @@ void PEFile::ConvertMDInternalToReadWrite() } } -void PEFile::OpenMDImport_Unsafe() +void PEAssembly::OpenMDImport() { CONTRACTL { @@ -649,23 +420,21 @@ void PEFile::OpenMDImport_Unsafe() if (m_pMDImport != NULL) return; if (!IsDynamic() - && GetILimage()->HasNTHeaders() - && GetILimage()->HasCorHeader()) + && GetPEImage()->HasNTHeaders() + && GetPEImage()->HasCorHeader()) { - m_pMDImport=GetILimage()->GetMDImport(); + m_pMDImport=GetPEImage()->GetMDImport(); } else { ThrowHR(COR_E_BADIMAGEFORMAT); } - m_bHasPersistentMDImport=TRUE; - _ASSERTE(m_pMDImport); m_pMDImport->AddRef(); } -void PEFile::OpenEmitter() +void PEAssembly::OpenEmitter() { CONTRACTL { @@ -681,7 +450,7 @@ void PEFile::OpenEmitter() ConvertMDInternalToReadWrite(); IMetaDataEmit *pIMDEmit = NULL; - IfFailThrow(GetMetaDataPublicInterfaceFromInternal((void*)GetPersistentMDImport(), + IfFailThrow(GetMetaDataPublicInterfaceFromInternal((void*)GetMDImport(), IID_IMetaDataEmit, (void **)&pIMDEmit)); @@ -690,39 +459,6 @@ void PEFile::OpenEmitter() pIMDEmit->Release(); } - -void PEFile::ReleaseMetadataInterfaces(BOOL bDestructor) -{ - CONTRACTL - { - INSTANCE_CHECK; - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - PRECONDITION(bDestructor||m_pMetadataLock->IsWriterLock()); - } - CONTRACTL_END; - _ASSERTE(bDestructor || !m_bHasPersistentMDImport); - - if (m_pImporter != NULL) - { - m_pImporter->Release(); - m_pImporter = NULL; - } - if (m_pEmitter != NULL) - { - m_pEmitter->Release(); - m_pEmitter = NULL; - } - - if (m_pMDImport != NULL) - { - m_pMDImport->Release(); - m_pMDImport=NULL; - } -} - - // ------------------------------------------------------------ // PE file access // ------------------------------------------------------------ @@ -740,7 +476,7 @@ void PEFile::ReleaseMetadataInterfaces(BOOL bDestructor) // Resource access // ------------------------------------------------------------ -void PEFile::GetEmbeddedResource(DWORD dwOffset, DWORD *cbResource, PBYTE *pbInMemoryResource) +void PEAssembly::GetEmbeddedResource(DWORD dwOffset, DWORD *cbResource, PBYTE *pbInMemoryResource) { CONTRACTL { @@ -756,10 +492,9 @@ void PEFile::GetEmbeddedResource(DWORD dwOffset, DWORD *cbResource, PBYTE *pbInM // m_loadedImage is probably preferable, but this may be called by security // before the image is loaded. - EnsureImageOpened(); - PEImage* image = GetILimage(); + PEImage* image = GetPEImage(); - PEImageLayoutHolder theImage(image->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED)); + PEImageLayout* theImage = image->GetOrCreateLayout(PEImageLayout::LAYOUT_ANY); if (!theImage->CheckResource(dwOffset)) ThrowHR(COR_E_BADIMAGEFORMAT); @@ -774,10 +509,7 @@ void PEFile::GetEmbeddedResource(DWORD dwOffset, DWORD *cbResource, PBYTE *pbInM // File loading // ------------------------------------------------------------ -PEAssembly * -PEFile::LoadAssembly( - mdAssemblyRef kAssemblyRef, - IMDInternalImport * pImport) +PEAssembly* PEAssembly::LoadAssembly(mdAssemblyRef kAssemblyRef) { CONTRACT(PEAssembly *) { @@ -790,9 +522,7 @@ PEFile::LoadAssembly( } CONTRACT_END; - if (pImport == NULL) - pImport = GetPersistentMDImport(); - + IMDInternalImport* pImport = GetMDImport(); if (((TypeFromToken(kAssemblyRef) != mdtAssembly) && (TypeFromToken(kAssemblyRef) != mdtAssemblyRef)) || (!pImport->IsValidToken(kAssemblyRef))) @@ -802,16 +532,16 @@ PEFile::LoadAssembly( AssemblySpec spec; - spec.InitializeSpec(kAssemblyRef, pImport, GetAppDomain()->FindAssembly(GetAssembly())); + spec.InitializeSpec(kAssemblyRef, pImport, GetAppDomain()->FindAssembly(this)); RETURN GetAppDomain()->BindAssemblySpec(&spec, TRUE); } -BOOL PEFile::GetResource(LPCSTR szName, DWORD *cbResource, - PBYTE *pbInMemoryResource, DomainAssembly** pAssemblyRef, - LPCSTR *szFileName, DWORD *dwLocation, - BOOL fSkipRaiseResolveEvent, DomainAssembly* pDomainAssembly, AppDomain* pAppDomain) +BOOL PEAssembly::GetResource(LPCSTR szName, DWORD *cbResource, + PBYTE *pbInMemoryResource, DomainAssembly** pAssemblyRef, + LPCSTR *szFileName, DWORD *dwLocation, + BOOL fSkipRaiseResolveEvent, DomainAssembly* pDomainAssembly, AppDomain* pAppDomain) { CONTRACTL { @@ -829,11 +559,11 @@ BOOL PEFile::GetResource(LPCSTR szName, DWORD *cbResource, DWORD dwOffset; mdManifestResource mdResource; Assembly* pAssembly = NULL; - PEFile* pPEFile = NULL; - ReleaseHolder pImport (GetMDImportWithRef()); + PEAssembly* pPEAssembly = NULL; + IMDInternalImport* pImport = GetMDImport(); if (SUCCEEDED(pImport->FindManifestResourceByName(szName, &mdResource))) { - pPEFile = this; + pPEAssembly = this; IfFailThrow(pImport->GetManifestResourceProps( mdResource, NULL, //&szName, @@ -846,13 +576,13 @@ BOOL PEFile::GetResource(LPCSTR szName, DWORD *cbResource, if (fSkipRaiseResolveEvent || pAppDomain == NULL) return FALSE; - DomainAssembly* pParentAssembly = GetAppDomain()->FindAssembly(GetAssembly()); + DomainAssembly* pParentAssembly = GetAppDomain()->FindAssembly(this); pAssembly = pAppDomain->RaiseResourceResolveEvent(pParentAssembly, szName); if (pAssembly == NULL) return FALSE; pDomainAssembly = pAssembly->GetDomainAssembly(); - pPEFile = pDomainAssembly->GetFile(); + pPEAssembly = pDomainAssembly->GetPEAssembly(); if (FAILED(pAssembly->GetManifestImport()->FindManifestResourceByName( szName, @@ -868,7 +598,7 @@ BOOL PEFile::GetResource(LPCSTR szName, DWORD *cbResource, *dwLocation = *dwLocation | 2; // ResourceLocation.containedInAnotherAssembly } - IfFailThrow(pPEFile->GetPersistentMDImport()->GetManifestResourceProps( + IfFailThrow(pPEAssembly->GetMDImport()->GetManifestResourceProps( mdResource, NULL, //&szName, &mdLinkRef, @@ -884,7 +614,7 @@ BOOL PEFile::GetResource(LPCSTR szName, DWORD *cbResource, return FALSE; AssemblySpec spec; - spec.InitializeSpec(mdLinkRef, GetPersistentMDImport(), pDomainAssembly); + spec.InitializeSpec(mdLinkRef, GetMDImport(), pDomainAssembly); pDomainAssembly = spec.LoadDomainAssembly(FILE_LOADED); if (dwLocation) { @@ -915,7 +645,7 @@ BOOL PEFile::GetResource(LPCSTR szName, DWORD *cbResource, return TRUE; } - pPEFile->GetEmbeddedResource(dwOffset, cbResource, pbInMemoryResource); + pPEAssembly->GetEmbeddedResource(dwOffset, cbResource, pbInMemoryResource); return TRUE; } @@ -926,24 +656,23 @@ BOOL PEFile::GetResource(LPCSTR szName, DWORD *cbResource, } } -void PEFile::GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine) +void PEAssembly::GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine) { WRAPPER_NO_CONTRACT; - if (IsResource() || IsDynamic()) + _ASSERTE(pdwKind != NULL && pdwMachine != NULL); + if (IsDynamic()) { - if (pdwKind) - *pdwKind = 0; - if (pdwMachine) - *pdwMachine = 0; + *pdwKind = 0; + *pdwMachine = 0; return; } - GetILimage()->GetPEKindAndMachine(pdwKind, pdwMachine); + GetPEImage()->GetPEKindAndMachine(pdwKind, pdwMachine); return; } -ULONG PEFile::GetILImageTimeDateStamp() +ULONG PEAssembly::GetPEImageTimeDateStamp() { CONTRACTL { @@ -953,62 +682,63 @@ ULONG PEFile::GetILImageTimeDateStamp() } CONTRACTL_END; - return GetLoadedIL()->GetTimeDateStamp(); -} - - -// ================================================================================ -// PEAssembly class - a PEFile which represents an assembly -// ================================================================================ - -// Statics initialization. -/* static */ -void PEAssembly::Attach() -{ - STANDARD_VM_CONTRACT; + return GetLoadedLayout()->GetTimeDateStamp(); } #ifndef DACCESS_COMPILE + PEAssembly::PEAssembly( BINDER_SPACE::Assembly* pBindResultInfo, IMetaDataEmit* pEmit, - PEFile *creator, - BOOL system, - PEImage * pPEImageIL /*= NULL*/, + PEAssembly *creator, + BOOL isSystem, + PEImage * pPEImage /*= NULL*/, BINDER_SPACE::Assembly * pHostAssembly /*= NULL*/) - - : PEFile(pBindResultInfo ? pBindResultInfo->GetPEImage() - : pPEImageIL), - m_creator(clr::SafeAddRef(creator)) { CONTRACTL { CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(pEmit, NULL_OK)); PRECONDITION(CheckPointer(creator, NULL_OK)); - PRECONDITION(pBindResultInfo == NULL || pPEImageIL == NULL); + PRECONDITION(pBindResultInfo == NULL || pPEImage == NULL); STANDARD_VM_CHECK; } CONTRACTL_END; - m_flags |= PEFILE_ASSEMBLY; - if (system) - m_flags |= PEFILE_SYSTEM; + m_creator = clr::SafeAddRef(creator); +#if _DEBUG + m_pDebugName = NULL; +#endif + m_PEImage = NULL; + m_MDImportIsRW_Debugger_Use_Only = FALSE; + m_pMDImport = NULL; + m_pImporter = NULL; + m_pEmitter = NULL; + m_refCount = 1; + m_isSystem = isSystem; + m_pHostAssembly = nullptr; + m_pFallbackBinder = nullptr; - // We require a mapping for the file. - EnsureImageOpened(); + pPEImage = pBindResultInfo ? pBindResultInfo->GetPEImage() : pPEImage; + if (pPEImage) + { + _ASSERTE(pPEImage->CheckUniqueInstance()); + pPEImage->AddRef(); + + // We require a mapping for the file. + pPEImage->GetOrCreateLayout(PEImageLayout::LAYOUT_ANY); + m_PEImage = pPEImage; + } // Open metadata eagerly to minimize failure windows if (pEmit == NULL) - OpenMDImport_Unsafe(); //constructor, cannot race with anything + OpenMDImport(); //constructor, cannot race with anything else { - _ASSERTE(!m_bHasPersistentMDImport); IfFailThrow(GetMetaDataInternalInterfaceFromPublic(pEmit, IID_IMDInternalImport, (void **)&m_pMDImport)); m_pEmitter = pEmit; pEmit->AddRef(); - m_bHasPersistentMDImport=TRUE; m_MDImportIsRW_Debugger_Use_Only = TRUE; } @@ -1040,7 +770,7 @@ PEAssembly::PEAssembly( } #if _DEBUG - GetCodeBaseOrName(m_debugName); + GetPathOrCodeBase(m_debugName); m_debugName.Normalize(); m_pDebugName = m_debugName; #endif @@ -1058,7 +788,7 @@ PEAssembly *PEAssembly::Open( PEAssembly * pPEAssembly = new PEAssembly( nullptr, // BindResult nullptr, // IMetaDataEmit - pParent, // PEFile creator + pParent, // PEAssembly creator FALSE, // isSystem pPEImageIL, pHostAssembly); @@ -1082,6 +812,29 @@ PEAssembly::~PEAssembly() if (m_creator != NULL) m_creator->Release(); + if (m_pImporter != NULL) + { + m_pImporter->Release(); + m_pImporter = NULL; + } + + if (m_pEmitter != NULL) + { + m_pEmitter->Release(); + m_pEmitter = NULL; + } + + if (m_pMDImport != NULL) + { + m_pMDImport->Release(); + m_pMDImport = NULL; + } + + if (m_PEImage != NULL) + m_PEImage->Release(); + + if (m_pHostAssembly != NULL) + m_pHostAssembly->Release(); } /* static */ @@ -1126,12 +879,9 @@ PEAssembly *PEAssembly::DoOpenSystem() RETURN new PEAssembly(pBoundAssembly, NULL, NULL, TRUE); } -PEAssembly* PEAssembly::Open(BINDER_SPACE::Assembly* pBindResult, - BOOL isSystem) +PEAssembly* PEAssembly::Open(BINDER_SPACE::Assembly* pBindResult) { - - return new PEAssembly(pBindResult,NULL,NULL,isSystem); - + return new PEAssembly(pBindResult,NULL,NULL, /*isSystem*/ false); }; /* static */ @@ -1151,15 +901,12 @@ PEAssembly *PEAssembly::Create(PEAssembly *pParentAssembly, // we have.) SafeComHolder pEmit; pAssemblyEmit->QueryInterface(IID_IMetaDataEmit, (void **)&pEmit); - PEAssemblyHolder pFile(new PEAssembly(NULL, pEmit, pParentAssembly, FALSE)); - RETURN pFile.Extract(); + RETURN new PEAssembly(NULL, pEmit, pParentAssembly, FALSE); } - #endif // #ifndef DACCESS_COMPILE - #ifndef DACCESS_COMPILE // ------------------------------------------------------------ @@ -1179,23 +926,23 @@ const SString &PEAssembly::GetEffectivePath() } CONTRACTL_END; - PEAssembly *pAssembly = this; + PEAssembly* pPEAssembly = this; - while (pAssembly->m_identity == NULL - || pAssembly->m_identity->GetPath().IsEmpty()) + while (pPEAssembly->m_PEImage == NULL + || pPEAssembly->m_PEImage->GetPath().IsEmpty()) { - if (pAssembly->m_creator) - pAssembly = pAssembly->m_creator->GetAssembly(); + if (pPEAssembly->m_creator) + pPEAssembly = pPEAssembly->m_creator; else // Unmanaged exe which loads byte[]/IStream assemblies return SString::Empty(); } - return pAssembly->m_identity->GetPath(); + return pPEAssembly->m_PEImage->GetPath(); } // Codebase is the fusion codebase or path for the assembly. It is in URL format. -// Note this may be obtained from the parent PEFile if we don't have a path or fusion +// Note this may be obtained from the parent PEAssembly if we don't have a path or fusion // assembly. // Returns false if the assembly was loaded from a bundle, true otherwise BOOL PEAssembly::GetCodeBase(SString &result) @@ -1210,13 +957,14 @@ BOOL PEAssembly::GetCodeBase(SString &result) } CONTRACTL_END; - auto ilImage = GetILimage(); - if (ilImage == nullptr || !ilImage->IsInBundle()) + PEImage* ilImage = GetPEImage(); + if (ilImage == NULL || !ilImage->IsInBundle()) { // All other cases use the file path. result.Set(GetEffectivePath()); if (!result.IsEmpty()) PathToUrl(result); + return TRUE; } else @@ -1322,7 +1070,7 @@ BOOL PEAssembly::FindLastPathSeparator(const SString &path, SString::Iterator &i // Metadata access // ------------------------------------------------------------ -HRESULT PEFile::GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHORT *pRevision) +HRESULT PEAssembly::GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHORT *pRevision) { CONTRACTL { @@ -1337,19 +1085,11 @@ HRESULT PEFile::GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHOR } CONTRACTL_END; - AssemblyMetaDataInternal md; + _ASSERTE(GetMDImport()->IsValidToken(TokenFromRid(1, mdtAssembly))); + HRESULT hr = S_OK;; - if (m_bHasPersistentMDImport) - { - _ASSERTE(GetPersistentMDImport()->IsValidToken(TokenFromRid(1, mdtAssembly))); - IfFailRet(GetPersistentMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, &md, NULL)); - } - else - { - ReleaseHolder pImport(GetMDImportWithRef()); - _ASSERTE(pImport->IsValidToken(TokenFromRid(1, mdtAssembly))); - IfFailRet(pImport->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, &md, NULL)); - } + AssemblyMetaDataInternal md; + IfFailRet(GetMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, &md, NULL)); if (pMajor != NULL) *pMajor = md.usMajorVersion; @@ -1360,55 +1100,30 @@ HRESULT PEFile::GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHOR if (pRevision != NULL) *pRevision = md.usRevisionNumber; - return hr; -} - - - -void PEFile::EnsureImageOpened() -{ - WRAPPER_NO_CONTRACT; - if (IsDynamic()) - return; - - GetILimage()->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED)->Release(); + return S_OK; } #endif // #ifndef DACCESS_COMPILE #ifdef DACCESS_COMPILE -void -PEFile::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) +void PEAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - // sizeof(PEFile) == 0xb8 DAC_ENUM_VTHIS(); - EMEM_OUT(("MEM: %p PEFile\n", dac_cast(this))); + EMEM_OUT(("MEM: %p PEAssembly\n", dac_cast(this))); #ifdef _DEBUG // Not a big deal if it's NULL or fails. m_debugName.EnumMemoryRegions(flags); #endif - if (m_identity.IsValid()) + if (m_PEImage.IsValid()) { - m_identity->EnumMemoryRegions(flags); + m_PEImage->EnumMemoryRegions(flags); } - if (GetILimage().IsValid()) - { - GetILimage()->EnumMemoryRegions(flags); - } -} - -void -PEAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) -{ - WRAPPER_NO_CONTRACT; - - PEFile::EnumMemoryRegions(flags); if (m_creator.IsValid()) { @@ -1426,7 +1141,7 @@ PEAssembly::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) // It can return an empty if the name isn't available or the object isn't initialized // enough to get a name, but it mustn't crash. //------------------------------------------------------------------------------- -LPCWSTR PEFile::GetPathForErrorMessages() +LPCWSTR PEAssembly::GetPathForErrorMessages() { CONTRACTL { @@ -1439,7 +1154,7 @@ LPCWSTR PEFile::GetPathForErrorMessages() if (!IsDynamic()) { - return m_identity->GetPathForErrorMessages(); + return m_PEImage->GetPathForErrorMessages(); } else { @@ -1449,7 +1164,7 @@ LPCWSTR PEFile::GetPathForErrorMessages() #ifdef DACCESS_COMPILE -TADDR PEFile::GetMDInternalRWAddress() +TADDR PEAssembly::GetMDInternalRWAddress() { if (!m_MDImportIsRW_Debugger_Use_Only) return 0; @@ -1467,13 +1182,13 @@ TADDR PEFile::GetMDInternalRWAddress() // 3) ASSUMPTION: We are assuming that no pointer adjustment is required to convert between // IMDInternalImport*, IMDInternalImportENC* and MDInternalRW*. Ideally I was hoping to do this with a // static_cast<> but the compiler complains that the ENC<->RW is an unrelated conversion. - return (TADDR) m_pMDImport_UseAccessor; + return (TADDR)m_pMDImport_UseAccessor; } } #endif -// Returns the AssemblyBinder* instance associated with the PEFile -PTR_AssemblyBinder PEFile::GetAssemblyBinder() +// Returns the AssemblyBinder* instance associated with the PEAssembly +PTR_AssemblyBinder PEAssembly::GetAssemblyBinder() { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/pefile.h b/src/coreclr/vm/peassembly.h similarity index 57% rename from src/coreclr/vm/pefile.h rename to src/coreclr/vm/peassembly.h index 317c9c544228f..adc19df11bc9b 100644 --- a/src/coreclr/vm/pefile.h +++ b/src/coreclr/vm/peassembly.h @@ -1,14 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // -------------------------------------------------------------------------------- -// PEFile.h +// PEAssembly.h // // -------------------------------------------------------------------------------- -#ifndef PEFILE_H_ -#define PEFILE_H_ +#ifndef PEASSEMBLY_H_ +#define PEASSEMBLY_H_ // -------------------------------------------------------------------------------- // Required headers @@ -41,7 +41,6 @@ class Module; class EditAndContinueModule; -class PEFile; class PEAssembly; class SimpleRWLock; @@ -52,23 +51,25 @@ typedef VPTR(PEAssembly) PTR_PEAssembly; // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- -// A PEFile is an input to the CLR loader. It is produced as a result of +// A PEAssembly is an input to the CLR loader. It is produced as a result of // binding, usually through fusion (although there are a few less common methods to // obtain one which do not go through fusion, e.g. IJW loads) // -// Although a PEFile is usually a disk based PE file (hence the name), it is not +// Although a PEAssembly is usually a disk based PE file, it is not // always the case. Thus it is a conscious decision to not export access to the PE // file directly; rather the specific information required should be provided via // individual query API. // -// There are multiple "flavors" of PEFiles: +// There are multiple "flavors" of PEAssemblies: // // 1. HMODULE - these PE Files are loaded in response to "spontaneous" OS callbacks. // These should only occur for .exe main modules and IJW dlls loaded via LoadLibrary // or static imports in umnanaged code. +// These get their PEImage loaded directly in PEImage::LoadImage(HMODULE hMod) // -// 2. Fusion loads - these are the most common case. A path is obtained from fusion and -// the result is loaded via PEImage. +// 2. Assemblies loaded directly or indirectly by the managed code - these are the most +// common case. A path is obtained from assembly binding and the result is loaded +// via PEImage: // a. Display name loads - these are metadata-based binds // b. Path loads - these are loaded from an explicit path // @@ -78,19 +79,14 @@ typedef VPTR(PEAssembly) PTR_PEAssembly; // for reflection-based modules. // // See also file:..\inc\corhdr.h#ManagedHeader for more on the format of managed images. -// See code:Module for more on modules // -------------------------------------------------------------------------------- -typedef VPTR(class PEFile) PTR_PEFile; - -typedef ReleaseHolder IMDInternalImportHolder; - -class PEFile +class PEAssembly final { // ------------------------------------------------------------ // SOS support // ------------------------------------------------------------ - VPTR_BASE_CONCRETE_VTABLE_CLASS(PEFile) + VPTR_BASE_CONCRETE_VTABLE_CLASS(PEAssembly) public: @@ -109,54 +105,15 @@ class PEFile CHECK Invariant(); #endif -private: - // ------------------------------------------------------------ - // Loader access API - // ------------------------------------------------------------ - - friend class DomainFile; - -public: - void LoadLibrary(BOOL allowNativeSkip = TRUE); - - -private: - // For use inside LoadLibrary callback - void SetLoadedHMODULE(HMODULE hMod); - - // DO NOT USE !!! this is to be removed when we move to new fusion binding API - friend class DomainAssembly; - - // Helper for creating metadata for CreateDynamic - friend class Assembly; - friend class COMDynamicWrite; - friend class AssemblyNative; - static void DefineEmitScope( - GUID iid, - void **ppEmit); - -protected: - IMDInternalImportHolder GetMDImport(); - -public: - // ------------------------------------------------------------ - // Generic PEFile - can be used to access metadata - // ------------------------------------------------------------ - - static PEFile *Open(PEImage *image); - // ------------------------------------------------------------ // Identity // ------------------------------------------------------------ #ifndef DACCESS_COMPILE - BOOL Equals(PEFile *pFile); + BOOL Equals(PEAssembly *pPEAssembly); BOOL Equals(PEImage *pImage); #endif // DACCESS_COMPILE - - void GetMVID(GUID *pMvid); - // ------------------------------------------------------------ // Descriptive strings // ------------------------------------------------------------ @@ -170,8 +127,22 @@ class PEFile const SString &GetModuleFileNameHint(); #endif // DACCESS_COMPILE + LPCWSTR GetPathForErrorMessages(); + + // This returns a non-empty path representing the source of the assembly; it may + // be the parent assembly for dynamic or memory assemblies + const SString& GetEffectivePath(); + + // Codebase is the fusion codebase or path for the assembly. It is in URL format. + // Note this may be obtained from the parent PEAssembly if we don't have a path or fusion + // assembly. + BOOL GetCodeBase(SString& result); + // Full name is the most descriptive name available (path, codebase, or name as appropriate) - void GetCodeBaseOrName(SString &result); + void GetPathOrCodeBase(SString& result); + + // Display name is the fusion binding name for an assembly + void GetDisplayName(SString& result, DWORD flags = 0); #ifdef LOGGING // This is useful for log messages @@ -182,68 +153,49 @@ class PEFile // Checks // ------------------------------------------------------------ - CHECK CheckLoaded(BOOL allowNativeSkip = TRUE); void ValidateForExecution(); BOOL IsMarkedAsNoPlatform(); - // ------------------------------------------------------------ // Classification // ------------------------------------------------------------ - BOOL IsAssembly() const; - PTR_PEAssembly AsAssembly(); BOOL IsSystem() const; BOOL IsDynamic() const; - BOOL IsResource() const; - BOOL IsIStream() const; - // Returns self (if assembly) or containing assembly (if module) - PEAssembly *GetAssembly() const; // ------------------------------------------------------------ // Metadata access // ------------------------------------------------------------ - BOOL HasMetadata(); - - IMDInternalImport *GetPersistentMDImport(); - IMDInternalImport *GetMDImportWithRef(); - void MakeMDImportPersistent() {m_bHasPersistentMDImport=TRUE;}; + IMDInternalImport *GetMDImport(); #ifndef DACCESS_COMPILE IMetaDataEmit *GetEmitter(); - IMetaDataAssemblyEmit *GetAssemblyEmitter(); IMetaDataImport2 *GetRWImporter(); - IMetaDataAssemblyImport *GetAssemblyImporter(); #else TADDR GetMDInternalRWAddress(); #endif // DACCESS_COMPILE + void ConvertMDInternalToReadWrite(); + + void GetMVID(GUID* pMvid); + ULONG GetHashAlgId(); + HRESULT GetVersion(USHORT* pMajor, USHORT* pMinor, USHORT* pBuild, USHORT* pRevision); + BOOL IsStrongNamed(); LPCUTF8 GetSimpleName(); HRESULT GetScopeName(LPCUTF8 * pszName); - BOOL IsStrongNameVerified(); - BOOL IsStrongNamed(); const void *GetPublicKey(DWORD *pcbPK); - ULONG GetHashAlgId(); - HRESULT GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHORT *pRevision); LPCSTR GetLocale(); DWORD GetFlags(); - HRESULT GetFlagsNoTrigger(DWORD * pdwFlags); + // ------------------------------------------------------------ // PE file access // ------------------------------------------------------------ - BOOL IsIbcOptimized(); BOOL IsReadyToRun(); - WORD GetSubsystem(); - mdToken GetEntryPointToken( -#ifdef _DEBUG - BOOL bAssumeLoaded = FALSE -#endif //_DEBUG - ); - BOOL IsILOnly(); - BOOL IsDll(); + mdToken GetEntryPointToken(); + BOOL IsILOnly(); TADDR GetIL(RVA il); PTR_VOID GetRvaField(RVA field); @@ -266,15 +218,14 @@ class PEFile LPCSTR *szFileName, DWORD *dwLocation, BOOL fSkipRaiseResolveEvent, DomainAssembly* pDomainAssembly, AppDomain* pAppDomain); + #ifndef DACCESS_COMPILE PTR_CVOID GetMetadata(COUNT_T *pSize); #endif - PTR_CVOID GetLoadedMetadata(COUNT_T *pSize); + PTR_CVOID GetLoadedMetadata(COUNT_T *pSize); void GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine); - - ULONG GetILImageTimeDateStamp(); - + ULONG GetPEImageTimeDateStamp(); // ------------------------------------------------------------ // Image memory access @@ -288,32 +239,54 @@ class PEFile // in the no-IL image case. // ------------------------------------------------------------ + BOOL HasPEImage() + { + LIMITED_METHOD_DAC_CONTRACT; + return m_PEImage != NULL; + } + + PEImage* GetPEImage() + { + LIMITED_METHOD_DAC_CONTRACT; + return m_PEImage; + } + + void EnsureLoaded(); + + BOOL HasLoadedPEImage() + { + LIMITED_METHOD_DAC_CONTRACT; + return HasPEImage() && GetPEImage()->HasLoadedLayout(); + } + + PTR_PEImageLayout GetLoadedLayout() + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + _ASSERTE(HasPEImage()); + return GetPEImage()->GetLoadedLayout(); + }; + + BOOL IsLoaded() + { + return IsDynamic() || HasLoadedPEImage(); + } + + BOOL IsPtrInPEImage(PTR_CVOID data); + // For IJW purposes only - this asserts that we have an IJW image. HMODULE GetIJWBase(); // The debugger can tolerate a null value here for native only loading cases - PTR_VOID GetDebuggerContents(COUNT_T *pSize = NULL); + PTR_VOID GetDebuggerContents(COUNT_T* pSize = NULL); #ifndef DACCESS_COMPILE // Returns the IL image range; may force a LoadLibrary - const void *GetManagedFileContents(COUNT_T *pSize = NULL); + const void* GetManagedFileContents(COUNT_T* pSize = NULL); #endif // DACCESS_COMPILE - PTR_CVOID GetLoadedImageContents(COUNT_T *pSize = NULL); - - // ------------------------------------------------------------ - // Native image access - // ------------------------------------------------------------ - - // Does the loader support using a native image for this file? - // Some implementation restrictions prevent native images from being used - // in some cases. - PTR_PEImageLayout GetLoaded(); - PTR_PEImageLayout GetLoadedIL(); - IStream * GetPdbStream(); - void ClearPdbStream(); - BOOL IsLoaded(BOOL bAllowNativeSkip=TRUE) ; - BOOL IsPtrInILImage(PTR_CVOID data); + PTR_CVOID GetLoadedImageContents(COUNT_T* pSize = NULL); // ------------------------------------------------------------ // Resource access @@ -325,141 +298,18 @@ class PEFile // File loading // ------------------------------------------------------------ - PEAssembly * LoadAssembly( - mdAssemblyRef kAssemblyRef, - IMDInternalImport * pImport = NULL); - -protected: - // ------------------------------------------------------------ - // Internal constants - // ------------------------------------------------------------ - - enum - { - PEFILE_SYSTEM = 0x01, - PEFILE_ASSEMBLY = 0x02, - }; - - // ------------------------------------------------------------ - // Internal routines - // ------------------------------------------------------------ - -#ifndef DACCESS_COMPILE - PEFile(PEImage *image); - virtual ~PEFile(); -#else - virtual ~PEFile() {} -#endif - - void OpenMDImport(); - void OpenMDImport_Unsafe(); - void OpenImporter(); - void OpenEmitter(); - - void ReleaseMetadataInterfaces(BOOL bDestructor); - - - friend class Module; - -#ifndef DACCESS_COMPILE - void EnsureImageOpened(); -#endif // DACCESS_COMPILE - - friend class ClrDataAccess; + PEAssembly * LoadAssembly(mdAssemblyRef kAssemblyRef); // ------------------------------------------------------------ - // Instance fields + // Assembly Binder and host assembly (BINDER_SPACE::Assembly) // ------------------------------------------------------------ -#ifdef _DEBUG - LPCWSTR m_pDebugName; - SString m_debugName; -#endif - - // Identity image - PTR_PEImage m_identity; - // IL image, NULL if we didn't need to open the file - PTR_PEImage m_openedILimage; - // This flag is not updated atomically with m_pMDImport. Its fine for debugger usage - // but don't rely on it in the runtime. In runtime try QI'ing the m_pMDImport for - // IID_IMDInternalImportENC - BOOL m_MDImportIsRW_Debugger_Use_Only; - Volatile m_bHasPersistentMDImport; - -#ifndef DACCESS_COMPILE - IMDInternalImport *m_pMDImport; -#else - IMDInternalImport *m_pMDImport_UseAccessor; -#endif - IMetaDataImport2 *m_pImporter; - IMetaDataEmit *m_pEmitter; - SimpleRWLock *m_pMetadataLock; - Volatile m_refCount; - int m_flags; - -public: - - PTR_PEImage GetILimage() - { - CONTRACTL - { - THROWS; - MODE_ANY; - GC_TRIGGERS; - } - CONTRACTL_END; -#ifndef DACCESS_COMPILE - if (m_openedILimage == NULL && m_identity != NULL) - { - PEImage* pOpenedILimage; - m_identity->Clone(MDInternalImport_Default,&pOpenedILimage); - if (InterlockedCompareExchangeT(&m_openedILimage,pOpenedILimage,NULL) != NULL) - pOpenedILimage->Release(); - } -#endif - return m_openedILimage; - } - - PEImage *GetOpenedILimage() - { - LIMITED_METHOD_DAC_CONTRACT; - _ASSERTE(HasOpenedILimage()); - return m_openedILimage; - } - - - BOOL HasOpenedILimage() - { - LIMITED_METHOD_DAC_CONTRACT; - return m_openedILimage != NULL; - - } - - BOOL HasLoadedIL() + bool HasHostAssembly() { - LIMITED_METHOD_DAC_CONTRACT; - return HasOpenedILimage() && GetOpenedILimage()->HasLoadedLayout(); + STATIC_CONTRACT_WRAPPER; + return GetHostAssembly() != NULL; } - LPCWSTR GetPathForErrorMessages(); - - static PEFile* Dummy(); - - void ConvertMDInternalToReadWrite(); - -protected: - PTR_BINDER_SPACE_Assembly m_pHostAssembly; - - // For certain assemblies, we do not have m_pHostAssembly since they are not bound using an actual binder. - // An example is Ref-Emitted assemblies. Thus, when such assemblies trigger load of their dependencies, - // we need to ensure they are loaded in appropriate load context. - // - // To enable this, we maintain a concept of "FallbackBinder", which will be set to the Binder of the - // assembly that created the dynamic assembly. If the creator assembly is dynamic itself, then its fallback - // load context would be propagated to the assembly being dynamically generated. - PTR_AssemblyBinder m_pFallbackBinder; - -public: // Returns a non-AddRef'ed BINDER_SPACE::Assembly* PTR_BINDER_SPACE_Assembly GetHostAssembly() { @@ -467,8 +317,9 @@ class PEFile return m_pHostAssembly; } - // Returns the AssemblyBinder* instance associated with the PEFile - // which owns the context into which the current PEFile was loaded. + // Returns the AssemblyBinder* instance associated with the PEAssembly + // which owns the context into which the current PEAssembly was loaded. + // For Dynamic assemblies this is the fallback binder. PTR_AssemblyBinder GetAssemblyBinder(); #ifndef DACCESS_COMPILE @@ -480,8 +331,7 @@ class PEFile #endif //!DACCESS_COMPILE - bool HasHostAssembly() - { STATIC_CONTRACT_WRAPPER; return GetHostAssembly() != nullptr; } + ULONG HashIdentity(); PTR_AssemblyBinder GetFallbackBinder() { @@ -489,111 +339,122 @@ class PEFile return m_pFallbackBinder; } -}; // class PEFile - - -class PEAssembly : public PEFile -{ - VPTR_VTABLE_CLASS(PEAssembly, PEFile) - public: // ------------------------------------------------------------ - // Statics initialization. - // ------------------------------------------------------------ - static - void Attach(); - - // ------------------------------------------------------------ - // Public API + // Creation entry points // ------------------------------------------------------------ // CoreCLR's PrivBinder PEAssembly creation entrypoint - static PEAssembly * Open( - PEAssembly * pParent, - PEImage * pPEImageIL, - BINDER_SPACE::Assembly * pHostAssembly); + static PEAssembly* Open( + PEAssembly* pParent, + PEImage* pPEImageIL, + BINDER_SPACE::Assembly* pHostAssembly); // This opens the canonical System.Private.CoreLib.dll - static PEAssembly *OpenSystem(); -#ifdef DACCESS_COMPILE - virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); -#endif + static PEAssembly* OpenSystem(); - static PEAssembly *Open( - BINDER_SPACE::Assembly* pBindResult, - BOOL isSystem); + static PEAssembly* Open(BINDER_SPACE::Assembly* pBindResult); - static PEAssembly *Create( - PEAssembly *pParentAssembly, - IMetaDataAssemblyEmit *pEmit); + static PEAssembly* Create( + PEAssembly* pParentAssembly, + IMetaDataAssemblyEmit* pEmit); - private: - // Private helpers for crufty exception handling reasons - static PEAssembly *DoOpenSystem(); + // ------------------------------------------------------------ + // Utility functions + // ------------------------------------------------------------ - public: + static void PathToUrl(SString& string); + static void UrlToPath(SString& string); + static BOOL FindLastPathSeparator(const SString& path, SString::Iterator& i); +private: // ------------------------------------------------------------ - // binding & source + // Loader access API // ------------------------------------------------------------ - ULONG HashIdentity(); + // Private helper for crufty exception handling reasons + static PEAssembly* DoOpenSystem(); // ------------------------------------------------------------ - // Descriptive strings + // Internal routines // ------------------------------------------------------------ - // This returns a non-empty path representing the source of the assembly; it may - // be the parent assembly for dynamic or memory assemblies - const SString &GetEffectivePath(); +#ifdef DACCESS_COMPILE + // just to make the DAC and GCC happy. + virtual ~PEAssembly() {}; + PEAssembly() = default; +#else + PEAssembly( + BINDER_SPACE::Assembly* pBindResultInfo, + IMetaDataEmit* pEmit, + PEAssembly* creator, + BOOL isSystem, + PEImage* pPEImageIL = NULL, + BINDER_SPACE::Assembly* pHostAssembly = NULL + ); - // Codebase is the fusion codebase or path for the assembly. It is in URL format. - // Note this may be obtained from the parent PEFile if we don't have a path or fusion - // assembly. - BOOL GetCodeBase(SString &result); + virtual ~PEAssembly(); +#endif - // Display name is the fusion binding name for an assembly - void GetDisplayName(SString &result, DWORD flags = 0); + void OpenMDImport(); + void OpenImporter(); + void OpenEmitter(); - // ------------------------------------------------------------ - // Metadata access - // ------------------------------------------------------------ +private: - LPCUTF8 GetSimpleName(); + // ------------------------------------------------------------ + // Instance fields + // ------------------------------------------------------------ - // ------------------------------------------------------------ - // Utility functions - // ------------------------------------------------------------ +#ifdef _DEBUG + LPCWSTR m_pDebugName; + SString m_debugName; +#endif - static void PathToUrl(SString &string); - static void UrlToPath(SString &string); - static BOOL FindLastPathSeparator(const SString &path, SString::Iterator &i); + // IL image, NULL if dynamic + PTR_PEImage m_PEImage; - protected: + PTR_PEAssembly m_creator; + // This flag is not updated atomically with m_pMDImport. Its fine for debugger usage + // but don't rely on it in the runtime. In runtime try QI'ing the m_pMDImport for + // IID_IMDInternalImportENC + BOOL m_MDImportIsRW_Debugger_Use_Only; + union + { #ifndef DACCESS_COMPILE - PEAssembly( - BINDER_SPACE::Assembly* pBindResultInfo, - IMetaDataEmit *pEmit, - PEFile *creator, - BOOL system, - PEImage * pPEImageIL = NULL, - BINDER_SPACE::Assembly * pHostAssembly = NULL - ); - virtual ~PEAssembly(); + IMDInternalImport* m_pMDImport; +#else + // NB: m_pMDImport_UseAccessor appears to be never assigned a value, but its purpose is just + // to be a placeholder that has the same type and offset as m_pMDImport. + // + // The field has a different name so it would be an error to use directly. + // Only GetMDInternalRWAddress is supposed to use it via (TADDR)m_pMDImport_UseAccessor, + // which at that point will match the m_pMDImport on the debuggee side. + // See more scary comments in GetMDInternalRWAddress. + IMDInternalImport* m_pMDImport_UseAccessor; #endif + }; - private: - // ------------------------------------------------------------ - // Instance fields - // ------------------------------------------------------------ + IMetaDataImport2* m_pImporter; + IMetaDataEmit* m_pEmitter; - PTR_PEFile m_creator; -}; + Volatile m_refCount; + bool m_isSystem; + PTR_BINDER_SPACE_Assembly m_pHostAssembly; + + // For certain assemblies, we do not have m_pHostAssembly since they are not bound using an actual binder. + // An example is Ref-Emitted assemblies. Thus, when such assemblies trigger load of their dependencies, + // we need to ensure they are loaded in appropriate load context. + // + // To enable this, we maintain a concept of "FallbackBinder", which will be set to the Binder of the + // assembly that created the dynamic assembly. If the creator assembly is dynamic itself, then its fallback + // load context would be propagated to the assembly being dynamically generated. + PTR_AssemblyBinder m_pFallbackBinder; -typedef ReleaseHolder PEFileHolder; +}; // class PEAssembly typedef ReleaseHolder PEAssemblyHolder; -#endif // PEFILE_H_ +#endif // PEASSEMBLY_H_ diff --git a/src/coreclr/vm/pefile.inl b/src/coreclr/vm/peassembly.inl similarity index 56% rename from src/coreclr/vm/pefile.inl rename to src/coreclr/vm/peassembly.inl index e00136064bc1e..42102f13a05da 100644 --- a/src/coreclr/vm/pefile.inl +++ b/src/coreclr/vm/peassembly.inl @@ -1,13 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // -------------------------------------------------------------------------------- -// PEFile.inl +// PEAssembly.inl // // -------------------------------------------------------------------------------- -#ifndef PEFILE_INL_ -#define PEFILE_INL_ +#ifndef PEASSEMBLY_INL_ +#define PEASSEMBLY_INL_ #include "check.h" #include "simplerwlock.hpp" @@ -15,7 +15,7 @@ #include "peimagelayout.inl" #if CHECK_INVARIANTS -inline CHECK PEFile::Invariant() +inline CHECK PEAssembly::Invariant() { CONTRACT_CHECK { @@ -29,14 +29,12 @@ inline CHECK PEFile::Invariant() if (IsDynamic()) { // dynamic module case - CHECK(m_openedILimage == NULL); + CHECK(m_PEImage == NULL); CHECK(CheckPointer(m_pEmitter)); } else { - // If m_image is null, then we should have a native image. However, this is not valid initially - // during construction. We should find a way to assert this. - CHECK(CheckPointer((PEImage*) m_openedILimage, NULL_OK)); + CHECK(CheckPointer((PEImage*)m_PEImage)); } CHECK_OK; } @@ -46,7 +44,7 @@ inline CHECK PEFile::Invariant() // AddRef/Release // ------------------------------------------------------------ -inline ULONG PEFile::AddRef() +inline ULONG PEAssembly::AddRef() { CONTRACTL { @@ -61,7 +59,7 @@ inline ULONG PEFile::AddRef() return FastInterlockIncrement(&m_refCount); } -inline ULONG PEFile::Release() +inline ULONG PEAssembly::Release() { CONTRACT(COUNT_T) { @@ -88,7 +86,7 @@ inline ULONG PEAssembly::HashIdentity() { CONTRACTL { - PRECONDITION(CheckPointer(m_identity)); + PRECONDITION(CheckPointer(m_PEImage)); MODE_ANY; THROWS; GC_TRIGGERS; @@ -97,7 +95,7 @@ inline ULONG PEAssembly::HashIdentity() return m_pHostAssembly->GetAssemblyName()->Hash(BINDER_SPACE::AssemblyName::INCLUDE_VERSION); } -inline void PEFile::ValidateForExecution() +inline void PEAssembly::ValidateForExecution() { CONTRACTL { @@ -110,7 +108,7 @@ inline void PEFile::ValidateForExecution() // // Ensure reference assemblies are not loaded for execution // - ReleaseHolder mdImport(this->GetMDImportWithRef()); + IMDInternalImport* mdImport = GetMDImport(); if (mdImport->GetCustomAttributeByName(TokenFromRid(1, mdtAssembly), g_ReferenceAssemblyAttribute, NULL, @@ -121,7 +119,7 @@ inline void PEFile::ValidateForExecution() // // Ensure platform is valid for execution // - if (!IsDynamic() && !IsResource()) + if (!IsDynamic()) { if (IsMarkedAsNoPlatform()) { @@ -131,14 +129,14 @@ inline void PEFile::ValidateForExecution() } -inline BOOL PEFile::IsMarkedAsNoPlatform() +inline BOOL PEAssembly::IsMarkedAsNoPlatform() { WRAPPER_NO_CONTRACT; return (IsAfPA_NoPlatform(GetFlags())); } -inline void PEFile::GetMVID(GUID *pMvid) +inline void PEAssembly::GetMVID(GUID *pMvid) { CONTRACTL { @@ -149,14 +147,14 @@ inline void PEFile::GetMVID(GUID *pMvid) } CONTRACTL_END; - IfFailThrow(GetPersistentMDImport()->GetScopeProps(NULL, pMvid)); + IfFailThrow(GetMDImport()->GetScopeProps(NULL, pMvid)); } // ------------------------------------------------------------ // Descriptive strings // ------------------------------------------------------------ -inline const SString& PEFile::GetPath() +inline const SString& PEAssembly::GetPath() { CONTRACTL { @@ -169,17 +167,18 @@ inline const SString& PEFile::GetPath() } CONTRACTL_END; - if (IsDynamic() || m_identity->IsInBundle ()) + if (IsDynamic() || m_PEImage->IsInBundle ()) { return SString::Empty(); } - return m_identity->GetPath(); + + return m_PEImage->GetPath(); } // // Returns the identity path even for single-file/bundled apps. // -inline const SString& PEFile::GetIdentityPath() +inline const SString& PEAssembly::GetIdentityPath() { CONTRACTL { @@ -192,15 +191,16 @@ inline const SString& PEFile::GetIdentityPath() } CONTRACTL_END; - if (m_identity == nullptr) + if (m_PEImage == nullptr) { return SString::Empty(); } - return m_identity->GetPath(); + + return m_PEImage->GetPath(); } #ifdef DACCESS_COMPILE -inline const SString &PEFile::GetModuleFileNameHint() +inline const SString &PEAssembly::GetModuleFileNameHint() { CONTRACTL { @@ -216,12 +216,12 @@ inline const SString &PEFile::GetModuleFileNameHint() return SString::Empty(); } else - return m_identity->GetModuleFileNameHintForDAC(); + return m_PEImage->GetModuleFileNameHintForDAC(); } #endif // DACCESS_COMPILE #ifdef LOGGING -inline LPCWSTR PEFile::GetDebugName() +inline LPCWSTR PEAssembly::GetDebugName() { CONTRACTL { @@ -245,108 +245,29 @@ inline LPCWSTR PEFile::GetDebugName() // Classification // ------------------------------------------------------------ -inline BOOL PEFile::IsAssembly() const -{ - LIMITED_METHOD_DAC_CONTRACT; - - return (m_flags & PEFILE_ASSEMBLY) != 0; -} - -inline PTR_PEAssembly PEFile::AsAssembly() -{ - LIMITED_METHOD_DAC_CONTRACT; - - if (IsAssembly()) - return dac_cast(this); - else - return dac_cast(nullptr); -} - -inline BOOL PEFile::IsSystem() const +inline BOOL PEAssembly::IsSystem() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; - return (m_flags & PEFILE_SYSTEM) != 0; + return m_isSystem; } -inline BOOL PEFile::IsDynamic() const +inline BOOL PEAssembly::IsDynamic() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; - return m_identity == NULL; -} - -inline BOOL PEFile::IsResource() const -{ - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - return FALSE; -} - -inline BOOL PEFile::IsIStream() const -{ - LIMITED_METHOD_CONTRACT; - - return FALSE; -} - -inline PEAssembly *PEFile::GetAssembly() const -{ - WRAPPER_NO_CONTRACT; - _ASSERTE(IsAssembly()); - return dac_cast(this); + return m_PEImage == NULL; } // ------------------------------------------------------------ // Metadata access // ------------------------------------------------------------ - -inline BOOL PEFile::HasMetadata() -{ - CONTRACTL - { - INSTANCE_CHECK; - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - SUPPORTS_DAC; - } - CONTRACTL_END; - - return !IsResource(); -} - -inline IMDInternalImportHolder PEFile::GetMDImport() +inline IMDInternalImport* PEAssembly::GetMDImport() { WRAPPER_NO_CONTRACT; - if (m_bHasPersistentMDImport) - return IMDInternalImportHolder(GetPersistentMDImport(),FALSE); - else - return IMDInternalImportHolder(GetMDImportWithRef(),TRUE); -}; -inline IMDInternalImport* PEFile::GetPersistentMDImport() -{ -/* - CONTRACT(IMDInternalImport *) - { - INSTANCE_CHECK; - PRECONDITION(!IsResource()); - POSTCONDITION(CheckPointer(RETVAL)); - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACT_END; -*/ - SUPPORTS_DAC; -#if !defined(__GNUC__) - - _ASSERTE(!IsResource()); -#endif #ifdef DACCESS_COMPILE WRAPPER_NO_CONTRACT; return DacGetMDImport(this, true); @@ -355,56 +276,16 @@ inline IMDInternalImport* PEFile::GetPersistentMDImport() return m_pMDImport; #endif -} - -inline IMDInternalImport *PEFile::GetMDImportWithRef() -{ -/* - CONTRACT(IMDInternalImport *) - { - INSTANCE_CHECK; - PRECONDITION(!IsResource()); - POSTCONDITION(CheckPointer(RETVAL)); - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACT_END; -*/ -#if !defined(__GNUC__) - _ASSERTE(!IsResource()); -#endif -#ifdef DACCESS_COMPILE - WRAPPER_NO_CONTRACT; - return DacGetMDImport(this, true); -#else - CONTRACTL - { - NOTHROW; - WRAPPER(GC_TRIGGERS); - MODE_ANY; - CAN_TAKE_LOCK; - } - CONTRACTL_END; - - GCX_PREEMP(); - SimpleReadLockHolder lock(m_pMetadataLock); - if(m_pMDImport) - m_pMDImport->AddRef(); - return m_pMDImport; -#endif -} +}; #ifndef DACCESS_COMPILE -inline IMetaDataImport2 *PEFile::GetRWImporter() +inline IMetaDataImport2 *PEAssembly::GetRWImporter() { CONTRACT(IMetaDataImport2 *) { INSTANCE_CHECK; - PRECONDITION(!IsResource()); POSTCONDITION(CheckPointer(RETVAL)); - PRECONDITION(m_bHasPersistentMDImport); GC_NOTRIGGER; THROWS; MODE_ANY; @@ -417,16 +298,14 @@ inline IMetaDataImport2 *PEFile::GetRWImporter() RETURN m_pImporter; } -inline IMetaDataEmit *PEFile::GetEmitter() +inline IMetaDataEmit *PEAssembly::GetEmitter() { CONTRACT(IMetaDataEmit *) { INSTANCE_CHECK; MODE_ANY; GC_NOTRIGGER; - PRECONDITION(!IsResource()); POSTCONDITION(CheckPointer(RETVAL)); - PRECONDITION(m_bHasPersistentMDImport); THROWS; } CONTRACT_END; @@ -440,40 +319,10 @@ inline IMetaDataEmit *PEFile::GetEmitter() #endif // DACCESS_COMPILE -// The simple name is not actually very simple. The name returned comes from one of -// various metadata tables, depending on whether this is a manifest module, -// non-manifest module, or something else -inline LPCUTF8 PEFile::GetSimpleName() -{ - CONTRACT(LPCUTF8) - { - INSTANCE_CHECK; - MODE_ANY; - POSTCONDITION(CheckPointer(RETVAL)); - NOTHROW; - SUPPORTS_DAC; - WRAPPER(GC_TRIGGERS); - } - CONTRACT_END; - - if (IsAssembly()) - RETURN dac_cast(this)->GetSimpleName(); - else - { - LPCUTF8 szScopeName; - if (FAILED(GetScopeName(&szScopeName))) - { - szScopeName = ""; - } - RETURN szScopeName; - } -} - - // Same as the managed Module.ScopeName property, this unconditionally looks in the // metadata Module table to get the name. Useful for profilers and others who don't // like sugar coating on their names. -inline HRESULT PEFile::GetScopeName(LPCUTF8 * pszName) +inline HRESULT PEAssembly::GetScopeName(LPCUTF8 * pszName) { CONTRACTL { @@ -493,14 +342,7 @@ inline HRESULT PEFile::GetScopeName(LPCUTF8 * pszName) // PE file access // ------------------------------------------------------------ -inline BOOL PEFile::IsIbcOptimized() -{ - WRAPPER_NO_CONTRACT; - - return FALSE; -} - -inline BOOL PEFile::IsReadyToRun() +inline BOOL PEAssembly::IsReadyToRun() { CONTRACTL { @@ -511,9 +353,9 @@ inline BOOL PEFile::IsReadyToRun() } CONTRACTL_END; - if (HasOpenedILimage()) + if (HasPEImage()) { - return GetLoadedIL()->HasReadyToRunHeader(); + return GetLoadedLayout()->HasReadyToRunHeader(); } else { @@ -521,63 +363,37 @@ inline BOOL PEFile::IsReadyToRun() } } -inline WORD PEFile::GetSubsystem() -{ - WRAPPER_NO_CONTRACT; - - if (IsResource() || IsDynamic()) - return 0; - - return GetLoadedIL()->GetSubsystem(); -} - -inline mdToken PEFile::GetEntryPointToken( -#ifdef _DEBUG - BOOL bAssumeLoaded -#endif //_DEBUG - ) +inline mdToken PEAssembly::GetEntryPointToken() { WRAPPER_NO_CONTRACT; - if (IsResource() || IsDynamic()) + if (IsDynamic()) return mdTokenNil; - _ASSERTE (!bAssumeLoaded || HasLoadedIL ()); - return GetOpenedILimage()->GetEntryPointToken(); + return GetPEImage()->GetEntryPointToken(); } -inline BOOL PEFile::IsILOnly() +inline BOOL PEAssembly::IsILOnly() { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; CONTRACT_VIOLATION(ThrowsViolation|GCViolation|FaultViolation); - if (IsResource() || IsDynamic()) + if (IsDynamic()) return FALSE; - return GetOpenedILimage()->IsILOnly(); -} - -inline BOOL PEFile::IsDll() -{ - WRAPPER_NO_CONTRACT; - - if (IsResource() || IsDynamic()) - return TRUE; - - return GetOpenedILimage()->IsDll(); + return GetPEImage()->IsILOnly(); } -inline PTR_VOID PEFile::GetRvaField(RVA field) +inline PTR_VOID PEAssembly::GetRvaField(RVA field) { CONTRACT(void *) { INSTANCE_CHECK; PRECONDITION(!IsDynamic()); - PRECONDITION(!IsResource()); PRECONDITION(CheckRvaField(field)); - PRECONDITION(CheckLoaded()); + PRECONDITION(HasLoadedPEImage()); NOTHROW; GC_NOTRIGGER; MODE_ANY; @@ -589,17 +405,16 @@ inline PTR_VOID PEFile::GetRvaField(RVA field) // Note that the native image Rva fields are currently cut off before // this point. We should not get here for an IL only native image. - RETURN dac_cast(GetLoadedIL()->GetRvaData(field,NULL_OK)); + RETURN dac_cast(GetLoadedLayout()->GetRvaData(field,NULL_OK)); } -inline CHECK PEFile::CheckRvaField(RVA field) +inline CHECK PEAssembly::CheckRvaField(RVA field) { CONTRACT_CHECK { INSTANCE_CHECK; PRECONDITION(!IsDynamic()); - PRECONDITION(!IsResource()); - PRECONDITION(CheckLoaded()); + PRECONDITION(HasLoadedPEImage()); NOTHROW; GC_NOTRIGGER; MODE_ANY; @@ -609,18 +424,17 @@ inline CHECK PEFile::CheckRvaField(RVA field) // Note that the native image Rva fields are currently cut off before // this point. We should not get here for an IL only native image. - CHECK(GetLoadedIL()->CheckRva(field,NULL_OK)); + CHECK(GetLoadedLayout()->CheckRva(field,NULL_OK)); CHECK_OK; } -inline CHECK PEFile::CheckRvaField(RVA field, COUNT_T size) +inline CHECK PEAssembly::CheckRvaField(RVA field, COUNT_T size) { CONTRACT_CHECK { INSTANCE_CHECK; PRECONDITION(!IsDynamic()); - PRECONDITION(!IsResource()); - PRECONDITION(CheckLoaded()); + PRECONDITION(HasLoadedPEImage()); NOTHROW; GC_NOTRIGGER; MODE_ANY; @@ -630,11 +444,11 @@ inline CHECK PEFile::CheckRvaField(RVA field, COUNT_T size) // Note that the native image Rva fields are currently cut off before // this point. We should not get here for an IL only native image. - CHECK(GetLoadedIL()->CheckRva(field, size,0,NULL_OK)); + CHECK(GetLoadedLayout()->CheckRva(field, size,0,NULL_OK)); CHECK_OK; } -inline BOOL PEFile::HasTls() +inline BOOL PEAssembly::HasTls() { CONTRACTL { @@ -642,24 +456,21 @@ inline BOOL PEFile::HasTls() NOTHROW; GC_NOTRIGGER; MODE_ANY; - PRECONDITION(CheckLoaded()); + PRECONDITION(IsLoaded()); } CONTRACTL_END; - // Resource modules do not contain TLS data. - if (IsResource()) - return FALSE; // Dynamic modules do not contain TLS data. - else if (IsDynamic()) + if (IsDynamic()) return FALSE; // ILOnly modules do not contain TLS data. else if (IsILOnly()) return FALSE; else - return GetLoadedIL()->HasTls(); + return GetLoadedLayout()->HasTls(); } -inline BOOL PEFile::IsRvaFieldTls(RVA field) +inline BOOL PEAssembly::IsRvaFieldTls(RVA field) { CONTRACTL { @@ -667,30 +478,30 @@ inline BOOL PEFile::IsRvaFieldTls(RVA field) NOTHROW; GC_NOTRIGGER; MODE_ANY; - PRECONDITION(CheckLoaded()); + PRECONDITION(IsLoaded()); } CONTRACTL_END; if (!HasTls()) return FALSE; - PTR_VOID address = PTR_VOID(GetLoadedIL()->GetRvaData(field)); + PTR_VOID address = PTR_VOID(GetLoadedLayout()->GetRvaData(field)); COUNT_T tlsSize; - PTR_VOID tlsRange = GetLoadedIL()->GetTlsRange(&tlsSize); + PTR_VOID tlsRange = GetLoadedLayout()->GetTlsRange(&tlsSize); return (address >= tlsRange && address < (dac_cast(tlsRange)+tlsSize)); } -inline UINT32 PEFile::GetFieldTlsOffset(RVA field) +inline UINT32 PEAssembly::GetFieldTlsOffset(RVA field) { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckRvaField(field)); PRECONDITION(IsRvaFieldTls(field)); - PRECONDITION(CheckLoaded()); + PRECONDITION(HasLoadedPEImage()); NOTHROW; GC_NOTRIGGER; MODE_ANY; @@ -698,14 +509,14 @@ inline UINT32 PEFile::GetFieldTlsOffset(RVA field) CONTRACTL_END; return (UINT32)(dac_cast(GetRvaField(field)) - - dac_cast(GetLoadedIL()->GetTlsRange())); + dac_cast(GetLoadedLayout()->GetTlsRange())); } -inline UINT32 PEFile::GetTlsIndex() +inline UINT32 PEAssembly::GetTlsIndex() { CONTRACTL { - PRECONDITION(CheckLoaded()); + PRECONDITION(HasLoadedPEImage()); INSTANCE_CHECK; PRECONDITION(HasTls()); NOTHROW; @@ -714,18 +525,17 @@ inline UINT32 PEFile::GetTlsIndex() } CONTRACTL_END; - return GetLoadedIL()->GetTlsIndex(); + return GetLoadedLayout()->GetTlsIndex(); } -inline const void *PEFile::GetInternalPInvokeTarget(RVA target) +inline const void *PEAssembly::GetInternalPInvokeTarget(RVA target) { CONTRACT(void *) { INSTANCE_CHECK; PRECONDITION(!IsDynamic()); - PRECONDITION(!IsResource()); PRECONDITION(CheckInternalPInvokeTarget(target)); - PRECONDITION(CheckLoaded()); + PRECONDITION(HasLoadedPEImage()); NOTHROW; GC_NOTRIGGER; MODE_ANY; @@ -733,17 +543,16 @@ inline const void *PEFile::GetInternalPInvokeTarget(RVA target) } CONTRACT_END; - RETURN (void*)GetLoadedIL()->GetRvaData(target); + RETURN (void*)GetLoadedLayout()->GetRvaData(target); } -inline CHECK PEFile::CheckInternalPInvokeTarget(RVA target) +inline CHECK PEAssembly::CheckInternalPInvokeTarget(RVA target) { CONTRACT_CHECK { INSTANCE_CHECK; PRECONDITION(!IsDynamic()); - PRECONDITION(!IsResource()); - PRECONDITION(CheckLoaded()); + PRECONDITION(HasLoadedPEImage()); NOTHROW; GC_NOTRIGGER; MODE_ANY; @@ -751,16 +560,16 @@ inline CHECK PEFile::CheckInternalPInvokeTarget(RVA target) CONTRACT_CHECK_END; CHECK(!IsILOnly()); - CHECK(GetLoadedIL()->CheckRva(target)); + CHECK(GetLoadedLayout()->CheckRva(target)); CHECK_OK; } -inline IMAGE_COR_VTABLEFIXUP *PEFile::GetVTableFixups(COUNT_T *pCount/*=NULL*/) +inline IMAGE_COR_VTABLEFIXUP *PEAssembly::GetVTableFixups(COUNT_T *pCount/*=NULL*/) { CONTRACT(IMAGE_COR_VTABLEFIXUP *) { - PRECONDITION(CheckLoaded()); + PRECONDITION(HasLoadedPEImage()); INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; @@ -769,26 +578,25 @@ inline IMAGE_COR_VTABLEFIXUP *PEFile::GetVTableFixups(COUNT_T *pCount/*=NULL*/) } CONTRACT_END; - if (IsResource() || IsDynamic() || IsILOnly()) + if (IsDynamic() || IsILOnly()) { if (pCount != NULL) *pCount = 0; RETURN NULL; } else - RETURN GetLoadedIL()->GetVTableFixups(pCount); + RETURN GetLoadedLayout()->GetVTableFixups(pCount); } -inline void *PEFile::GetVTable(RVA rva) +inline void *PEAssembly::GetVTable(RVA rva) { CONTRACT(void *) { INSTANCE_CHECK; PRECONDITION(!IsDynamic()); - PRECONDITION(!IsResource()); - PRECONDITION(CheckLoaded()); + PRECONDITION(HasLoadedPEImage()); PRECONDITION(!IsILOnly()); - PRECONDITION(GetLoadedIL()->CheckRva(rva)); + PRECONDITION(GetLoadedLayout()->CheckRva(rva)); NOTHROW; GC_NOTRIGGER; MODE_ANY; @@ -796,18 +604,17 @@ inline void *PEFile::GetVTable(RVA rva) } CONTRACT_END; - RETURN (void *)GetLoadedIL()->GetRvaData(rva); + RETURN (void *)GetLoadedLayout()->GetRvaData(rva); } // @todo: this is bad to expose. But it is needed to support current IJW thunks -inline HMODULE PEFile::GetIJWBase() +inline HMODULE PEAssembly::GetIJWBase() { CONTRACTL { INSTANCE_CHECK; PRECONDITION(!IsDynamic()); - PRECONDITION(!IsResource()); - PRECONDITION(CheckLoaded()); + PRECONDITION(HasLoadedPEImage()); PRECONDITION(!IsILOnly()); NOTHROW; GC_NOTRIGGER; @@ -815,10 +622,10 @@ inline HMODULE PEFile::GetIJWBase() } CONTRACTL_END; - return (HMODULE) dac_cast(GetLoadedIL()->GetBase()); + return (HMODULE) dac_cast(GetLoadedLayout()->GetBase()); } -inline PTR_VOID PEFile::GetDebuggerContents(COUNT_T *pSize/*=NULL*/) +inline PTR_VOID PEAssembly::GetDebuggerContents(COUNT_T *pSize/*=NULL*/) { CONTRACT(PTR_VOID) { @@ -835,12 +642,12 @@ inline PTR_VOID PEFile::GetDebuggerContents(COUNT_T *pSize/*=NULL*/) // helper thread. The debugger will have to expect a zero base // in some circumstances. - if (IsLoaded()) + if (HasLoadedPEImage()) { if (pSize != NULL) - *pSize = GetLoaded()->GetSize(); + *pSize = GetLoadedLayout()->GetSize(); - RETURN GetLoaded()->GetBase(); + RETURN GetLoadedLayout()->GetBase(); } else { @@ -851,7 +658,7 @@ inline PTR_VOID PEFile::GetDebuggerContents(COUNT_T *pSize/*=NULL*/) } } -inline PTR_CVOID PEFile::GetLoadedImageContents(COUNT_T *pSize/*=NULL*/) +inline PTR_CVOID PEAssembly::GetLoadedImageContents(COUNT_T *pSize/*=NULL*/) { CONTRACTL { @@ -863,13 +670,13 @@ inline PTR_CVOID PEFile::GetLoadedImageContents(COUNT_T *pSize/*=NULL*/) } CONTRACTL_END; - if (IsLoaded() && !IsDynamic()) + if (HasLoadedPEImage()) { if (pSize != NULL) { - *pSize = GetLoaded()->GetSize(); + *pSize = GetLoadedLayout()->GetSize(); } - return GetLoaded()->GetBase(); + return GetLoadedLayout()->GetBase(); } else { @@ -882,32 +689,32 @@ inline PTR_CVOID PEFile::GetLoadedImageContents(COUNT_T *pSize/*=NULL*/) } #ifndef DACCESS_COMPILE -inline const void *PEFile::GetManagedFileContents(COUNT_T *pSize/*=NULL*/) +inline const void *PEAssembly::GetManagedFileContents(COUNT_T *pSize/*=NULL*/) { CONTRACT(const void *) { INSTANCE_CHECK; - PRECONDITION(CheckLoaded()); + PRECONDITION(HasLoadedPEImage()); WRAPPER(THROWS); WRAPPER(GC_TRIGGERS); MODE_ANY; - POSTCONDITION((!GetLoaded()->GetSize()) || CheckPointer(RETVAL)); + POSTCONDITION((!GetLoadedLayout()->GetSize()) || CheckPointer(RETVAL)); } CONTRACT_END; // Right now, we will trigger a LoadLibrary for the caller's sake, // even if we are in a scenario where we could normally avoid it. - LoadLibrary(FALSE); + EnsureLoaded(); if (pSize != NULL) - *pSize = GetLoadedIL()->GetSize(); + *pSize = GetLoadedLayout()->GetSize(); - RETURN GetLoadedIL()->GetBase(); + RETURN GetLoadedLayout()->GetBase(); } #endif // DACCESS_COMPILE -inline BOOL PEFile::IsPtrInILImage(PTR_CVOID data) +inline BOOL PEAssembly::IsPtrInPEImage(PTR_CVOID data) { CONTRACTL { @@ -919,49 +726,13 @@ inline BOOL PEFile::IsPtrInILImage(PTR_CVOID data) } CONTRACTL_END; - if (HasOpenedILimage()) + if (HasPEImage()) { - return GetOpenedILimage()->IsPtrInImage(data); + return GetPEImage()->IsPtrInImage(data); } else return FALSE; } -// ------------------------------------------------------------ -// Native image access -// ------------------------------------------------------------ - -inline PTR_PEImageLayout PEFile::GetLoadedIL() -{ - LIMITED_METHOD_CONTRACT; - SUPPORTS_DAC; - - _ASSERTE(HasOpenedILimage()); - - return GetOpenedILimage()->GetLoadedLayout(); -}; - -inline BOOL PEFile::IsLoaded(BOOL bAllowNative/*=TRUE*/) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - if(IsDynamic()) - return TRUE; - return HasLoadedIL(); -}; - - -inline PTR_PEImageLayout PEFile::GetLoaded() -{ - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - return GetLoadedIL(); -}; - // ------------------------------------------------------------ // Descriptive strings @@ -995,14 +766,14 @@ inline LPCSTR PEAssembly::GetSimpleName() CONTRACTL { NOTHROW; - if (!m_bHasPersistentMDImport) { GC_TRIGGERS;} else {DISABLED(GC_TRIGGERS);}; + DISABLED(GC_TRIGGERS); MODE_ANY; SUPPORTS_DAC; } CONTRACTL_END; LPCSTR name = ""; - IMDInternalImportHolder pImport = GetMDImport(); + IMDInternalImport* pImport = GetMDImport(); if (pImport != NULL) { if (FAILED(pImport->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, &name, NULL, NULL))) @@ -1014,7 +785,7 @@ inline LPCSTR PEAssembly::GetSimpleName() return name; } -inline BOOL PEFile::IsStrongNamed() +inline BOOL PEAssembly::IsStrongNamed() { CONTRACTL { @@ -1035,7 +806,7 @@ inline BOOL PEFile::IsStrongNamed() // Check to see if this assembly has had its strong name signature verified yet. // -inline const void *PEFile::GetPublicKey(DWORD *pcbPK) +inline const void *PEAssembly::GetPublicKey(DWORD *pcbPK) { CONTRACTL { @@ -1051,7 +822,7 @@ inline const void *PEFile::GetPublicKey(DWORD *pcbPK) return pPK; } -inline ULONG PEFile::GetHashAlgId() +inline ULONG PEAssembly::GetHashAlgId() { CONTRACTL { @@ -1066,7 +837,7 @@ inline ULONG PEFile::GetHashAlgId() return hashAlgId; } -inline LPCSTR PEFile::GetLocale() +inline LPCSTR PEAssembly::GetLocale() { CONTRACTL { @@ -1081,11 +852,10 @@ inline LPCSTR PEFile::GetLocale() return md.szLocale; } -inline DWORD PEFile::GetFlags() +inline DWORD PEAssembly::GetFlags() { CONTRACTL { - PRECONDITION(IsAssembly()); INSTANCE_CHECK; if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS; if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS; @@ -1099,43 +869,4 @@ inline DWORD PEFile::GetFlags() return flags; } -// In the cases where you know the module is loaded, and cannot tolerate triggering and -// loading, this alternative to PEFile::GetFlags is useful. Profiling API uses this. -inline HRESULT PEFile::GetFlagsNoTrigger(DWORD * pdwFlags) -{ - CONTRACTL - { - PRECONDITION(IsAssembly()); - INSTANCE_CHECK; - NOTHROW; - GC_NOTRIGGER; - FORBID_FAULT; - MODE_ANY; - } - CONTRACTL_END; - - _ASSERTE (pdwFlags != NULL); - - if (!m_bHasPersistentMDImport) - return E_FAIL; - - return GetPersistentMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, NULL, pdwFlags); -} - -// ------------------------------------------------------------ -// Metadata access -// ------------------------------------------------------------ - -inline void PEFile::OpenMDImport() -{ - WRAPPER_NO_CONTRACT; - //need synchronization - _ASSERTE(m_pMetadataLock->LockTaken() && m_pMetadataLock->IsWriterLock()); - OpenMDImport_Unsafe(); -} - -inline PEFile* PEFile::Dummy() -{ - return (PEFile*)(-1); -} -#endif // PEFILE_INL_ +#endif // PEASSEMBLY_INL_ diff --git a/src/coreclr/vm/peimage.cpp b/src/coreclr/vm/peimage.cpp index 412d67c938f5e..25aeb9625ec66 100644 --- a/src/coreclr/vm/peimage.cpp +++ b/src/coreclr/vm/peimage.cpp @@ -61,44 +61,20 @@ CHECK PEImage::CheckStartup() CHECK_OK; } -/* static */ -CHECK PEImage::CheckLayoutFormat(PEDecoder *pe) -{ - CONTRACT_CHECK - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACT_CHECK_END; - - CHECK(pe->IsILOnly()); - CHECK_OK; -} - CHECK PEImage::CheckILFormat() { WRAPPER_NO_CONTRACT; - - PTR_PEImageLayout pLayoutToCheck; - PEImageLayoutHolder pLayoutHolder; - - if (HasLoadedLayout()) - { - pLayoutToCheck = GetLoadedLayout(); - } - else - { - pLayoutHolder = GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED); - pLayoutToCheck = pLayoutHolder; - } - - CHECK(pLayoutToCheck->CheckILFormat()); - + CHECK(GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->CheckILFormat()); CHECK_OK; }; +// PEImage is always unique on CoreCLR so a simple pointer check is sufficient in PEImage::Equals +CHECK PEImage::CheckUniqueInstance() +{ + CHECK(GetPath().IsEmpty() || m_bInHashMap); + CHECK_OK; +} + PEImage::~PEImage() { CONTRACTL @@ -116,7 +92,7 @@ PEImage::~PEImage() if (m_pLayoutLock) delete m_pLayoutLock; - if(m_hFile!=INVALID_HANDLE_VALUE && m_bOwnHandle) + if(m_hFile!=INVALID_HANDLE_VALUE) CloseHandle(m_hFile); for (unsigned int i=0;iDeleteValue(GetIDHash(), &locator); + PEImage* deleted = (PEImage *)s_Images->DeleteValue(GetPathHash(), &locator); _ASSERTE(deleted == this); } } @@ -252,44 +228,6 @@ CHECK PEImage::CheckCanonicalFullPath(const SString &path) CHECK_OK; } -BOOL PEImage::PathEquals(const SString &p1, const SString &p2) -{ - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - -#ifdef FEATURE_CASE_SENSITIVE_FILESYSTEM - return p1.Equals(p2); -#else - return p1.EqualsCaseInsensitive(p2); -#endif -} - -#ifndef TARGET_UNIX -/* static */ -void PEImage::GetPathFromDll(HINSTANCE hMod, SString &result) -{ - CONTRACTL - { - PRECONDITION(CheckStartup()); - PRECONDITION(CheckPointer(hMod)); - PRECONDITION(CheckValue(result)); - THROWS; - GC_NOTRIGGER; - MODE_ANY; - INJECT_FAULT(COMPlusThrowOM();); - } - CONTRACTL_END; - - WszGetModuleFileName(hMod, result); - -} -#endif // !TARGET_UNIX - /* static */ BOOL PEImage::CompareImage(UPTR u1, UPTR u2) { @@ -307,16 +245,25 @@ BOOL PEImage::CompareImage(UPTR u1, UPTR u2) // This is the value stored in the table PEImage *pImage = (PEImage *) u2; + if (pLocator->m_bIsInBundle != pImage->IsInBundle()) + { + return FALSE; + } BOOL ret = FALSE; HRESULT hr; EX_TRY { SString path(SString::Literal, pLocator->m_pPath); - BOOL isInBundle = pLocator->m_bIsInBundle; - if (PathEquals(path, pImage->GetPath()) && - (!isInBundle == !pImage->IsInBundle())) + +#ifdef FEATURE_CASE_SENSITIVE_FILESYSTEM + if (pImage->GetPath().Equals(path)) +#else + if (pImage->GetPath().EqualsCaseInsensitive(path)) +#endif + { ret = TRUE; + } } EX_CATCH_HRESULT(hr); //ignores failure! return ret; @@ -335,8 +282,8 @@ BOOL PEImage::Equals(PEImage *pImage) CONTRACTL_END; // PEImage is always unique on CoreCLR so a simple pointer check is sufficient - _ASSERTE(m_bInHashMap || GetPath().IsEmpty()); - _ASSERTE(pImage->m_bInHashMap || pImage->GetPath().IsEmpty()); + _ASSERTE(CheckUniqueInstance()); + _ASSERTE(pImage->CheckUniqueInstance()); return dac_cast(pImage) == dac_cast(this); } @@ -791,18 +738,16 @@ void PEImage::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) PEImage::PEImage(): m_path(), m_refCount(1), - m_bundleFileLocation(), m_bInHashMap(FALSE), + m_bundleFileLocation(), + m_hFile(INVALID_HANDLE_VALUE), + m_dwPEKind(0), + m_dwMachine(0), #ifdef METADATATRACKER_DATA m_pMDTracker(NULL), #endif // METADATATRACKER_DATA m_pMDImport(NULL), - m_pNativeMDImport(NULL), - m_hFile(INVALID_HANDLE_VALUE), - m_bOwnHandle(true), - m_dwPEKind(0), - m_dwMachine(0), - m_fCachedKindAndMachine(FALSE) + m_pNativeMDImport(NULL) { CONTRACTL { @@ -816,48 +761,48 @@ PEImage::PEImage(): m_pLayoutLock=new SimpleRWLock(PREEMPTIVE,LOCK_TYPE_DEFAULT); } -PTR_PEImageLayout PEImage::GetLayout(DWORD imageLayoutMask,DWORD flags) +// Misnomer under the DAC, but has a lot of callers. The DAC can't create layouts, so in that +// case this is a get. +PTR_PEImageLayout PEImage::GetOrCreateLayout(DWORD imageLayoutMask) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; - PTR_PEImageLayout pRetVal; - -#ifndef DACCESS_COMPILE - // First attempt to find an existing layout matching imageLayoutMask. If that fails, - // and the caller has asked us to create layouts if needed, then try again passing - // the create flag to GetLayoutInternal. We need this to be synchronized, but the common - // case is that the layout already exists, so use a reader-writer lock. - GCX_PREEMP(); - { - SimpleReadLockHolder lock(m_pLayoutLock); - pRetVal=GetLayoutInternal(imageLayoutMask,flags&(~LAYOUT_CREATEIFNEEDED)); - } + // First attempt to find an existing layout matching imageLayoutMask. + // If that fails, try again with auto-creating helper. + // Note: we use reader-writer lock, but only writes are synchronized. + PTR_PEImageLayout pRetVal = GetExistingLayoutInternal(imageLayoutMask); - if (!(pRetVal || (flags&LAYOUT_CREATEIFNEEDED)==0)) + if (pRetVal == NULL) { +#ifndef DACCESS_COMPILE + GCX_PREEMP(); SimpleWriteLockHolder lock(m_pLayoutLock); - pRetVal = GetLayoutInternal(imageLayoutMask,flags); - } - - return pRetVal; - + pRetVal = GetOrCreateLayoutInternal(imageLayoutMask); #else - // In DAC builds, we can't create any layouts - we must require that they already exist. - // We also don't take any AddRefs or locks in DAC builds - it's inspection-only. - pRetVal = GetExistingLayoutInternal(imageLayoutMask); - if ((pRetVal==NULL) && (flags & LAYOUT_CREATEIFNEEDED)) - { + // In DAC builds, we can't create any layouts - we must require that they already exist. + // We also don't take any AddRefs or locks in DAC builds - it's inspection-only. _ASSERTE_MSG(false, "DACization error - caller expects PEImage layout to exist and it doesn't"); DacError(E_UNEXPECTED); +#endif } + return pRetVal; -#endif } #ifndef DACCESS_COMPILE -PTR_PEImageLayout PEImage::GetLayoutInternal(DWORD imageLayoutMask,DWORD flags) +void PEImage::SetLayout(DWORD dwLayout, PEImageLayout* pLayout) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE(dwLayout < IMAGE_COUNT); + _ASSERTE(m_pLayoutLock->IsWriterLock()); + _ASSERTE(m_pLayouts[dwLayout] == NULL); + + m_pLayouts[dwLayout] = pLayout; +} + +PTR_PEImageLayout PEImage::GetOrCreateLayoutInternal(DWORD imageLayoutMask) { CONTRACTL { @@ -869,9 +814,9 @@ PTR_PEImageLayout PEImage::GetLayoutInternal(DWORD imageLayoutMask,DWORD flags) PTR_PEImageLayout pRetVal=GetExistingLayoutInternal(imageLayoutMask); - if (pRetVal==NULL && (flags&LAYOUT_CREATEIFNEEDED)) + if (pRetVal==NULL) { - _ASSERTE(HasID()); + _ASSERTE(HasPath()); BOOL bIsMappedLayoutSuitable = ((imageLayoutMask & PEImageLayout::LAYOUT_MAPPED) != 0); BOOL bIsFlatLayoutSuitable = ((imageLayoutMask & PEImageLayout::LAYOUT_FLAT) != 0); @@ -906,11 +851,8 @@ PTR_PEImageLayout PEImage::GetLayoutInternal(DWORD imageLayoutMask,DWORD flags) } } - if (pRetVal != NULL) - { - pRetVal->AddRef(); - } - + _ASSERTE(pRetVal != NULL); + _ASSERTE(this->IsOpened()); return pRetVal; } @@ -982,9 +924,10 @@ PTR_PEImageLayout PEImage::CreateLayoutMapped() } else { - PEImageLayoutHolder flatPE(GetLayoutInternal(PEImageLayout::LAYOUT_FLAT,LAYOUT_CREATEIFNEEDED)); + PEImageLayout* flatPE = GetOrCreateLayout(PEImageLayout::LAYOUT_FLAT); if (!flatPE->CheckFormat() || !flatPE->IsILOnly()) ThrowHR(COR_E_BADIMAGEFORMAT); + pRetVal=PEImageLayout::LoadFromFlat(flatPE); SetLayout(IMAGE_MAPPED,pRetVal); } @@ -1034,6 +977,9 @@ PTR_PEImage PEImage::LoadFlat(const void *flat, COUNT_T size) PEImageHolder pImage(new PEImage()); PTR_PEImageLayout pLayout = PEImageLayout::CreateFlat(flat,size,pImage); _ASSERTE(!pLayout->IsMapped()); + + SimpleWriteLockHolder lock(pImage->m_pLayoutLock); + pImage->SetLayout(IMAGE_FLAT,pLayout); RETURN dac_cast(pImage.Extract()); } @@ -1051,8 +997,8 @@ PTR_PEImage PEImage::LoadImage(HMODULE hMod) CONTRACT_END; StackSString path; - GetPathFromDll(hMod, path); - PEImageHolder pImage(PEImage::OpenImage(path,(MDInternalImportFlags)(0))); + WszGetModuleFileName(hMod, path); + PEImageHolder pImage(PEImage::OpenImage(path, MDInternalImport_Default)); if (pImage->HasLoadedLayout()) RETURN dac_cast(pImage.Extract()); @@ -1134,18 +1080,6 @@ void PEImage::Load() } } -void PEImage::SetLoadedHMODULE(HMODULE hMod) -{ - WRAPPER_NO_CONTRACT; - SimpleWriteLockHolder lock(m_pLayoutLock); - if(m_pLayouts[IMAGE_LOADED]) - { - _ASSERTE(m_pLayouts[IMAGE_LOADED]->GetBase()==hMod); - return; - } - SetLayout(IMAGE_LOADED,PEImageLayout::CreateFromHMODULE(hMod,this,TRUE)); -} - void PEImage::LoadFromMapped() { STANDARD_VM_CONTRACT; @@ -1156,10 +1090,13 @@ void PEImage::LoadFromMapped() return; } - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_MAPPED,LAYOUT_CREATEIFNEEDED)); + PEImageLayout* pLayout = GetOrCreateLayout(PEImageLayout::LAYOUT_MAPPED); SimpleWriteLockHolder lock(m_pLayoutLock); - if(m_pLayouts[IMAGE_LOADED]==NULL) - SetLayout(IMAGE_LOADED,pLayout.Extract()); + if (m_pLayouts[IMAGE_LOADED] == NULL) + { + pLayout->AddRef(); + SetLayout(IMAGE_LOADED, pLayout); + } } void PEImage::LoadNoFile() @@ -1173,38 +1110,18 @@ void PEImage::LoadNoFile() if (HasLoadedLayout()) return; - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,0)); + PEImageLayout* pLayout = GetExistingLayoutInternal(PEImageLayout::LAYOUT_ANY); if (!pLayout->CheckILOnly()) ThrowHR(COR_E_BADIMAGEFORMAT); - SimpleWriteLockHolder lock(m_pLayoutLock); - if(m_pLayouts[IMAGE_LOADED]==NULL) - SetLayout(IMAGE_LOADED,pLayout.Extract()); -} - - -void PEImage::LoadNoMetaData() -{ - STANDARD_VM_CONTRACT; - - if (HasLoadedLayout()) - return; SimpleWriteLockHolder lock(m_pLayoutLock); - if (m_pLayouts[IMAGE_LOADED]!=NULL) - return; - if (m_pLayouts[IMAGE_FLAT]!=NULL) + if (m_pLayouts[IMAGE_LOADED] == NULL) { - m_pLayouts[IMAGE_FLAT]->AddRef(); - SetLayout(IMAGE_LOADED,m_pLayouts[IMAGE_FLAT]); - } - else - { - _ASSERTE(!m_path.IsEmpty()); - SetLayout(IMAGE_LOADED,PEImageLayout::LoadFlat(this)); + pLayout->AddRef(); + SetLayout(IMAGE_LOADED, pLayout); } } - #endif //DACCESS_COMPILE //------------------------------------------------------------------------------- @@ -1264,22 +1181,6 @@ HANDLE PEImage::GetFileHandle() return m_hFile; } -void PEImage::SetFileHandle(HANDLE hFile) -{ - CONTRACTL - { - STANDARD_VM_CHECK; - } - CONTRACTL_END; - - SimpleWriteLockHolder lock(m_pLayoutLock); - if (m_hFile == INVALID_HANDLE_VALUE) - { - m_hFile = hFile; - m_bOwnHandle = false; - } -} - HRESULT PEImage::TryOpenFile() { STANDARD_VM_CONTRACT; @@ -1290,7 +1191,7 @@ HRESULT PEImage::TryOpenFile() return S_OK; { ErrorModeHolder mode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); - m_hFile=WszCreateFile((LPCWSTR)GetPathToLoad(), + m_hFile=WszCreateFile((LPCWSTR)GetPathToLoad(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, diff --git a/src/coreclr/vm/peimage.h b/src/coreclr/vm/peimage.h index af86e35ccaec4..679b3e024d337 100644 --- a/src/coreclr/vm/peimage.h +++ b/src/coreclr/vm/peimage.h @@ -26,9 +26,6 @@ class SimpleRWLock; // -------------------------------------------------------------------------------- class Crst; -class Thread; - -Thread* GetThreadNULLOk(); // -------------------------------------------------------------------------------- // PEImage is a PE file loaded by our "simulated LoadLibrary" mechanism. A PEImage @@ -56,92 +53,54 @@ struct CV_INFO_PDB70 typedef DPTR(class PEImage) PTR_PEImage; -class PEImage +class PEImage final { -public: - // ------------------------------------------------------------ - // Public constants - // ------------------------------------------------------------ - - enum - { - LAYOUT_CREATEIFNEEDED=1 - }; - PTR_PEImageLayout GetLayout(DWORD imageLayoutMask,DWORD flags); //with ref - PTR_PEImageLayout GetLoadedLayout(); //no ref - BOOL IsOpened(); - BOOL HasLoadedLayout(); public: // ------------------------------------------------------------ // Public API // ------------------------------------------------------------ + // initialize static data (i.e. locks, unique instance cache, etc..) static void Startup(); - // Normal constructed PEImages do NOT share images between calls and - // cannot be accessed by Get methods. - // - // DO NOT USE these unless you want a private copy-on-write mapping of - // the file. - - - -public: ~PEImage(); PEImage(); + BOOL Equals(PEImage* pImage); + + ULONG AddRef(); + ULONG Release(); + #ifndef DACCESS_COMPILE - static PTR_PEImage LoadFlat( - const void *flat, - COUNT_T size); + static PTR_PEImage LoadFlat(const void *flat, COUNT_T size); #ifndef TARGET_UNIX - static PTR_PEImage LoadImage( - HMODULE hMod); + static PTR_PEImage LoadImage(HMODULE hMod); #endif // !TARGET_UNIX static PTR_PEImage OpenImage( LPCWSTR pPath, MDInternalImportFlags flags = MDInternalImport_Default, BundleFileLocation bundleFileLocation = BundleFileLocation::Invalid()); - - // clones the image with new flags (this is pretty much about cached / noncached difference) - void Clone(MDInternalImportFlags flags, PTR_PEImage* ppImage) - { - if (GetPath().IsEmpty()) - { - AddRef(); - *ppImage = this; - } - else - *ppImage = PEImage::OpenImage(GetPath(), flags); - - }; - - static PTR_PEImage FindById(UINT64 uStreamAsmId, DWORD dwModuleId); - static PTR_PEImage FindByPath(LPCWSTR pPath, - BOOL isInBundle = TRUE); - static PTR_PEImage FindByShortPath(LPCWSTR pPath); - static PTR_PEImage FindByLongPath(LPCWSTR pPath); + static PTR_PEImage FindByPath(LPCWSTR pPath, BOOL isInBundle = TRUE); void AddToHashMap(); void Load(); - void SetLoadedHMODULE(HMODULE hMod); - void LoadNoMetaData(); void LoadNoFile(); void LoadFromMapped(); #endif - BOOL HasID(); - ULONG GetIDHash(); + BOOL IsOpened(); + PTR_PEImageLayout GetOrCreateLayout(DWORD imageLayoutMask); - // Refcount above images. - ULONG AddRef(); - ULONG Release(); + BOOL HasLoadedLayout(); + PTR_PEImageLayout GetLoadedLayout(); - // Accessors - const SString &GetPath(); + BOOL HasPath(); + ULONG GetPathHash(); + const SString& GetPath(); const SString& GetPathToLoad(); + BOOL IsFile(); BOOL IsInBundle() const; HANDLE GetFileHandle(); @@ -149,14 +108,10 @@ class PEImage INT64 GetSize() const; INT64 GetUncompressedSize() const; - void SetFileHandle(HANDLE hFile); HRESULT TryOpenFile(); LPCWSTR GetPathForErrorMessages(); - // Equality - BOOL Equals(PEImage *pImage); - void GetMVID(GUID *pMvid); BOOL HasV1Metadata(); IMDInternalImport* GetMDImport(); @@ -165,54 +120,53 @@ class PEImage BOOL HasContents() ; BOOL IsPtrInImage(PTR_CVOID data); - CHECK CheckFormat(); - - // Check utilites - CHECK CheckILFormat(); - static CHECK CheckCanonicalFullPath(const SString &path); - static CHECK CheckStartup(); - PTR_CVOID GetMetadata(COUNT_T *pSize = NULL); - -#ifndef TARGET_UNIX - static void GetPathFromDll(HINSTANCE hMod, SString &result); -#endif // !TARGET_UNIX - static BOOL PathEquals(const SString &p1, const SString &p2); - - void SetModuleFileNameHintForDAC(); -#ifdef DACCESS_COMPILE - void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); - const SString &GetModuleFileNameHintForDAC(); -#endif BOOL HasNTHeaders(); BOOL HasCorHeader(); BOOL HasReadyToRunHeader(); + BOOL HasDirectoryEntry(int entry); + BOOL Has32BitNTHeaders(); + + void GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine); + + BOOL IsILOnly(); BOOL IsReferenceAssembly(); BOOL IsComponentAssembly(); - PTR_CVOID GetNativeManifestMetadata(COUNT_T *pSize = NULL); - BOOL HasDirectoryEntry(int entry); + + PTR_CVOID GetNativeManifestMetadata(COUNT_T* pSize = NULL); mdToken GetEntryPointToken(); DWORD GetCorHeaderFlags(); - BOOL IsILOnly(); - BOOL IsDll(); - WORD GetSubsystem(); - BOOL IsFileLocked(); - BOOL IsIbcOptimized(); - BOOL Has32BitNTHeaders(); + PTR_CVOID GetMetadata(COUNT_T* pSize = NULL); + + // Check utilites + static CHECK CheckStartup(); + static CHECK CheckCanonicalFullPath(const SString& path); + + CHECK CheckFormat(); + CHECK CheckILFormat(); + CHECK CheckUniqueInstance(); void VerifyIsAssembly(); + void SetModuleFileNameHintForDAC(); +#ifdef DACCESS_COMPILE + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); + const SString &GetModuleFileNameHintForDAC(); +#endif + private: #ifndef DACCESS_COMPILE // Get or create the layout corresponding to the mask, with an AddRef - PTR_PEImageLayout GetLayoutInternal(DWORD imageLayoutMask, DWORD flags); + PTR_PEImageLayout GetOrCreateLayoutInternal(DWORD imageLayoutMask); // Create the mapped layout PTR_PEImageLayout CreateLayoutMapped(); // Create the flat layout PTR_PEImageLayout CreateLayoutFlat(BOOL bPermitWriteableSections); + + void SetLayout(DWORD dwLayout, PTR_PEImageLayout pLayout); #endif // Get an existing layout corresponding to the mask, no AddRef PTR_PEImageLayout GetExistingLayoutInternal(DWORD imageLayoutMask); @@ -249,28 +203,83 @@ class PEImage void DECLSPEC_NORETURN ThrowFormat(HRESULT hr); - static CHECK CheckLayoutFormat(PEDecoder *pe); +public: + class IJWFixupData + { + private: + Crst m_lock; + void* m_base; + DWORD m_flags; + PTR_LoaderHeap m_DllThunkHeap; + + // the fixup for the next iteration in FixupVTables + // we use it to make sure that we do not try to fix up the same entry twice + // if there was a pass that was aborted in the middle + COUNT_T m_iNextFixup; + COUNT_T m_iNextMethod; + + enum { + e_FIXED_UP = 0x1 + }; + + public: + IJWFixupData(void* pBase); + ~IJWFixupData(); + void* GetBase() { LIMITED_METHOD_CONTRACT; return m_base; } + Crst* GetLock() { LIMITED_METHOD_CONTRACT; return &m_lock; } + BOOL IsFixedUp() { LIMITED_METHOD_CONTRACT; return m_flags & e_FIXED_UP; } + void SetIsFixedUp() { LIMITED_METHOD_CONTRACT; m_flags |= e_FIXED_UP; } + PTR_LoaderHeap GetThunkHeap(); + void MarkMethodFixedUp(COUNT_T iFixup, COUNT_T iMethod); + BOOL IsMethodFixedUp(COUNT_T iFixup, COUNT_T iMethod); + }; + + static IJWFixupData* GetIJWData(void* pBase); + static PTR_LoaderHeap GetDllThunkHeap(void* pBase); + static void UnloadIJWModule(void* pBase); + +private: // ------------------------------------------------------------ - // Instance members + // Static fields // ------------------------------------------------------------ - SString m_path; - LONG m_refCount; + static CrstStatic s_hashLock; + static PtrHashMap* s_Images; - BundleFileLocation m_bundleFileLocation; // If this image is located within a single-file bundle, - // the location within the bundle. If m_bundleFileLocation is valid, - // it takes precedence over m_path for loading. +//@TODO:workaround: Remove this when we have one PEImage per mapped image, +//@TODO:workaround: and move the lock there +// This is for IJW thunk initialization, as it is no longer guaranteed +// that the initialization will occur under the loader lock. + static CrstStatic s_ijwHashLock; + static PtrHashMap* s_ijwFixupDataHash; + + // ------------------------------------------------------------ + // Instance fields + // ------------------------------------------------------------ + + SString m_path; + LONG m_refCount; + + // means this is a unique (deduped) instance. + BOOL m_bInHashMap; + + // If this image is located within a single-file bundle, the location within the bundle. + // If m_bundleFileLocation is valid, it takes precedence over m_path for loading. + BundleFileLocation m_bundleFileLocation; + + // valid handle if we tried to open the file/path and succeeded. + HANDLE m_hFile; + + DWORD m_dwPEKind; + DWORD m_dwMachine; // This variable will have the data of module name. // It is only used by DAC to remap fusion loaded modules back to // disk IL. This really is a workaround. The real fix is for fusion loader // hook (public API on hosting) to take an additional file name hint. // We are piggy backing on the fact that module name is the same as file name!!! - // - SString m_sModuleFileNameHintUsedByDac; // This is only used by DAC - -protected: + SString m_sModuleFileNameHintUsedByDac; // This is only used by DAC enum { @@ -282,11 +291,6 @@ class PEImage SimpleRWLock *m_pLayoutLock; PTR_PEImageLayout m_pLayouts[IMAGE_COUNT] ; - BOOL m_bInHashMap; -#ifndef DACCESS_COMPILE - void SetLayout(DWORD dwLayout, PTR_PEImageLayout pLayout); -#endif // DACCESS_COMPILE - #ifdef METADATATRACKER_DATA class MetaDataTracker *m_pMDTracker; @@ -294,75 +298,6 @@ class PEImage IMDInternalImport* m_pMDImport; IMDInternalImport* m_pNativeMDImport; - - -private: - - - // ------------------------------------------------------------ - // Static members - // ------------------------------------------------------------ - - static CrstStatic s_hashLock; - - static PtrHashMap *s_Images; - - HANDLE m_hFile; - bool m_bOwnHandle; - - //@TODO:workaround: Remove this when we have one PEImage per mapped image, - //@TODO:workaround: and move the lock there - // This is for IJW thunk initialization, as it is no longer guaranteed - // that the initialization will occur under the loader lock. - static CrstStatic s_ijwHashLock; - static PtrHashMap *s_ijwFixupDataHash; - -public: - class IJWFixupData - { - private: - Crst m_lock; - void *m_base; - DWORD m_flags; - PTR_LoaderHeap m_DllThunkHeap; - - // the fixup for the next iteration in FixupVTables - // we use it to make sure that we do not try to fix up the same entry twice - // if there was a pass that was aborted in the middle - COUNT_T m_iNextFixup; - COUNT_T m_iNextMethod; - - enum { - e_FIXED_UP = 0x1 - }; - - public: - IJWFixupData(void *pBase); - ~IJWFixupData(); - void *GetBase() { LIMITED_METHOD_CONTRACT; return m_base; } - Crst *GetLock() { LIMITED_METHOD_CONTRACT; return &m_lock; } - BOOL IsFixedUp() { LIMITED_METHOD_CONTRACT; return m_flags & e_FIXED_UP; } - void SetIsFixedUp() { LIMITED_METHOD_CONTRACT; m_flags |= e_FIXED_UP; } - PTR_LoaderHeap GetThunkHeap(); - void MarkMethodFixedUp(COUNT_T iFixup, COUNT_T iMethod); - BOOL IsMethodFixedUp(COUNT_T iFixup, COUNT_T iMethod); - }; - - static IJWFixupData *GetIJWData(void *pBase); - static PTR_LoaderHeap GetDllThunkHeap(void *pBase); - static void UnloadIJWModule(void *pBase); - -private: - DWORD m_dwPEKind; - DWORD m_dwMachine; - BOOL m_fCachedKindAndMachine; - - - -public: - void CachePEKindAndMachine(); - void GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine); - }; FORCEINLINE void PEImageRelease(PEImage *i) diff --git a/src/coreclr/vm/peimage.inl b/src/coreclr/vm/peimage.inl index b855d379bd31e..8dc72d416fac3 100644 --- a/src/coreclr/vm/peimage.inl +++ b/src/coreclr/vm/peimage.inl @@ -106,24 +106,6 @@ inline BOOL PEImage::IsFile() return !GetPathToLoad().IsEmpty(); } -#ifndef DACCESS_COMPILE -inline void PEImage::SetLayout(DWORD dwLayout, PEImageLayout* pLayout) -{ - LIMITED_METHOD_CONTRACT; - _ASSERTE(dwLayoutHasNTHeaders(); - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - return pLayout->HasNTHeaders(); - } + return GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->HasNTHeaders(); } inline BOOL PEImage::HasCorHeader() { WRAPPER_NO_CONTRACT; - if (HasLoadedLayout()) - return GetLoadedLayout()->HasCorHeader(); - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - return pLayout->HasCorHeader(); - } + return GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->HasCorHeader(); } inline BOOL PEImage::IsComponentAssembly() { WRAPPER_NO_CONTRACT; - if (HasLoadedLayout()) - return GetLoadedLayout()->IsComponentAssembly(); - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - return pLayout->IsComponentAssembly(); - } + return GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->IsComponentAssembly(); } inline BOOL PEImage::HasReadyToRunHeader() { WRAPPER_NO_CONTRACT; - if (HasLoadedLayout()) - return GetLoadedLayout()->HasReadyToRunHeader(); - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - return pLayout->HasReadyToRunHeader(); - } + return GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->HasReadyToRunHeader(); } inline BOOL PEImage::HasDirectoryEntry(int entry) { WRAPPER_NO_CONTRACT; - if (HasLoadedLayout()) - return GetLoadedLayout()->HasDirectoryEntry(entry); - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - return pLayout->HasDirectoryEntry(entry); - } + return GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->HasDirectoryEntry(entry); } inline mdToken PEImage::GetEntryPointToken() { WRAPPER_NO_CONTRACT; - if (HasLoadedLayout()) - { - PTR_PEImageLayout pLayout = GetLoadedLayout(); - if (!pLayout->HasManagedEntryPoint()) - return mdTokenNil; - return pLayout->GetEntryPointToken(); - } - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - if (!pLayout->HasManagedEntryPoint()) - return mdTokenNil; - return pLayout->GetEntryPointToken(); - } + PEImageLayout* pLayout = GetOrCreateLayout(PEImageLayout::LAYOUT_ANY); + if (!pLayout->HasManagedEntryPoint()) + return mdTokenNil; + return pLayout->GetEntryPointToken(); } inline DWORD PEImage::GetCorHeaderFlags() { WRAPPER_NO_CONTRACT; - - if (HasLoadedLayout()) - { - PTR_PEImageLayout pLayout = GetLoadedLayout(); - return VAL32(pLayout->GetCorHeader()->Flags); - } - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - return VAL32(pLayout->GetCorHeader()->Flags); - } + return VAL32(GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->GetCorHeader()->Flags); } inline BOOL PEImage::MDImportLoaded() @@ -299,93 +240,32 @@ inline BOOL PEImage::HasV1Metadata() inline BOOL PEImage::IsILOnly() { WRAPPER_NO_CONTRACT; - if (HasLoadedLayout()) - return GetLoadedLayout()->IsILOnly(); - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - return pLayout->IsILOnly(); - } -} - -inline WORD PEImage::GetSubsystem() -{ - WRAPPER_NO_CONTRACT; - SUPPORTS_DAC; - - if (HasLoadedLayout()) - return GetLoadedLayout()->GetSubsystem(); - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - return pLayout->GetSubsystem(); - } -} - -inline BOOL PEImage::IsDll() -{ - WRAPPER_NO_CONTRACT; - if (HasLoadedLayout()) - return GetLoadedLayout()->IsDll(); - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - return pLayout->IsDll(); - } -} - -inline BOOL PEImage::IsIbcOptimized() -{ - return false; + return GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->IsILOnly(); } inline PTR_CVOID PEImage::GetNativeManifestMetadata(COUNT_T *pSize) { WRAPPER_NO_CONTRACT; - if (HasLoadedLayout()) - return GetLoadedLayout()->GetNativeManifestMetadata(pSize); - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - return pLayout->GetNativeManifestMetadata(pSize); - } + return GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->GetNativeManifestMetadata(pSize); } inline PTR_CVOID PEImage::GetMetadata(COUNT_T *pSize) { WRAPPER_NO_CONTRACT; - if (HasLoadedLayout()) - return GetLoadedLayout()->GetMetadata(pSize); - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - return pLayout->GetMetadata(pSize); - } + return GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->GetMetadata(pSize); } inline BOOL PEImage::HasContents() { WRAPPER_NO_CONTRACT; - if (HasLoadedLayout()) - return GetLoadedLayout()->HasContents(); - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - return pLayout->HasContents(); - } + return GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->HasContents(); } inline CHECK PEImage::CheckFormat() { WRAPPER_NO_CONTRACT; - if (HasLoadedLayout()) - CHECK(GetLoadedLayout()->CheckFormat()); - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - CHECK(pLayout->CheckFormat()); - } + CHECK(GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->CheckFormat()); CHECK_OK; } @@ -429,15 +309,13 @@ inline PTR_PEImage PEImage::FindByPath(LPCWSTR pPath, BOOL isInBundle /* = TRUE DWORD dwHash = CaseHashHelper(pPath, (COUNT_T) wcslen(pPath)); #endif return (PEImage *) s_Images->LookupValue(dwHash, &locator); - } /* static */ inline PTR_PEImage PEImage::OpenImage(LPCWSTR pPath, MDInternalImportFlags flags /* = MDInternalImport_Default */, BundleFileLocation bundleFileLocation) { - BOOL fUseCache = !((flags & MDInternalImport_NoCache) == MDInternalImport_NoCache); - - if (!fUseCache) + BOOL forbidCache = (flags & MDInternalImport_NoCache); + if (forbidCache) { PEImageHolder pImage(new PEImage); pImage->Init(pPath, bundleFileLocation); @@ -447,8 +325,6 @@ inline PTR_PEImage PEImage::OpenImage(LPCWSTR pPath, MDInternalImportFlags flags CrstHolder holder(&s_hashLock); PEImage* found = FindByPath(pPath, bundleFileLocation.IsValid()); - - if (found == (PEImage*) INVALIDENTRY) { // We did not find the entry in the Cache, and we've been asked to only use the cache. @@ -470,15 +346,8 @@ inline PTR_PEImage PEImage::OpenImage(LPCWSTR pPath, MDInternalImportFlags flags } #endif -inline BOOL PEImage::IsFileLocked() -{ - WRAPPER_NO_CONTRACT; - return (m_pLayouts[IMAGE_FLAT])!=NULL || (m_pLayouts[IMAGE_MAPPED])!=NULL ; -} - #ifndef DACCESS_COMPILE - inline void PEImage::AddToHashMap() { CONTRACTL @@ -490,40 +359,30 @@ inline void PEImage::AddToHashMap() CONTRACTL_END; _ASSERTE(s_hashLock.OwnedByCurrentThread()); - s_Images->InsertValue(GetIDHash(),this); + s_Images->InsertValue(GetPathHash(),this); m_bInHashMap=TRUE; } #endif - - - inline BOOL PEImage::Has32BitNTHeaders() { WRAPPER_NO_CONTRACT; - if (HasLoadedLayout()) - return GetLoadedLayout()->Has32BitNTHeaders(); - else - { - PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED)); - return pLayout->Has32BitNTHeaders(); - } + return GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->Has32BitNTHeaders(); } -inline BOOL PEImage::HasID() +inline BOOL PEImage::HasPath() { LIMITED_METHOD_CONTRACT; - return !GetPath().IsEmpty(); } -inline ULONG PEImage::GetIDHash() +inline ULONG PEImage::GetPathHash() { CONTRACT(ULONG) { - PRECONDITION(HasID()); + PRECONDITION(HasPath()); MODE_ANY; GC_NOTRIGGER; THROWS; @@ -537,7 +396,7 @@ inline ULONG PEImage::GetIDHash() #endif } -inline void PEImage::CachePEKindAndMachine() +inline void PEImage::GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine) { CONTRACTL { @@ -547,40 +406,20 @@ inline void PEImage::CachePEKindAndMachine() } CONTRACTL_END; - // Do nothing if we have cached the information already - if(m_fCachedKindAndMachine) - return; - - PEImageLayoutHolder pLayout; - if (HasLoadedLayout()) - { - pLayout.Assign(GetLoadedLayout(), false); - } - else + // first check if we have a valid PE kind + if (VolatileLoad(&m_dwPEKind) == 0) { - pLayout.Assign(GetLayout(PEImageLayout::LAYOUT_MAPPED|PEImageLayout::LAYOUT_FLAT, - PEImage::LAYOUT_CREATEIFNEEDED)); - } - - // Compute result into a local variables first - DWORD dwPEKind, dwMachine; - pLayout->GetPEKindAndMachine(&dwPEKind, &dwMachine); + // Compute result into a local variables first + DWORD dwPEKind, dwMachine; + GetOrCreateLayout(PEImageLayout::LAYOUT_ANY)->GetPEKindAndMachine(&dwPEKind, &dwMachine); - // Write the final result into the lock-free cache. - m_dwPEKind = dwPEKind; - m_dwMachine = dwMachine; - MemoryBarrier(); - m_fCachedKindAndMachine = TRUE; -} + // Write the final results - first machine, then kind. + m_dwMachine = dwMachine; + VolatileStore(&m_dwPEKind, dwPEKind); + } -inline void PEImage::GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine) -{ - WRAPPER_NO_CONTRACT; - CachePEKindAndMachine(); - if (pdwKind) - *pdwKind = m_dwPEKind; - if (pdwMachine) - *pdwMachine = m_dwMachine; + *pdwKind = m_dwPEKind; + *pdwMachine = m_dwMachine; } #endif // PEIMAGE_INL_ diff --git a/src/coreclr/vm/peimagelayout.cpp b/src/coreclr/vm/peimagelayout.cpp index 33081b9b60586..e4c4c274cf309 100644 --- a/src/coreclr/vm/peimagelayout.cpp +++ b/src/coreclr/vm/peimagelayout.cpp @@ -806,7 +806,7 @@ PEImageLayout::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { WRAPPER_NO_CONTRACT; DAC_ENUM_VTHIS(); - EMEM_OUT(("MEM: %p PEFile\n", dac_cast(this))); + EMEM_OUT(("MEM: %p PEAssembly\n", dac_cast(this))); PEDecoder::EnumMemoryRegions(flags,false); } #endif //DACCESS_COMPILE diff --git a/src/coreclr/vm/perfinfo.cpp b/src/coreclr/vm/perfinfo.cpp index b645052f46d2e..667223fedc605 100644 --- a/src/coreclr/vm/perfinfo.cpp +++ b/src/coreclr/vm/perfinfo.cpp @@ -27,28 +27,28 @@ PerfInfo::PerfInfo(int pid) } // Logs image loads into the process' perfinfo-%d.map file -void PerfInfo::LogImage(PEFile* pFile, WCHAR* guid) +void PerfInfo::LogImage(PEAssembly* pPEAssembly, WCHAR* guid) { CONTRACTL { THROWS; GC_NOTRIGGER; MODE_PREEMPTIVE; - PRECONDITION(pFile != nullptr); + PRECONDITION(pPEAssembly != nullptr); PRECONDITION(guid != nullptr); } CONTRACTL_END; SString value; - const SString& path = pFile->GetPath(); + const SString& path = pPEAssembly->GetPath(); if (path.IsEmpty()) { return; } SIZE_T baseAddr = 0; - if (pFile->IsReadyToRun()) + if (pPEAssembly->IsReadyToRun()) { - PEImageLayout *pLoadedLayout = pFile->GetLoaded(); + PEImageLayout *pLoadedLayout = pPEAssembly->GetLoadedLayout(); if (pLoadedLayout) { baseAddr = (SIZE_T)pLoadedLayout->GetBase(); diff --git a/src/coreclr/vm/perfinfo.h b/src/coreclr/vm/perfinfo.h index 759a844f30925..16b06865925c6 100644 --- a/src/coreclr/vm/perfinfo.h +++ b/src/coreclr/vm/perfinfo.h @@ -22,7 +22,7 @@ class PerfInfo { public: PerfInfo(int pid); ~PerfInfo(); - void LogImage(PEFile* pFile, WCHAR* guid); + void LogImage(PEAssembly* pPEAssembly, WCHAR* guid); private: CFileStream* m_Stream; diff --git a/src/coreclr/vm/perfmap.cpp b/src/coreclr/vm/perfmap.cpp index 31da16cac5586..48f178aeb67c3 100644 --- a/src/coreclr/vm/perfmap.cpp +++ b/src/coreclr/vm/perfmap.cpp @@ -219,22 +219,22 @@ void PerfMap::LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, cons } -void PerfMap::LogImageLoad(PEFile * pFile) +void PerfMap::LogImageLoad(PEAssembly * pPEAssembly) { if (s_enabled) { - s_Current->LogImage(pFile); + s_Current->LogImage(pPEAssembly); } } // Log an image load to the map. -void PerfMap::LogImage(PEFile * pFile) +void PerfMap::LogImage(PEAssembly * pPEAssembly) { CONTRACTL{ THROWS; GC_NOTRIGGER; MODE_PREEMPTIVE; - PRECONDITION(pFile != nullptr); + PRECONDITION(pPEAssembly != nullptr); } CONTRACTL_END; @@ -247,9 +247,9 @@ void PerfMap::LogImage(PEFile * pFile) EX_TRY { WCHAR wszSignature[39]; - GetNativeImageSignature(pFile, wszSignature, lengthof(wszSignature)); + GetNativeImageSignature(pPEAssembly, wszSignature, lengthof(wszSignature)); - m_PerfInfo->LogImage(pFile, wszSignature); + m_PerfInfo->LogImage(pPEAssembly, wszSignature); } EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); } @@ -361,10 +361,10 @@ void PerfMap::LogStubs(const char* stubType, const char* stubOwner, PCODE pCode, EX_CATCH{} EX_END_CATCH(SwallowAllExceptions); } -void PerfMap::GetNativeImageSignature(PEFile * pFile, WCHAR * pwszSig, unsigned int nSigSize) +void PerfMap::GetNativeImageSignature(PEAssembly * pPEAssembly, WCHAR * pwszSig, unsigned int nSigSize) { CONTRACTL{ - PRECONDITION(pFile != nullptr); + PRECONDITION(pPEAssembly != nullptr); PRECONDITION(pwszSig != nullptr); PRECONDITION(nSigSize >= 39); } CONTRACTL_END; @@ -372,7 +372,7 @@ void PerfMap::GetNativeImageSignature(PEFile * pFile, WCHAR * pwszSig, unsigned // We use the MVID as the signature, since ready to run images // don't have a native image signature. GUID mvid; - pFile->GetMVID(&mvid); + pPEAssembly->GetMVID(&mvid); if(!StringFromGUID2(mvid, pwszSig, nSigSize)) { pwszSig[0] = '\0'; @@ -417,7 +417,7 @@ void NativeImagePerfMap::LogDataForModule(Module * pModule) { STANDARD_VM_CONTRACT; - PEImageLayout * pLoadedLayout = pModule->GetFile()->GetLoaded(); + PEImageLayout * pLoadedLayout = pModule->GetPEAssembly()->GetLoadedLayout(); _ASSERTE(pLoadedLayout != nullptr); ReadyToRunInfo::MethodIterator mi(pModule->GetReadyToRunInfo()); diff --git a/src/coreclr/vm/perfmap.h b/src/coreclr/vm/perfmap.h index 14595813877d8..587a776e68276 100644 --- a/src/coreclr/vm/perfmap.h +++ b/src/coreclr/vm/perfmap.h @@ -57,17 +57,17 @@ class PerfMap void LogMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, const char *optimizationTier); // Does the actual work to log an image - void LogImage(PEFile * pFile); + void LogImage(PEAssembly * pPEAssembly); // Get the image signature and store it as a string. - static void GetNativeImageSignature(PEFile * pFile, WCHAR * pwszSig, unsigned int nSigSize); + static void GetNativeImageSignature(PEAssembly * pPEAssembly, WCHAR * pwszSig, unsigned int nSigSize); public: // Initialize the map for the current process. static void Initialize(); // Log a native image load to the map. - static void LogImageLoad(PEFile * pFile); + static void LogImageLoad(PEAssembly * pPEAssembly); // Log a JIT compiled method to the map. static void LogJITCompiledMethod(MethodDesc * pMethod, PCODE pCode, size_t codeSize, PrepareCodeConfig *pConfig); diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index 4f08f247da765..5c47a34f70487 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -2131,7 +2131,7 @@ HRESULT ProfToEEInterfaceImpl::GetTokenAndMetaDataFromFunction( // Yay! EE_THREAD_NOT_REQUIRED; - // PEFile::GetRWImporter and GetReadablePublicMetaDataInterface take locks + // PEAssembly::GetRWImporter and GetReadablePublicMetaDataInterface take locks CAN_TAKE_LOCK; } @@ -3977,11 +3977,11 @@ DWORD ProfToEEInterfaceImpl::GetModuleFlags(Module * pModule) } CONTRACTL_END; - PEFile * pPEFile = pModule->GetFile(); - if (pPEFile == NULL) + PEAssembly * pPEAssembly = pModule->GetPEAssembly(); + if (pPEAssembly == NULL) { // Hopefully this should never happen; but just in case, don't try to determine the - // flags without a PEFile. + // flags without a PEAssembly. return 0; } @@ -3996,15 +3996,15 @@ DWORD ProfToEEInterfaceImpl::GetModuleFlags(Module * pModule) dwRet |= (COR_PRF_MODULE_DISK | COR_PRF_MODULE_NGEN); } #endif - // Not NGEN or ReadyToRun. - if (pPEFile->HasOpenedILimage()) + // Not Dynamic. + if (pPEAssembly->HasPEImage()) { - PEImage * pILImage = pPEFile->GetOpenedILimage(); + PEImage * pILImage = pPEAssembly->GetPEImage(); if (pILImage->IsFile()) { dwRet |= COR_PRF_MODULE_DISK; } - if (pPEFile->GetLoadedIL()->IsFlat()) + if (pPEAssembly->GetLoadedLayout()->IsFlat()) { dwRet |= COR_PRF_MODULE_FLAT_LAYOUT; } @@ -4020,11 +4020,6 @@ DWORD ProfToEEInterfaceImpl::GetModuleFlags(Module * pModule) dwRet |= COR_PRF_MODULE_COLLECTIBLE; } - if (pModule->IsResource()) - { - dwRet |= COR_PRF_MODULE_RESOURCE; - } - return dwRet; } @@ -4086,7 +4081,7 @@ HRESULT ProfToEEInterfaceImpl::GetModuleInfo2(ModuleID moduleId, EX_TRY { - PEFile * pFile = pModule->GetFile(); + PEAssembly * pFile = pModule->GetPEAssembly(); // Pick some safe defaults to begin with. if (ppBaseLoadAddress != NULL) @@ -4209,7 +4204,7 @@ HRESULT ProfToEEInterfaceImpl::GetModuleMetaData(ModuleID moduleId, // but we might be able to lift that restriction and make this be // EE_THREAD_NOT_REQUIRED. - // PEFile::GetRWImporter & PEFile::GetEmitter & + // PEAssembly::GetRWImporter & PEAssembly::GetEmitter & // GetReadablePublicMetaDataInterface take locks CAN_TAKE_LOCK; @@ -4244,14 +4239,6 @@ HRESULT ProfToEEInterfaceImpl::GetModuleMetaData(ModuleID moduleId, return CORPROF_E_DATAINCOMPLETE; } - // Make sure we can get the importer first - if (pModule->IsResource()) - { - if (ppOut) - *ppOut = NULL; - return S_FALSE; - } - // Decide which type of open mode we are in to see which you require. if ((dwOpenFlags & ofWrite) == 0) { @@ -4299,7 +4286,7 @@ HRESULT ProfToEEInterfaceImpl::GetILFunctionBody(ModuleID moduleId, // Yay! MODE_ANY; - // PEFile::CheckLoaded & Module::GetDynamicIL both take a lock + // Module::GetDynamicIL both take a lock CAN_TAKE_LOCK; } @@ -4337,9 +4324,9 @@ HRESULT ProfToEEInterfaceImpl::GetILFunctionBody(ModuleID moduleId, IMDInternalImport *pImport = pModule->GetMDImport(); _ASSERTE(pImport); - PEFile *pFile = pModule->GetFile(); + PEAssembly *pPEAssembly = pModule->GetPEAssembly(); - if (!pFile->CheckLoaded()) + if (!pPEAssembly->HasLoadedPEImage()) return (CORPROF_E_DATAINCOMPLETE); LPCBYTE pbMethod = NULL; @@ -4354,7 +4341,7 @@ HRESULT ProfToEEInterfaceImpl::GetILFunctionBody(ModuleID moduleId, IfFailRet(pImport->GetMethodImplProps(methodId, &RVA, &dwImplFlags)); // Check to see if the method has associated IL - if ((RVA == 0 && !pFile->IsDynamic()) || !(IsMiIL(dwImplFlags) || IsMiOPTIL(dwImplFlags) || IsMiInternalCall(dwImplFlags))) + if ((RVA == 0 && !pPEAssembly->IsDynamic()) || !(IsMiIL(dwImplFlags) || IsMiOPTIL(dwImplFlags) || IsMiInternalCall(dwImplFlags))) { return (CORPROF_E_FUNCTION_NOT_IL); } @@ -4449,7 +4436,7 @@ HRESULT ProfToEEInterfaceImpl::GetILFunctionBodyAllocator(ModuleID modul Module * pModule = (Module *) moduleId; if (pModule->IsBeingUnloaded() || - !pModule->GetFile()->CheckLoaded()) + !pModule->GetPEAssembly()->HasLoadedPEImage()) { return (CORPROF_E_DATAINCOMPLETE); } @@ -4472,7 +4459,7 @@ HRESULT ProfToEEInterfaceImpl::SetILFunctionBody(ModuleID moduleId, { CONTRACTL { - // PEFile::GetEmitter, Module::SetDynamicIL all throw + // PEAssembly::GetEmitter, Module::SetDynamicIL all throw THROWS; // Locks are taken (see CAN_TAKE_LOCK below), which may cause mode switch to @@ -4482,7 +4469,7 @@ HRESULT ProfToEEInterfaceImpl::SetILFunctionBody(ModuleID moduleId, // Yay! MODE_ANY; - // Module::SetDynamicIL & PEFile::CheckLoaded & PEFile::GetEmitter take locks + // Module::SetDynamicIL & PEAssembly::GetEmitter take locks CAN_TAKE_LOCK; } diff --git a/src/coreclr/vm/readytoruninfo.cpp b/src/coreclr/vm/readytoruninfo.cpp index 4a6052b1ef162..bf77758eeccdf 100644 --- a/src/coreclr/vm/readytoruninfo.cpp +++ b/src/coreclr/vm/readytoruninfo.cpp @@ -392,7 +392,7 @@ BOOL ReadyToRunInfo::IsReadyToRunEnabled() // Any other value: Handle of the log file. static FILE * volatile s_r2rLogFile = (FILE *)(-1); -static void LogR2r(const char *msg, PEFile *pFile) +static void LogR2r(const char *msg, PEAssembly *pPEAssembly) { STANDARD_VM_CONTRACT; @@ -430,7 +430,7 @@ static void LogR2r(const char *msg, PEFile *pFile) if (r2rLogFile == NULL) return; - fprintf(r2rLogFile, "%s: \"%S\".\n", msg, pFile->GetPath().GetUnicode()); + fprintf(r2rLogFile, "%s: \"%S\".\n", msg, pPEAssembly->GetPath().GetUnicode()); fflush(r2rLogFile); } @@ -503,7 +503,7 @@ static NativeImage *AcquireCompositeImage(Module * pModule, PEImageLayout * pLay if (ownerCompositeExecutableName != NULL) { - AssemblyBinder *binder = pModule->GetFile()->GetAssemblyBinder(); + AssemblyBinder *binder = pModule->GetPEAssembly()->GetAssemblyBinder(); return binder->LoadNativeImage(pModule, ownerCompositeExecutableName); } @@ -514,7 +514,7 @@ PTR_ReadyToRunInfo ReadyToRunInfo::Initialize(Module * pModule, AllocMemTracker { STANDARD_VM_CONTRACT; - PEFile * pFile = pModule->GetFile(); + PEAssembly * pFile = pModule->GetPEAssembly(); if (!IsReadyToRunEnabled()) { @@ -529,13 +529,13 @@ PTR_ReadyToRunInfo ReadyToRunInfo::Initialize(Module * pModule, AllocMemTracker return NULL; } - if (!pFile->HasLoadedIL()) + if (!pFile->HasLoadedPEImage()) { - DoLog("Ready to Run disabled - no loaded IL image"); + DoLog("Ready to Run disabled - no loaded PE image"); return NULL; } - PEImageLayout * pLayout = pFile->GetLoadedIL(); + PEImageLayout * pLayout = pFile->GetLoadedLayout(); if (!pLayout->HasReadyToRunHeader()) { DoLog("Ready to Run header not found"); diff --git a/src/coreclr/vm/runtimehandles.cpp b/src/coreclr/vm/runtimehandles.cpp index 620ead8289e4f..5c436a73c9000 100644 --- a/src/coreclr/vm/runtimehandles.cpp +++ b/src/coreclr/vm/runtimehandles.cpp @@ -2728,7 +2728,7 @@ void QCALLTYPE ModuleHandle::GetPEKind(QCall::ModuleHandle pModule, DWORD* pdwPE QCALL_CONTRACT; BEGIN_QCALL; - pModule->GetFile()->GetPEKindAndMachine(pdwPEKind, pdwMachine); + pModule->GetPEAssembly()->GetPEKindAndMachine(pdwPEKind, pdwMachine); END_QCALL; } @@ -2742,10 +2742,6 @@ FCIMPL1(INT32, ModuleHandle::GetMDStreamVersion, ReflectModuleBaseObject * pModu FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); Module *pModule = refModule->GetModule(); - - if (pModule->IsResource()) - return 0; - return pModule->GetMDImport()->GetMetadataStreamVersion(); } FCIMPLEND @@ -2787,10 +2783,6 @@ FCIMPL1(INT32, ModuleHandle::GetToken, ReflectModuleBaseObject * pModuleUNSAFE) FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); Module *pModule = refModule->GetModule(); - - if (pModule->IsResource()) - return mdModuleNil; - return pModule->GetMDImport()->GetModuleFromScope(); } FCIMPLEND @@ -2805,10 +2797,6 @@ FCIMPL1(IMDInternalImport*, ModuleHandle::GetMetadataImport, ReflectModuleBaseOb FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle")); Module *pModule = refModule->GetModule(); - - if (pModule->IsResource()) - return NULL; - return pModule->GetMDImport(); } FCIMPLEND diff --git a/src/coreclr/vm/siginfo.cpp b/src/coreclr/vm/siginfo.cpp index a3aea61ba7b2b..4c438360513cb 100644 --- a/src/coreclr/vm/siginfo.cpp +++ b/src/coreclr/vm/siginfo.cpp @@ -3547,7 +3547,7 @@ BOOL CompareTypeTokens(mdToken tk1, mdToken tk2, Module *pModule1, Module *pModu #ifdef DACCESS_COMPILE ThrowHR(hr); #else - EEFileLoadException::Throw(pModule2->GetFile(), hr); + EEFileLoadException::Throw(pModule2->GetPEAssembly(), hr); #endif //!DACCESS_COMPILE } // CompareTypeTokens diff --git a/src/coreclr/vm/typeparse.cpp b/src/coreclr/vm/typeparse.cpp index 84ce7124c473c..258b50d86916b 100644 --- a/src/coreclr/vm/typeparse.cpp +++ b/src/coreclr/vm/typeparse.cpp @@ -1415,7 +1415,7 @@ TypeName::GetTypeHaveAssemblyHelper( if (pManifestModule->LookupFile(mdFile)) continue; - pManifestModule->LoadModule(GetAppDomain(), mdFile, FALSE); + pManifestModule->LoadModule(GetAppDomain(), mdFile); th = GetTypeHaveAssemblyHelper(pAssembly, bThrowIfNotFound, bIgnoreCase, NULL, FALSE); @@ -1479,7 +1479,7 @@ DomainAssembly * LoadDomainAssembly( { // If the requesting assembly has Fallback LoadContext binder available, // then set it up in the AssemblySpec. - PEFile *pRequestingAssemblyManifestFile = pRequestingAssembly->GetManifestFile(); + PEAssembly *pRequestingAssemblyManifestFile = pRequestingAssembly->GetManifestFile(); spec.SetFallbackBinderForRequestingAssembly(pRequestingAssemblyManifestFile->GetFallbackBinder()); } diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props index 3d070f437073b..711bc0d4ae5a3 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -218,6 +218,7 @@ + @@ -237,7 +238,7 @@ - + sharedhost Dotnet_CLI_SharedHost HostSrc + afterInstallExecute false true sharedhost diff --git a/src/installer/tests/HostActivation.Tests/NativeHostApis.cs b/src/installer/tests/HostActivation.Tests/NativeHostApis.cs index aaabf8e571bcd..d9feb540d70bc 100644 --- a/src/installer/tests/HostActivation.Tests/NativeHostApis.cs +++ b/src/installer/tests/HostActivation.Tests/NativeHostApis.cs @@ -461,6 +461,52 @@ public void Hostfxr_get_dotnet_environment_info_with_multilevel_lookup_only() } } + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] // Multi-level lookup is only supported on Windows. + public void Hostfxr_get_dotnet_environment_info_with_multilevel_lookup_only_self_register_program_files() + { + var f = new SdkResolutionFixture(sharedTestState); + + string expectedFrameworkNames = string.Join(';', new[] + { + "HostFxr.Test.A", + "HostFxr.Test.A", + "HostFxr.Test.B", + }); + + string expectedFrameworkVersions = string.Join(';', new[] + { + "1.2.3", + "3.0.0", + "5.6.7-A", + }); + + string expectedFrameworkPaths = string.Join(';', new[] + { + Path.Combine(f.ProgramFilesGlobalFrameworksDir, "HostFxr.Test.A"), + Path.Combine(f.ProgramFilesGlobalFrameworksDir, "HostFxr.Test.A"), + Path.Combine(f.ProgramFilesGlobalFrameworksDir, "HostFxr.Test.B"), + }); + + using (TestOnlyProductBehavior.Enable(f.Dotnet.GreatestVersionHostFxrFilePath)) + { + // We pass f.WorkingDir so that we don't resolve dotnet_dir to the global installation + // in the native side. + f.Dotnet.Exec(f.AppDll, new[] { "hostfxr_get_dotnet_environment_info", f.WorkingDir }) + .EnvironmentVariable("TEST_MULTILEVEL_LOOKUP_PROGRAM_FILES", f.ProgramFiles) + // Test with a self-registered path the same as ProgramFiles, with a trailing slash. Expect this to be de-duped + .EnvironmentVariable("TEST_MULTILEVEL_LOOKUP_SELF_REGISTERED", Path.Combine(f.ProgramFiles, "dotnet") + Path.DirectorySeparatorChar) + .CaptureStdOut() + .CaptureStdErr() + .Execute() + .Should().Pass() + .And.HaveStdOutContaining("hostfxr_get_dotnet_environment_info:Success") + .And.HaveStdOutContaining($"hostfxr_get_dotnet_environment_info framework names:[{expectedFrameworkNames}]") + .And.HaveStdOutContaining($"hostfxr_get_dotnet_environment_info framework versions:[{expectedFrameworkVersions}]") + .And.HaveStdOutContaining($"hostfxr_get_dotnet_environment_info framework paths:[{expectedFrameworkPaths}]"); + } + } + [Fact] public void Hostfxr_get_dotnet_environment_info_global_install_path() { diff --git a/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/Microsoft.DotNet.CoreSetup.Packaging.Tests.csproj b/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/Microsoft.DotNet.CoreSetup.Packaging.Tests.csproj index 8dcef20c22dea..73a3fda2b55fd 100644 --- a/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/Microsoft.DotNet.CoreSetup.Packaging.Tests.csproj +++ b/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/Microsoft.DotNet.CoreSetup.Packaging.Tests.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Cipher.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Cipher.cs index c1abefa490d75..42020d9217b9a 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Cipher.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Cipher.cs @@ -15,7 +15,6 @@ internal static extern SafeEvpCipherCtxHandle EvpCipherCreate( IntPtr cipher, ref byte key, int keyLength, - int effectivekeyLength, ref byte iv, int enc); diff --git a/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs b/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs index d6ac21cf3219f..051b412b1199d 100644 --- a/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs +++ b/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs @@ -98,7 +98,7 @@ public static void StopProfile() { } - // Called by the AOT profiler to save profile data into Module.aot_profile_data + // Called by the AOT profiler to save profile data into INTERNAL.aot_profile_data [MethodImplAttribute(MethodImplOptions.NoInlining)] public static unsafe void DumpAotProfileData(ref byte buf, int len, string extraArg) { diff --git a/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs index f38bb375b347e..7fbaf9cc32eab 100644 --- a/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs +++ b/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs @@ -136,8 +136,9 @@ static Ldap() [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi)] public static extern int ldap_set_option_referral([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref LdapReferralCallback outValue); + // Note that ldap_start_tls_s has a different signature across Windows LDAP and OpenLDAP [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_start_tls_s", CharSet = CharSet.Ansi)] - public static extern int ldap_start_tls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls); + public static extern int ldap_start_tls(ConnectionHandle ldapHandle, IntPtr serverControls, IntPtr clientControls); [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_parse_result", CharSet = CharSet.Ansi)] public static extern int ldap_parse_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref int serverError, ref IntPtr dn, ref IntPtr message, ref IntPtr referral, ref IntPtr control, byte freeIt); diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs index f960ed7e881c5..ce77602722126 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs @@ -14,7 +14,6 @@ internal static partial SafeEvpCipherCtxHandle EvpCipherCreate( IntPtr cipher, ref byte key, int keyLength, - int effectivekeyLength, ref byte iv, int enc); diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/RC2BCryptModes.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/RC2BCryptModes.cs index 7c7503b8b9cb0..5caf5f0c8da7e 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/RC2BCryptModes.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/RC2BCryptModes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics; using System.Security.Cryptography; using Internal.NativeCrypto; @@ -26,10 +27,8 @@ private static SafeAlgorithmHandle OpenRC2Algorithm(string cipherMode, int effec SafeAlgorithmHandle hAlg = Cng.BCryptOpenAlgorithmProvider(Cng.BCRYPT_RC2_ALGORITHM, null, Cng.OpenAlgorithmProviderFlags.NONE); hAlg.SetCipherMode(cipherMode); - if (effectiveKeyLength != 0) - { - Cng.SetEffectiveKeyLength(hAlg, effectiveKeyLength); - } + Debug.Assert(effectiveKeyLength > 0); + Cng.SetEffectiveKeyLength(hAlg, effectiveKeyLength); return hAlg; } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Interop/Windows/Crypt32/Interop.CertDuplicateCertificateContext.cs b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertDuplicateCertificateContext_IntPtr.cs similarity index 100% rename from src/libraries/System.Security.Cryptography.Pkcs/src/Interop/Windows/Crypt32/Interop.CertDuplicateCertificateContext.cs rename to src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertDuplicateCertificateContext_IntPtr.cs diff --git a/src/libraries/Common/src/System/IO/FileSystem.Attributes.Windows.cs b/src/libraries/Common/src/System/IO/FileSystem.Attributes.Windows.cs index ad087304b4e5a..7e7afcec97a72 100644 --- a/src/libraries/Common/src/System/IO/FileSystem.Attributes.Windows.cs +++ b/src/libraries/Common/src/System/IO/FileSystem.Attributes.Windows.cs @@ -9,11 +9,7 @@ using System.IO; using System.Text; -#if MS_IO_REDIST -namespace Microsoft.IO -#else namespace System.IO -#endif { internal static partial class FileSystem { diff --git a/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs b/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs index 821f878796e84..dba07a8fb4156 100644 --- a/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs +++ b/src/libraries/Common/src/System/IO/FileSystem.DirectoryCreation.Windows.cs @@ -9,11 +9,7 @@ using System.IO; using System.Text; -#if MS_IO_REDIST -namespace Microsoft.IO -#else namespace System.IO -#endif { internal static partial class FileSystem { diff --git a/src/libraries/Common/src/System/IO/PathInternal.CaseSensitivity.cs b/src/libraries/Common/src/System/IO/PathInternal.CaseSensitivity.cs index 80fc6b43ff607..32769debc29d1 100644 --- a/src/libraries/Common/src/System/IO/PathInternal.CaseSensitivity.cs +++ b/src/libraries/Common/src/System/IO/PathInternal.CaseSensitivity.cs @@ -3,10 +3,6 @@ using System.Diagnostics; -#if MS_IO_REDIST -using Microsoft.IO; -#endif - namespace System.IO { /// Contains internal path helpers that are shared between many projects. @@ -28,11 +24,7 @@ internal static bool IsCaseSensitive { get { -#if MS_IO_REDIST - return false; // Windows is always case-insensitive -#else return !(OperatingSystem.IsWindows() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || OperatingSystem.IsTvOS() || OperatingSystem.IsWatchOS()); -#endif } } } diff --git a/src/libraries/Common/src/System/IO/PathInternal.cs b/src/libraries/Common/src/System/IO/PathInternal.cs index ff9d79caee253..52aaa59072dd7 100644 --- a/src/libraries/Common/src/System/IO/PathInternal.cs +++ b/src/libraries/Common/src/System/IO/PathInternal.cs @@ -15,13 +15,8 @@ internal static partial class PathInternal /// internal static bool StartsWithDirectorySeparator(ReadOnlySpan path) => path.Length > 0 && IsDirectorySeparator(path[0]); -#if MS_IO_REDIST - internal static string EnsureTrailingSeparator(string path) - => EndsInDirectorySeparator(path) ? path : path + DirectorySeparatorCharAsString; -#else internal static string EnsureTrailingSeparator(string path) => EndsInDirectorySeparator(path.AsSpan()) ? path : path + DirectorySeparatorCharAsString; -#endif internal static bool IsRoot(ReadOnlySpan path) => path.Length == GetRootLength(path); @@ -248,10 +243,6 @@ internal static bool EndsInDirectorySeparator(ReadOnlySpan path) => internal static string GetLinkTargetFullPath(string path, string pathToTarget) => IsPartiallyQualified(pathToTarget.AsSpan()) ? -#if MS_IO_REDIST - Path.Combine(Path.GetDirectoryName(path), pathToTarget) : pathToTarget; -#else Path.Join(Path.GetDirectoryName(path.AsSpan()), pathToTarget.AsSpan()) : pathToTarget; -#endif } } diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackStream.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackStream.cs index 346098414b39b..9491c563668f7 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackStream.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackStream.cs @@ -358,6 +358,54 @@ private HttpRequestData ParseHeaders(ReadOnlySpan buffer) } public async Task WaitForCancellationAsync(bool ignoreIncomingData = true) + { + bool readCanceled = false; + bool writeCanceled = false; + + async Task WaitForReadCancellation() + { + try + { + if (ignoreIncomingData) + { + await DrainResponseData(); + } + else + { + int bytesRead = await _stream.ReadAsync(new byte[1]); + if (bytesRead != 0) + { + throw new Exception($"Unexpected data received while waiting for client cancllation."); + } + } + } + catch (QuicStreamAbortedException ex) when (ex.ErrorCode == Http3LoopbackConnection.H3_REQUEST_CANCELLED) + { + readCanceled = true; + } + } + + async Task WaitForWriteCancellation() + { + try + { + await _stream.WaitForWriteCompletionAsync(); + } + catch (QuicStreamAbortedException ex) when (ex.ErrorCode == Http3LoopbackConnection.H3_REQUEST_CANCELLED) + { + writeCanceled = true; + } + } + + await Task.WhenAll(WaitForReadCancellation(), WaitForWriteCancellation()); + + if (!readCanceled && !writeCanceled) + { + throw new Exception("Both read and write completed successfully; expected clien cancellation"); + } + } + + private async Task DrainResponseData() { while (true) { @@ -368,11 +416,10 @@ public async Task WaitForCancellationAsync(bool ignoreIncomingData = true) case null: // end of stream reached. return; - case DataFrame when ignoreIncomingData == true: + case DataFrame: break; default: - Debug.Fail("Unexpected frame type while waiting for client cancellation."); - throw new Exception(); + throw new Exception($"Unexpected frame type {frameType} while draining response data."); } } } diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs index c90753dd4025d..1587fc46dc6b4 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs @@ -226,6 +226,7 @@ public async Task NoCallback_BadCertificate_ThrowsException(string url) [OuterLoop("Uses external servers")] [ConditionalFact(nameof(ClientSupportsDHECipherSuites))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60190")] public async Task NoCallback_RevokedCertificate_NoRevocationChecking_Succeeds() { using (HttpClient client = CreateHttpClient()) diff --git a/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs b/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs index f6cc44f67e7c9..60153c0b4975d 100644 --- a/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/ResponseStreamTest.cs @@ -227,7 +227,43 @@ await client.GetAsync(remoteServer.EchoUri, HttpCompletionOption.ResponseHeaders } } } + #if NETCOREAPP + [OuterLoop] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser))] + public async Task BrowserHttpHandler_Streaming() + { + var WebAssemblyEnableStreamingResponseKey = new HttpRequestOptionsKey("WebAssemblyEnableStreamingResponse"); + + var size = 1500 * 1024 * 1024; + var req = new HttpRequestMessage(HttpMethod.Get, Configuration.Http.RemoteSecureHttp11Server.BaseUri + "large.ashx?size=" + size); + + req.Options.Set(WebAssemblyEnableStreamingResponseKey, true); + + using (HttpClient client = CreateHttpClientForRemoteServer(Configuration.Http.RemoteSecureHttp11Server)) + // we need to switch off Response buffering of default ResponseContentRead option + using (HttpResponseMessage response = await client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead)) + { + Assert.Equal(typeof(StreamContent), response.Content.GetType()); + + Assert.Equal("application/octet-stream", response.Content.Headers.ContentType.MediaType); + Assert.True(size == response.Content.Headers.ContentLength, "ContentLength"); + + var stream = await response.Content.ReadAsStreamAsync(); + Assert.Equal("ReadOnlyStream", stream.GetType().Name); + var buffer = new byte[1024 * 1024]; + int totalCount = 0; + int fetchedCount = 0; + do + { + // with WebAssemblyEnableStreamingResponse option set, we will be using https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader/read + fetchedCount = await stream.ReadAsync(buffer, 0, buffer.Length); + totalCount += fetchedCount; + } while (fetchedCount != 0); + Assert.Equal(size, totalCount); + } + } + [Theory] [InlineData(TransferType.ContentLength, TransferError.ContentLengthTooLarge)] [InlineData(TransferType.Chunked, TransferError.MissingChunkTerminator)] diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/GenericHandler.cs b/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/GenericHandler.cs index f129157b1d916..846a30fd9951e 100644 --- a/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/GenericHandler.cs +++ b/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/GenericHandler.cs @@ -83,6 +83,11 @@ public async Task Invoke(HttpContext context) await TestHandler.InvokeAsync(context); return; } + if (path.Equals(new PathString("/large.ashx"))) + { + await LargeResponseHandler.InvokeAsync(context); + return; + } // Default handling. await EchoHandler.InvokeAsync(context); diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/Handlers/LargeResponse.cs b/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/Handlers/LargeResponse.cs new file mode 100644 index 0000000000000..41e21fd3cb5eb --- /dev/null +++ b/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/Handlers/LargeResponse.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace NetCoreServer +{ + public class LargeResponseHandler + { + public static async Task InvokeAsync(HttpContext context) + { + RequestHelper.AddResponseCookies(context); + + if (!AuthenticationHelper.HandleAuthentication(context)) + { + return; + } + + // Add original request method verb as a custom response header. + context.Response.Headers.Add("X-HttpRequest-Method", context.Request.Method); + + var size = 1024; + if (context.Request.Query.TryGetValue("size", out var value)) + { + size = Int32.Parse(value); + } + context.Response.ContentType = "application/octet-stream"; + context.Response.ContentLength = size; + const int bufferSize = 1024 * 100; + var bytes = new byte[bufferSize]; + Random.Shared.NextBytes(bytes); + var remaining = size; + while (remaining > 0) + { + var send = Math.Min(remaining, bufferSize); + await context.Response.Body.WriteAsync(bytes, 0, send); + remaining -= send; + } + } + } +} diff --git a/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/NetCoreServer.csproj b/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/NetCoreServer.csproj index 875277b02d31a..d5c11a7905ae9 100644 --- a/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/NetCoreServer.csproj +++ b/src/libraries/Common/tests/System/Net/Prerequisites/NetCoreServer/NetCoreServer.csproj @@ -18,6 +18,7 @@ + diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index 77496e80d24c7..c4e2e657c07ab 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -48,6 +48,8 @@ public static partial class PlatformDetection public static bool IsNotArm64Process => !IsArm64Process; public static bool IsArmOrArm64Process => IsArmProcess || IsArm64Process; public static bool IsNotArmNorArm64Process => !IsArmOrArm64Process; + public static bool IsX86Process => RuntimeInformation.ProcessArchitecture == Architecture.X86; + public static bool IsNotX86Process => !IsX86Process; public static bool IsArgIteratorSupported => IsMonoRuntime || (IsWindows && IsNotArmProcess); public static bool IsArgIteratorNotSupported => !IsArgIteratorSupported; public static bool Is32BitProcess => IntPtr.Size == 4; @@ -312,12 +314,6 @@ private static Version GetICUVersion() version & 0xFF); } - private static readonly Lazy _net5CompatFileStream = new Lazy(() => GetStaticNonPublicBooleanPropertyValue("System.IO.Strategies.FileStreamHelpers", "UseNet5CompatStrategy")); - - public static bool IsNet5CompatFileStreamEnabled => _net5CompatFileStream.Value; - - public static bool IsNet5CompatFileStreamDisabled => !IsNet5CompatFileStreamEnabled; - private static readonly Lazy s_fileLockingDisabled = new Lazy(() => GetStaticNonPublicBooleanPropertyValue("Microsoft.Win32.SafeHandles.SafeFileHandle", "DisableFileLocking")); public static bool IsFileLockingEnabled => IsWindows || !s_fileLockingDisabled.Value; diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index f13edb1872ebe..2cbcfbb1c089e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs @@ -248,19 +248,17 @@ private static void BindProperty(PropertyInfo property, object instance, IConfig return; } - object propertyValue = property.GetValue(instance); bool hasSetter = property.SetMethod != null && (property.SetMethod.IsPublic || options.BindNonPublicProperties); - if (propertyValue == null && !hasSetter) + if (!hasSetter) { - // Property doesn't have a value and we cannot set it so there is no - // point in going further down the graph + // The property cannot be set so there is no point going further return; } - propertyValue = GetPropertyValue(property, instance, config, options); + object propertyValue = GetPropertyValue(property, instance, config, options); - if (propertyValue != null && hasSetter) + if (propertyValue != null) { property.SetValue(instance, propertyValue); } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs index c5dbd9d90821a..6629557ce89be 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/ConfigurationBinderTests.cs @@ -117,6 +117,11 @@ public class ByteArrayOptions public byte[] MyByteArray { get; set; } } + public class GetterOnlyOptions + { + public string MyString => throw new NotImplementedException(); + } + [Fact] public void CanBindIConfigurationSection() { @@ -343,6 +348,20 @@ public void ThrowsIfPropertyInConfigMissingInNestedModel() Assert.Equal(expectedMessage, ex.Message); } + [Fact] + public void DoesNotExecuteGetterIfNoSetter() + { + var dic = new Dictionary + { + {"MyString", "hello world"} + }; + var configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.AddInMemoryCollection(dic); + var config = configurationBuilder.Build(); + + var _ = config.Get(); + } + [Fact] public void GetDefaultsWhenDataDoesNotExist() { diff --git a/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.cs b/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.cs index feef64fc2dde1..c9719bcdbbc92 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.cs @@ -15,23 +15,24 @@ public partial class ChainedConfigurationProvider : Microsoft.Extensions.Configu { public ChainedConfigurationProvider(Microsoft.Extensions.Configuration.ChainedConfigurationSource source) { } public void Dispose() { } - public System.Collections.Generic.IEnumerable GetChildKeys(System.Collections.Generic.IEnumerable earlierKeys, string parentPath) { throw null; } + public System.Collections.Generic.IEnumerable GetChildKeys(System.Collections.Generic.IEnumerable earlierKeys, string? parentPath) { throw null; } public Microsoft.Extensions.Primitives.IChangeToken GetReloadToken() { throw null; } public void Load() { } - public void Set(string key, string value) { } - public bool TryGet(string key, out string value) { throw null; } + public void Set(string key, string? value) { } + public bool TryGet(string key, out string? value) { throw null; } } public partial class ChainedConfigurationSource : Microsoft.Extensions.Configuration.IConfigurationSource { public ChainedConfigurationSource() { } - public Microsoft.Extensions.Configuration.IConfiguration Configuration { get { throw null; } set { } } + [System.Diagnostics.CodeAnalysis.DisallowNull] + public Microsoft.Extensions.Configuration.IConfiguration? Configuration { get { throw null; } set { } } public bool ShouldDisposeConfiguration { get { throw null; } set { } } public Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) { throw null; } } public sealed partial class ConfigurationManager : Microsoft.Extensions.Configuration.IConfigurationBuilder, Microsoft.Extensions.Configuration.IConfigurationRoot, System.IDisposable { public ConfigurationManager() { } - public string this[string key] { get { throw null; } set { throw null; } } + public string? this[string key] { get { throw null; } set { throw null; } } public IConfigurationSection GetSection(string key) { throw null; } public System.Collections.Generic.IEnumerable GetChildren() { throw null; } public void Dispose() { throw null; } @@ -55,19 +56,19 @@ public partial class ConfigurationKeyComparer : System.Collections.Generic.IComp { public ConfigurationKeyComparer() { } public static Microsoft.Extensions.Configuration.ConfigurationKeyComparer Instance { get { throw null; } } - public int Compare(string x, string y) { throw null; } + public int Compare(string? x, string? y) { throw null; } } public abstract partial class ConfigurationProvider : Microsoft.Extensions.Configuration.IConfigurationProvider { protected ConfigurationProvider() { } - protected System.Collections.Generic.IDictionary Data { get { throw null; } set { } } - public virtual System.Collections.Generic.IEnumerable GetChildKeys(System.Collections.Generic.IEnumerable earlierKeys, string parentPath) { throw null; } + protected System.Collections.Generic.IDictionary Data { get { throw null; } set { } } + public virtual System.Collections.Generic.IEnumerable GetChildKeys(System.Collections.Generic.IEnumerable earlierKeys, string? parentPath) { throw null; } public Microsoft.Extensions.Primitives.IChangeToken GetReloadToken() { throw null; } public virtual void Load() { } protected void OnReload() { } - public virtual void Set(string key, string value) { } + public virtual void Set(string key, string? value) { } public override string ToString() { throw null; } - public virtual bool TryGet(string key, out string value) { throw null; } + public virtual bool TryGet(string key, out string? value) { throw null; } } public partial class ConfigurationReloadToken : Microsoft.Extensions.Primitives.IChangeToken { @@ -75,12 +76,12 @@ public ConfigurationReloadToken() { } public bool ActiveChangeCallbacks { get { throw null; } } public bool HasChanged { get { throw null; } } public void OnReload() { } - public System.IDisposable RegisterChangeCallback(System.Action callback, object state) { throw null; } + public System.IDisposable RegisterChangeCallback(System.Action callback, object? state) { throw null; } } public partial class ConfigurationRoot : Microsoft.Extensions.Configuration.IConfiguration, Microsoft.Extensions.Configuration.IConfigurationRoot, System.IDisposable { public ConfigurationRoot(System.Collections.Generic.IList providers) { } - public string this[string key] { get { throw null; } set { } } + public string? this[string key] { get { throw null; } set { } } public System.Collections.Generic.IEnumerable Providers { get { throw null; } } public void Dispose() { } public System.Collections.Generic.IEnumerable GetChildren() { throw null; } @@ -91,10 +92,10 @@ public void Reload() { } public partial class ConfigurationSection : Microsoft.Extensions.Configuration.IConfiguration, Microsoft.Extensions.Configuration.IConfigurationSection { public ConfigurationSection(Microsoft.Extensions.Configuration.IConfigurationRoot root, string path) { } - public string this[string key] { get { throw null; } set { } } + public string? this[string key] { get { throw null; } set { } } public string Key { get { throw null; } } public string Path { get { throw null; } } - public string Value { get { throw null; } set { } } + public string? Value { get { throw null; } set { } } public System.Collections.Generic.IEnumerable GetChildren() { throw null; } public Microsoft.Extensions.Primitives.IChangeToken GetReloadToken() { throw null; } public Microsoft.Extensions.Configuration.IConfigurationSection GetSection(string key) { throw null; } @@ -102,7 +103,7 @@ public ConfigurationSection(Microsoft.Extensions.Configuration.IConfigurationRoo public static partial class MemoryConfigurationBuilderExtensions { public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddInMemoryCollection(this Microsoft.Extensions.Configuration.IConfigurationBuilder configurationBuilder) { throw null; } - public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddInMemoryCollection(this Microsoft.Extensions.Configuration.IConfigurationBuilder configurationBuilder, System.Collections.Generic.IEnumerable> initialData) { throw null; } + public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddInMemoryCollection(this Microsoft.Extensions.Configuration.IConfigurationBuilder configurationBuilder, System.Collections.Generic.IEnumerable>? initialData) { throw null; } } public abstract partial class StreamConfigurationProvider : Microsoft.Extensions.Configuration.ConfigurationProvider { @@ -114,23 +115,24 @@ public override void Load() { } public abstract partial class StreamConfigurationSource : Microsoft.Extensions.Configuration.IConfigurationSource { protected StreamConfigurationSource() { } - public System.IO.Stream Stream { get { throw null; } set { } } + [System.Diagnostics.CodeAnalysis.DisallowNull] + public System.IO.Stream? Stream { get { throw null; } set { } } public abstract Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder); } } namespace Microsoft.Extensions.Configuration.Memory { - public partial class MemoryConfigurationProvider : Microsoft.Extensions.Configuration.ConfigurationProvider, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable + public partial class MemoryConfigurationProvider : Microsoft.Extensions.Configuration.ConfigurationProvider, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { public MemoryConfigurationProvider(Microsoft.Extensions.Configuration.Memory.MemoryConfigurationSource source) { } - public void Add(string key, string value) { } - public System.Collections.Generic.IEnumerator> GetEnumerator() { throw null; } + public void Add(string key, string? value) { } + public System.Collections.Generic.IEnumerator> GetEnumerator() { throw null; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; } } public partial class MemoryConfigurationSource : Microsoft.Extensions.Configuration.IConfigurationSource { public MemoryConfigurationSource() { } - public System.Collections.Generic.IEnumerable> InitialData { get { throw null; } set { } } + public System.Collections.Generic.IEnumerable>? InitialData { get { throw null; } set { } } public Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) { throw null; } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.csproj b/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.csproj index 311697da63901..0ab0a2842d718 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.csproj @@ -1,10 +1,15 @@ - netstandard2.0;$(NetFrameworkMinimum) + $(NetCoreAppCurrent);netstandard2.0;$(NetFrameworkMinimum) + enable + + + + diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationProvider.cs index a240f3da8e7d1..eb9bed0021145 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationProvider.cs @@ -40,7 +40,7 @@ public ChainedConfigurationProvider(ChainedConfigurationSource source) /// The key. /// The value. /// True if a value for the specified key was found, otherwise false. - public bool TryGet(string key, out string value) + public bool TryGet(string key, out string? value) { value = _config[key]; return !string.IsNullOrEmpty(value); @@ -51,7 +51,7 @@ public bool TryGet(string key, out string value) /// /// The key. /// The value. - public void Set(string key, string value) => _config[key] = value; + public void Set(string key, string? value) => _config[key] = value; /// /// Returns a change token if this provider supports change tracking, null otherwise. @@ -74,7 +74,7 @@ public void Load() { } /// The child keys. public IEnumerable GetChildKeys( IEnumerable earlierKeys, - string parentPath) + string? parentPath) { IConfiguration section = parentPath == null ? _config : _config.GetSection(parentPath); var keys = new List(); diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationSource.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationSource.cs index 27391aead76fd..b5a9c68c522db 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationSource.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationSource.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.Extensions.Configuration { /// @@ -11,7 +13,8 @@ public class ChainedConfigurationSource : IConfigurationSource /// /// The chained configuration. /// - public IConfiguration Configuration { get; set; } + [DisallowNull] + public IConfiguration? Configuration { get; set; } /// /// Whether the chained configuration should be disposed when the diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs index b5dc31fdffe73..00cca781d47f4 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationKeyComparer.cs @@ -27,7 +27,7 @@ public class ConfigurationKeyComparer : IComparer /// First string. /// Second string. /// Less than 0 if x is less than y, 0 if x is equal to y and greater than 0 if x is greater than y. - public int Compare(string x, string y) + public int Compare(string? x, string? y) { string[] xParts = x?.Split(_keyDelimiterArray, StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty(); string[] yParts = y?.Split(_keyDelimiterArray, StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty(); diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs index 8ce08d822426c..6fe4c1a004663 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using Microsoft.Extensions.Configuration.Memory; @@ -38,7 +39,7 @@ public ConfigurationManager() } /// - public string this[string key] + public string? this[string key] { get { @@ -338,7 +339,7 @@ public bool Remove(KeyValuePair item) return wasRemoved; } - public bool TryGetValue(string key, out object value) + public bool TryGetValue(string key, [NotNullWhen(true)] out object? value) { return _properties.TryGetValue(key, out value); } diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationProvider.cs index e337bd3148331..9fbeded4fc3de 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationProvider.cs @@ -21,13 +21,13 @@ public abstract class ConfigurationProvider : IConfigurationProvider /// protected ConfigurationProvider() { - Data = new Dictionary(StringComparer.OrdinalIgnoreCase); + Data = new Dictionary(StringComparer.OrdinalIgnoreCase); } /// /// The configuration key value pairs for this provider. /// - protected IDictionary Data { get; set; } + protected IDictionary Data { get; set; } /// /// Attempts to find a value with the given key, returns true if one is found, false otherwise. @@ -35,7 +35,7 @@ protected ConfigurationProvider() /// The key to lookup. /// The value found at key if one is found. /// True if key has a value, false otherwise. - public virtual bool TryGet(string key, out string value) + public virtual bool TryGet(string key, out string? value) => Data.TryGetValue(key, out value); /// @@ -43,7 +43,7 @@ public virtual bool TryGet(string key, out string value) /// /// The configuration key to set. /// The value to set. - public virtual void Set(string key, string value) + public virtual void Set(string key, string? value) => Data[key] = value; /// @@ -60,13 +60,13 @@ public virtual void Load() /// The list of keys for this provider. public virtual IEnumerable GetChildKeys( IEnumerable earlierKeys, - string parentPath) + string? parentPath) { var results = new List(); if (parentPath is null) { - foreach (KeyValuePair kv in Data) + foreach (KeyValuePair kv in Data) { results.Add(Segment(kv.Key, 0)); } @@ -75,7 +75,7 @@ public virtual IEnumerable GetChildKeys( { Debug.Assert(ConfigurationPath.KeyDelimiter == ":"); - foreach (KeyValuePair kv in Data) + foreach (KeyValuePair kv in Data) { if (kv.Key.Length > parentPath.Length && kv.Key.StartsWith(parentPath, StringComparison.OrdinalIgnoreCase) && diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationReloadToken.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationReloadToken.cs index fad07ebfdacb9..7aceba29fe55b 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationReloadToken.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationReloadToken.cs @@ -33,7 +33,7 @@ public class ConfigurationReloadToken : IChangeToken /// The callback to invoke. /// State to be passed into the callback. /// The registration. - public IDisposable RegisterChangeCallback(Action callback, object state) => _cts.Token.Register(callback, state); + public IDisposable RegisterChangeCallback(Action callback, object? state) => _cts.Token.Register(callback, state); /// /// Used to trigger the change token when a reload occurs. diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationRoot.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationRoot.cs index cfe56a20978e5..397ef5160b1ec 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationRoot.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationRoot.cs @@ -47,7 +47,7 @@ public ConfigurationRoot(IList providers) /// /// The configuration key. /// The configuration value. - public string this[string key] + public string? this[string key] { get => GetConfiguration(_providers, key); set => SetConfiguration(_providers, key, value); @@ -111,13 +111,13 @@ public void Dispose() } } - internal static string GetConfiguration(IList providers, string key) + internal static string? GetConfiguration(IList providers, string key) { for (int i = providers.Count - 1; i >= 0; i--) { IConfigurationProvider provider = providers[i]; - if (provider.TryGet(key, out string value)) + if (provider.TryGet(key, out string? value)) { return value; } @@ -126,7 +126,7 @@ internal static string GetConfiguration(IList providers, return null; } - internal static void SetConfiguration(IList providers, string key, string value) + internal static void SetConfiguration(IList providers, string key, string? value) { if (providers.Count == 0) { diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationSection.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationSection.cs index da3fbb733a3a1..0896e587d4082 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationSection.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationSection.cs @@ -14,7 +14,7 @@ public class ConfigurationSection : IConfigurationSection { private readonly IConfigurationRoot _root; private readonly string _path; - private string _key; + private string? _key; /// /// Initializes a new instance. @@ -61,7 +61,7 @@ public string Key /// /// Gets or sets the section value. /// - public string Value + public string? Value { get { @@ -78,13 +78,12 @@ public string Value /// /// The configuration key. /// The configuration value. - public string this[string key] + public string? this[string key] { get { return _root[ConfigurationPath.Combine(Path, key)]; } - set { _root[ConfigurationPath.Combine(Path, key)] = value; diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/InternalConfigurationRootExtensions.cs b/src/libraries/Microsoft.Extensions.Configuration/src/InternalConfigurationRootExtensions.cs index bff5c52710400..7fd17a98acf47 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/InternalConfigurationRootExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/InternalConfigurationRootExtensions.cs @@ -18,7 +18,7 @@ internal static class InternalConfigurationRootExtensions /// Configuration from which to retrieve sub-sections. /// Key of a section of which children to retrieve. /// Immediate children sub-sections of section specified by key. - internal static IEnumerable GetChildrenImplementation(this IConfigurationRoot root, string path) + internal static IEnumerable GetChildrenImplementation(this IConfigurationRoot root, string? path) { return root.Providers .Aggregate(Enumerable.Empty(), diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationBuilderExtensions.cs b/src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationBuilderExtensions.cs index 996f8a876b9c3..15ed46a26a5b9 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationBuilderExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationBuilderExtensions.cs @@ -36,7 +36,7 @@ public static IConfigurationBuilder AddInMemoryCollection(this IConfigurationBui /// The . public static IConfigurationBuilder AddInMemoryCollection( this IConfigurationBuilder configurationBuilder, - IEnumerable> initialData) + IEnumerable>? initialData) { if (configurationBuilder == null) { diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationProvider.cs index 84a0b142e0fbc..0e7f0be02fec7 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationProvider.cs @@ -10,7 +10,7 @@ namespace Microsoft.Extensions.Configuration.Memory /// /// In-memory implementation of /// - public class MemoryConfigurationProvider : ConfigurationProvider, IEnumerable> + public class MemoryConfigurationProvider : ConfigurationProvider, IEnumerable> { private readonly MemoryConfigurationSource _source; @@ -29,7 +29,7 @@ public MemoryConfigurationProvider(MemoryConfigurationSource source) if (_source.InitialData != null) { - foreach (KeyValuePair pair in _source.InitialData) + foreach (KeyValuePair pair in _source.InitialData) { Data.Add(pair.Key, pair.Value); } @@ -41,7 +41,7 @@ public MemoryConfigurationProvider(MemoryConfigurationSource source) /// /// The configuration key. /// The configuration value. - public void Add(string key, string value) + public void Add(string key, string? value) { Data.Add(key, value); } @@ -50,7 +50,7 @@ public void Add(string key, string value) /// Returns an enumerator that iterates through the collection. /// /// An enumerator that can be used to iterate through the collection. - public IEnumerator> GetEnumerator() + public IEnumerator> GetEnumerator() { return Data.GetEnumerator(); } diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationSource.cs b/src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationSource.cs index e11891595e414..412df6534c110 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationSource.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/MemoryConfigurationSource.cs @@ -13,7 +13,7 @@ public class MemoryConfigurationSource : IConfigurationSource /// /// The initial key value configuration pairs. /// - public IEnumerable> InitialData { get; set; } + public IEnumerable>? InitialData { get; set; } /// /// Builds the for this source. diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/Microsoft.Extensions.Configuration.csproj b/src/libraries/Microsoft.Extensions.Configuration/src/Microsoft.Extensions.Configuration.csproj index bc0bf6e7cc443..10fd1c6acdcb6 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/Microsoft.Extensions.Configuration.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration/src/Microsoft.Extensions.Configuration.csproj @@ -1,8 +1,11 @@ - netstandard2.0;$(NetFrameworkMinimum) + $(NetCoreAppCurrent);netstandard2.0;$(NetFrameworkMinimum) + enable true + + false Implementation of key-value pair based configuration for Microsoft.Extensions.Configuration. Includes the memory configuration provider. diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Configuration/src/Resources/Strings.resx index 941bf0cc34873..8f6038211e50d 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.Configuration/src/Resources/Strings.resx @@ -1,4 +1,4 @@ - + - - - diff --git a/src/libraries/Microsoft.IO.Redist/src/Microsoft/IO/StringExtensions.cs b/src/libraries/Microsoft.IO.Redist/src/Microsoft/IO/StringExtensions.cs deleted file mode 100644 index fbe320a857ca0..0000000000000 --- a/src/libraries/Microsoft.IO.Redist/src/Microsoft/IO/StringExtensions.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Runtime.CompilerServices; - -namespace Microsoft.IO -{ - public static class StringExtensions - { - public delegate void SpanAction(Span span, TArg arg); - - public static bool Contains(this string s, char value) - { - return s.IndexOf(value) != -1; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static bool EqualsOrdinal(this ReadOnlySpan span, ReadOnlySpan value) - { - if (span.Length != value.Length) - return false; - if (value.Length == 0) // span.Length == value.Length == 0 - return true; - return span.SequenceEqual(value); - } - - public static unsafe string Create(int length, TState state, SpanAction action) - { - if (action == null) - throw new ArgumentNullException(nameof(action)); - - if (length <= 0) - { - if (length == 0) - return string.Empty; - throw new ArgumentOutOfRangeException(nameof(length)); - } - - string result = new string('\0', length); - fixed (char* r = result) - { - action(new Span(r, length), state); - } - return result; - } - - internal static unsafe string Concat(ReadOnlySpan str0, ReadOnlySpan str1) - { - var result = new string('\0', checked(str0.Length + str1.Length)); - fixed (char* resultPtr = result) - { - var resultSpan = new Span(resultPtr, result.Length); - - str0.CopyTo(resultSpan); - str1.CopyTo(resultSpan.Slice(str0.Length)); - } - return result; - } - - internal static unsafe string Concat(ReadOnlySpan str0, ReadOnlySpan str1, ReadOnlySpan str2) - { - var result = new string('\0', checked(str0.Length + str1.Length + str2.Length)); - fixed (char* resultPtr = result) - { - var resultSpan = new Span(resultPtr, result.Length); - - str0.CopyTo(resultSpan); - resultSpan = resultSpan.Slice(str0.Length); - - str1.CopyTo(resultSpan); - resultSpan = resultSpan.Slice(str1.Length); - - str2.CopyTo(resultSpan); - } - return result; - } - } -} diff --git a/src/libraries/Microsoft.IO.Redist/src/Microsoft/IO/ThrowHelper.cs b/src/libraries/Microsoft.IO.Redist/src/Microsoft/IO/ThrowHelper.cs deleted file mode 100644 index 31e3766c51494..0000000000000 --- a/src/libraries/Microsoft.IO.Redist/src/Microsoft/IO/ThrowHelper.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.IO; - -namespace Microsoft.IO -{ - internal static class ThrowHelper - { - internal static void ThrowEndOfFileException() - { - throw new EndOfStreamException(SR.IO_EOF_ReadBeyondEOF); - } - } -} diff --git a/src/libraries/Microsoft.IO.Redist/src/Resources/Strings.resx b/src/libraries/Microsoft.IO.Redist/src/Resources/Strings.resx deleted file mode 100644 index 66a414fe02e6d..0000000000000 --- a/src/libraries/Microsoft.IO.Redist/src/Resources/Strings.resx +++ /dev/null @@ -1,125 +0,0 @@ - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - The target file '{0}' is a directory, not a file. - - - Invalid File or Directory attributes value. - - - Second path fragment must not be a drive or UNC name. - - - Path must not be a drive. - - - File name cannot be null. - - - Path cannot be null. - - - Enum value was out of legal range. - - - Empty file name is not legal. - - - Empty path name is not legal. - - - Illegal characters in path '{0}'. - - - Invalid seek origin. - - - The directory specified, '{0}', is not a subdirectory of '{1}'. - - - Path cannot be the empty string or all whitespace. - - - Cannot create '{0}' because a file or directory with the same name already exists. - - - The specified directory '{0}' cannot be created. - - - Unable to read beyond the end of the stream. - - - The file '{0}' already exists. - - - Unable to find the specified file. - - - Could not find file '{0}'. - - - The file is too long. This operation is currently limited to supporting files less than 2 gigabytes in size. - - - The link's file system entry type is inconsistent with that of its target: {0} - - - Could not find a part of the path. - - - Could not find a part of the path '{0}'. - - - The specified file name or path is too long, or a component of the specified path is too long. - - - The process cannot access the file '{0}' because it is being used by another process. - - - The process cannot access the file because it is being used by another process. - - - Source and destination path must be different. - - - Source and destination path must have identical roots. Move will not work across volumes. - - - [Unknown] - - - Access to the path is denied. - - - Access to the path '{0}' is denied. - - - File encryption is not supported on this platform. - - - The path '{0}' is too long, or a component of the specified path is too long. - - - Basepath argument is not fully qualified. - - - The path is empty. - - - Drive name must be a root directory (i.e. 'C:\') or a drive letter ('C'). - - - Non-negative number required. - - diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index b846ab63ea730..1351a67f30f3e 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -48,9 +48,8 @@ - - - + + diff --git a/src/libraries/Microsoft.NETCore.Platforms/tests/Microsoft.NETCore.Platforms.Tests.csproj b/src/libraries/Microsoft.NETCore.Platforms/tests/Microsoft.NETCore.Platforms.Tests.csproj index a2a273ed6e042..4148acef7d780 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/tests/Microsoft.NETCore.Platforms.Tests.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/tests/Microsoft.NETCore.Platforms.Tests.csproj @@ -6,6 +6,7 @@ + diff --git a/src/libraries/Native/Unix/System.Native/pal_io.c b/src/libraries/Native/Unix/System.Native/pal_io.c index 9d313dd6e9951..49aaeca6c2078 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.c +++ b/src/libraries/Native/Unix/System.Native/pal_io.c @@ -1015,7 +1015,7 @@ int32_t SystemNative_FAllocate(intptr_t fd, int64_t offset, int64_t length) int fileDescriptor = ToFileDescriptor(fd); int32_t result; #if HAVE_FALLOCATE // Linux - while ((result = fallocate(fileDescriptor, FALLOC_FL_KEEP_SIZE, (off_t)offset, (off_t)length)) == EINTR); + while ((result = fallocate(fileDescriptor, FALLOC_FL_KEEP_SIZE, (off_t)offset, (off_t)length)) == -1 && errno == EINTR); #elif defined(F_PREALLOCATE) // macOS fstore_t fstore; fstore.fst_flags = F_ALLOCATEALL; // Allocate all requested space or no space at all. diff --git a/src/libraries/Native/Unix/System.Native/pal_process.c b/src/libraries/Native/Unix/System.Native/pal_process.c index 5e97d958f74d1..fabdfae76187c 100644 --- a/src/libraries/Native/Unix/System.Native/pal_process.c +++ b/src/libraries/Native/Unix/System.Native/pal_process.c @@ -191,6 +191,24 @@ static int SetGroups(uint32_t* userGroups, int32_t userGroupsLength, uint32_t* p return rv; } +typedef void (*VoidIntFn)(int); + +static +VoidIntFn +handler_from_sigaction (struct sigaction *sa) +{ + if (((unsigned int)sa->sa_flags) & SA_SIGINFO) + { + // work around -Wcast-function-type + void (*tmp)(void) = (void (*)(void))sa->sa_sigaction; + return (void (*)(int))tmp; + } + else + { + return sa->sa_handler; + } +} + int32_t SystemNative_ForkAndExecProcess(const char* filename, char* const argv[], char* const envp[], @@ -371,7 +389,7 @@ int32_t SystemNative_ForkAndExecProcess(const char* filename, } if (!sigaction(sig, NULL, &sa_old)) { - void (*oldhandler)(int) = (((unsigned int)sa_old.sa_flags) & SA_SIGINFO) ? (void (*)(int))sa_old.sa_sigaction : sa_old.sa_handler; + void (*oldhandler)(int) = handler_from_sigaction (&sa_old); if (oldhandler != SIG_IGN && oldhandler != SIG_DFL) { // It has a custom handler, put the default handler back. diff --git a/src/libraries/Native/Unix/System.Native/pal_random.js b/src/libraries/Native/Unix/System.Native/pal_random.js index 8e7c7af05f131..c0bbc9c9f0f9e 100644 --- a/src/libraries/Native/Unix/System.Native/pal_random.js +++ b/src/libraries/Native/Unix/System.Native/pal_random.js @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -var DotNetEntropyLib = { +const DotNetEntropyLib = { $DOTNETENTROPY: { // batchedQuotaMax is the max number of bytes as specified by the api spec. // If the byteLength of array is greater than 65536, throw a QuotaExceededError and terminate the algorithm. @@ -10,13 +10,13 @@ var DotNetEntropyLib = { getBatchedRandomValues: function (buffer, bufferLength) { // for modern web browsers // map the work array to the memory buffer passed with the length - for (var i = 0; i < bufferLength; i += this.batchedQuotaMax) { - var view = new Uint8Array(Module.HEAPU8.buffer, buffer + i, Math.min(bufferLength - i, this.batchedQuotaMax)); + for (let i = 0; i < bufferLength; i += this.batchedQuotaMax) { + const view = new Uint8Array(Module.HEAPU8.buffer, buffer + i, Math.min(bufferLength - i, this.batchedQuotaMax)); crypto.getRandomValues(view) } } }, - dotnet_browser_entropy : function (buffer, bufferLength) { + dotnet_browser_entropy: function (buffer, bufferLength) { // check that we have crypto available if (typeof crypto === 'object' && typeof crypto['getRandomValues'] === 'function') { DOTNETENTROPY.getBatchedRandomValues(buffer, bufferLength) diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.c index c907f83a524e7..4dd95a119de59 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.c @@ -216,14 +216,8 @@ int32_t AndroidCryptoNative_CipherSetKeyAndIV(CipherCtx* ctx, uint8_t* key, uint return ReinitializeCipher(ctx); } -CipherCtx* AndroidCryptoNative_CipherCreate(CipherInfo* type, uint8_t* key, int32_t keySizeInBits, int32_t effectiveKeyLength, uint8_t* iv, int32_t enc) +CipherCtx* AndroidCryptoNative_CipherCreate(CipherInfo* type, uint8_t* key, int32_t keySizeInBits, uint8_t* iv, int32_t enc) { - if (effectiveKeyLength != 0) - { - LOG_ERROR("Non-zero effectiveKeyLength is not supported"); - return FAIL; - } - CipherCtx* ctx = AndroidCryptoNative_CipherCreatePartial(type); // Update the key size if provided diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.h index fda90fcc6284f..28d2fc52e8225 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.h +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_cipher.h @@ -25,7 +25,7 @@ typedef struct CipherCtx } CipherCtx; PALEXPORT int32_t AndroidCryptoNative_CipherIsSupported(CipherInfo* type); -PALEXPORT CipherCtx* AndroidCryptoNative_CipherCreate(CipherInfo* type, uint8_t* key, int32_t keySizeInBits, int32_t effectiveKeyLength, uint8_t* iv, int32_t enc); +PALEXPORT CipherCtx* AndroidCryptoNative_CipherCreate(CipherInfo* type, uint8_t* key, int32_t keySizeInBits, uint8_t* iv, int32_t enc); PALEXPORT CipherCtx* AndroidCryptoNative_CipherCreatePartial(CipherInfo* type); PALEXPORT int32_t AndroidCryptoNative_CipherSetTagLength(CipherCtx* ctx, int32_t tagLength); PALEXPORT int32_t AndroidCryptoNative_CipherSetKeyAndIV(CipherCtx* ctx, uint8_t* key, uint8_t* iv, int32_t enc); diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.h index 2e783f49352de..5675f4c0ca7fb 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.h +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.h @@ -303,6 +303,7 @@ const EVP_CIPHER* EVP_chacha20_poly1305(void); FALLBACK_FUNCTION(EVP_CIPHER_CTX_reset) \ REQUIRED_FUNCTION(EVP_CIPHER_CTX_set_key_length) \ REQUIRED_FUNCTION(EVP_CIPHER_CTX_set_padding) \ + RENAMED_FUNCTION(EVP_CIPHER_get_nid, EVP_CIPHER_nid) \ REQUIRED_FUNCTION(EVP_CipherFinal_ex) \ REQUIRED_FUNCTION(EVP_CipherInit_ex) \ REQUIRED_FUNCTION(EVP_CipherUpdate) \ @@ -757,6 +758,7 @@ FOR_ALL_OPENSSL_FUNCTIONS #define EVP_CIPHER_CTX_reset EVP_CIPHER_CTX_reset_ptr #define EVP_CIPHER_CTX_set_key_length EVP_CIPHER_CTX_set_key_length_ptr #define EVP_CIPHER_CTX_set_padding EVP_CIPHER_CTX_set_padding_ptr +#define EVP_CIPHER_get_nid EVP_CIPHER_get_nid_ptr #define EVP_CipherFinal_ex EVP_CipherFinal_ex_ptr #define EVP_CipherInit_ex EVP_CipherInit_ex_ptr #define EVP_CipherUpdate EVP_CipherUpdate_ptr @@ -1120,6 +1122,7 @@ FOR_ALL_OPENSSL_FUNCTIONS #define EVP_PKEY_get_base_id EVP_PKEY_base_id #define EVP_PKEY_get_size EVP_PKEY_size #define SSL_get1_peer_certificate SSL_get_peer_certificate +#define EVP_CIPHER_get_nid EVP_CIPHER_nid #endif diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/osslcompat_30.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native/osslcompat_30.h index dba69f1382d2f..f7de24624eb98 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/osslcompat_30.h +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/osslcompat_30.h @@ -19,6 +19,7 @@ void ERR_new(void); void ERR_set_debug(const char *file, int line, const char *func); void ERR_set_error(int lib, int reason, const char *fmt, ...); int EVP_CIPHER_CTX_get_original_iv(EVP_CIPHER_CTX *ctx, void *buf, size_t len); +int EVP_CIPHER_get_nid(const EVP_CIPHER *e); int EVP_MD_get_size(const EVP_MD* md); int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX* ctx, int bits); int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX* ctx, const EVP_MD* md); diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.c index 40cfde7fea6f6..351a2cd1ca8cc 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.c @@ -9,7 +9,7 @@ #define KEEP_CURRENT_DIRECTION -1 EVP_CIPHER_CTX* -CryptoNative_EvpCipherCreate2(const EVP_CIPHER* type, uint8_t* key, int32_t keyLength, int32_t effectiveKeyLength, unsigned char* iv, int32_t enc) +CryptoNative_EvpCipherCreate2(const EVP_CIPHER* type, uint8_t* key, int32_t keyLength, unsigned char* iv, int32_t enc) { EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) @@ -43,15 +43,22 @@ CryptoNative_EvpCipherCreate2(const EVP_CIPHER* type, uint8_t* key, int32_t keyL } } - if (effectiveKeyLength > 0) + int nid = EVP_CIPHER_get_nid(type); + + switch (nid) { - // Necessary for RC2 - ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, effectiveKeyLength, NULL); - if (ret <= 0) - { - EVP_CIPHER_CTX_free(ctx); - return NULL; - } + case NID_rc2_ecb: + case NID_rc2_cbc: + // Necessary for RC2 + ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, keyLength, NULL); + if (ret <= 0) + { + EVP_CIPHER_CTX_free(ctx); + return NULL; + } + break; + default: + break; } // Perform final initialization specifying the remaining arguments diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.h index c0d652a5e67b6..e9586fa93e958 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.h +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.h @@ -6,7 +6,7 @@ #include "opensslshim.h" PALEXPORT EVP_CIPHER_CTX* -CryptoNative_EvpCipherCreate2(const EVP_CIPHER* type, uint8_t* key, int32_t keyLength, int32_t effectiveKeyLength, unsigned char* iv, int32_t enc); +CryptoNative_EvpCipherCreate2(const EVP_CIPHER* type, uint8_t* key, int32_t keyLength, unsigned char* iv, int32_t enc); PALEXPORT EVP_CIPHER_CTX* CryptoNative_EvpCipherCreatePartial(const EVP_CIPHER* type); diff --git a/src/libraries/System.CodeDom/tests/System/CodeDom/Compiler/CSharpCodeGeneratorTests.cs b/src/libraries/System.CodeDom/tests/System/CodeDom/Compiler/CSharpCodeGeneratorTests.cs index 8b9f94b0dbc7b..0256638f5f6a8 100644 --- a/src/libraries/System.CodeDom/tests/System/CodeDom/Compiler/CSharpCodeGeneratorTests.cs +++ b/src/libraries/System.CodeDom/tests/System/CodeDom/Compiler/CSharpCodeGeneratorTests.cs @@ -9,7 +9,6 @@ namespace System.CodeDom.Compiler.Tests { - [ActiveIssue("https://github.com/dotnet/runtime/issues/57363", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoInterpreter))] public class CSharpCodeGeneratorTests { private static IEnumerable Identifier_TestData() diff --git a/src/libraries/System.Collections/src/System/Collections/Generic/SortedSet.cs b/src/libraries/System.Collections/src/System/Collections/Generic/SortedSet.cs index 4b5b4b732fdeb..6829f94dec62e 100644 --- a/src/libraries/System.Collections/src/System/Collections/Generic/SortedSet.cs +++ b/src/libraries/System.Collections/src/System/Collections/Generic/SortedSet.cs @@ -1681,41 +1681,27 @@ public Node DeepClone(int count) #if DEBUG Debug.Assert(count == GetCount()); #endif - - // Breadth-first traversal to recreate nodes, preorder traversal to replicate nodes. - - var originalNodes = new Stack(2 * Log2(count) + 2); - var newNodes = new Stack(2 * Log2(count) + 2); Node newRoot = ShallowClone(); - Node? originalCurrent = this; - Node newCurrent = newRoot; + var pendingNodes = new Stack<(Node source, Node target)>(2 * Log2(count) + 2); + pendingNodes.Push((this, newRoot)); - while (originalCurrent != null) + while (pendingNodes.TryPop(out var next)) { - originalNodes.Push(originalCurrent); - newNodes.Push(newCurrent); - newCurrent.Left = originalCurrent.Left?.ShallowClone(); - originalCurrent = originalCurrent.Left; - newCurrent = newCurrent.Left!; - } + Node clonedNode; - while (originalNodes.Count != 0) - { - originalCurrent = originalNodes.Pop(); - newCurrent = newNodes.Pop(); - - Node? originalRight = originalCurrent.Right; - Node? newRight = originalRight?.ShallowClone(); - newCurrent.Right = newRight; + if (next.source.Left is Node left) + { + clonedNode = left.ShallowClone(); + next.target.Left = clonedNode; + pendingNodes.Push((left, clonedNode)); + } - while (originalRight != null) + if (next.source.Right is Node right) { - originalNodes.Push(originalRight); - newNodes.Push(newRight!); - newRight!.Left = originalRight.Left?.ShallowClone(); - originalRight = originalRight.Left; - newRight = newRight.Left; + clonedNode = right.ShallowClone(); + next.target.Right = clonedNode; + pendingNodes.Push((right, clonedNode)); } } diff --git a/src/libraries/System.Collections/tests/Generic/List/List.Generic.Tests.EnsureCapacity.cs b/src/libraries/System.Collections/tests/Generic/List/List.Generic.Tests.EnsureCapacity.cs index c643df16ef087..cfbd15a6d5394 100644 --- a/src/libraries/System.Collections/tests/Generic/List/List.Generic.Tests.EnsureCapacity.cs +++ b/src/libraries/System.Collections/tests/Generic/List/List.Generic.Tests.EnsureCapacity.cs @@ -1,6 +1,5 @@ // 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.Collections.Generic; using Xunit; diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs index 6d0517bc195e9..9923589b24627 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs @@ -374,11 +374,11 @@ private void ParseSpecs(string? metricsSpecs) { if (!MetricSpec.TryParse(specString, out MetricSpec spec)) { - Log.Message("Failed to parse metric spec: {specString}"); + Log.Message($"Failed to parse metric spec: {specString}"); } else { - Log.Message("Parsed metric: {spec}"); + Log.Message($"Parsed metric: {spec}"); if (spec.InstrumentName != null) { _aggregationManager!.Include(spec.MeterName, spec.InstrumentName); diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterCategory.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterCategory.cs index db9a8e52f4242..8fd6b54519b7d 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterCategory.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/PerformanceCounterCategory.cs @@ -190,7 +190,7 @@ public static bool CounterExists(string counterName, string categoryName, string } /// - /// Registers one extensible performance category of type NumberOfItems32 with the system + /// Registers one extensible performance category with counter type NumberOfItems32 with the system /// [Obsolete("This overload of PerformanceCounterCategory.Create has been deprecated. Use System.Diagnostics.PerformanceCounterCategory.Create(string categoryName, string categoryHelp, PerformanceCounterCategoryType categoryType, string counterName, string counterHelp) instead.")] public static PerformanceCounterCategory Create(string categoryName, string categoryHelp, string counterName, string counterHelp) @@ -199,6 +199,9 @@ public static PerformanceCounterCategory Create(string categoryName, string cate return Create(categoryName, categoryHelp, PerformanceCounterCategoryType.Unknown, new CounterCreationDataCollection(new CounterCreationData[] { customData })); } + /// + /// Registers one extensible performance category of the specified category type with counter type NumberOfItems32 with the system + /// public static PerformanceCounterCategory Create(string categoryName, string categoryHelp, PerformanceCounterCategoryType categoryType, string counterName, string counterHelp) { CounterCreationData customData = new CounterCreationData(counterName, counterHelp, PerformanceCounterType.NumberOfItems32); @@ -206,7 +209,7 @@ public static PerformanceCounterCategory Create(string categoryName, string cate } /// - /// Registers the extensible performance category with the system on the local machine + /// Registers the extensible performance category with the system on the local machine /// [Obsolete("This overload of PerformanceCounterCategory.Create has been deprecated. Use System.Diagnostics.PerformanceCounterCategory.Create(string categoryName, string categoryHelp, PerformanceCounterCategoryType categoryType, CounterCreationDataCollection counterData) instead.")] public static PerformanceCounterCategory Create(string categoryName, string categoryHelp, CounterCreationDataCollection counterData) diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/tests/CounterSampleCalculatorTests.cs b/src/libraries/System.Diagnostics.PerformanceCounter/tests/CounterSampleCalculatorTests.cs index 4173d201c8a89..37b34bf373019 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/tests/CounterSampleCalculatorTests.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/tests/CounterSampleCalculatorTests.cs @@ -13,9 +13,9 @@ public static class CounterSampleCalculatorTests [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] public static void CounterSampleCalculator_ElapsedTime() { - var name = nameof(CounterSampleCalculator_ElapsedTime) + "_Counter"; + string categoryName = nameof(CounterSampleCalculator_ElapsedTime) + "_Category"; - PerformanceCounter counterSample = CreateCounter(name, PerformanceCounterType.ElapsedTime); + PerformanceCounter counterSample = CreateCounter(categoryName, PerformanceCounterType.ElapsedTime); counterSample.RawValue = Stopwatch.GetTimestamp(); DateTime Start = DateTime.Now; @@ -25,27 +25,26 @@ public static void CounterSampleCalculator_ElapsedTime() var counterVal = Helpers.RetryOnAllPlatforms(() => counterSample.NextValue()); var dateTimeVal = DateTime.Now.Subtract(Start).TotalSeconds; - Helpers.DeleteCategory(name); + Helpers.DeleteCategory(categoryName); Assert.True(Math.Abs(dateTimeVal - counterVal) < .3); } - public static PerformanceCounter CreateCounter(string name, PerformanceCounterType counterType) + public static PerformanceCounter CreateCounter(string categoryName, PerformanceCounterType counterType) { - var category = name + "_Category"; - var instance = name + "_Instance"; + string counterName = categoryName + "_Counter"; CounterCreationDataCollection ccdc = new CounterCreationDataCollection(); CounterCreationData ccd = new CounterCreationData(); ccd.CounterType = counterType; - ccd.CounterName = name; + ccd.CounterName = counterName; ccdc.Add(ccd); - Helpers.DeleteCategory(name); - PerformanceCounterCategory.Create(category, "description", PerformanceCounterCategoryType.SingleInstance, ccdc); + Helpers.DeleteCategory(categoryName); + PerformanceCounterCategory.Create(categoryName, "description", PerformanceCounterCategoryType.SingleInstance, ccdc); - Assert.True(Helpers.PerformanceCounterCategoryCreated(category)); + Helpers.VerifyPerformanceCounterCategoryCreated(categoryName); - return new PerformanceCounter(category, name, false); + return new PerformanceCounter(categoryName, counterName, readOnly:false); } } } diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/tests/Helpers.cs b/src/libraries/System.Diagnostics.PerformanceCounter/tests/Helpers.cs index 0cf90e9e4682e..d33a5bbbe0974 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/tests/Helpers.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/tests/Helpers.cs @@ -17,37 +17,53 @@ internal class Helpers public static bool CanWriteToPerfCounters { get => PlatformDetection.IsNotWindowsNanoServer; } public static bool CanReadNetPerfCounters { get => File.Exists(Environment.SystemDirectory + Path.DirectorySeparatorChar + "netfxperf.dll"); } - public static string CreateCategory(string name, PerformanceCounterCategoryType categoryType) + public static void CreateCategory(string categoryName, PerformanceCounterCategoryType categoryType) { - var category = name + "_Category"; + string counterName = categoryName.Replace("_Category", "_Counter"); + CreateCategory(categoryName, counterName, categoryType); + } + + public static void CreateCategory(string categoryName, string counterName, PerformanceCounterCategoryType categoryType) + { + Assert.EndsWith("_Category", categoryName); + Assert.EndsWith("_Counter", counterName); - // If the categry already exists, delete it, then create it. - DeleteCategory(name); - PerformanceCounterCategory.Create(category, "description", categoryType, name, "counter description"); + // If the category already exists, delete it, then create it. + DeleteCategory(categoryName); + PerformanceCounterCategory.Create(categoryName, "description", categoryType, counterName, "counter description"); - Assert.True(PerformanceCounterCategoryCreated(category)); - return category; + VerifyPerformanceCounterCategoryCreated(categoryName); } - public static bool PerformanceCounterCategoryCreated(string category) + public static void VerifyPerformanceCounterCategoryCreated(string categoryName) { + Assert.EndsWith("_Category", categoryName); int tries = 0; - while (!PerformanceCounterCategory.Exists(category) && tries < 10) + while (!PerformanceCounterCategory.Exists(categoryName) && tries < 10) { System.Threading.Thread.Sleep(100); tries++; } - return PerformanceCounterCategory.Exists(category); + Assert.True(PerformanceCounterCategory.Exists(categoryName)); } - public static void DeleteCategory(string name) + public static void DeleteCategory(string categoryName) { - var category = name + "_Category"; - if (PerformanceCounterCategory.Exists(category)) + Assert.EndsWith("_Category", categoryName); + if (PerformanceCounterCategory.Exists(categoryName)) + { + PerformanceCounterCategory.Delete(categoryName); + } + + int tries = 0; + while (PerformanceCounterCategory.Exists(categoryName) && tries < 10) { - PerformanceCounterCategory.Delete(category); + System.Threading.Thread.Sleep(100); + tries++; } + + Assert.True(!PerformanceCounterCategory.Exists(categoryName)); } public static T RetryOnAllPlatforms(Func func) diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterCategoryTests.cs b/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterCategoryTests.cs index 1760032fa2535..77b13ae280d75 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterCategoryTests.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterCategoryTests.cs @@ -80,60 +80,59 @@ public static void PerformanceCounterCategory_GetCounterHelp_Invalid() [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] public static void PerformanceCounterCategory_CategoryType_MultiInstance() { - var name = nameof(PerformanceCounterCategory_CategoryType_MultiInstance) + "_Counter"; + string categoryName = nameof(PerformanceCounterCategory_CategoryType_MultiInstance) + "_Category"; - var category = Helpers.CreateCategory(name, PerformanceCounterCategoryType.MultiInstance); + Helpers.CreateCategory(categoryName, PerformanceCounterCategoryType.MultiInstance); - PerformanceCounterCategory pcc = Helpers.RetryOnAllPlatforms(() => new PerformanceCounterCategory(category)); + PerformanceCounterCategory pcc = Helpers.RetryOnAllPlatforms(() => new PerformanceCounterCategory(categoryName)); Assert.Equal(PerformanceCounterCategoryType.MultiInstance, Helpers.RetryOnAllPlatforms(() => pcc.CategoryType)); - PerformanceCounterCategory.Delete(category); + PerformanceCounterCategory.Delete(categoryName); } [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] public static void PerformanceCounterCategory_CategoryType_SingleInstance() { - var name = nameof(PerformanceCounterCategory_CategoryType_SingleInstance) + "_Counter"; + string categoryName = nameof(PerformanceCounterCategory_CategoryType_SingleInstance) + "_Category"; - var category = Helpers.CreateCategory(name, PerformanceCounterCategoryType.SingleInstance); + Helpers.CreateCategory(categoryName, PerformanceCounterCategoryType.SingleInstance); - PerformanceCounterCategory pcc = Helpers.RetryOnAllPlatforms(() => new PerformanceCounterCategory(category)); + PerformanceCounterCategory pcc = Helpers.RetryOnAllPlatforms(() => new PerformanceCounterCategory(categoryName)); Assert.Equal(PerformanceCounterCategoryType.SingleInstance, Helpers.RetryOnAllPlatforms(() => pcc.CategoryType)); - PerformanceCounterCategory.Delete(category); + PerformanceCounterCategory.Delete(categoryName); } #pragma warning disable 0618 // obsolete warning [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteToPerfCounters))] public static void PerformanceCounterCategory_Create_Obsolete() { - var name = nameof(PerformanceCounterCategory_Create_Obsolete) + "_Counter"; - var category = name + "_Category"; + string categoryName = nameof(PerformanceCounterCategory_Create_Obsolete) + "_Category"; + string counterName = nameof(PerformanceCounterCategory_Create_Obsolete) + "_Counter"; - Helpers.DeleteCategory(category); + Helpers.DeleteCategory(categoryName); - PerformanceCounterCategory.Create(category, "category help", name, "counter help"); + PerformanceCounterCategory.Create(categoryName, "category help", counterName, "counter help"); - Assert.True(PerformanceCounterCategory.Exists(category)); - PerformanceCounterCategory.Delete(category); + Assert.True(PerformanceCounterCategory.Exists(categoryName)); + PerformanceCounterCategory.Delete(categoryName); } [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteToPerfCounters))] public static void PerformanceCounterCategory_Create_Obsolete_CCD() { - var name = nameof(PerformanceCounterCategory_Create_Obsolete_CCD) + "_Counter"; - var category = name + "_Category"; + string categoryName = nameof(PerformanceCounterCategory_Create_Obsolete) + "_Category"; - CounterCreationData ccd = new CounterCreationData(name, "counter help", PerformanceCounterType.NumberOfItems32); + CounterCreationData ccd = new CounterCreationData(categoryName, "counter help", PerformanceCounterType.NumberOfItems32); CounterCreationDataCollection ccdc = new CounterCreationDataCollection(); ccdc.Add(ccd); - Helpers.DeleteCategory(category); + Helpers.DeleteCategory(categoryName); - PerformanceCounterCategory.Create(category, "category help", ccdc); + PerformanceCounterCategory.Create(categoryName, "category help", ccdc); - Assert.True(PerformanceCounterCategory.Exists(category)); - PerformanceCounterCategory.Delete(category); + Assert.True(PerformanceCounterCategory.Exists(categoryName)); + PerformanceCounterCategory.Delete(categoryName); } #pragma warning restore 0618 @@ -207,12 +206,12 @@ public static void PerformanceCounterCategory_DeleteCategory_Invalid() [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteToPerfCounters))] public static void PerformanceCounterCategory_DeleteCategory() { - var name = nameof(PerformanceCounterCategory_DeleteCategory) + "_Counter"; - var category = Helpers.CreateCategory(name, PerformanceCounterCategoryType.SingleInstance); + string categoryName = nameof(PerformanceCounterCategory_DeleteCategory) + "_Category"; + Helpers.CreateCategory(categoryName, PerformanceCounterCategoryType.SingleInstance); - PerformanceCounterCategory.Delete(category); + PerformanceCounterCategory.Delete(categoryName); - Assert.False(PerformanceCounterCategory.Exists(category)); + Assert.False(PerformanceCounterCategory.Exists(categoryName)); } [Fact] @@ -226,14 +225,14 @@ public static void PerformanceCounterCategory_Exists_Invalid() [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] public static void PerformanceCounterCategory_GetCounters() { - var name = nameof(PerformanceCounterCategory_GetCounters) + "_Counter"; - var category = Helpers.CreateCategory(name, PerformanceCounterCategoryType.SingleInstance); + string categoryName = nameof(PerformanceCounterCategory_GetCounters) + "_Category"; + Helpers.CreateCategory(categoryName, PerformanceCounterCategoryType.SingleInstance); - PerformanceCounterCategory pcc = Helpers.RetryOnAllPlatforms(() => new PerformanceCounterCategory(category)); + PerformanceCounterCategory pcc = Helpers.RetryOnAllPlatforms(() => new PerformanceCounterCategory(categoryName)); PerformanceCounter[] counters = pcc.GetCounters(); Assert.True(counters.Length > 0); - PerformanceCounterCategory.Delete(category); + PerformanceCounterCategory.Delete(categoryName); } [Fact] diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterTests.cs b/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterTests.cs index bfaf5fba64b3d..f54bde425313f 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterTests.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceCounterTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Specialized; +using System.Threading; using Xunit; namespace System.Diagnostics.Tests @@ -26,14 +27,15 @@ public static void PerformanceCounter_CreateCounter_EmptyCounter() [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteToPerfCounters))] public static void PerformanceCounter_CreateCounter_Count0() { - var name = nameof(PerformanceCounter_CreateCounter_Count0) + "_Counter"; - using (PerformanceCounter counterSample = CreateCounterWithCategory(name, false, PerformanceCounterCategoryType.SingleInstance)) + string categoryName = nameof(PerformanceCounter_CreateCounter_Count0) + "_Category"; + using (PerformanceCounter counterSample = CreateCounterWithCategory(categoryName, readOnly:false, PerformanceCounterCategoryType.SingleInstance)) { counterSample.RawValue = 0; Assert.Equal(0, counterSample.RawValue); - Helpers.DeleteCategory(name); } + + Helpers.DeleteCategory(categoryName); } [Fact] @@ -50,37 +52,40 @@ public static void PerformanceCounter_CreateCounter_ProcessorCounter() [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] public static void PerformanceCounter_CreateCounter_MultiInstanceReadOnly() { - var name = nameof(PerformanceCounter_CreateCounter_MultiInstanceReadOnly) + "_Counter"; - var instance = name + "_Instance"; + string categoryName = nameof(PerformanceCounter_CreateCounter_MultiInstanceReadOnly) + "_Category"; + string counterName = nameof(PerformanceCounter_CreateCounter_MultiInstanceReadOnly) + "_Counter"; + string instanceName = nameof(PerformanceCounter_CreateCounter_MultiInstanceReadOnly) + "_Instance"; - var category = Helpers.CreateCategory(name, PerformanceCounterCategoryType.MultiInstance); + Helpers.CreateCategory(categoryName, counterName, PerformanceCounterCategoryType.MultiInstance); - using (PerformanceCounter counterSample = Helpers.RetryOnAllPlatforms(() => new PerformanceCounter(category, name, instance))) + using (PerformanceCounter counterSample = Helpers.RetryOnAllPlatforms(() => new PerformanceCounter(categoryName, counterName, instanceName))) { - Assert.Equal(name, counterSample.CounterName); - Assert.Equal(category, counterSample.CategoryName); - Assert.Equal(instance, counterSample.InstanceName); + Assert.Equal(counterName, counterSample.CounterName); + Assert.Equal(categoryName, counterSample.CategoryName); + Assert.Equal(instanceName, counterSample.InstanceName); Assert.Equal("counter description", Helpers.RetryOnAllPlatforms(() => counterSample.CounterHelp)); Assert.True(counterSample.ReadOnly); - Helpers.DeleteCategory(name); } + + Helpers.DeleteCategory(categoryName); } [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] public static void PerformanceCounter_CreateCounter_SetReadOnly() { - var name = nameof(PerformanceCounter_CreateCounter_SetReadOnly) + "_Counter"; + string categoryName = nameof(PerformanceCounter_CreateCounter_SetReadOnly) + "_Category"; + string counterName = nameof(PerformanceCounter_CreateCounter_SetReadOnly) + "_Counter"; - var category = Helpers.CreateCategory(name, PerformanceCounterCategoryType.SingleInstance); + Helpers.CreateCategory(categoryName, PerformanceCounterCategoryType.SingleInstance); - using (PerformanceCounter counterSample = Helpers.RetryOnAllPlatforms(() => new PerformanceCounter(category, name))) + using (PerformanceCounter counterSample = Helpers.RetryOnAllPlatforms(() => new PerformanceCounter(categoryName, counterName))) { counterSample.ReadOnly = false; Assert.False(counterSample.ReadOnly); } - Helpers.DeleteCategory(name); + Helpers.DeleteCategory(categoryName); } [Fact] @@ -106,11 +111,11 @@ public static void PerformanceCounter_SetRawValue_ReadOnly() [Fact] public static void PerformanceCounter_GetRawValue_EmptyCategoryName() { - var name = nameof(PerformanceCounter_GetRawValue_EmptyCategoryName) + "_Counter"; + string counterName = nameof(PerformanceCounter_GetRawValue_EmptyCategoryName) + "_Counter"; using (PerformanceCounter counterSample = new PerformanceCounter()) { counterSample.ReadOnly = false; - counterSample.CounterName = name; + counterSample.CounterName = counterName; Assert.Throws(() => counterSample.RawValue); } @@ -119,11 +124,11 @@ public static void PerformanceCounter_GetRawValue_EmptyCategoryName() [Fact] public static void PerformanceCounter_GetRawValue_EmptyCounterName() { - var name = nameof(PerformanceCounter_GetRawValue_EmptyCounterName) + "_Counter"; + string categoryName = nameof(PerformanceCounter_GetRawValue_EmptyCounterName) + "_Category"; using (PerformanceCounter counterSample = new PerformanceCounter()) { counterSample.ReadOnly = false; - counterSample.CategoryName = name + "_Category"; + counterSample.CategoryName = categoryName; Assert.Throws(() => counterSample.RawValue); } @@ -132,27 +137,40 @@ public static void PerformanceCounter_GetRawValue_EmptyCounterName() [Fact] public static void PerformanceCounter_GetRawValue_CounterDoesNotExist() { - var name = nameof(PerformanceCounter_GetRawValue_CounterDoesNotExist) + "_Counter"; + string categoryName = nameof(PerformanceCounter_GetRawValue_CounterDoesNotExist) + "_Category"; + string counterName = nameof(PerformanceCounter_GetRawValue_CounterDoesNotExist) + "_Counter"; + using (PerformanceCounter counterSample = new PerformanceCounter()) { counterSample.ReadOnly = false; - counterSample.CounterName = name; - counterSample.CategoryName = name + "_Category"; + counterSample.CounterName = counterName; + counterSample.CategoryName = categoryName; Assert.Throws(() => counterSample.RawValue); } } - [ActiveIssue("https://github.com/dotnet/runtime/issues/29753")] [Fact] public static void PerformanceCounter_NextValue_ProcessorCounter() { - using (PerformanceCounter counterSample = new PerformanceCounter("Processor", "Interrupts/sec", "0", ".")) + using (PerformanceCounter counterSample = new PerformanceCounter("Processor", "Interrupts/sec", "_Total", ".")) { - Helpers.RetryOnAllPlatforms(() => counterSample.NextValue()); - System.Threading.Thread.Sleep(30); - - Assert.True(Helpers.RetryOnAllPlatforms(() => counterSample.NextValue()) > 0); + float val; + int counter = 0; + do + { + // Ensure we don't always return zero for a counter we know is not always zero + val = Helpers.RetryOnAllPlatforms(() => counterSample.NextValue()); + if (val > 0f) + { + break; + } + counter++; + Thread.Sleep(100); + } + while (counter < 20); + + Assert.True(val > 0f); } } @@ -182,116 +200,127 @@ public static void PerformanceCounter_BeginInitEndInit_ProcessorCounter() [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] public static void PerformanceCounter_Decrement() { - var name = nameof(PerformanceCounter_Decrement) + "_Counter"; - using (PerformanceCounter counterSample = CreateCounterWithCategory(name, false, PerformanceCounterCategoryType.SingleInstance)) + string categoryName = nameof(PerformanceCounter_Decrement) + "_Category"; + using (PerformanceCounter counterSample = CreateCounterWithCategory(categoryName, readOnly:false, PerformanceCounterCategoryType.SingleInstance)) { counterSample.RawValue = 10; Helpers.RetryOnAllPlatforms(() => counterSample.Decrement()); Assert.Equal(9, counterSample.RawValue); - Helpers.DeleteCategory(name); } + + Helpers.DeleteCategory(categoryName); } [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] public static void PerformanceCounter_Increment() { - var name = nameof(PerformanceCounter_Increment) + "_Counter"; - using (PerformanceCounter counterSample = CreateCounterWithCategory(name, false, PerformanceCounterCategoryType.SingleInstance)) + string categoryName = nameof(PerformanceCounter_Increment) + "_Category"; + using (PerformanceCounter counterSample = CreateCounterWithCategory(categoryName, readOnly:false, PerformanceCounterCategoryType.SingleInstance)) { counterSample.RawValue = 10; Helpers.RetryOnAllPlatforms(() => counterSample.Increment()); Assert.Equal(11, Helpers.RetryOnAllPlatforms(() => counterSample.NextSample().RawValue)); - Helpers.DeleteCategory(name); } + + Helpers.DeleteCategory(categoryName); } [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] public static void PerformanceCounter_IncrementBy_IncrementBy2() { - var name = nameof(PerformanceCounter_IncrementBy_IncrementBy2) + "_Counter"; - using (PerformanceCounter counterSample = CreateCounterWithCategory(name, false, PerformanceCounterCategoryType.SingleInstance)) + string categoryName = nameof(PerformanceCounter_IncrementBy_IncrementBy2) + "_Category"; + using (PerformanceCounter counterSample = CreateCounterWithCategory(categoryName, readOnly:false, PerformanceCounterCategoryType.SingleInstance)) { counterSample.RawValue = 10; Helpers.RetryOnAllPlatforms(() => counterSample.IncrementBy(2)); - Assert.Equal(12, counterSample.RawValue); - Helpers.DeleteCategory(name); + Assert.Equal(12, Helpers.RetryOnAllPlatforms(() => counterSample.NextSample().RawValue)); } + + Helpers.DeleteCategory(categoryName); } [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] public static void PerformanceCounter_IncrementBy_IncrementByReadOnly() { - var name = nameof(PerformanceCounter_IncrementBy_IncrementByReadOnly) + "_Counter"; - using (PerformanceCounter counterSample = CreateCounterWithCategory(name, true, PerformanceCounterCategoryType.SingleInstance)) + string categoryName = nameof(PerformanceCounter_IncrementBy_IncrementByReadOnly) + "_Category"; + using (PerformanceCounter counterSample = CreateCounterWithCategory(categoryName, readOnly:true, PerformanceCounterCategoryType.SingleInstance)) { Assert.Throws(() => counterSample.IncrementBy(2)); - Helpers.DeleteCategory(name); } + + Helpers.DeleteCategory(categoryName); } [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] public static void PerformanceCounter_Increment_IncrementReadOnly() { - var name = nameof(PerformanceCounter_Increment_IncrementReadOnly) + "_Counter"; - using (PerformanceCounter counterSample = CreateCounterWithCategory(name, true, PerformanceCounterCategoryType.SingleInstance)) + string categoryName = nameof(PerformanceCounter_Increment_IncrementReadOnly) + "_Category"; + using (PerformanceCounter counterSample = CreateCounterWithCategory(categoryName, readOnly:true, PerformanceCounterCategoryType.SingleInstance)) { Assert.Throws(() => counterSample.Increment()); - Helpers.DeleteCategory(name); } + + Helpers.DeleteCategory(categoryName); } [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] public static void PerformanceCounter_Decrement_DecrementReadOnly() { - var name = nameof(PerformanceCounter_Decrement_DecrementReadOnly) + "_Counter"; - using (PerformanceCounter counterSample = CreateCounterWithCategory(name, true, PerformanceCounterCategoryType.SingleInstance)) + string categoryName = nameof(PerformanceCounter_Decrement_DecrementReadOnly) + "_Category"; + using (PerformanceCounter counterSample = CreateCounterWithCategory(categoryName, readOnly:true, PerformanceCounterCategoryType.SingleInstance)) { Assert.Throws(() => counterSample.Decrement()); - Helpers.DeleteCategory(name); } + + Helpers.DeleteCategory(categoryName); } [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteToPerfCounters))] public static void PerformanceCounter_RemoveInstance() { - var name = nameof(PerformanceCounter_RemoveInstance) + "_Counter"; - using (PerformanceCounter counterSample = CreateCounterWithCategory(name, false, PerformanceCounterCategoryType.SingleInstance)) + string categoryName = nameof(PerformanceCounter_RemoveInstance) + "_Category"; + using (PerformanceCounter counterSample = CreateCounterWithCategory(categoryName, readOnly:false, PerformanceCounterCategoryType.SingleInstance)) { counterSample.RawValue = 100; counterSample.RemoveInstance(); counterSample.Close(); Assert.NotNull(counterSample); - Helpers.DeleteCategory(name); } + + Helpers.DeleteCategory(categoryName); } [ConditionalFact(typeof(Helpers), nameof(Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters))] public static void PerformanceCounter_NextSample_MultiInstance() { - var name = nameof(PerformanceCounter_NextSample_MultiInstance) + "_Counter"; - var instance = name + "_Instance"; + string categoryName = nameof(PerformanceCounter_NextSample_MultiInstance) + "_Category"; + string counterName = nameof(PerformanceCounter_NextSample_MultiInstance) + "_Counter"; + string instanceName = nameof(PerformanceCounter_NextSample_MultiInstance) + "_Instance"; - var category = Helpers.CreateCategory(name, PerformanceCounterCategoryType.MultiInstance); + Helpers.CreateCategory(categoryName, PerformanceCounterCategoryType.MultiInstance); - using (PerformanceCounter counterSample = new PerformanceCounter(category, name, instance, false)) + using (PerformanceCounter counterSample = new PerformanceCounter(categoryName, counterName, instanceName, readOnly:false)) { counterSample.RawValue = 10; Helpers.RetryOnAllPlatforms(() => counterSample.Decrement()); Assert.Equal(9, counterSample.RawValue); - Helpers.DeleteCategory(name); } + + Helpers.DeleteCategory(categoryName); } - public static PerformanceCounter CreateCounterWithCategory(string name, bool readOnly, PerformanceCounterCategoryType categoryType ) + public static PerformanceCounter CreateCounterWithCategory(string categoryName, bool readOnly, PerformanceCounterCategoryType categoryType) { - var category = Helpers.CreateCategory(name, categoryType); + Helpers.CreateCategory(categoryName, categoryType); + + string counterName = categoryName.Replace("_Category", "_Counter"); - PerformanceCounter counterSample = Helpers.RetryOnAllPlatforms(() => new PerformanceCounter(category, name, readOnly)); + PerformanceCounter counterSample = Helpers.RetryOnAllPlatforms(() => new PerformanceCounter(categoryName, counterName, readOnly)); return counterSample; } diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceDataTests.cs b/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceDataTests.cs index d2864ae7bd3e3..a48b07878b4d0 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceDataTests.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/tests/PerformanceDataTests.cs @@ -18,7 +18,7 @@ public PerformanceDataTests(PerformanceDataTestsFixture fixture) } // We run the test only if the stress mode is enabled and the process is elvated. - private static bool IsRunnableEnvironnement => Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters && TestEnvironment.IsStressModeEnabled && RemoteExecutor.IsSupported; + private static bool IsRunnableEnvironment => Helpers.IsElevatedAndCanWriteAndReadNetPerfCounters && TestEnvironment.IsStressModeEnabled && RemoteExecutor.IsSupported; /// /// This test was taken from System.Diagnostics.PerformanceData documentation https://msdn.microsoft.com/en-us/library/system.diagnostics.performancedata(v=vs.110).aspx @@ -26,7 +26,7 @@ public PerformanceDataTests(PerformanceDataTestsFixture fixture) /// ctrpp.exe -legacy provider.man /// rc.exe /r /i "c:\Program Files\Microsoft SDKs\Windows\v6.0\Include" provider.rc /// - [ConditionalFact(nameof(PerformanceDataTests.IsRunnableEnvironnement))] + [ConditionalFact(nameof(PerformanceDataTests.IsRunnableEnvironment))] public void PerformanceCounter_PerformanceData() { // We run test in isolated process to avoid interferences on internal performance counter shared state with other tests. diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj index 108bf2f43b9f2..8ee73ae4c1d28 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj +++ b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj @@ -67,7 +67,11 @@ + + + Common\System\LocalAppContextSwitches.Common.cs + Common\Interop\Linux\OpenLdap\Interop.Ldap.cs diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs index 701fae2610828..d67782f40ad36 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs @@ -123,7 +123,31 @@ internal static int BindToDirectory(ConnectionHandle ld, string who, string pass } } - internal static int StartTls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls) => Interop.Ldap.ldap_start_tls(ldapHandle, ref ServerReturnValue, ref Message, ServerControls, ClientControls); + internal static int StartTls(ConnectionHandle ldapHandle, ref int serverReturnValue, ref IntPtr message, IntPtr serverControls, IntPtr clientControls) + { + // Windows and Linux have different signatures for ldap_start_tls_s. + // On Linux, we don't have a serverReturnValue or the message/result parameter. + // + // So in the PAL here, just emulate. + + int error = Interop.Ldap.ldap_start_tls(ldapHandle, serverControls, clientControls); + + // On Windows, serverReturnValue only has meaning if the result code is LDAP_OTHER. + // If OpenLDAP returns that, we don't have a better code, so assign that through. + // If we get any other error, assign serverReturnValue to 0 since it shouldn't be read. + if (error == (int)ResultCode.Other) + { + serverReturnValue = error; + } + else + { + serverReturnValue = 0; + } + + // We don't have a referrer/message/result value, so just set it to NULL. + message = IntPtr.Zero; + return error; + } // openldap doesn't have a ldap_stop_tls function. Returning true as no-op for Linux. internal static byte StopTls(ConnectionHandle ldapHandle) => 1; diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs index 2383e816e1ddb..a7e43947e2031 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs @@ -16,6 +16,13 @@ public ConnectionHandle() _needDispose = true; } + internal ConnectionHandle(string uri) + :base(true) + { + Interop.Ldap.ldap_initialize(out handle, uri); + _needDispose = true; + } + internal ConnectionHandle(IntPtr value, bool disposeHandle) : base(true) { _needDispose = disposeHandle; diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs index 02c8f0c239587..6adf1ebac982c 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs @@ -20,7 +20,7 @@ private void InternalInitConnectionHandle(string hostname) throw new NullReferenceException(); } - _ldapHandle = new ConnectionHandle(); + _ldapHandle = new ConnectionHandle($"ldap://{hostname}:{((LdapDirectoryIdentifier)_directoryIdentifier).PortNumber}"); } private int InternalConnectToServer() @@ -79,13 +79,39 @@ private int InternalConnectToServer() private int InternalBind(NetworkCredential tempCredential, SEC_WINNT_AUTH_IDENTITY_EX cred, BindMethod method) { int error; - if (tempCredential == null && (AuthType == AuthType.External || AuthType == AuthType.Kerberos)) + + if (LocalAppContextSwitches.UseBasicAuthFallback) { - error = BindSasl(); + if (tempCredential == null && (AuthType == AuthType.External || AuthType == AuthType.Kerberos)) + { + error = BindSasl(); + } + else + { + error = LdapPal.BindToDirectory(_ldapHandle, cred.user, cred.password); + } } else { - error = LdapPal.BindToDirectory(_ldapHandle, cred.user, cred.password); + if (method == BindMethod.LDAP_AUTH_NEGOTIATE) + { + if (tempCredential == null) + { + error = BindSasl(); + } + else + { + // Explicit credentials were provided. If we call ldap_bind_s it will + // return LDAP_NOT_SUPPORTED, so just skip the P/Invoke. + error = (int)LdapError.NotSupported; + } + } + else + { + // Basic and Anonymous are handled elsewhere. + Debug.Assert(AuthType != AuthType.Anonymous && AuthType != AuthType.Basic); + error = (int)LdapError.AuthUnknown; + } } return error; diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs index 5b28020eed2fd..9a200fc5ba218 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs @@ -641,11 +641,14 @@ public unsafe void StartTransportLayerSecurity(DirectoryControlCollection contro response.ResponseName = "1.3.6.1.4.1.1466.20037"; throw new TlsOperationException(response); } - else if (LdapErrorMappings.IsLdapError(error)) + + if (LdapErrorMappings.IsLdapError(error)) { string errorMessage = LdapErrorMappings.MapResultCode(error); throw new LdapException(error, errorMessage); } + + throw new LdapException(error); } } finally diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LocalAppContextSwitches.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LocalAppContextSwitches.cs new file mode 100644 index 0000000000000..59ddfdf7f10ed --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LocalAppContextSwitches.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; + +namespace System +{ + internal static partial class LocalAppContextSwitches + { + private static int s_useBasicAuthFallback; + + public static bool UseBasicAuthFallback + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => GetCachedSwitchValue("System.DirectoryServices.Protocols.UseBasicAuthFallback", ref s_useBasicAuthFallback); + } + } +} diff --git a/src/libraries/System.Drawing.Common/tests/FontTests.cs b/src/libraries/System.Drawing.Common/tests/FontTests.cs index de260a5914083..899bd4e3c1040 100644 --- a/src/libraries/System.Drawing.Common/tests/FontTests.cs +++ b/src/libraries/System.Drawing.Common/tests/FontTests.cs @@ -800,7 +800,7 @@ public void ToLogFont_Invoke_ReturnsExpected(FontStyle fontStyle, byte gdiCharSe Assert.Equal(font.Italic ? 1 : 0, logFont.lfItalic); Assert.Equal(font.Underline ? 1 : 0, logFont.lfUnderline); Assert.Equal(font.Strikeout ? 1 : 0, logFont.lfStrikeOut); - Assert.Equal(font.GdiCharSet, logFont.lfCharSet); + Assert.Equal(SystemFonts.DefaultFont.GdiCharSet <= 2 ? font.GdiCharSet : SystemFonts.DefaultFont.GdiCharSet, logFont.lfCharSet); Assert.Equal(0, logFont.lfOutPrecision); Assert.Equal(0, logFont.lfClipPrecision); Assert.Equal(0, logFont.lfQuality); @@ -837,7 +837,7 @@ public void ToLogFont_InvokeGraphics_ReturnsExpected(TextRenderingHint textRende Assert.Equal(0, logFont.lfItalic); Assert.Equal(0, logFont.lfUnderline); Assert.Equal(0, logFont.lfStrikeOut); - Assert.Equal(1, logFont.lfCharSet); + Assert.Equal(SystemFonts.DefaultFont.GdiCharSet <= 2 ? font.GdiCharSet : SystemFonts.DefaultFont.GdiCharSet, logFont.lfCharSet); Assert.Equal(0, logFont.lfOutPrecision); Assert.Equal(0, logFont.lfClipPrecision); Assert.Equal(0, logFont.lfQuality); diff --git a/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln b/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln index 1958430a9e5ab..c4e10f55f1aa7 100644 --- a/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln +++ b/src/libraries/System.IO.FileSystem/System.IO.FileSystem.sln @@ -21,8 +21,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO.FileSystem.Disabl EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO.FileSystem.Manual.Tests", "tests\ManualTests\System.IO.FileSystem.Manual.Tests.csproj", "{534152EB-14A8-4EF4-B181-342A555337F1}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO.FileSystem.Net5Compat.Tests", "tests\Net5CompatTests\System.IO.FileSystem.Net5Compat.Tests.csproj", "{48E07F12-8597-40DE-8A37-CCBEB9D54012}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO.FileSystem.Tests", "tests\System.IO.FileSystem.Tests.csproj", "{3A8E16D3-8A22-4076-BB48-2CD1FBFAF81B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServices.Unsafe", "..\System.Runtime.CompilerServices.Unsafe\ref\System.Runtime.CompilerServices.Unsafe.csproj", "{79A74577-C550-4264-B352-51D304796B89}" diff --git a/src/libraries/System.IO.FileSystem/tests/File/Append.cs b/src/libraries/System.IO.FileSystem/tests/File/Append.cs index 8cb28b7ca38ac..68160715a7d63 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/Append.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/Append.cs @@ -8,6 +8,8 @@ namespace System.IO.Tests { public class File_AppendText : File_ReadWriteAllText { + protected override bool IsAppend => true; + protected override void Write(string path, string content) { var writer = File.AppendText(path); @@ -15,34 +17,26 @@ protected override void Write(string path, string content) writer.Dispose(); } - [Fact] - public override void Overwrite() + protected override void Write(string path, string content, Encoding encoding) { - string path = GetTestFilePath(); - string lines = new string('c', 200); - string appendLines = new string('b', 100); - Write(path, lines); - Write(path, appendLines); - Assert.Equal(lines + appendLines, Read(path)); + var writer = new StreamWriter(path, IsAppend, encoding); + writer.Write(content); + writer.Dispose(); } } public class File_AppendAllText : File_ReadWriteAllText { + protected override bool IsAppend => true; + protected override void Write(string path, string content) { File.AppendAllText(path, content); } - [Fact] - public override void Overwrite() + protected override void Write(string path, string content, Encoding encoding) { - string path = GetTestFilePath(); - string lines = new string('c', 200); - string appendLines = new string('b', 100); - Write(path, lines); - Write(path, appendLines); - Assert.Equal(lines + appendLines, Read(path)); + File.AppendAllText(path, content, encoding); } } @@ -62,21 +56,12 @@ public void NullEncoding() public class File_AppendAllLines : File_ReadWriteAllLines_Enumerable { + protected override bool IsAppend => true; + protected override void Write(string path, string[] content) { File.AppendAllLines(path, content); } - - [Fact] - public override void Overwrite() - { - string path = GetTestFilePath(); - string[] lines = new string[] { new string('c', 200) }; - string[] appendLines = new string[] { new string('b', 100) }; - Write(path, lines); - Write(path, appendLines); - Assert.Equal(new string[] { lines[0], appendLines[0] }, Read(path)); - } } public class File_AppendAllLines_Encoded : File_AppendAllLines diff --git a/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs index 457366266d69c..dbe1d5197fcdf 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/AppendAsync.cs @@ -10,18 +10,11 @@ namespace System.IO.Tests { public class File_AppendAllTextAsync : File_ReadWriteAllTextAsync { + protected override bool IsAppend => true; + protected override Task WriteAsync(string path, string content) => File.AppendAllTextAsync(path, content); - [Fact] - public override async Task OverwriteAsync() - { - string path = GetTestFilePath(); - string lines = new string('c', 200); - string appendLines = new string('b', 100); - await WriteAsync(path, lines); - await WriteAsync(path, appendLines); - Assert.Equal(lines + appendLines, await ReadAsync(path)); - } + protected override Task WriteAsync(string path, string content, Encoding encoding) => File.AppendAllTextAsync(path, content, encoding); [Fact] public override Task TaskAlreadyCanceledAsync() @@ -60,18 +53,9 @@ public override Task TaskAlreadyCanceledAsync() public class File_AppendAllLinesAsync : File_ReadWriteAllLines_EnumerableAsync { - protected override Task WriteAsync(string path, string[] content) => File.AppendAllLinesAsync(path, content); + protected override bool IsAppend => true; - [Fact] - public override async Task OverwriteAsync() - { - string path = GetTestFilePath(); - string[] lines = new string[] { new string('c', 200) }; - string[] appendLines = new string[] { new string('b', 100) }; - await WriteAsync(path, lines); - await WriteAsync(path, appendLines); - Assert.Equal(new string[] { lines[0], appendLines[0] }, await ReadAsync(path)); - } + protected override Task WriteAsync(string path, string[] content) => File.AppendAllLinesAsync(path, content); [Fact] public override Task TaskAlreadyCanceledAsync() diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs index 54c7643766335..679ff9b5b7986 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs @@ -2,8 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Text; +using System.Threading; using System.Threading.Tasks; using Xunit; +using System.IO.Pipes; +using Microsoft.DotNet.XUnitExtensions; namespace System.IO.Tests { @@ -172,5 +175,62 @@ public void ProcFs_NotEmpty(string path) { Assert.InRange(File.ReadAllBytes(path).Length, 1, int.MaxValue); } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] // DOS device paths (\\.\ and \\?\) are a Windows concept + [ActiveIssue("https://github.com/dotnet/runtime/issues/60427")] + public async Task ReadAllBytes_NonSeekableFileStream_InWindows() + { + string pipeName = FileSystemTest.GetNamedPipeServerStreamName(); + string pipePath = Path.GetFullPath($@"\\.\pipe\{pipeName}"); + + var namedPipeWriterStream = new NamedPipeServerStream(pipeName, PipeDirection.Out); + var contentBytes = new byte[] { 1, 2, 3 }; + + using (var cts = new CancellationTokenSource()) + { + Task writingServerTask = WaitConnectionAndWritePipeStreamAsync(namedPipeWriterStream, contentBytes, cts.Token); + Task readTask = Task.Run(() => File.ReadAllBytes(pipePath), cts.Token); + cts.CancelAfter(TimeSpan.FromSeconds(3)); + + await writingServerTask; + byte[] readBytes = await readTask; + Assert.Equal(contentBytes, readBytes); + } + + static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream namedPipeWriterStream, byte[] contentBytes, CancellationToken cancellationToken) + { + await using (namedPipeWriterStream) + { + await namedPipeWriterStream.WaitForConnectionAsync(cancellationToken); + await namedPipeWriterStream.WriteAsync(contentBytes, cancellationToken); + } + } + } + + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] + public async Task ReadAllBytes_NonSeekableFileStream_InUnix() + { + string fifoPath = GetTestFilePath(); + Assert.Equal(0, mkfifo(fifoPath, 438 /* 666 in octal */ )); + + var contentBytes = new byte[] { 1, 2, 3 }; + + await Task.WhenAll( + Task.Run(() => + { + byte[] readBytes = File.ReadAllBytes(fifoPath); + Assert.Equal(contentBytes, readBytes); + }), + Task.Run(() => + { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Write, FileShare.Read); + foreach (byte content in contentBytes) + { + fs.WriteByte(content); + } + })); + } } } diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs index 748c01dbffb8f..be562f15ca953 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs @@ -5,6 +5,8 @@ using System.Threading; using System.Threading.Tasks; using Xunit; +using System.IO.Pipes; +using Microsoft.DotNet.XUnitExtensions; namespace System.IO.Tests { @@ -186,5 +188,61 @@ public async Task ProcFs_NotEmpty(string path) { Assert.InRange((await File.ReadAllBytesAsync(path)).Length, 1, int.MaxValue); } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] // DOS device paths (\\.\ and \\?\) are a Windows concept + public async Task ReadAllBytesAsync_NonSeekableFileStream_InWindows() + { + string pipeName = FileSystemTest.GetNamedPipeServerStreamName(); + string pipePath = Path.GetFullPath($@"\\.\pipe\{pipeName}"); + + var namedPipeWriterStream = new NamedPipeServerStream(pipeName, PipeDirection.Out); + var contentBytes = new byte[] { 1, 2, 3 }; + + using (var cts = new CancellationTokenSource()) + { + Task writingServerTask = WaitConnectionAndWritePipeStreamAsync(namedPipeWriterStream, contentBytes, cts.Token); + Task readTask = File.ReadAllBytesAsync(pipePath, cts.Token); + cts.CancelAfter(TimeSpan.FromSeconds(50)); + + await writingServerTask; + byte[] readBytes = await readTask; + Assert.Equal(contentBytes, readBytes); + } + + static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream namedPipeWriterStream, byte[] contentBytes, CancellationToken cancellationToken) + { + await using (namedPipeWriterStream) + { + await namedPipeWriterStream.WaitForConnectionAsync(cancellationToken); + await namedPipeWriterStream.WriteAsync(contentBytes, cancellationToken); + } + } + } + + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] + public async Task ReadAllBytesAsync_NonSeekableFileStream_InUnix() + { + string fifoPath = GetTestFilePath(); + Assert.Equal(0, mkfifo(fifoPath, 438 /* 666 in octal */ )); + + var contentBytes = new byte[] { 1, 2, 3 }; + + await Task.WhenAll( + Task.Run(async () => + { + byte[] readBytes = await File.ReadAllBytesAsync(fifoPath); + Assert.Equal(contentBytes, readBytes); + }), + Task.Run(() => + { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Write, FileShare.Read); + foreach (byte content in contentBytes) + { + fs.WriteByte(content); + } + })); + } } } diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllLines.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllLines.cs index 99c94b450790f..99de941c39175 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllLines.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllLines.cs @@ -12,6 +12,8 @@ public class File_ReadWriteAllLines_Enumerable : FileSystemTest { #region Utilities + protected virtual bool IsAppend { get; } + protected virtual void Write(string path, string[] content) { File.WriteAllLines(path, (IEnumerable)content); @@ -66,15 +68,28 @@ public void ValidWrite(int size) Assert.Equal(lines, Read(path)); } - [Fact] - public virtual void Overwrite() + [Theory] + [InlineData(200, 100)] + [InlineData(50_000, 40_000)] // tests a different code path than the line above + public void AppendOrOverwrite(int linesSizeLength, int overwriteLinesLength) { string path = GetTestFilePath(); - string[] lines = new string[] { new string('c', 200) }; - string[] overwriteLines = new string[] { new string('b', 100) }; + string[] lines = new string[] { new string('c', linesSizeLength) }; + string[] overwriteLines = new string[] { new string('b', overwriteLinesLength) }; + Write(path, lines); Write(path, overwriteLines); - Assert.Equal(overwriteLines, Read(path)); + + if (IsAppend) + { + Assert.Equal(new string[] { lines[0], overwriteLines[0] }, Read(path)); + } + else + { + Assert.DoesNotContain("Append", GetType().Name); // ensure that all "Append" types override this property + + Assert.Equal(overwriteLines, Read(path)); + } } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsFileLockingEnabled))] diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllLinesAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllLinesAsync.cs index b2a1288639db3..3114e649e6635 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllLinesAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllLinesAsync.cs @@ -15,6 +15,8 @@ public class File_ReadWriteAllLines_EnumerableAsync : FileSystemTest { #region Utilities + protected virtual bool IsAppend { get; } + protected virtual Task WriteAsync(string path, string[] content) => File.WriteAllLinesAsync(path, content); @@ -64,15 +66,29 @@ public async Task ValidWriteAsync(int size) Assert.Equal(lines, await ReadAsync(path)); } - [Fact] - public virtual async Task OverwriteAsync() + + [Theory] + [InlineData(200, 100)] + [InlineData(50_000, 40_000)] // tests a different code path than the line above + public async Task AppendOrOverwrite(int linesSizeLength, int overwriteLinesLength) { string path = GetTestFilePath(); - string[] lines = { new string('c', 200) }; - string[] overwriteLines = { new string('b', 100) }; + string[] lines = new string[] { new string('c', linesSizeLength) }; + string[] overwriteLines = new string[] { new string('b', overwriteLinesLength) }; + await WriteAsync(path, lines); await WriteAsync(path, overwriteLines); - Assert.Equal(overwriteLines, await ReadAsync(path)); + + if (IsAppend) + { + Assert.Equal(new string[] { lines[0], overwriteLines[0] }, await ReadAsync(path)); + } + else + { + Assert.DoesNotContain("Append", GetType().Name); // ensure that all "Append" types override this property + + Assert.Equal(overwriteLines, await ReadAsync(path)); + } } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsFileLockingEnabled))] diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllText.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllText.cs index 1dbe303849658..8c9c1e66e72a4 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllText.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllText.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Generic; using System.Text; using Xunit; @@ -10,11 +11,18 @@ public class File_ReadWriteAllText : FileSystemTest { #region Utilities + protected virtual bool IsAppend { get; } + protected virtual void Write(string path, string content) { File.WriteAllText(path, content); } + protected virtual void Write(string path, string content, Encoding encoding) + { + File.WriteAllText(path, content, encoding); + } + protected virtual string Read(string path) { return File.ReadAllText(path); @@ -73,15 +81,28 @@ public void ValidWrite(int size) Assert.Equal(toWrite, Read(path)); } - [Fact] - public virtual void Overwrite() + [Theory] + [InlineData(200, 100)] + [InlineData(50_000, 40_000)] // tests a different code path than the line above + public void AppendOrOverwrite(int linesSizeLength, int overwriteLinesLength) { string path = GetTestFilePath(); - string lines = new string('c', 200); - string overwriteLines = new string('b', 100); + string lines = new string('c', linesSizeLength); + string overwriteLines = new string('b', overwriteLinesLength); + Write(path, lines); Write(path, overwriteLines); - Assert.Equal(overwriteLines, Read(path)); + + if (IsAppend) + { + Assert.Equal(lines + overwriteLines, Read(path)); + } + else + { + Assert.DoesNotContain("Append", GetType().Name); // ensure that all "Append" types override this property + + Assert.Equal(overwriteLines, Read(path)); + } } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsFileLockingEnabled))] @@ -133,6 +154,56 @@ public void WriteToReadOnlyFile() } } + public static IEnumerable OutputIsTheSameAsForStreamWriter_Args() + { + string longText = new string('z', 50_000); + foreach (Encoding encoding in new[] { Encoding.Unicode , new UTF8Encoding(encoderShouldEmitUTF8Identifier: true), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false) }) + { + foreach (string text in new[] { null, string.Empty, " ", "shortText", longText }) + { + yield return new object[] { text, encoding }; + } + } + } + + [Theory] + [MemberData(nameof(OutputIsTheSameAsForStreamWriter_Args))] + public void OutputIsTheSameAsForStreamWriter(string content, Encoding encoding) + { + string filePath = GetTestFilePath(); + Write(filePath, content, encoding); // it uses System.IO.File APIs + + string swPath = GetTestFilePath(); + using (StreamWriter sw = new StreamWriter(swPath, IsAppend, encoding)) + { + sw.Write(content); + } + + Assert.Equal(File.ReadAllText(swPath, encoding), File.ReadAllText(filePath, encoding)); + Assert.Equal(File.ReadAllBytes(swPath), File.ReadAllBytes(filePath)); // ensure Preamble was stored + } + + [Theory] + [MemberData(nameof(OutputIsTheSameAsForStreamWriter_Args))] + public void OutputIsTheSameAsForStreamWriter_Overwrite(string content, Encoding encoding) + { + string filePath = GetTestFilePath(); + string swPath = GetTestFilePath(); + + for (int i = 0; i < 2; i++) + { + Write(filePath, content, encoding); // it uses System.IO.File APIs + + using (StreamWriter sw = new StreamWriter(swPath, IsAppend, encoding)) + { + sw.Write(content); + } + } + + Assert.Equal(File.ReadAllText(swPath, encoding), File.ReadAllText(filePath, encoding)); + Assert.Equal(File.ReadAllBytes(swPath), File.ReadAllBytes(filePath)); // ensure Preamble was stored once + } + #endregion } diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllTextAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllTextAsync.cs index 3ad76c272fff6..4a33f94f7b8f8 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllTextAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllTextAsync.cs @@ -12,10 +12,14 @@ namespace System.IO.Tests [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] public class File_ReadWriteAllTextAsync : FileSystemTest { + protected virtual bool IsAppend { get; } + #region Utilities protected virtual Task WriteAsync(string path, string content) => File.WriteAllTextAsync(path, content); + protected virtual Task WriteAsync(string path, string content, Encoding encoding) => File.WriteAllTextAsync(path, content, encoding); + protected virtual Task ReadAsync(string path) => File.ReadAllTextAsync(path); #endregion @@ -72,15 +76,28 @@ public async Task ValidWriteAsync(int size) Assert.Equal(toWrite, await ReadAsync(path)); } - [Fact] - public virtual async Task OverwriteAsync() + [Theory] + [InlineData(200, 100)] + [InlineData(50_000, 40_000)] // tests a different code path than the line above + public async Task AppendOrOverwriteAsync(int linesSizeLength, int overwriteLinesLength) { string path = GetTestFilePath(); - string lines = new string('c', 200); - string overwriteLines = new string('b', 100); + string lines = new string('c', linesSizeLength); + string overwriteLines = new string('b', overwriteLinesLength); + await WriteAsync(path, lines); - await WriteAsync(path, overwriteLines); - Assert.Equal(overwriteLines, await ReadAsync(path)); + await WriteAsync(path, overwriteLines); ; + + if (IsAppend) + { + Assert.Equal(lines + overwriteLines, await ReadAsync(path)); + } + else + { + Assert.DoesNotContain("Append", GetType().Name); // ensure that all "Append" types override this property + + Assert.Equal(overwriteLines, await ReadAsync(path)); + } } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsFileLockingEnabled))] @@ -141,6 +158,44 @@ public virtual Task TaskAlreadyCanceledAsync() async () => await File.WriteAllTextAsync(path, "", token)); } + [Theory] + [MemberData(nameof(File_ReadWriteAllText.OutputIsTheSameAsForStreamWriter_Args), MemberType = typeof(File_ReadWriteAllText))] + public async Task OutputIsTheSameAsForStreamWriterAsync(string content, Encoding encoding) + { + string filePath = GetTestFilePath(); + await WriteAsync(filePath, content, encoding); // it uses System.File.IO APIs + + string swPath = GetTestFilePath(); + using (StreamWriter sw = new StreamWriter(swPath, IsAppend, encoding)) + { + await sw.WriteAsync(content); + } + + Assert.Equal(await File.ReadAllTextAsync(swPath, encoding), await File.ReadAllTextAsync(filePath, encoding)); + Assert.Equal(await File.ReadAllBytesAsync(swPath), await File.ReadAllBytesAsync(filePath)); // ensure Preamble was stored + } + + [Theory] + [MemberData(nameof(File_ReadWriteAllText.OutputIsTheSameAsForStreamWriter_Args), MemberType = typeof(File_ReadWriteAllText))] + public async Task OutputIsTheSameAsForStreamWriter_OverwriteAsync(string content, Encoding encoding) + { + string filePath = GetTestFilePath(); + string swPath = GetTestFilePath(); + + for (int i = 0; i < 2; i++) + { + await WriteAsync(filePath, content, encoding); // it uses System.File.IO APIs + + using (StreamWriter sw = new StreamWriter(swPath, IsAppend, encoding)) + { + await sw.WriteAsync(content); + } + } + + Assert.Equal(await File.ReadAllTextAsync(swPath, encoding), await File.ReadAllTextAsync(filePath, encoding)); + Assert.Equal(await File.ReadAllBytesAsync(swPath), await File.ReadAllBytesAsync(filePath)); // ensure Preamble was stored once + } + #endregion } diff --git a/src/libraries/System.IO.FileSystem/tests/FileInfo/AppendText.cs b/src/libraries/System.IO.FileSystem/tests/FileInfo/AppendText.cs index eb86294b11974..2a73f63ecf04f 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileInfo/AppendText.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileInfo/AppendText.cs @@ -1,12 +1,15 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Text; using Xunit; namespace System.IO.Tests { public class FileInfo_AppendText : File_ReadWriteAllText { + protected override bool IsAppend => true; + protected override void Write(string path, string content) { var writer = new FileInfo(path).AppendText(); @@ -14,15 +17,11 @@ protected override void Write(string path, string content) writer.Dispose(); } - [Fact] - public override void Overwrite() + protected override void Write(string path, string content, Encoding encoding) { - string path = GetTestFilePath(); - string lines = new string('c', 200); - string appendline = new string('b', 100); - Write(path, lines); - Write(path, appendline); - Assert.Equal(lines + appendline, Read(path)); + var writer = new StreamWriter(path, IsAppend, encoding); + writer.Write(content); + writer.Dispose(); } } } diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/DeleteOnClose.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/DeleteOnClose.cs index 72150266a2ce0..ea32adc5352ad 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/DeleteOnClose.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/DeleteOnClose.cs @@ -10,6 +10,7 @@ namespace System.IO.Tests public class FileStream_DeleteOnClose : FileSystemTest { [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsFileLockingEnabled), nameof(PlatformDetection.IsThreadingSupported))] + [OuterLoop] public async Task OpenOrCreate_DeleteOnClose_UsableAsMutex() { var cts = new CancellationTokenSource(); @@ -69,7 +70,7 @@ public async Task OpenOrCreate_DeleteOnClose_UsableAsMutex() } // Wait for 1000 locks. - cts.CancelAfter(TimeSpan.FromSeconds(60)); // Test timeout. + cts.CancelAfter(TimeSpan.FromSeconds(120)); // Test timeout (reason for outerloop) Volatile.Write(ref locksRemaining, 500); await Task.WhenAll(tasks); diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/DevicesPipesAndSockets.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/DevicesPipesAndSockets.cs new file mode 100644 index 0000000000000..ede852c7305b3 --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/DevicesPipesAndSockets.cs @@ -0,0 +1,219 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.XUnitExtensions; +using Microsoft.Win32.SafeHandles; +using System.Collections.Generic; +using System.IO.Pipes; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace System.IO.Tests +{ + [PlatformSpecific(TestPlatforms.AnyUnix)] + public class DevicesPipesAndSockets : FileSystemTest + { + [Theory] + [MemberData(nameof(DevicePath_FileOptions_TestData))] + public void CharacterDevice_FileStream_Write(string devicePath, FileOptions fileOptions) + { + FileStreamOptions options = new() { Options = fileOptions, Access = FileAccess.Write, Share = FileShare.Write }; + using FileStream fs = new(devicePath, options); + fs.Write(Encoding.UTF8.GetBytes("foo")); + } + + [Theory] + [MemberData(nameof(DevicePath_FileOptions_TestData))] + public async Task CharacterDevice_FileStream_WriteAsync(string devicePath, FileOptions fileOptions) + { + FileStreamOptions options = new() { Options = fileOptions, Access = FileAccess.Write, Share = FileShare.Write }; + using FileStream fs = new(devicePath, options); + await fs.WriteAsync(Encoding.UTF8.GetBytes("foo")); + } + + [Theory] + [MemberData(nameof(DevicePath_TestData))] + public void CharacterDevice_WriteAllBytes(string devicePath) + { + File.WriteAllBytes(devicePath, Encoding.UTF8.GetBytes("foo")); + } + + [Theory] + [MemberData(nameof(DevicePath_TestData))] + public async Task CharacterDevice_WriteAllBytesAsync(string devicePath) + { + await File.WriteAllBytesAsync(devicePath, Encoding.UTF8.GetBytes("foo")); + } + + [Theory] + [MemberData(nameof(DevicePath_TestData))] + public void CharacterDevice_WriteAllText(string devicePath) + { + File.WriteAllText(devicePath, "foo"); + } + + [Theory] + [MemberData(nameof(DevicePath_TestData))] + public async Task CharacterDevice_WriteAllTextAsync(string devicePath) + { + await File.WriteAllTextAsync(devicePath, "foo"); + } + + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] + public async Task NamedPipe_ReadWrite() + { + string fifoPath = GetTestFilePath(); + Assert.Equal(0, mkfifo(fifoPath, 438 /* 666 in octal */ )); + + await Task.WhenAll( + Task.Run(() => + { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + ReadByte(fs, 42); + }), + Task.Run(() => + { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Write, FileShare.Read); + WriteByte(fs, 42); + })); + } + + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] + public async Task NamedPipe_ReadWrite_Async() + { + string fifoPath = GetTestFilePath(); + Assert.Equal(0, mkfifo(fifoPath, 438 /* 666 in octal */ )); + + await Task.WhenAll( + Task.Run(async () => { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + await ReadByteAsync(fs, 42); + }), + Task.Run(async () => + { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Write, FileShare.Read); + await WriteByteAsync(fs, 42); + })); + } + + private const int AF_UNIX = 1; + private const int SOCK_STREAM = 1; + + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] + public unsafe void SocketPair_ReadWrite() + { + int* ptr = stackalloc int[2]; + Assert.Equal(0, socketpair(AF_UNIX, SOCK_STREAM, 0, ptr)); + + using var readFileStream = new FileStream(new SafeFileHandle((IntPtr)ptr[0], ownsHandle: true), FileAccess.Read); + using var writeFileStream = new FileStream(new SafeFileHandle((IntPtr)ptr[1], ownsHandle: true), FileAccess.Write); + + Task.WhenAll( + Task.Run(() => ReadByte(readFileStream, 42)), + Task.Run(() => WriteByte(writeFileStream, 42))).GetAwaiter().GetResult(); + } + + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] + public void SocketPair_ReadWrite_Async() + { + unsafe + { + int* ptr = stackalloc int[2]; + Assert.Equal(0, socketpair(AF_UNIX, SOCK_STREAM, 0, ptr)); + + using var readFileStream = new FileStream(new SafeFileHandle((IntPtr)ptr[0], ownsHandle: true), FileAccess.Read); + using var writeFileStream = new FileStream(new SafeFileHandle((IntPtr)ptr[1], ownsHandle: true), FileAccess.Write); + + Task.WhenAll( + ReadByteAsync(readFileStream, 42), + WriteByteAsync(writeFileStream, 42)).GetAwaiter().GetResult(); + } + } + + private static void ReadByte(FileStream fs, byte expected) + { + var buffer = new byte[1]; + Assert.Equal(1, fs.Read(buffer)); + Assert.Equal(expected, buffer[0]); + } + + private static void WriteByte(FileStream fs, byte value) + { + fs.Write(new byte[] { value }); + fs.Flush(); + } + + private static async Task ReadByteAsync(FileStream fs, byte expected) + { + var buffer = new byte[1]; + Assert.Equal(1, await fs.ReadAsync(buffer)); + Assert.Equal(expected, buffer[0]); + } + + private static async Task WriteByteAsync(FileStream fs, byte value) + { + await fs.WriteAsync(new byte[] { value }); + await fs.FlushAsync(); + } + + private static Lazy> AvailableDevicePaths = new Lazy>(() => + { + List paths = new(); + FileStreamOptions options = new() { Access = FileAccess.Write, Share = FileShare.Write }; + + foreach (string devicePath in new[] { "/dev/tty", "/dev/console", "/dev/null", "/dev/zero" }) + { + if (!File.Exists(devicePath)) + { + continue; + } + + try + { + File.Open(devicePath, options).Dispose(); + } + catch (Exception ex) + { + if (ex is IOException || ex is UnauthorizedAccessException) + { + continue; + } + + throw; + } + + paths.Add(devicePath); + } + + return paths; + }); + + public static IEnumerable DevicePath_FileOptions_TestData() + { + foreach (string devicePath in AvailableDevicePaths.Value) + { + foreach (FileOptions options in new[] { FileOptions.None, FileOptions.Asynchronous }) + { + yield return new object[] { devicePath, options}; + } + } + } + + public static IEnumerable DevicePath_TestData() + { + foreach (string devicePath in AvailableDevicePaths.Value) + { + yield return new object[] { devicePath }; + } + } + + [DllImport("libc")] + private static unsafe extern int socketpair(int domain, int type, int protocol, int* ptr); + } +} diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs index 4e2fb6fd2046e..af30be04c8673 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/ReadAsync.cs @@ -101,7 +101,7 @@ public async Task ReadAsyncCanceledFile(int bufferSize, bool isAsync) } } - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported), nameof(PlatformDetection.IsNet5CompatFileStreamDisabled))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [InlineData(FileShare.None, FileOptions.Asynchronous)] // FileShare.None: exclusive access [InlineData(FileShare.ReadWrite, FileOptions.Asynchronous)] // FileShare.ReadWrite: others can write to the file, the length can't be cached [InlineData(FileShare.None, FileOptions.None)] diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/SafeFileHandle.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/SafeFileHandle.cs index 0740eed02f0d8..49b31884761ab 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/SafeFileHandle.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/SafeFileHandle.cs @@ -65,89 +65,5 @@ public void AccessFlushesFileClosesHandle() Assert.Equal(TestBuffer.Length, fsr.Length); } } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNet5CompatFileStreamEnabled))] - public async Task ThrowWhenHandlePositionIsChanged_sync() - { - await ThrowWhenHandlePositionIsChanged(useAsync: false); - } - - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported), nameof(PlatformDetection.IsNet5CompatFileStreamEnabled))] - public async Task ThrowWhenHandlePositionIsChanged_async() - { - await ThrowWhenHandlePositionIsChanged(useAsync: true); - } - - private async Task ThrowWhenHandlePositionIsChanged(bool useAsync) - { - string fileName = GetTestFilePath(); - - using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite, 0x100, useAsync)) - { - // write some data to move the position, flush to ensure OS position is updated - fs.Write(TestBuffer, 0, TestBuffer.Length); - fs.Flush(); - - if (fs.SafeFileHandle.IsInvalid) - { - // nothing to test - return; - } - - using (FileStream fsr = new FileStream(fs.SafeFileHandle, FileAccess.Read, TestBuffer.Length, useAsync)) - { - Assert.Equal(TestBuffer.Length, fs.Position); - Assert.Equal(TestBuffer.Length, fsr.Position); - - // Operations on original filestream will fail if data is in buffer and position changes. - - // Put data in FS write buffer and update position from FSR - fs.WriteByte(0); - fsr.Position = 0; - - if (useAsync - // Async I/O behaviors differ due to kernel-based implementation on Windows - && OperatingSystem.IsWindows() - // ReadAsync which in this case (single byte written to buffer) calls FlushAsync is now 100% async - // so it does not complete synchronously anymore - && PlatformDetection.IsNet5CompatFileStreamEnabled) - { - Assert.Throws(() => FSAssert.CompletesSynchronously(fs.ReadAsync(new byte[1], 0, 1))); - } - else - { - await Assert.ThrowsAsync(() => fs.ReadAsync(new byte[1], 0, 1)); - } - - fs.WriteByte(0); - fsr.Position++; - Assert.Throws(() => fs.Read(new byte[1], 0, 1)); - - fs.WriteByte(0); - fsr.Position++; - await Assert.ThrowsAsync(() => fs.ReadAsync(new byte[1], 0, 1)); - - fs.WriteByte(0); - fsr.Position++; - Assert.Throws(() => fs.ReadByte()); - - fs.WriteByte(0); - fsr.Position++; - Assert.Throws(() => fs.Seek(0, SeekOrigin.End)); - - fs.WriteByte(0); - fsr.Position++; - Assert.Throws(() => fs.SetLength(2)); - - fs.WriteByte(0); - fsr.Position++; - Assert.Throws(() => fs.Flush()); - - fs.WriteByte(0); - fsr.Position++; - Assert.Throws(() => fs.Dispose()); - } - } - } } } diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/WriteAsync.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/WriteAsync.cs index 06a9422589ee8..86eef052df1b4 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/WriteAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/WriteAsync.cs @@ -229,18 +229,6 @@ public async Task ManyConcurrentWriteAsyncs_OuterLoop( { writes[i] = WriteAsync(fs, expectedData, i * writeSize, writeSize, cancellationToken); Assert.Null(writes[i].Exception); - if (useAsync) - { - // To ensure that the buffer of a FileStream opened for async IO is flushed - // by FlushAsync in asynchronous way, we aquire a lock for every buffered WriteAsync. - // The side effect of this is that the Position of FileStream is not updated until - // the lock is released by a previous operation. - // So now all WriteAsync calls should be awaited before starting another async file operation. - if (PlatformDetection.IsNet5CompatFileStreamEnabled) - { - Assert.Equal((i + 1) * writeSize, fs.Position); - } - } } await Task.WhenAll(writes); diff --git a/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/Net5CompatSwitchTests.cs b/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/Net5CompatSwitchTests.cs deleted file mode 100644 index fb70c4d3c47d0..0000000000000 --- a/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/Net5CompatSwitchTests.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Reflection; -using Xunit; - -namespace System.IO.Tests -{ - public class Net5CompatSwitchTests - { - [Fact] - public static void LegacySwitchIsHonored() - { - Assert.True(PlatformDetection.IsNet5CompatFileStreamEnabled); - - string filePath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); - - using (FileStream fileStream = File.Create(filePath)) - { - object strategy = fileStream - .GetType() - .GetField("_strategy", BindingFlags.NonPublic | BindingFlags.Instance) - .GetValue(fileStream); - - Assert.Contains("Net5Compat", strategy.GetType().FullName); - } - - File.Delete(filePath); - } - } -} diff --git a/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/System.IO.FileSystem.Net5Compat.Tests.csproj b/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/System.IO.FileSystem.Net5Compat.Tests.csproj deleted file mode 100644 index 54b9c2622937d..0000000000000 --- a/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/System.IO.FileSystem.Net5Compat.Tests.csproj +++ /dev/null @@ -1,53 +0,0 @@ - - - true - true - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix - - --working-dir=/test-dir - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/runtimeconfig.template.json b/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/runtimeconfig.template.json deleted file mode 100644 index 6e843517fe47a..0000000000000 --- a/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/runtimeconfig.template.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "configProperties": { - "System.IO.UseNet5CompatFileStream": true - } -} diff --git a/src/libraries/System.IO.FileSystem/tests/RandomAccess/NoBuffering.Windows.cs b/src/libraries/System.IO.FileSystem/tests/RandomAccess/NoBuffering.Windows.cs index 8bb39e4b2893f..ef60a9f223fb2 100644 --- a/src/libraries/System.IO.FileSystem/tests/RandomAccess/NoBuffering.Windows.cs +++ b/src/libraries/System.IO.FileSystem/tests/RandomAccess/NoBuffering.Windows.cs @@ -180,18 +180,17 @@ public async Task WriteAsyncUsingMultipleBuffers(bool asyncOperation, bool async Assert.Equal(content, File.ReadAllBytes(filePath)); } - [Fact] - public async Task ReadWriteAsyncUsingNonPageSizedMultipleBuffers() + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ReadWriteAsyncUsingMultipleBuffers(bool memoryPageSized) { string filePath = GetTestFilePath(); - // The Windows scatter/gather APIs accept segments that are exactly one page long. - // Combined with the FILE_FLAG_NO_BUFFERING's requirements, the segments must also - // be aligned at page size boundaries and have a size of a multiple of the page size. - // Using segments with a length of twice the page size adheres to the second requirement - // but not the first. The RandomAccess implementation will see it and issue sequential - // read/write syscalls per segment, instead of one scatter/gather syscall. - // This test verifies that fallback behavior. - int bufferSize = Environment.SystemPageSize * 2; + // We test with buffers both one and two memory pages long. In the former case, + // the I/O operations will issue one scatter/gather API call, and in the latter + // case they will issue multiple calls; one per buffer. The buffers must still + // be aligned to comply with FILE_FLAG_NO_BUFFERING's requirements. + int bufferSize = Environment.SystemPageSize * (memoryPageSized ? 1 : 2); int fileSize = bufferSize * 2; byte[] content = RandomNumberGenerator.GetBytes(fileSize); @@ -205,10 +204,22 @@ public async Task ReadWriteAsyncUsingNonPageSizedMultipleBuffers() await RandomAccess.WriteAsync(handle, new ReadOnlyMemory[] { firstHalf, secondHalf }, 0); buffer.GetSpan().Clear(); - await RandomAccess.ReadAsync(handle, new Memory[] { firstHalf, secondHalf }, 0); + long nRead = await RandomAccess.ReadAsync(handle, new Memory[] { firstHalf, secondHalf }, 0); + + Assert.Equal(buffer.GetSpan().Length, nRead); + AssertExtensions.SequenceEqual(buffer.GetSpan(), content.AsSpan()); } + } + + [Fact] + public async Task ReadWriteAsyncUsingEmptyBuffers() + { + string filePath = GetTestFilePath(); + using SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, FileOptions.Asynchronous | NoBuffering); - Assert.Equal(content, await File.ReadAllBytesAsync(filePath)); + long nRead = await RandomAccess.ReadAsync(handle, Array.Empty>(), 0); + Assert.Equal(0, nRead); + await RandomAccess.WriteAsync(handle, Array.Empty>(), 0); } // when using FileOptions.Asynchronous we are testing Scatter&Gather APIs on Windows (FILE_FLAG_OVERLAPPED requirement) diff --git a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj index 62245742929df..abf73ff35986c 100644 --- a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj +++ b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj @@ -119,6 +119,7 @@ + diff --git a/src/libraries/System.IO.Ports/pkg/runtime.osx-arm64.runtime.native.System.IO.Ports.proj b/src/libraries/System.IO.Ports/pkg/runtime.osx-arm64.runtime.native.System.IO.Ports.proj new file mode 100644 index 0000000000000..e6410bd635cd2 --- /dev/null +++ b/src/libraries/System.IO.Ports/pkg/runtime.osx-arm64.runtime.native.System.IO.Ports.proj @@ -0,0 +1,7 @@ + + + + + true + + diff --git a/src/libraries/System.IO/System.IO.sln b/src/libraries/System.IO/System.IO.sln index 190c3aa32bae0..e4ba7a8f57e4f 100644 --- a/src/libraries/System.IO/System.IO.sln +++ b/src/libraries/System.IO/System.IO.sln @@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO", "ref\System.IO. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO", "src\System.IO.csproj", "{0769544B-1A5D-4D74-94FD-899DF6C39D62}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO.Net5Compat.Tests", "tests\Net5CompatTests\System.IO.Net5Compat.Tests.csproj", "{0217540D-FA86-41B3-9754-7BB5096ABA3E}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO.Tests", "tests\System.IO.Tests.csproj", "{72923407-7B7B-44A8-BCA6-2DB562835A8F}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServices.Unsafe", "..\System.Runtime.CompilerServices.Unsafe\ref\System.Runtime.CompilerServices.Unsafe.csproj", "{602525FF-EE47-4938-8979-32DC962109E4}" diff --git a/src/libraries/System.IO/tests/Net5CompatTests/System.IO.Net5Compat.Tests.csproj b/src/libraries/System.IO/tests/Net5CompatTests/System.IO.Net5Compat.Tests.csproj deleted file mode 100644 index c07749abe26b0..0000000000000 --- a/src/libraries/System.IO/tests/Net5CompatTests/System.IO.Net5Compat.Tests.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - System.IO - true - true - true - $(NetCoreAppCurrent) - - - - - - - - - - - - - - - - - diff --git a/src/libraries/System.IO/tests/Net5CompatTests/runtimeconfig.template.json b/src/libraries/System.IO/tests/Net5CompatTests/runtimeconfig.template.json deleted file mode 100644 index 6e843517fe47a..0000000000000 --- a/src/libraries/System.IO/tests/Net5CompatTests/runtimeconfig.template.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "configProperties": { - "System.IO.UseNet5CompatFileStream": true - } -} diff --git a/src/libraries/System.Memory/ref/System.Memory.cs b/src/libraries/System.Memory/ref/System.Memory.cs index 1ddd8df16a6b5..a11ae2b6cf15b 100644 --- a/src/libraries/System.Memory/ref/System.Memory.cs +++ b/src/libraries/System.Memory/ref/System.Memory.cs @@ -314,6 +314,7 @@ public void Rewind(long count) { } public bool TryReadTo(out System.ReadOnlySpan span, T delimiter, T delimiterEscape, bool advancePastDelimiter = true) { throw null; } public bool TryReadToAny(out System.Buffers.ReadOnlySequence sequence, System.ReadOnlySpan delimiters, bool advancePastDelimiter = true) { throw null; } public bool TryReadToAny(out System.ReadOnlySpan span, System.ReadOnlySpan delimiters, bool advancePastDelimiter = true) { throw null; } + public bool TryReadExact(int count, out System.Buffers.ReadOnlySequence sequence) { throw null; } } public readonly partial struct StandardFormat : System.IEquatable { diff --git a/src/libraries/System.Memory/src/System/Buffers/SequenceReader.Search.cs b/src/libraries/System.Memory/src/System/Buffers/SequenceReader.Search.cs index af602ae6ae4a2..71a626dd80ed3 100644 --- a/src/libraries/System.Memory/src/System/Buffers/SequenceReader.Search.cs +++ b/src/libraries/System.Memory/src/System/Buffers/SequenceReader.Search.cs @@ -502,6 +502,32 @@ public bool TryReadTo(out ReadOnlySequence sequence, ReadOnlySpan delimite return false; } + /// + /// Try to read data with given . + /// + /// Read count. + /// The read data, if successfully read requested data. + /// true if remaining items in current is enough for . + public bool TryReadExact(int count, out ReadOnlySequence sequence) + { + if (count < 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count); + } + if (count > Remaining) + { + sequence = default; + return false; + } + + sequence = Sequence.Slice(Position, count); + if (count != 0) + { + Advance(count); + } + return true; + } + /// /// Advance until the given , if found. /// diff --git a/src/libraries/System.Memory/tests/SequenceReader/ReadTo.cs b/src/libraries/System.Memory/tests/SequenceReader/ReadTo.cs index 57ceb9e5985cf..b042eb9d556b8 100644 --- a/src/libraries/System.Memory/tests/SequenceReader/ReadTo.cs +++ b/src/libraries/System.Memory/tests/SequenceReader/ReadTo.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Linq; using System.Buffers; using Xunit; @@ -107,6 +108,38 @@ public void TryReadTo_Sequence(bool advancePastDelimiter, bool useEscapeOverload } } + [Fact] + public void TryReadExact_Sequence() + { + ReadOnlySequence data = SequenceFactory.Create(new int[][] { + new int[] { 0 }, + new int[] { 1, 2 }, + new int[] { }, + new int[] { 3, 4 } + }); + + var sequenceReader = new SequenceReader(data); + + Assert.True(sequenceReader.TryReadExact(0, out ReadOnlySequence sequence)); + Assert.Equal(0, sequence.Length); + + for (int i = 0; i < 2; i++) + { + Assert.True(sequenceReader.TryReadExact(2, out sequence)); + Assert.Equal(Enumerable.Range(i * 2, 2), sequence.ToArray()); + } + + // There is only 1 item in sequence reader + Assert.False(sequenceReader.TryReadExact(2, out _)); + + // The last 1 item was not advanced so still can be fetched + Assert.True(sequenceReader.TryReadExact(1, out sequence)); + Assert.Equal(1, sequence.Length); + Assert.Equal(4, sequence.FirstSpan[0]); + + Assert.True(sequenceReader.End); + } + [Theory, InlineData(false), InlineData(true),] diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs index 72051c9d1d800..498b04b0b135a 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs @@ -1305,7 +1305,8 @@ protected override void Dispose(bool disposing) else { // We shouldn't be using a managed instance here, but don't have much choice -- we - // need to remove the stream from the connection's GOAWAY collection. + // need to remove the stream from the connection's GOAWAY collection and properly abort. + stream.AbortStream(); stream._connection.RemoveStream(stream._stream); stream._connection = null!; } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Finalization.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Finalization.cs index e54798becb1d8..0430fdfb7ec3d 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Finalization.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Finalization.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Net.Quic; using System.Net.Test.Common; using System.Runtime.CompilerServices; using System.Threading; @@ -27,9 +28,8 @@ private static Task GetAndDropResponse(HttpClient client, Uri url) [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.SupportsAlpn))] public async Task IncompleteResponseStream_ResponseDropped_CancelsRequestToServer() { - if (UseVersion == HttpVersion30) + if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) { - // [ActiveIssue("https://github.com/dotnet/runtime/issues/58234")] return; } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs index 60abf523ef0a2..66e594c34fca5 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs @@ -283,6 +283,11 @@ private static uint HandleEventShutdownInitiatedByTransport(State state, ref Con state.ConnectTcs = null; } + // To throw QuicConnectionAbortedException (instead of QuicOperationAbortedException) out of AcceptStreamAsync() since + // it wasn't our side who shutdown the connection. + // We should rather keep the Status and propagate it either in a different exception or as a different field of QuicConnectionAbortedException. + // See: https://github.com/dotnet/runtime/issues/60133 + state.AbortErrorCode = 0; state.AcceptQueue.Writer.TryComplete(); return MsQuicStatusCodes.Success; } diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs index 359078e59cd0b..c857ab33a1eee 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs @@ -1933,7 +1933,7 @@ public void SetSocketOption(SocketOptionLevel optionLevel, SocketOptionName opti // Throw an appropriate SocketException if the native call fails. if (errorCode != SocketError.Success) { - UpdateStatusAfterSocketErrorAndThrowException(errorCode); + UpdateStatusAfterSocketOptionErrorAndThrowException(errorCode); } } @@ -2015,7 +2015,7 @@ public void SetRawSocketOption(int optionLevel, int optionName, ReadOnlySpan option if (errorCode != SocketError.Success) { - UpdateStatusAfterSocketErrorAndThrowException(errorCode); + UpdateStatusAfterSocketOptionErrorAndThrowException(errorCode); } return realOptionLength; @@ -3432,7 +3432,7 @@ internal unsafe void SetSocketOption(SocketOptionLevel optionLevel, SocketOption // Throw an appropriate SocketException if the native call fails. if (errorCode != SocketError.Success) { - UpdateStatusAfterSocketErrorAndThrowException(errorCode); + UpdateStatusAfterSocketOptionErrorAndThrowException(errorCode); } } @@ -3445,7 +3445,7 @@ private void SetMulticastOption(SocketOptionName optionName, MulticastOption MR) // Throw an appropriate SocketException if the native call fails. if (errorCode != SocketError.Success) { - UpdateStatusAfterSocketErrorAndThrowException(errorCode); + UpdateStatusAfterSocketOptionErrorAndThrowException(errorCode); } } @@ -3472,7 +3472,7 @@ private void SetLingerOption(LingerOption lref) // Throw an appropriate SocketException if the native call fails. if (errorCode != SocketError.Success) { - UpdateStatusAfterSocketErrorAndThrowException(errorCode); + UpdateStatusAfterSocketOptionErrorAndThrowException(errorCode); } } @@ -3486,7 +3486,7 @@ private void SetLingerOption(LingerOption lref) // Throw an appropriate SocketException if the native call fails. if (errorCode != SocketError.Success) { - UpdateStatusAfterSocketErrorAndThrowException(errorCode); + UpdateStatusAfterSocketOptionErrorAndThrowException(errorCode); } return lingerOption; @@ -3502,7 +3502,7 @@ private void SetLingerOption(LingerOption lref) // Throw an appropriate SocketException if the native call fails. if (errorCode != SocketError.Success) { - UpdateStatusAfterSocketErrorAndThrowException(errorCode); + UpdateStatusAfterSocketOptionErrorAndThrowException(errorCode); } return multicastOption; @@ -3519,7 +3519,7 @@ private void SetLingerOption(LingerOption lref) // Throw an appropriate SocketException if the native call fails. if (errorCode != SocketError.Success) { - UpdateStatusAfterSocketErrorAndThrowException(errorCode); + UpdateStatusAfterSocketOptionErrorAndThrowException(errorCode); } return multicastOption; @@ -3690,11 +3690,19 @@ internal void SetToDisconnected() } } - private void UpdateStatusAfterSocketErrorAndThrowException(SocketError error, [CallerMemberName] string? callerName = null) + private void UpdateStatusAfterSocketOptionErrorAndThrowException(SocketError error, [CallerMemberName] string? callerName = null) + { + // Don't disconnect socket for unknown options. + bool disconnectOnFailure = error != SocketError.ProtocolOption && + error != SocketError.OperationNotSupported; + UpdateStatusAfterSocketErrorAndThrowException(error, disconnectOnFailure, callerName); + } + + private void UpdateStatusAfterSocketErrorAndThrowException(SocketError error, bool disconnectOnFailure = true, [CallerMemberName] string? callerName = null) { // Update the internal state of this socket according to the error before throwing. var socketException = new SocketException((int)error); - UpdateStatusAfterSocketError(socketException); + UpdateStatusAfterSocketError(socketException, disconnectOnFailure); if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, socketException, memberName: callerName); throw socketException; } @@ -3702,18 +3710,18 @@ private void UpdateStatusAfterSocketErrorAndThrowException(SocketError error, [C // UpdateStatusAfterSocketError(socketException) - updates the status of a connected socket // on which a failure occurred. it'll go to winsock and check if the connection // is still open and if it needs to update our internal state. - internal void UpdateStatusAfterSocketError(SocketException socketException) + internal void UpdateStatusAfterSocketError(SocketException socketException, bool disconnectOnFailure = true) { - UpdateStatusAfterSocketError(socketException.SocketErrorCode); + UpdateStatusAfterSocketError(socketException.SocketErrorCode, disconnectOnFailure); } - internal void UpdateStatusAfterSocketError(SocketError errorCode) + internal void UpdateStatusAfterSocketError(SocketError errorCode, bool disconnectOnFailure = true) { // If we already know the socket is disconnected // we don't need to do anything else. - if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, $"errorCode:{errorCode}"); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, $"errorCode:{errorCode}, disconnectOnFailure:{disconnectOnFailure}"); - if (_isConnected && (_handle.IsInvalid || (errorCode != SocketError.WouldBlock && + if (disconnectOnFailure && _isConnected && (_handle.IsInvalid || (errorCode != SocketError.WouldBlock && errorCode != SocketError.IOPending && errorCode != SocketError.NoBufferSpaceAvailable && errorCode != SocketError.TimedOut))) { diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketOptionNameTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketOptionNameTest.cs index e6868e4a6fbeb..5073f60c3e6a1 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketOptionNameTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketOptionNameTest.cs @@ -562,6 +562,132 @@ public void Get_AcceptConnection_Succeeds() } } + [Fact] + public void GetUnsupportedSocketOption_DoesNotDisconnectSocket() + { + (Socket socket1, Socket socket2) = SocketTestExtensions.CreateConnectedSocketPair(); + using (socket1) + using (socket2) + { + SocketException se = Assert.Throws(() => socket1.GetSocketOption(SocketOptionLevel.Socket, (SocketOptionName)(-1))); + Assert.True(se.SocketErrorCode == SocketError.ProtocolOption || + se.SocketErrorCode == SocketError.OperationNotSupported, $"SocketError: {se.SocketErrorCode}"); + + Assert.True(socket1.Connected, "Connected"); + } + } + + [Fact] + public void GetUnsupportedSocketOptionBytesArg_DoesNotDisconnectSocket() + { + (Socket socket1, Socket socket2) = SocketTestExtensions.CreateConnectedSocketPair(); + using (socket1) + using (socket2) + { + var optionValue = new byte[4]; + SocketException se = Assert.Throws(() => socket1.GetSocketOption(SocketOptionLevel.Socket, (SocketOptionName)(-1), optionValue)); + Assert.True(se.SocketErrorCode == SocketError.ProtocolOption || + se.SocketErrorCode == SocketError.OperationNotSupported, $"SocketError: {se.SocketErrorCode}"); + + Assert.True(socket1.Connected, "Connected"); + } + } + + [Fact] + public void GetUnsupportedSocketOptionLengthArg_DoesNotDisconnectSocket() + { + (Socket socket1, Socket socket2) = SocketTestExtensions.CreateConnectedSocketPair(); + using (socket1) + using (socket2) + { + SocketException se = Assert.Throws(() => socket1.GetSocketOption(SocketOptionLevel.Socket, (SocketOptionName)(-1), optionLength: 4)); + Assert.True(se.SocketErrorCode == SocketError.ProtocolOption || + se.SocketErrorCode == SocketError.OperationNotSupported, $"SocketError: {se.SocketErrorCode}"); + + Assert.True(socket1.Connected, "Connected"); + } + } + + [Fact] + public void SetUnsupportedSocketOptionIntArg_DoesNotDisconnectSocket() + { + (Socket socket1, Socket socket2) = SocketTestExtensions.CreateConnectedSocketPair(); + using (socket1) + using (socket2) + { + SocketException se = Assert.Throws(() => socket1.SetSocketOption(SocketOptionLevel.Socket, (SocketOptionName)(-1), optionValue: 1)); + Assert.True(se.SocketErrorCode == SocketError.ProtocolOption || + se.SocketErrorCode == SocketError.OperationNotSupported, $"SocketError: {se.SocketErrorCode}"); + + Assert.True(socket1.Connected, "Connected"); + } + } + + [Fact] + public void SetUnsupportedSocketOptionBytesArg_DoesNotDisconnectSocket() + { + (Socket socket1, Socket socket2) = SocketTestExtensions.CreateConnectedSocketPair(); + using (socket1) + using (socket2) + { + var optionValue = new byte[4]; + SocketException se = Assert.Throws(() => socket1.SetSocketOption(SocketOptionLevel.Socket, (SocketOptionName)(-1), optionValue)); + Assert.True(se.SocketErrorCode == SocketError.ProtocolOption || + se.SocketErrorCode == SocketError.OperationNotSupported, $"SocketError: {se.SocketErrorCode}"); + + Assert.True(socket1.Connected, "Connected"); + } + } + + [Fact] + public void SetUnsupportedSocketOptionBoolArg_DoesNotDisconnectSocket() + { + (Socket socket1, Socket socket2) = SocketTestExtensions.CreateConnectedSocketPair(); + using (socket1) + using (socket2) + { + bool optionValue = true; + SocketException se = Assert.Throws(() => socket1.SetSocketOption(SocketOptionLevel.Socket, (SocketOptionName)(-1), optionValue)); + Assert.True(se.SocketErrorCode == SocketError.ProtocolOption || + se.SocketErrorCode == SocketError.OperationNotSupported, $"SocketError: {se.SocketErrorCode}"); + + Assert.True(socket1.Connected, "Connected"); + } + } + + [Fact] + public void GetUnsupportedRawSocketOption_DoesNotDisconnectSocket() + { + (Socket socket1, Socket socket2) = SocketTestExtensions.CreateConnectedSocketPair(); + using (socket1) + using (socket2) + { + var optionValue = new byte[4]; + SocketException se = Assert.Throws(() => socket1.GetRawSocketOption(SOL_SOCKET, -1, optionValue)); + Assert.True(se.SocketErrorCode == SocketError.ProtocolOption || + se.SocketErrorCode == SocketError.OperationNotSupported, $"SocketError: {se.SocketErrorCode}"); + + Assert.True(socket1.Connected, "Connected"); + } + } + + [Fact] + public void SetUnsupportedRawSocketOption_DoesNotDisconnectSocket() + { + (Socket socket1, Socket socket2) = SocketTestExtensions.CreateConnectedSocketPair(); + using (socket1) + using (socket2) + { + var optionValue = new byte[4]; + SocketException se = Assert.Throws(() => socket1.SetRawSocketOption(SOL_SOCKET, -1, optionValue)); + Assert.True(se.SocketErrorCode == SocketError.ProtocolOption || + se.SocketErrorCode == SocketError.OperationNotSupported, $"SocketError: {se.SocketErrorCode}"); + + Assert.True(socket1.Connected, "Connected"); + } + } + + private static int SOL_SOCKET = OperatingSystem.IsLinux() ? 1 : (int)SocketOptionLevel.Socket; } [Collection("NoParallelTests")] diff --git a/src/libraries/System.Net.WebSockets.Client/tests/CancelTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/CancelTest.cs index 9e400c3f723a9..752ca8ece8189 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/CancelTest.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/CancelTest.cs @@ -22,7 +22,7 @@ public async Task ConnectAsync_Cancel_ThrowsCancellationException(Uri server) var cts = new CancellationTokenSource(100); var ub = new UriBuilder(server); - ub.Query = "delay20sec"; + ub.Query = PlatformDetection.IsBrowser ? "delay20sec" : "delay10sec"; var ex = await Assert.ThrowsAnyAsync(() => cws.ConnectAsync(ub.Uri, cts.Token)); Assert.True(WebSocketState.Closed == cws.State, $"Actual {cws.State} when {ex}"); diff --git a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs index f861739278f95..556e6672b806c 100644 --- a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs @@ -958,8 +958,10 @@ private void TestToString(string format, IFormatProvider provider) where T : [Fact] public void AdditionInt64() { TestAddition(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AdditionSingle() { TestAddition(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AdditionDouble() { TestAddition(); } private void TestAddition() where T : struct { @@ -1023,8 +1025,10 @@ private void TestAdditionOverflow() where T : struct [Fact] public void SubtractionInt64() { TestSubtraction(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void SubtractionSingle() { TestSubtraction(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void SubtractionDouble() { TestSubtraction(); } private void TestSubtraction() where T : struct { @@ -1088,8 +1092,10 @@ private void TestSubtractionOverflow() where T : struct [Fact] public void MultiplicationInt64() { TestMultiplication(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationSingle() { TestMultiplication(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationDouble() { TestMultiplication(); } private void TestMultiplication() where T : struct { @@ -1122,8 +1128,10 @@ private void TestMultiplication() where T : struct [Fact] public void MultiplicationWithScalarInt64() { TestMultiplicationWithScalar(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationWithScalarSingle() { TestMultiplicationWithScalar(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationWithScalarDouble() { TestMultiplicationWithScalar(); } private void TestMultiplicationWithScalar() where T : struct { @@ -1164,8 +1172,10 @@ private void TestMultiplicationWithScalar() where T : struct [Fact] public void DivisionInt64() { TestDivision(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionSingle() { TestDivision(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionDouble() { TestDivision(); } private void TestDivision() where T : struct { @@ -1224,8 +1234,10 @@ private void TestDivisionByZeroException() where T : struct [Fact] public void UnaryMinusInt64() { TestUnaryMinus(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void UnaryMinusSingle() { TestUnaryMinus(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void UnaryMinusDouble() { TestUnaryMinus(); } private void TestUnaryMinus() where T : struct { @@ -1424,8 +1436,10 @@ private void TestBitwiseAndNot() where T : struct [Fact] public void VectorGreaterThanInt64() { TestVectorGreaterThan(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void VectorGreaterThanSingle() { TestVectorGreaterThan(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void VectorGreaterThanDouble() { TestVectorGreaterThan(); } private void TestVectorGreaterThan() where T : struct { @@ -1461,8 +1475,10 @@ private void TestVectorGreaterThan() where T : struct [Fact] public void GreaterThanOrEqualInt64() { TestVectorGreaterThanOrEqual(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void GreaterThanOrEqualSingle() { TestVectorGreaterThanOrEqual(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void GreaterThanOrEqualDouble() { TestVectorGreaterThanOrEqual(); } private void TestVectorGreaterThanOrEqual() where T : struct { @@ -1714,8 +1730,10 @@ private void TestVectorGreaterThanOrEqualAll() where T : struct [Fact] public void LessThanInt64() { TestVectorLessThan(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanSingle() { TestVectorLessThan(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanDouble() { TestVectorLessThan(); } private void TestVectorLessThan() where T : struct { @@ -1751,8 +1769,10 @@ private void TestVectorLessThan() where T : struct [Fact] public void LessThanOrEqualInt64() { TestVectorLessThanOrEqual(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanOrEqualSingle() { TestVectorLessThanOrEqual(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanOrEqualDouble() { TestVectorLessThanOrEqual(); } private void TestVectorLessThanOrEqual() where T : struct { @@ -1788,8 +1808,10 @@ private void TestVectorLessThanOrEqual() where T : struct [Fact] public void LessThanAnyInt64() { TestVectorLessThanAny(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanAnySingle() { TestVectorLessThanAny(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanAnyDouble() { TestVectorLessThanAny(); } private void TestVectorLessThanAny() where T : struct { @@ -2114,8 +2136,10 @@ private void TestVectorEqualsAll() where T : struct [Fact] public void ConditionalSelectInt64() { TestConditionalSelect(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void ConditionalSelectSingle() { TestConditionalSelect(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void ConditionalSelectDouble() { TestConditionalSelect(); } private void TestConditionalSelect() where T : struct { @@ -2166,8 +2190,10 @@ private void TestConditionalSelect() where T : struct [Fact] public void DotProductInt64() { TestDotProduct(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DotProductSingle() { TestDotProduct(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DotProductDouble() { TestDotProduct(); } private void TestDotProduct() where T : struct { @@ -2202,8 +2228,10 @@ private void TestDotProduct() where T : struct [Fact] public void MaxInt64() { TestMax(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MaxSingle() { TestMax(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MaxDouble() { TestMax(); } private void TestMax() where T : struct { @@ -2238,8 +2266,10 @@ private void TestMax() where T : struct [Fact] public void MinInt64() { TestMin(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MinSingle() { TestMin(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MinDouble() { TestMin(); } private void TestMin() where T : struct { @@ -2274,8 +2304,10 @@ private void TestMin() where T : struct [Fact] public void SquareRootInt64() { TestSquareRoot(-1); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void SquareRootSingle() { TestSquareRoot(6); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void SquareRootDouble() { TestSquareRoot(15); } private void TestSquareRoot(int precision = -1) where T : struct, IEquatable { @@ -2368,8 +2400,10 @@ public void FloorDouble() [Fact] public void AbsInt64() { TestAbs(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AbsSingle() { TestAbs(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AbsDouble() { TestAbs(); } private void TestAbs() where T : struct { @@ -2406,8 +2440,10 @@ private void TestAbs() where T : struct [Fact] public void MultiplicationReflectionInt64() { TestMultiplicationReflection(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationReflectionSingle() { TestMultiplicationReflection(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationReflectionDouble() { TestMultiplicationReflection(); } private void TestMultiplicationReflection() where T : struct { @@ -2443,8 +2479,10 @@ private void TestMultiplicationReflection() where T : struct [Fact] public void AdditionReflectionInt64() { TestAdditionReflection(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AdditionReflectionSingle() { TestAdditionReflection(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AdditionReflectionDouble() { TestAdditionReflection(); } private void TestAdditionReflection() where T : struct { @@ -2480,8 +2518,10 @@ private void TestAdditionReflection() where T : struct [Fact] public void DivisionReflectionInt64() { TestDivisionReflection(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionReflectionSingle() { TestDivisionReflection(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionReflectionDouble() { TestDivisionReflection(); } private void TestDivisionReflection() where T : struct { diff --git a/src/libraries/System.Numerics.Vectors/tests/Util.cs b/src/libraries/System.Numerics.Vectors/tests/Util.cs index 4fb55a716afd1..135b3fc0e65e4 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Util.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Util.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Linq; - namespace System.Numerics.Tests { public static class Util @@ -93,57 +91,150 @@ public static T GenerateSingleValue(int min = 1, int max = 100) where T : str public static T Abs(T value) where T : struct { - Type[] unsignedTypes = new[] { typeof(byte), typeof(ushort), typeof(uint), typeof(ulong) }; - if (unsignedTypes.Contains(typeof(T))) - { - return value; - } - - dynamic dyn = (dynamic)value; - var abs = Math.Abs(dyn); - T ret = (T)abs; - return ret; + // unsigned types + if (value is byte) return value; + else if (value is ushort) return value; + else if (value is uint) return value; + else if (value is ulong) return value; + // signed types + else if (value is short) return (T)(ValueType)(short) ( Math.Abs((short) (ValueType)value) ); + else if (value is int) return (T)(ValueType)(int) ( Math.Abs((int) (ValueType)value) ); + else if (value is long) return (T)(ValueType)(long) ( Math.Abs((long) (ValueType)value) ); + else if (value is sbyte) return (T)(ValueType)(sbyte) ( Math.Abs((sbyte) (ValueType)value) ); + else if (value is float) return (T)(ValueType)(float) ( Math.Abs((float) (ValueType)value) ); + else if (value is double) return (T)(ValueType)(double) ( Math.Abs((double)(ValueType)value) ); + else throw new NotImplementedException(); } public static T Sqrt(T value) where T : struct { - return unchecked((T)(dynamic)(Math.Sqrt((dynamic)value))); + unchecked + { + if (value is short) return (T)(ValueType)(short) ( Math.Sqrt((short) (ValueType)value) ); + else if (value is int) return (T)(ValueType)(int) ( Math.Sqrt((int) (ValueType)value) ); + else if (value is long) return (T)(ValueType)(long) ( Math.Sqrt((long) (ValueType)value) ); + else if (value is ushort) return (T)(ValueType)(ushort) ( Math.Sqrt((ushort)(ValueType)value) ); + else if (value is uint) return (T)(ValueType)(uint) ( Math.Sqrt((uint) (ValueType)value) ); + else if (value is ulong) return (T)(ValueType)(ulong) ( Math.Sqrt((ulong) (ValueType)value) ); + else if (value is byte) return (T)(ValueType)(byte) ( Math.Sqrt((byte) (ValueType)value) ); + else if (value is sbyte) return (T)(ValueType)(sbyte) ( Math.Sqrt((sbyte) (ValueType)value) ); + else if (value is float) return (T)(ValueType)(float) ( Math.Sqrt((float) (ValueType)value) ); + else if (value is double) return (T)(ValueType)(double) ( Math.Sqrt((double)(ValueType)value) ); + else throw new NotImplementedException(); + } } public static T Multiply(T left, T right) where T : struct { - return unchecked((T)((dynamic)left * right)); + unchecked + { + if (left is short) return (T)(ValueType)(short) ( (short) (ValueType)left * (short) (ValueType)right ); + else if (left is int) return (T)(ValueType)(int) ( (int) (ValueType)left * (int) (ValueType)right ); + else if (left is long) return (T)(ValueType)(long) ( (long) (ValueType)left * (long) (ValueType)right ); + else if (left is ushort) return (T)(ValueType)(ushort) ( (ushort)(ValueType)left * (ushort)(ValueType)right ); + else if (left is uint) return (T)(ValueType)(uint) ( (uint) (ValueType)left * (uint) (ValueType)right ); + else if (left is ulong) return (T)(ValueType)(ulong) ( (ulong) (ValueType)left * (ulong) (ValueType)right ); + else if (left is byte) return (T)(ValueType)(byte) ( (byte) (ValueType)left * (byte) (ValueType)right ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( (sbyte) (ValueType)left * (sbyte) (ValueType)right ); + else if (left is float) return (T)(ValueType)(float) ( (float) (ValueType)left * (float) (ValueType)right ); + else if (left is double) return (T)(ValueType)(double) ( (double)(ValueType)left * (double)(ValueType)right ); + else throw new NotImplementedException(); + } } public static T Divide(T left, T right) where T : struct { - return (T)((dynamic)left / right); + if (left is short) return (T)(ValueType)(short) ( (short) (ValueType)left / (short) (ValueType)right ); + else if (left is int) return (T)(ValueType)(int) ( (int) (ValueType)left / (int) (ValueType)right ); + else if (left is long) return (T)(ValueType)(long) ( (long) (ValueType)left / (long) (ValueType)right ); + else if (left is ushort) return (T)(ValueType)(ushort) ( (ushort)(ValueType)left / (ushort)(ValueType)right ); + else if (left is uint) return (T)(ValueType)(uint) ( (uint) (ValueType)left / (uint) (ValueType)right ); + else if (left is ulong) return (T)(ValueType)(ulong) ( (ulong) (ValueType)left / (ulong) (ValueType)right ); + else if (left is byte) return (T)(ValueType)(byte) ( (byte) (ValueType)left / (byte) (ValueType)right ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( (sbyte) (ValueType)left / (sbyte) (ValueType)right ); + else if (left is float) return (T)(ValueType)(float) ( (float) (ValueType)left / (float) (ValueType)right ); + else if (left is double) return (T)(ValueType)(double) ( (double)(ValueType)left / (double)(ValueType)right ); + else throw new NotImplementedException(); } public static T Add(T left, T right) where T : struct { - return unchecked((T)((dynamic)left + right)); + unchecked + { + if (left is short) return (T)(ValueType)(short) ( (short) (ValueType)left + (short) (ValueType)right ); + else if (left is int) return (T)(ValueType)(int) ( (int) (ValueType)left + (int) (ValueType)right ); + else if (left is long) return (T)(ValueType)(long) ( (long) (ValueType)left + (long) (ValueType)right ); + else if (left is ushort) return (T)(ValueType)(ushort) ( (ushort)(ValueType)left + (ushort)(ValueType)right ); + else if (left is uint) return (T)(ValueType)(uint) ( (uint) (ValueType)left + (uint) (ValueType)right ); + else if (left is ulong) return (T)(ValueType)(ulong) ( (ulong) (ValueType)left + (ulong) (ValueType)right ); + else if (left is byte) return (T)(ValueType)(byte) ( (byte) (ValueType)left + (byte) (ValueType)right ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( (sbyte) (ValueType)left + (sbyte) (ValueType)right ); + else if (left is float) return (T)(ValueType)(float) ( (float) (ValueType)left + (float) (ValueType)right ); + else if (left is double) return (T)(ValueType)(double) ( (double)(ValueType)left + (double)(ValueType)right ); + else throw new NotImplementedException(); + } } public static T Subtract(T left, T right) where T : struct { - return unchecked((T)((dynamic)left - right)); + unchecked + { + if (left is short) return (T)(ValueType)(short) ( (short) (ValueType)left - (short) (ValueType)right ); + else if (left is int) return (T)(ValueType)(int) ( (int) (ValueType)left - (int) (ValueType)right ); + else if (left is long) return (T)(ValueType)(long) ( (long) (ValueType)left - (long) (ValueType)right ); + else if (left is ushort) return (T)(ValueType)(ushort) ( (ushort)(ValueType)left - (ushort)(ValueType)right ); + else if (left is uint) return (T)(ValueType)(uint) ( (uint) (ValueType)left - (uint) (ValueType)right ); + else if (left is ulong) return (T)(ValueType)(ulong) ( (ulong) (ValueType)left - (ulong) (ValueType)right ); + else if (left is byte) return (T)(ValueType)(byte) ( (byte) (ValueType)left - (byte) (ValueType)right ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( (sbyte) (ValueType)left - (sbyte) (ValueType)right ); + else if (left is float) return (T)(ValueType)(float) ( (float) (ValueType)left - (float) (ValueType)right ); + else if (left is double) return (T)(ValueType)(double) ( (double)(ValueType)left - (double)(ValueType)right ); + else throw new NotImplementedException(); + } } public static T Xor(T left, T right) where T : struct { - return (T)((dynamic)left ^ right); + if (left is short) return (T)(ValueType)(short) ( (short) (ValueType)left ^ (short) (ValueType)right ); + else if (left is int) return (T)(ValueType)(int) ( (int) (ValueType)left ^ (int) (ValueType)right ); + else if (left is long) return (T)(ValueType)(long) ( (long) (ValueType)left ^ (long) (ValueType)right ); + else if (left is ushort) return (T)(ValueType)(ushort) ( (ushort)(ValueType)left ^ (ushort)(ValueType)right ); + else if (left is uint) return (T)(ValueType)(uint) ( (uint) (ValueType)left ^ (uint) (ValueType)right ); + else if (left is ulong) return (T)(ValueType)(ulong) ( (ulong) (ValueType)left ^ (ulong) (ValueType)right ); + else if (left is byte) return (T)(ValueType)(byte) ( (byte) (ValueType)left ^ (byte) (ValueType)right ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( (sbyte) (ValueType)left ^ (sbyte) (ValueType)right ); + else throw new NotImplementedException(); } public static T AndNot(T left, T right) where T : struct { - return (T)((dynamic)left & ~(dynamic)right); + if (left is short) return (T)(ValueType)(short) ( (short) (ValueType)left & ~(short) (ValueType)right ); + else if (left is int) return (T)(ValueType)(int) ( (int) (ValueType)left & ~(int) (ValueType)right ); + else if (left is long) return (T)(ValueType)(long) ( (long) (ValueType)left & ~(long) (ValueType)right ); + else if (left is ushort) return (T)(ValueType)(ushort) ( (ushort)(ValueType)left & ~(ushort)(ValueType)right ); + else if (left is uint) return (T)(ValueType)(uint) ( (uint) (ValueType)left & ~(uint) (ValueType)right ); + else if (left is ulong) return (T)(ValueType)(ulong) ( (ulong) (ValueType)left & ~(ulong) (ValueType)right ); + else if (left is byte) return (T)(ValueType)(byte) ( (byte) (ValueType)left & ~(byte) (ValueType)right ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( (sbyte) (ValueType)left & ~(sbyte) (ValueType)right ); + else throw new NotImplementedException(); } public static T OnesComplement(T left) where T : struct { - return unchecked((T)(~(dynamic)left)); + unchecked + { + if (left is short) return (T)(ValueType)(short) ( ~(short) (ValueType)left ); + else if (left is int) return (T)(ValueType)(int) ( ~(int) (ValueType)left ); + else if (left is long) return (T)(ValueType)(long) ( ~(long) (ValueType)left ); + else if (left is ushort) return (T)(ValueType)(ushort) ( ~(ushort)(ValueType)left ); + else if (left is uint) return (T)(ValueType)(uint) ( ~(uint) (ValueType)left ); + else if (left is ulong) return (T)(ValueType)(ulong) ( ~(ulong) (ValueType)left ); + else if (left is byte) return (T)(ValueType)(byte) ( ~(byte) (ValueType)left ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( ~(sbyte) (ValueType)left ); + else throw new NotImplementedException(); + } } + public static float Clamp(float value, float min, float max) { return value > max ? max : value < min ? min : value; @@ -151,36 +242,92 @@ public static float Clamp(float value, float min, float max) public static T Zero() where T : struct { - return (T)(dynamic)0; + if (typeof(T) == typeof(short)) return (T)(ValueType)(short) 0; + else if (typeof(T) == typeof(int)) return (T)(ValueType)(int) 0; + else if (typeof(T) == typeof(long)) return (T)(ValueType)(long) 0; + else if (typeof(T) == typeof(ushort)) return (T)(ValueType)(ushort) 0; + else if (typeof(T) == typeof(uint)) return (T)(ValueType)(uint) 0; + else if (typeof(T) == typeof(ulong)) return (T)(ValueType)(ulong) 0; + else if (typeof(T) == typeof(byte)) return (T)(ValueType)(byte) 0; + else if (typeof(T) == typeof(sbyte)) return (T)(ValueType)(sbyte) 0; + else if (typeof(T) == typeof(float)) return (T)(ValueType)(float) 0; + else if (typeof(T) == typeof(double)) return (T)(ValueType)(double) 0; + else throw new NotImplementedException(); } public static T One() where T : struct { - return (T)(dynamic)1; + if (typeof(T) == typeof(short)) return (T)(ValueType)(short) 1; + else if (typeof(T) == typeof(int)) return (T)(ValueType)(int) 1; + else if (typeof(T) == typeof(long)) return (T)(ValueType)(long) 1; + else if (typeof(T) == typeof(ushort)) return (T)(ValueType)(ushort) 1; + else if (typeof(T) == typeof(uint)) return (T)(ValueType)(uint) 1; + else if (typeof(T) == typeof(ulong)) return (T)(ValueType)(ulong) 1; + else if (typeof(T) == typeof(byte)) return (T)(ValueType)(byte) 1; + else if (typeof(T) == typeof(sbyte)) return (T)(ValueType)(sbyte) 1; + else if (typeof(T) == typeof(float)) return (T)(ValueType)(float) 1; + else if (typeof(T) == typeof(double)) return (T)(ValueType)(double) 1; + else throw new NotImplementedException(); } public static bool GreaterThan(T left, T right) where T : struct { - var result = (dynamic)left > right; - return (bool)result; + if (left is short) return (short)(ValueType) left > (short)(ValueType) right; + else if (left is int) return (int)(ValueType) left > (int)(ValueType) right; + else if (left is long) return (long)(ValueType) left > (long)(ValueType) right; + else if (left is ushort) return (ushort)(ValueType) left > (ushort)(ValueType) right; + else if (left is uint) return (uint)(ValueType) left > (uint)(ValueType) right; + else if (left is ulong) return (ulong)(ValueType) left > (ulong)(ValueType) right; + else if (left is byte) return (byte)(ValueType) left > (byte)(ValueType) right; + else if (left is sbyte) return (sbyte)(ValueType) left > (sbyte)(ValueType) right; + else if (left is float) return (float)(ValueType) left > (float)(ValueType) right; + else if (left is double) return (double)(ValueType) left > (double)(ValueType) right; + else throw new NotImplementedException(); } public static bool GreaterThanOrEqual(T left, T right) where T : struct { - var result = (dynamic)left >= right; - return (bool)result; + if (left is short) return (short)(ValueType) left >= (short)(ValueType) right; + else if (left is int) return (int)(ValueType) left >= (int)(ValueType) right; + else if (left is long) return (long)(ValueType) left >= (long)(ValueType) right; + else if (left is ushort) return (ushort)(ValueType) left >= (ushort)(ValueType) right; + else if (left is uint) return (uint)(ValueType) left >= (uint)(ValueType) right; + else if (left is ulong) return (ulong)(ValueType) left >= (ulong)(ValueType) right; + else if (left is byte) return (byte)(ValueType) left >= (byte)(ValueType) right; + else if (left is sbyte) return (sbyte)(ValueType) left >= (sbyte)(ValueType) right; + else if (left is float) return (float)(ValueType) left >= (float)(ValueType) right; + else if (left is double) return (double)(ValueType) left >= (double)(ValueType) right; + else throw new NotImplementedException(); } public static bool LessThan(T left, T right) where T : struct { - var result = (dynamic)left < right; - return (bool)result; + if (left is short) return (short)(ValueType) left < (short)(ValueType) right; + else if (left is int) return (int)(ValueType) left < (int)(ValueType) right; + else if (left is long) return (long)(ValueType) left < (long)(ValueType) right; + else if (left is ushort) return (ushort)(ValueType) left < (ushort)(ValueType) right; + else if (left is uint) return (uint)(ValueType) left < (uint)(ValueType) right; + else if (left is ulong) return (ulong)(ValueType) left < (ulong)(ValueType) right; + else if (left is byte) return (byte)(ValueType) left < (byte)(ValueType) right; + else if (left is sbyte) return (sbyte)(ValueType) left < (sbyte)(ValueType) right; + else if (left is float) return (float)(ValueType) left < (float)(ValueType) right; + else if (left is double) return (double)(ValueType) left < (double)(ValueType) right; + else throw new NotImplementedException(); } public static bool LessThanOrEqual(T left, T right) where T : struct { - var result = (dynamic)left <= right; - return (bool)result; + if (left is short) return (short)(ValueType) left <= (short)(ValueType) right; + else if (left is int) return (int)(ValueType) left <= (int)(ValueType) right; + else if (left is long) return (long)(ValueType) left <= (long)(ValueType) right; + else if (left is ushort) return (ushort)(ValueType) left <= (ushort)(ValueType) right; + else if (left is uint) return (uint)(ValueType) left <= (uint)(ValueType) right; + else if (left is ulong) return (ulong)(ValueType) left <= (ulong)(ValueType) right; + else if (left is byte) return (byte)(ValueType) left <= (byte)(ValueType) right; + else if (left is sbyte) return (sbyte)(ValueType) left <= (sbyte)(ValueType) right; + else if (left is float) return (float)(ValueType) left <= (float)(ValueType) right; + else if (left is double) return (double)(ValueType) left <= (double)(ValueType) right; + else throw new NotImplementedException(); } public static bool AnyEqual(T[] left, T[] right) where T : struct diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs index 9f689b161bbd0..c2eab851bd60e 100644 --- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs @@ -86,8 +86,11 @@ internal static Exception GetIOError(int errorCode, string? path) _bufferSize = memory.Length; _memoryHandle = memory.Pin(); _overlapped = _fileHandle.ThreadPoolBinding!.AllocateNativeOverlapped(_preallocatedOverlapped); - _overlapped->OffsetLow = (int)fileOffset; - _overlapped->OffsetHigh = (int)(fileOffset >> 32); + if (_fileHandle.CanSeek) + { + _overlapped->OffsetLow = (int)fileOffset; + _overlapped->OffsetHigh = (int)(fileOffset >> 32); + } return _overlapped; } diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs index 9b38d148b2693..13847032fbec7 100644 --- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs @@ -16,6 +16,7 @@ public sealed partial class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid // not using bool? as it's not thread safe private volatile NullableBool _canSeek = NullableBool.Undefined; + private volatile NullableBool _supportsRandomAccess = NullableBool.Undefined; private bool _deleteOnClose; private bool _isLocked; @@ -33,6 +34,25 @@ private SafeFileHandle(bool ownsHandle) internal bool CanSeek => !IsClosed && GetCanSeek(); + internal bool SupportsRandomAccess + { + get + { + NullableBool supportsRandomAccess = _supportsRandomAccess; + if (supportsRandomAccess == NullableBool.Undefined) + { + _supportsRandomAccess = supportsRandomAccess = GetCanSeek() ? NullableBool.True : NullableBool.False; + } + + return supportsRandomAccess == NullableBool.True; + } + set + { + Debug.Assert(value == false); // We should only use the setter to disable random access. + _supportsRandomAccess = value ? NullableBool.True : NullableBool.False; + } + } + internal ThreadPoolBoundHandle? ThreadPoolBinding => null; internal void EnsureThreadPoolBindingInitialized() { /* nop */ } diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 867e13262ba6a..68f5c3af638c5 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -462,7 +462,6 @@ - @@ -1846,8 +1845,6 @@ - - @@ -2136,7 +2133,6 @@ - diff --git a/src/libraries/System.Private.CoreLib/src/System/Byte.cs b/src/libraries/System.Private.CoreLib/src/System/Byte.cs index 5e047136ae753..a22d6ff385c08 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Byte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Byte.cs @@ -285,11 +285,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IAdditionOperators.operator +(byte left, byte right) => (byte)(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IAdditionOperators.operator +(byte left, byte right) // => checked((byte)(left + right)); @@ -297,30 +297,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBinaryInteger.LeadingZeroCount(byte value) => (byte)(BitOperations.LeadingZeroCount(value) - 24); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBinaryInteger.PopCount(byte value) => (byte)BitOperations.PopCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBinaryInteger.RotateLeft(byte value, int rotateAmount) => (byte)((value << (rotateAmount & 7)) | (value >> ((8 - rotateAmount) & 7))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBinaryInteger.RotateRight(byte value, int rotateAmount) => (byte)((value >> (rotateAmount & 7)) | (value << ((8 - rotateAmount) & 7))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBinaryInteger.TrailingZeroCount(byte value) => (byte)(BitOperations.TrailingZeroCount(value << 24) - 24); @@ -328,11 +328,11 @@ static byte IBinaryInteger.TrailingZeroCount(byte value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(byte value) => BitOperations.IsPow2((uint)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBinaryNumber.Log2(byte value) => (byte)BitOperations.Log2(value); @@ -340,19 +340,19 @@ static byte IBinaryNumber.Log2(byte value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBitwiseOperators.operator &(byte left, byte right) => (byte)(left & right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBitwiseOperators.operator |(byte left, byte right) => (byte)(left | right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBitwiseOperators.operator ^(byte left, byte right) => (byte)(left ^ right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBitwiseOperators.operator ~(byte value) => (byte)(~value); @@ -360,19 +360,19 @@ static byte IBinaryNumber.Log2(byte value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(byte left, byte right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(byte left, byte right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(byte left, byte right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(byte left, byte right) => left >= right; @@ -380,11 +380,11 @@ static byte IBinaryNumber.Log2(byte value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IDecrementOperators.operator --(byte value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IDecrementOperators.operator --(byte value) // => checked(--value); @@ -392,11 +392,11 @@ static byte IBinaryNumber.Log2(byte value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IDivisionOperators.operator /(byte left, byte right) => (byte)(left / right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IDivisionOperators.operator /(byte left, byte right) // => checked((byte)(left / right)); @@ -404,11 +404,11 @@ static byte IBinaryNumber.Log2(byte value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(byte left, byte right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(byte left, byte right) => left != right; @@ -416,11 +416,11 @@ static byte IBinaryNumber.Log2(byte value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IIncrementOperators.operator ++(byte value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IIncrementOperators.operator ++(byte value) // => checked(++value); @@ -428,21 +428,21 @@ static byte IBinaryNumber.Log2(byte value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IModulusOperators.operator %(byte left, byte right) => (byte)(left % right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IModulusOperators.operator %(byte left, byte right) // => checked((byte)(left % right)); @@ -450,18 +450,18 @@ static byte IBinaryNumber.Log2(byte value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IMultiplyOperators.operator *(byte left, byte right) => (byte)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IMultiplyOperators.operator *(byte left, byte right) // => checked((byte)(left * right)); @@ -469,21 +469,21 @@ static byte IBinaryNumber.Log2(byte value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Abs(byte value) => value; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Clamp(byte value, byte min, byte max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static byte INumber.Create(TOther value) { @@ -550,7 +550,7 @@ static byte INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static byte INumber.CreateSaturating(TOther value) { @@ -637,7 +637,7 @@ static byte INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static byte INumber.CreateTruncating(TOther value) { @@ -704,31 +704,31 @@ static byte INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (byte Quotient, byte Remainder) INumber.DivRem(byte left, byte right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Max(byte x, byte y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Min(byte x, byte y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Sign(byte value) => (byte)((value == 0) ? 0 : 1); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out byte result) { @@ -914,11 +914,11 @@ static bool INumber.TryCreate(TOther value, out byte result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out byte result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out byte result) => TryParse(s, style, provider, out result); @@ -926,11 +926,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFo // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out byte result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -938,15 +938,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IShiftOperators.operator <<(byte value, int shiftAmount) => (byte)(value << shiftAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IShiftOperators.operator >>(byte value, int shiftAmount) => (byte)(value >> shiftAmount); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static byte IShiftOperators.operator >>>(byte value, int shiftAmount) // => (byte)(value >> shiftAmount); @@ -954,11 +954,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out byte result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -966,11 +966,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte ISubtractionOperators.operator -(byte left, byte right) => (byte)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte ISubtractionOperators.operator -(byte left, byte right) // => checked((byte)(left - right)); @@ -978,11 +978,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IUnaryNegationOperators.operator -(byte value) => (byte)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IUnaryNegationOperators.operator -(byte value) // => checked((byte)(-value)); @@ -990,11 +990,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IUnaryPlusOperators.operator +(byte value) => (byte)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IUnaryPlusOperators.operator +(byte value) // => checked((byte)(+value)); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Char.cs b/src/libraries/System.Private.CoreLib/src/System/Char.cs index 486e7e5d5d7d6..7ee503eb793a1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Char.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Char.cs @@ -1065,11 +1065,11 @@ public static int ConvertToUtf32(string s, int index) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IAdditionOperators.operator +(char left, char right) => (char)(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IAdditionOperators.operator +(char left, char right) // => checked((char)(left + right)); @@ -1077,30 +1077,30 @@ public static int ConvertToUtf32(string s, int index) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IAdditiveIdentity.AdditiveIdentity => (char)0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBinaryInteger.LeadingZeroCount(char value) => (char)(BitOperations.LeadingZeroCount(value) - 16); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBinaryInteger.PopCount(char value) => (char)BitOperations.PopCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBinaryInteger.RotateLeft(char value, int rotateAmount) => (char)((value << (rotateAmount & 15)) | (value >> ((16 - rotateAmount) & 15))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBinaryInteger.RotateRight(char value, int rotateAmount) => (char)((value >> (rotateAmount & 15)) | (value << ((16 - rotateAmount) & 15))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBinaryInteger.TrailingZeroCount(char value) => (char)(BitOperations.TrailingZeroCount(value << 16) - 16); @@ -1108,11 +1108,11 @@ static char IBinaryInteger.TrailingZeroCount(char value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(char value) => BitOperations.IsPow2((uint)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBinaryNumber.Log2(char value) => (char)BitOperations.Log2(value); @@ -1120,19 +1120,19 @@ static char IBinaryNumber.Log2(char value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBitwiseOperators.operator &(char left, char right) => (char)(left & right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBitwiseOperators.operator |(char left, char right) => (char)(left | right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBitwiseOperators.operator ^(char left, char right) => (char)(left ^ right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBitwiseOperators.operator ~(char value) => (char)(~value); @@ -1140,19 +1140,19 @@ static char IBinaryNumber.Log2(char value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(char left, char right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(char left, char right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(char left, char right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(char left, char right) => left >= right; @@ -1160,11 +1160,11 @@ static char IBinaryNumber.Log2(char value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IDecrementOperators.operator --(char value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IDecrementOperators.operator --(char value) // => checked(--value); @@ -1172,11 +1172,11 @@ static char IBinaryNumber.Log2(char value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IDivisionOperators.operator /(char left, char right) => (char)(left / right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IDivisionOperators.operator /(char left, char right) // => checked((char)(left / right)); @@ -1184,11 +1184,11 @@ static char IBinaryNumber.Log2(char value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(char left, char right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(char left, char right) => left != right; @@ -1196,11 +1196,11 @@ static char IBinaryNumber.Log2(char value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IIncrementOperators.operator ++(char value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IIncrementOperators.operator ++(char value) // => checked(++value); @@ -1208,21 +1208,21 @@ static char IBinaryNumber.Log2(char value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IModulusOperators.operator %(char left, char right) => (char)(left % right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IModulusOperators.operator %(char left, char right) // => checked((char)(left % right)); @@ -1230,18 +1230,18 @@ static char IBinaryNumber.Log2(char value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IMultiplicativeIdentity.MultiplicativeIdentity => (char)1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IMultiplyOperators.operator *(char left, char right) => (char)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IMultiplyOperators.operator *(char left, char right) // => checked((char)(left * right)); @@ -1249,21 +1249,21 @@ static char IBinaryNumber.Log2(char value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.One => (char)1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Zero => (char)0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Abs(char value) => value; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Clamp(char value, char min, char max) => (char)Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static char INumber.Create(TOther value) { @@ -1330,7 +1330,7 @@ static char INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static char INumber.CreateSaturating(TOther value) { @@ -1414,7 +1414,7 @@ static char INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static char INumber.CreateTruncating(TOther value) { @@ -1481,23 +1481,23 @@ static char INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (char Quotient, char Remainder) INumber.DivRem(char left, char right) => ((char, char))Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Max(char x, char y) => (char)Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Min(char x, char y) => (char)Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) { if (s.Length != 1) @@ -1507,11 +1507,11 @@ static char INumber.Parse(ReadOnlySpan s, NumberStyles style, IForma return s[0]; } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Sign(char value) => (char)((value == 0) ? 0 : 1); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out char result) { @@ -1689,11 +1689,11 @@ static bool INumber.TryCreate(TOther value, out char result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out char result) => TryParse(s, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out char result) { if (s.Length != 1) @@ -1709,11 +1709,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFo // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IParseable.Parse(string s, IFormatProvider? provider) => Parse(s); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out char result) => TryParse(s, out result); @@ -1721,15 +1721,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IShiftOperators.operator <<(char value, int shiftAmount) => (char)(value << shiftAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IShiftOperators.operator >>(char value, int shiftAmount) => (char)(value >> shiftAmount); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static char IShiftOperators.operator >>>(char value, int shiftAmount) // => (char)(value >> shiftAmount); @@ -1737,7 +1737,7 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) { if (s.Length != 1) @@ -1747,7 +1747,7 @@ static char ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? pr return s[0]; } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out char result) { if (s.Length != 1) @@ -1763,11 +1763,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char ISubtractionOperators.operator -(char left, char right) => (char)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char ISubtractionOperators.operator -(char left, char right) // => checked((char)(left - right)); @@ -1775,11 +1775,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IUnaryNegationOperators.operator -(char value) => (char)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IUnaryNegationOperators.operator -(char value) // => checked((char)(-value)); @@ -1787,11 +1787,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IUnaryPlusOperators.operator +(char value) => (char)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IUnaryPlusOperators.operator +(char value) // => checked((char)(+value)); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs index 205520defbdc8..e6fbd54165329 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs @@ -836,19 +836,19 @@ public string ToString(string? format, IFormatProvider? provider) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(DateOnly left, DateOnly right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(DateOnly left, DateOnly right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(DateOnly left, DateOnly right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(DateOnly left, DateOnly right) => left >= right; @@ -856,11 +856,11 @@ public string ToString(string? format, IFormatProvider? provider) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(DateOnly left, DateOnly right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(DateOnly left, DateOnly right) => left != right; @@ -868,21 +868,21 @@ public string ToString(string? format, IFormatProvider? provider) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateOnly IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateOnly IMinMaxValue.MaxValue => MaxValue; // // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateOnly IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider, DateTimeStyles.None); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out DateOnly result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -890,11 +890,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormat // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateOnly ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, provider, DateTimeStyles.None); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out DateOnly result) => TryParse(s, provider, DateTimeStyles.None, out result); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs index cc400c1ab32b1..1783d197b8ab8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs @@ -1513,11 +1513,11 @@ internal static bool TryCreate(int year, int month, int day, int hour, int minut // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTime IAdditionOperators.operator +(DateTime left, TimeSpan right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked DateTime IAdditionOperators.operator +(DateTime left, TimeSpan right) // => checked(left + right); @@ -1525,7 +1525,7 @@ internal static bool TryCreate(int year, int month, int day, int hour, int minut // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IAdditiveIdentity.AdditiveIdentity => default; @@ -1533,19 +1533,19 @@ static TimeSpan IAdditiveIdentity.AdditiveIdentity // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(DateTime left, DateTime right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(DateTime left, DateTime right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(DateTime left, DateTime right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(DateTime left, DateTime right) => left >= right; @@ -1553,11 +1553,11 @@ static TimeSpan IAdditiveIdentity.AdditiveIdentity // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(DateTime left, DateTime right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(DateTime left, DateTime right) => left != right; @@ -1565,21 +1565,21 @@ static TimeSpan IAdditiveIdentity.AdditiveIdentity // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTime IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTime IMinMaxValue.MaxValue => MaxValue; // // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTime IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out DateTime result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -1587,11 +1587,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormat // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTime ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, provider, DateTimeStyles.None); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out DateTime result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -1599,19 +1599,19 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvi // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTime ISubtractionOperators.operator -(DateTime left, TimeSpan right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked DateTime ISubtractionOperators.operator -(DateTime left, TimeSpan right) // => checked(left - right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan ISubtractionOperators.operator -(DateTime left, DateTime right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan ISubtractionOperators.operator -(DateTime left, DateTime right) // => checked(left - right); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs b/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs index d546d0029f711..1d4dc7dcfa3ff 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs @@ -870,11 +870,11 @@ public static implicit operator DateTimeOffset(DateTime dateTime) => // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTimeOffset IAdditionOperators.operator +(DateTimeOffset left, TimeSpan right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked DateTimeOffset IAdditionOperators.operator +(DateTimeOffset left, TimeSpan right) // => checked(left + right); @@ -882,26 +882,26 @@ public static implicit operator DateTimeOffset(DateTime dateTime) => // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IAdditiveIdentity.AdditiveIdentity => default; // // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(DateTimeOffset left, DateTimeOffset right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(DateTimeOffset left, DateTimeOffset right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(DateTimeOffset left, DateTimeOffset right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(DateTimeOffset left, DateTimeOffset right) => left >= right; @@ -909,11 +909,11 @@ public static implicit operator DateTimeOffset(DateTime dateTime) => // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(DateTimeOffset left, DateTimeOffset right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(DateTimeOffset left, DateTimeOffset right) => left != right; @@ -921,21 +921,21 @@ public static implicit operator DateTimeOffset(DateTime dateTime) => // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTimeOffset IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTimeOffset IMinMaxValue.MaxValue => MaxValue; // // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTimeOffset IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out DateTimeOffset result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -943,11 +943,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, I // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTimeOffset ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, provider, DateTimeStyles.None); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out DateTimeOffset result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -955,19 +955,19 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IForma // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTimeOffset ISubtractionOperators.operator -(DateTimeOffset left, TimeSpan right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked DateTimeOffset ISubtractionOperators.operator -(DateTimeOffset left, TimeSpan right) // => checked(left - right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan ISubtractionOperators.operator -(DateTimeOffset left, DateTimeOffset right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan ISubtractionOperators.operator -(DateTimeOffset left, DateTimeOffset right) // => checked(left - right); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs index 7463b64e581ac..c46fe5094cb32 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs @@ -1085,11 +1085,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IAdditionOperators.operator +(decimal left, decimal right) => checked(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IAdditionOperators.operator +(decimal left, decimal right) // => checked(left + right); @@ -1097,26 +1097,26 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IAdditiveIdentity.AdditiveIdentity => 0.0m; // // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(decimal left, decimal right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(decimal left, decimal right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(decimal left, decimal right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(decimal left, decimal right) => left >= right; @@ -1124,11 +1124,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IDecrementOperators.operator --(decimal value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IDecrementOperators.operator --(decimal value) // => checked(--value); @@ -1136,11 +1136,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IDivisionOperators.operator /(decimal left, decimal right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IDivisionOperators.operator /(decimal left, decimal right) // => checked(left / right); @@ -1148,11 +1148,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(decimal left, decimal right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(decimal left, decimal right) => left != right; @@ -1160,11 +1160,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IIncrementOperators.operator ++(decimal value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IIncrementOperators.operator ++(decimal value) // => checked(++value); @@ -1172,21 +1172,21 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IModulusOperators.operator %(decimal left, decimal right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IModulusOperators.operator %(decimal left, decimal right) // => checked(left % right); @@ -1194,18 +1194,18 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IMultiplicativeIdentity.MultiplicativeIdentity => 1.0m; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IMultiplyOperators.operator *(decimal left, decimal right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IMultiplyOperators.operator *(decimal left, decimal right) // => checked(left * right); @@ -1213,17 +1213,17 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.One => 1.0m; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Zero => 0.0m; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Abs(decimal value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static decimal INumber.Create(TOther value) { @@ -1290,7 +1290,7 @@ static decimal INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static decimal INumber.CreateSaturating(TOther value) { @@ -1357,7 +1357,7 @@ static decimal INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static decimal INumber.CreateTruncating(TOther value) { @@ -1424,35 +1424,35 @@ static decimal INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Clamp(decimal value, decimal min, decimal max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (decimal Quotient, decimal Remainder) INumber.DivRem(decimal left, decimal right) => (left / right, left % right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Max(decimal x, decimal y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Min(decimal x, decimal y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Sign(decimal value) => Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out decimal result) { @@ -1534,11 +1534,11 @@ static bool INumber.TryCreate(TOther value, out decimal result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out decimal result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out decimal result) => TryParse(s, style, provider, out result); @@ -1546,11 +1546,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out decimal result) => TryParse(s, NumberStyles.Number, provider, out result); @@ -1558,18 +1558,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatP // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Number, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out decimal result) => TryParse(s, NumberStyles.Number, provider, out result); @@ -1577,11 +1577,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvid // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal ISubtractionOperators.operator -(decimal left, decimal right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal ISubtractionOperators.operator -(decimal left, decimal right) // => checked(left - right); @@ -1589,11 +1589,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvid // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IUnaryNegationOperators.operator -(decimal value) => -value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IUnaryNegationOperators.operator -(decimal value) // => checked(-value); @@ -1601,11 +1601,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvid // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IUnaryPlusOperators.operator +(decimal value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IUnaryPlusOperators.operator +(decimal value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Double.cs b/src/libraries/System.Private.CoreLib/src/System/Double.cs index 170af80462676..95aa53a263b0e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Double.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Double.cs @@ -456,11 +456,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IAdditionOperators.operator +(double left, double right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IAdditionOperators.operator +(double left, double right) // => checked(left + right); @@ -468,14 +468,14 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IAdditiveIdentity.AdditiveIdentity => 0.0; // // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(double value) { ulong bits = BitConverter.DoubleToUInt64Bits(value); @@ -488,7 +488,7 @@ static bool IBinaryNumber.IsPow2(double value) && (significand == MinSignificand); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IBinaryNumber.Log2(double value) => Math.Log2(value); @@ -496,28 +496,28 @@ static double IBinaryNumber.Log2(double value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IBitwiseOperators.operator &(double left, double right) { ulong bits = BitConverter.DoubleToUInt64Bits(left) & BitConverter.DoubleToUInt64Bits(right); return BitConverter.UInt64BitsToDouble(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IBitwiseOperators.operator |(double left, double right) { ulong bits = BitConverter.DoubleToUInt64Bits(left) | BitConverter.DoubleToUInt64Bits(right); return BitConverter.UInt64BitsToDouble(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IBitwiseOperators.operator ^(double left, double right) { ulong bits = BitConverter.DoubleToUInt64Bits(left) ^ BitConverter.DoubleToUInt64Bits(right); return BitConverter.UInt64BitsToDouble(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IBitwiseOperators.operator ~(double value) { ulong bits = ~BitConverter.DoubleToUInt64Bits(value); @@ -528,19 +528,19 @@ static double IBinaryNumber.Log2(double value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(double left, double right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(double left, double right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(double left, double right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(double left, double right) => left >= right; @@ -548,11 +548,11 @@ static double IBinaryNumber.Log2(double value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IDecrementOperators.operator --(double value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IDecrementOperators.operator --(double value) // => checked(--value); @@ -560,11 +560,11 @@ static double IBinaryNumber.Log2(double value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IDivisionOperators.operator /(double left, double right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IDivisionOperators.operator /(double left, double right) // => checked(left / right); @@ -572,11 +572,11 @@ static double IBinaryNumber.Log2(double value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(double left, double right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(double left, double right) => left != right; @@ -584,200 +584,200 @@ static double IBinaryNumber.Log2(double value) // IFloatingPoint // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.E => Math.E; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Epsilon => Epsilon; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.NaN => NaN; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.NegativeInfinity => NegativeInfinity; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.NegativeZero => -0.0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Pi => Math.PI; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.PositiveInfinity => PositiveInfinity; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Tau => Math.Tau; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Acos(double x) => Math.Acos(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Acosh(double x) => Math.Acosh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Asin(double x) => Math.Asin(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Asinh(double x) => Math.Asinh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Atan(double x) => Math.Atan(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Atan2(double y, double x) => Math.Atan2(y, x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Atanh(double x) => Math.Atanh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.BitIncrement(double x) => Math.BitIncrement(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.BitDecrement(double x) => Math.BitDecrement(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Cbrt(double x) => Math.Cbrt(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Ceiling(double x) => Math.Ceiling(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.CopySign(double x, double y) => Math.CopySign(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Cos(double x) => Math.Cos(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Cosh(double x) => Math.Cosh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Exp(double x) => Math.Exp(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Floor(double x) => Math.Floor(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.FusedMultiplyAdd(double left, double right, double addend) => Math.FusedMultiplyAdd(left, right, addend); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.IEEERemainder(double left, double right) => Math.IEEERemainder(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TInteger IFloatingPoint.ILogB(double x) => TInteger.Create(Math.ILogB(x)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Log(double x) => Math.Log(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Log(double x, double newBase) => Math.Log(x, newBase); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Log2(double x) => Math.Log2(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Log10(double x) => Math.Log10(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.MaxMagnitude(double x, double y) => Math.MaxMagnitude(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.MinMagnitude(double x, double y) => Math.MinMagnitude(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Pow(double x, double y) => Math.Pow(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Round(double x) => Math.Round(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Round(double x, TInteger digits) => Math.Round(x, int.Create(digits)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Round(double x, MidpointRounding mode) => Math.Round(x, mode); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Round(double x, TInteger digits, MidpointRounding mode) => Math.Round(x, int.Create(digits), mode); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.ScaleB(double x, TInteger n) => Math.ScaleB(x, int.Create(n)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Sin(double x) => Math.Sin(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Sinh(double x) => Math.Sinh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Sqrt(double x) => Math.Sqrt(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Tan(double x) => Math.Tan(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Tanh(double x) => Math.Tanh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Truncate(double x) => Math.Truncate(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsFinite(double d) => IsFinite(d); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsInfinity(double d) => IsInfinity(d); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsNaN(double d) => IsNaN(d); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsNegative(double d) => IsNegative(d); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsNegativeInfinity(double d) => IsNegativeInfinity(d); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsNormal(double d) => IsNormal(d); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsPositiveInfinity(double d) => IsPositiveInfinity(d); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsSubnormal(double d) => IsSubnormal(d); // static double IFloatingPoint.AcosPi(double x) @@ -850,11 +850,11 @@ static double IFloatingPoint.Truncate(double x) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IIncrementOperators.operator ++(double value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IIncrementOperators.operator ++(double value) // => checked(++value); @@ -862,21 +862,21 @@ static double IFloatingPoint.Truncate(double x) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IModulusOperators.operator %(double left, double right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IModulusOperators.operator %(double left, double right) // => checked(left % right); @@ -884,18 +884,18 @@ static double IFloatingPoint.Truncate(double x) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IMultiplicativeIdentity.MultiplicativeIdentity => 1.0; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IMultiplyOperators.operator *(double left, double right) => (double)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IMultiplyOperators.operator *(double left, double right) // => checked((double)(left * right)); @@ -903,21 +903,21 @@ static double IFloatingPoint.Truncate(double x) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.One => 1.0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Zero => 0.0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Abs(double value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Clamp(double value, double min, double max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static double INumber.Create(TOther value) { @@ -984,7 +984,7 @@ static double INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static double INumber.CreateSaturating(TOther value) { @@ -1051,7 +1051,7 @@ static double INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static double INumber.CreateTruncating(TOther value) { @@ -1118,31 +1118,31 @@ static double INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (double Quotient, double Remainder) INumber.DivRem(double left, double right) => (left / right, left % right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Max(double x, double y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Min(double x, double y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Sign(double value) => Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out double result) { @@ -1224,11 +1224,11 @@ static bool INumber.TryCreate(TOther value, out double result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out double result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out double result) => TryParse(s, style, provider, out result); @@ -1236,11 +1236,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, I // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out double result) => TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, provider, out result); @@ -1248,18 +1248,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPr // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Float | NumberStyles.AllowThousands, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out double result) => TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, provider, out result); @@ -1267,11 +1267,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvide // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double ISubtractionOperators.operator -(double left, double right) => (double)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double ISubtractionOperators.operator -(double left, double right) // => checked((double)(left - right)); @@ -1279,11 +1279,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvide // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IUnaryNegationOperators.operator -(double value) => (double)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IUnaryNegationOperators.operator -(double value) // => checked((double)(-value)); @@ -1291,11 +1291,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvide // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IUnaryPlusOperators.operator +(double value) => (double)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IUnaryPlusOperators.operator +(double value) // => checked((double)(+value)); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Guid.cs b/src/libraries/System.Private.CoreLib/src/System/Guid.cs index 1704ceabfbb9d..50123b8d0be36 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Guid.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Guid.cs @@ -1234,7 +1234,7 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(Guid left, Guid right) { if (left._a != right._a) @@ -1295,7 +1295,7 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re return false; } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(Guid left, Guid right) { if (left._a != right._a) @@ -1356,7 +1356,7 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re return true; } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(Guid left, Guid right) { if (left._a != right._a) @@ -1417,7 +1417,7 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re return false; } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(Guid left, Guid right) { if (left._a != right._a) @@ -1482,11 +1482,11 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(Guid left, Guid right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(Guid left, Guid right) => left != right; @@ -1494,11 +1494,11 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Guid IParseable.Parse(string s, IFormatProvider? provider) => Parse(s); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out Guid result) => TryParse(s, out result); @@ -1506,11 +1506,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Guid ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out Guid result) => TryParse(s, out result); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Half.cs b/src/libraries/System.Private.CoreLib/src/System/Half.cs index 0318e094ea284..99b0b80d069c2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Half.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Half.cs @@ -707,11 +707,11 @@ private static double CreateDouble(bool sign, ushort exp, ulong sig) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IAdditionOperators.operator +(Half left, Half right) => (Half)((float)left + (float)right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IAdditionOperators.operator +(Half left, Half right) // => checked((Half)((float)left + (float)right)); @@ -719,14 +719,14 @@ private static double CreateDouble(bool sign, ushort exp, ulong sig) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IAdditiveIdentity.AdditiveIdentity => PositiveZero; // // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(Half value) { uint bits = BitConverter.HalfToUInt16Bits(value); @@ -739,7 +739,7 @@ static bool IBinaryNumber.IsPow2(Half value) && (significand == MinSignificand); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IBinaryNumber.Log2(Half value) => (Half)MathF.Log2((float)value); @@ -747,28 +747,28 @@ static Half IBinaryNumber.Log2(Half value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IBitwiseOperators.operator &(Half left, Half right) { ushort bits = (ushort)(BitConverter.HalfToUInt16Bits(left) & BitConverter.HalfToUInt16Bits(right)); return BitConverter.UInt16BitsToHalf(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IBitwiseOperators.operator |(Half left, Half right) { ushort bits = (ushort)(BitConverter.HalfToUInt16Bits(left) | BitConverter.HalfToUInt16Bits(right)); return BitConverter.UInt16BitsToHalf(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IBitwiseOperators.operator ^(Half left, Half right) { ushort bits = (ushort)(BitConverter.HalfToUInt16Bits(left) ^ BitConverter.HalfToUInt16Bits(right)); return BitConverter.UInt16BitsToHalf(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IBitwiseOperators.operator ~(Half value) { ushort bits = (ushort)(~BitConverter.HalfToUInt16Bits(value)); @@ -779,19 +779,19 @@ static Half IBinaryNumber.Log2(Half value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(Half left, Half right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(Half left, Half right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(Half left, Half right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(Half left, Half right) => left >= right; @@ -799,7 +799,7 @@ static Half IBinaryNumber.Log2(Half value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IDecrementOperators.operator --(Half value) { var tmp = (float)value; @@ -807,7 +807,7 @@ static Half IBinaryNumber.Log2(Half value) return (Half)tmp; } - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IDecrementOperators.operator --(Half value) // { // var tmp = (float)value; @@ -819,11 +819,11 @@ static Half IBinaryNumber.Log2(Half value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(Half left, Half right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(Half left, Half right) => left != right; @@ -831,11 +831,11 @@ static Half IBinaryNumber.Log2(Half value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IDivisionOperators.operator /(Half left, Half right) => (Half)((float)left / (float)right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IDivisionOperators.operator /(Half left, Half right) // => checked((Half)((float)left / (float)right)); @@ -843,59 +843,59 @@ static Half IBinaryNumber.Log2(Half value) // IFloatingPoint // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.E => (Half)MathF.E; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Epsilon => Epsilon; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.NaN => NaN; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.NegativeInfinity => NegativeInfinity; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.NegativeZero => NegativeZero; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Pi => (Half)MathF.PI; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.PositiveInfinity => PositiveInfinity; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Tau => (Half)MathF.Tau; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Acos(Half x) => (Half)MathF.Acos((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Acosh(Half x) => (Half)MathF.Acosh((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Asin(Half x) => (Half)MathF.Asin((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Asinh(Half x) => (Half)MathF.Asinh((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Atan(Half x) => (Half)MathF.Atan((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Atan2(Half y, Half x) => (Half)MathF.Atan2((float)y, (float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Atanh(Half x) => (Half)MathF.Atanh((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.BitIncrement(Half x) { ushort bits = BitConverter.HalfToUInt16Bits(x); @@ -921,7 +921,7 @@ static Half IFloatingPoint.BitIncrement(Half x) return BitConverter.UInt16BitsToHalf(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.BitDecrement(Half x) { ushort bits = BitConverter.HalfToUInt16Bits(x); @@ -947,140 +947,140 @@ static Half IFloatingPoint.BitDecrement(Half x) return BitConverter.UInt16BitsToHalf(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Cbrt(Half x) => (Half)MathF.Cbrt((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Ceiling(Half x) => (Half)MathF.Ceiling((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.CopySign(Half x, Half y) => (Half)MathF.CopySign((float)x, (float)y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Cos(Half x) => (Half)MathF.Cos((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Cosh(Half x) => (Half)MathF.Cosh((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Exp(Half x) => (Half)MathF.Exp((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Floor(Half x) => (Half)MathF.Floor((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.FusedMultiplyAdd(Half left, Half right, Half addend) => (Half)MathF.FusedMultiplyAdd((float)left, (float)right, (float)addend); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.IEEERemainder(Half left, Half right) => (Half)MathF.IEEERemainder((float)left, (float)right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TInteger IFloatingPoint.ILogB(Half x) => TInteger.Create(MathF.ILogB((float)x)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Log(Half x) => (Half)MathF.Log((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Log(Half x, Half newBase) => (Half)MathF.Log((float)x, (float)newBase); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Log2(Half x) => (Half)MathF.Log2((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Log10(Half x) => (Half)MathF.Log10((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.MaxMagnitude(Half x, Half y) => (Half)MathF.MaxMagnitude((float)x, (float)y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.MinMagnitude(Half x, Half y) => (Half)MathF.MinMagnitude((float)x, (float)y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Pow(Half x, Half y) => (Half)MathF.Pow((float)x, (float)y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Round(Half x) => (Half)MathF.Round((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Round(Half x, TInteger digits) => (Half)MathF.Round((float)x, int.Create(digits)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Round(Half x, MidpointRounding mode) => (Half)MathF.Round((float)x, mode); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Round(Half x, TInteger digits, MidpointRounding mode) => (Half)MathF.Round((float)x, int.Create(digits), mode); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.ScaleB(Half x, TInteger n) => (Half)MathF.ScaleB((float)x, int.Create(n)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Sin(Half x) => (Half)MathF.Sin((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Sinh(Half x) => (Half)MathF.Sinh((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Sqrt(Half x) => (Half)MathF.Sqrt((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Tan(Half x) => (Half)MathF.Tan((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Tanh(Half x) => (Half)MathF.Tanh((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Truncate(Half x) => (Half)MathF.Truncate((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsFinite(Half x) => IsFinite(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsInfinity(Half x) => IsInfinity(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsNaN(Half x) => IsNaN(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsNegative(Half x) => IsNegative(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsNegativeInfinity(Half x) => IsNegativeInfinity(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsNormal(Half x) => IsNormal(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsPositiveInfinity(Half x) => IsPositiveInfinity(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsSubnormal(Half x) => IsSubnormal(x); @@ -1154,7 +1154,7 @@ static Half IFloatingPoint.Truncate(Half x) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IIncrementOperators.operator ++(Half value) { var tmp = (float)value; @@ -1162,7 +1162,7 @@ static Half IFloatingPoint.Truncate(Half x) return (Half)tmp; } - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IIncrementOperators.operator ++(Half value) // { // var tmp = (float)value; @@ -1174,21 +1174,21 @@ static Half IFloatingPoint.Truncate(Half x) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IModulusOperators.operator %(Half left, Half right) => (Half)((float)left % (float)right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IModulusOperators.operator %(Half left, Half right) // => checked((Half)((float)left % (float)right)); @@ -1196,18 +1196,18 @@ static Half IFloatingPoint.Truncate(Half x) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IMultiplicativeIdentity.MultiplicativeIdentity => (Half)1.0f; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IMultiplyOperators.operator *(Half left, Half right) => (Half)((float)left * (float)right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IMultiplyOperators.operator *(Half left, Half right) // => checked((Half)((float)left * (float)right)); @@ -1215,21 +1215,21 @@ static Half IFloatingPoint.Truncate(Half x) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.One => (Half)1.0f; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Zero => PositiveZero; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Abs(Half value) => (Half)MathF.Abs((float)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Clamp(Half value, Half min, Half max) => (Half)Math.Clamp((float)value, (float)min, (float)max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static Half INumber.Create(TOther value) { @@ -1296,7 +1296,7 @@ static Half INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static Half INumber.CreateSaturating(TOther value) { @@ -1363,7 +1363,7 @@ static Half INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static Half INumber.CreateTruncating(TOther value) { @@ -1430,31 +1430,31 @@ static Half INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (Half Quotient, Half Remainder) INumber.DivRem(Half left, Half right) => ((Half, Half))((float)left / (float)right, (float)left % (float)right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Max(Half x, Half y) => (Half)MathF.Max((float)x, (float)y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Min(Half x, Half y) => (Half)MathF.Min((float)x, (float)y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Sign(Half value) => (Half)MathF.Sign((float)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out Half result) { @@ -1536,11 +1536,11 @@ static bool INumber.TryCreate(TOther value, out Half result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out Half result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out Half result) => TryParse(s, style, provider, out result); @@ -1548,11 +1548,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFo // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out Half result) => TryParse(s, DefaultParseStyle, provider, out result); @@ -1560,18 +1560,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half ISignedNumber.NegativeOne => (Half)(-1.0f); // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, DefaultParseStyle, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out Half result) => TryParse(s, DefaultParseStyle, provider, out result); @@ -1579,11 +1579,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half ISubtractionOperators.operator -(Half left, Half right) => (Half)((float)left - (float)right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half ISubtractionOperators.operator -(Half left, Half right) // => checked((Half)((float)left - (float)right)); @@ -1591,11 +1591,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IUnaryNegationOperators.operator -(Half value) => (Half)(-(float)value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IUnaryNegationOperators.operator -(Half value) // => checked((Half)(-(float)value)); @@ -1603,11 +1603,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IUnaryPlusOperators.operator +(Half value) => value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IUnaryPlusOperators.operator +(Half value) // => checked(value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/IAdditionOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IAdditionOperators.cs index fb09cfac334c8..3b800fb629f66 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IAdditionOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IAdditionOperators.cs @@ -13,7 +13,7 @@ namespace System /// The type that implements this interface. /// The type that will be added to . /// The type that contains the sum of and . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IAdditionOperators where TSelf : IAdditionOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IAdditiveIdentity.cs b/src/libraries/System.Private.CoreLib/src/System/IAdditiveIdentity.cs index 5b07145c32837..deecaa3273b69 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IAdditiveIdentity.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IAdditiveIdentity.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for getting the additive identity of a given type. /// The type that implements this interface. /// The type that contains the additive identify of . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IAdditiveIdentity where TSelf : IAdditiveIdentity { diff --git a/src/libraries/System.Private.CoreLib/src/System/IBitwiseOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IBitwiseOperators.cs index d4d1a35d0e66f..b811f83745c96 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IBitwiseOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IBitwiseOperators.cs @@ -13,7 +13,7 @@ namespace System /// The type that implements this interface. /// The type that will is used in the operation with . /// The type that contains the result of op . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IBitwiseOperators where TSelf : IBitwiseOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IComparisonOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IComparisonOperators.cs index 5bd4a22e28c96..7576c9777b427 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IComparisonOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IComparisonOperators.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for comparing two values to determine relative order. /// The type that implements this interface. /// The type that will be compared with . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IComparisonOperators : IComparable, IComparable, diff --git a/src/libraries/System.Private.CoreLib/src/System/IDecrementOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IDecrementOperators.cs index 9a240b14a9614..aa61af7af8f4c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IDecrementOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IDecrementOperators.cs @@ -11,7 +11,7 @@ namespace System { /// Defines a mechanism for decrementing a given value. /// The type that implements this interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IDecrementOperators where TSelf : IDecrementOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IDivisionOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IDivisionOperators.cs index 4beba8cddbddf..f8b7aaa72e97a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IDivisionOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IDivisionOperators.cs @@ -13,7 +13,7 @@ namespace System /// The type that implements this interface. /// The type that will divide . /// The type that contains the quotient of and . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IDivisionOperators where TSelf : IDivisionOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IEqualityOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IEqualityOperators.cs index f6f8fa5050a97..b969575744794 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IEqualityOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IEqualityOperators.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for comparing two values to determine equality. /// The type that implements this interface. /// The type that will be compared with . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IEqualityOperators : IEquatable where TSelf : IEqualityOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IFloatingPoint.cs b/src/libraries/System.Private.CoreLib/src/System/IFloatingPoint.cs index cb69e03fd771f..0b9a2f5da83bd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IFloatingPoint.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IFloatingPoint.cs @@ -11,7 +11,7 @@ namespace System { /// Defines a floating-point type. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IFloatingPoint : ISignedNumber where TSelf : IFloatingPoint @@ -332,7 +332,7 @@ static abstract TSelf ScaleB(TSelf x, TInteger n) /// Defines a floating-point type that is represented in a base-2 format. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IBinaryFloatingPoint : IBinaryNumber, IFloatingPoint diff --git a/src/libraries/System.Private.CoreLib/src/System/IIncrementOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IIncrementOperators.cs index 5b4986a5fc22a..ca036a24c7533 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IIncrementOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IIncrementOperators.cs @@ -11,7 +11,7 @@ namespace System { /// Defines a mechanism for incrementing a given value. /// The type that implements this interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IIncrementOperators where TSelf : IIncrementOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IInteger.cs b/src/libraries/System.Private.CoreLib/src/System/IInteger.cs index 89ec036bb147a..16b2079f3ae66 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IInteger.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IInteger.cs @@ -11,7 +11,7 @@ namespace System { /// Defines an integer type that is represented in a base-2 format. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IBinaryInteger : IBinaryNumber, IShiftOperators diff --git a/src/libraries/System.Private.CoreLib/src/System/IMinMaxValue.cs b/src/libraries/System.Private.CoreLib/src/System/IMinMaxValue.cs index cc1eae3787394..38e2c534d1cf3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IMinMaxValue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IMinMaxValue.cs @@ -11,7 +11,7 @@ namespace System { /// Defines a mechanism for getting the minimum and maximum value of a type. /// The type that implements this interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IMinMaxValue where TSelf : IMinMaxValue { diff --git a/src/libraries/System.Private.CoreLib/src/System/IModulusOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IModulusOperators.cs index 24b5beae107e2..9ecebb4f79eae 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IModulusOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IModulusOperators.cs @@ -14,7 +14,7 @@ namespace System /// The type that will divide . /// The type that contains the modulus or remainder of and . /// This type represents the % in C# which is often used to compute the remainder and may differ from an actual modulo operation depending on the type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IModulusOperators where TSelf : IModulusOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IMultiplicativeIdentity.cs b/src/libraries/System.Private.CoreLib/src/System/IMultiplicativeIdentity.cs index 9560071ae51c9..86ba9371f7184 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IMultiplicativeIdentity.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IMultiplicativeIdentity.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for getting the multiplicative identity of a given type. /// The type that implements this interface. /// The type that contains the multiplicative identify of . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IMultiplicativeIdentity where TSelf : IMultiplicativeIdentity { diff --git a/src/libraries/System.Private.CoreLib/src/System/IMultiplyOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IMultiplyOperators.cs index e9fc0fc1c1943..1be0097923595 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IMultiplyOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IMultiplyOperators.cs @@ -13,7 +13,7 @@ namespace System /// The type that implements this interface. /// The type that will multiply . /// The type that contains the product of and . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IMultiplyOperators where TSelf : IMultiplyOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/INumber.cs b/src/libraries/System.Private.CoreLib/src/System/INumber.cs index c1a4f8b109c34..8ffa8429fd1a9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/INumber.cs +++ b/src/libraries/System.Private.CoreLib/src/System/INumber.cs @@ -13,7 +13,7 @@ namespace System { /// Defines a number type. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface INumber : IAdditionOperators, IAdditiveIdentity, @@ -153,7 +153,7 @@ static abstract bool TryCreate(TOther value, out TSelf result) /// Defines a number that is represented in a base-2 format. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IBinaryNumber : IBitwiseOperators, INumber @@ -172,7 +172,7 @@ public interface IBinaryNumber /// Defines a number type which can represent both positive and negative values. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface ISignedNumber : INumber where TSelf : ISignedNumber @@ -183,7 +183,7 @@ public interface ISignedNumber /// Defines a number type which can only represent positive values, that is it cannot represent negative values. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IUnsignedNumber : INumber where TSelf : IUnsignedNumber diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs index a30543ced5933..2bfcd01604047 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Directory.cs @@ -5,16 +5,9 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; - -#if MS_IO_REDIST -using Microsoft.IO.Enumeration; - -namespace Microsoft.IO -#else using System.IO.Enumeration; namespace System.IO -#endif { public static partial class Directory { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryInfo.cs b/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryInfo.cs index da8cdec7ab0ee..1aeef2f7501a8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryInfo.cs @@ -5,16 +5,9 @@ using System.IO; using System.Collections.Generic; using System.Diagnostics; - -#if MS_IO_REDIST -using Microsoft.IO.Enumeration; - -namespace Microsoft.IO -#else using System.IO.Enumeration; namespace System.IO -#endif { public sealed partial class DirectoryInfo : FileSystemInfo { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/DisableMediaInsertionPrompt.cs b/src/libraries/System.Private.CoreLib/src/System/IO/DisableMediaInsertionPrompt.cs index 6510200f2c2fb..6ea4d7893f272 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/DisableMediaInsertionPrompt.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/DisableMediaInsertionPrompt.cs @@ -1,13 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if MS_IO_REDIST -using System; - -namespace Microsoft.IO -#else namespace System.IO -#endif { /// /// Simple wrapper to safely disable the normal media insertion prompt for diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Windows.cs index 76c0e277f05bd..27a15cb6c192b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Windows.cs @@ -4,11 +4,7 @@ using System; using System.IO; -#if MS_IO_REDIST -namespace Microsoft.IO.Enumeration -#else namespace System.IO.Enumeration -#endif { /// Provides a lower level view of to help process and filter find results. public unsafe ref partial struct FileSystemEntry diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.cs index 7ec26cc0f0a44..bea0714fdf211 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.cs @@ -4,11 +4,7 @@ using System; using System.IO; -#if MS_IO_REDIST -namespace Microsoft.IO.Enumeration -#else namespace System.IO.Enumeration -#endif { /// Provides a lower level view of to help process and filter find results. public ref partial struct FileSystemEntry diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerable.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerable.cs index 0785e2e10ce4f..3f2e5a3b324ad 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerable.cs @@ -6,11 +6,7 @@ using System.Collections.Generic; using System.Threading; -#if MS_IO_REDIST -namespace Microsoft.IO.Enumeration -#else namespace System.IO.Enumeration -#endif { /// /// Enumerable that allows utilizing custom filter predicates and tranform delegates. diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs index 378d037bb0fd2..00868756b91d1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs @@ -5,11 +5,7 @@ using System.Collections.Generic; using System.IO; -#if MS_IO_REDIST -namespace Microsoft.IO.Enumeration -#else namespace System.IO.Enumeration -#endif { internal static class FileSystemEnumerableFactory { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs index 46b5cbc9bc131..265ac541bed12 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs @@ -11,11 +11,7 @@ using System.Runtime.InteropServices; using System.Threading; -#if MS_IO_REDIST -namespace Microsoft.IO.Enumeration -#else namespace System.IO.Enumeration -#endif { /// Enumerates the file system elements of the provided type that are being searched and filtered by a . public unsafe abstract partial class FileSystemEnumerator : CriticalFinalizerObject, IEnumerator diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.cs index 07dbad8408470..6f22a9729b5d0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.cs @@ -6,11 +6,7 @@ using System.Collections.Generic; using System.Runtime.ConstrainedExecution; -#if MS_IO_REDIST -namespace Microsoft.IO.Enumeration -#else namespace System.IO.Enumeration -#endif { /// Enumerates the file system elements of the provided type that are being searched and filtered by a . /// The type of the result produced by this file system enumerator. diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs index fc3c83e4837b2..6ee823c5739db 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs @@ -4,11 +4,7 @@ using System; using System.Text; -#if MS_IO_REDIST -namespace Microsoft.IO.Enumeration -#else namespace System.IO.Enumeration -#endif { /// Provides methods for matching file system names. public static class FileSystemName @@ -101,7 +97,7 @@ public static bool MatchesSimpleExpression(ReadOnlySpan expression, ReadOn // cannot contain wildcards, while the expression may contain wildcards. // // Expression wild cards are evaluated as shown in the nondeterministic - // finite automatons below. Note that ~* and ~? are DOS_STAR and DOS_QM. + // finite automata below. Note that ~* and ~? are DOS_STAR and DOS_QM. // // ~* is DOS_STAR, ~? is DOS_QM, and ~. is DOS_DOT // diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/EnumerationOptions.cs b/src/libraries/System.Private.CoreLib/src/System/IO/EnumerationOptions.cs index 952d8132488c2..a48d7ce4d0b17 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/EnumerationOptions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/EnumerationOptions.cs @@ -4,11 +4,7 @@ using System; using System.IO; -#if MS_IO_REDIST -namespace Microsoft.IO -#else namespace System.IO -#endif { /// Provides file and directory enumeration options. public class EnumerationOptions diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index 9296fdc0993aa..e63935c5f0c80 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -12,14 +12,7 @@ using System.Threading.Tasks; using Microsoft.Win32.SafeHandles; -#if MS_IO_REDIST -using System; -using System.IO; - -namespace Microsoft.IO -#else namespace System.IO -#endif { // Class for creating FileStream objects, and some basic file management // routines such as Delete, etc. @@ -29,31 +22,19 @@ public static partial class File private const int MaxByteArrayLength = 0x7FFFFFC7; private static Encoding? s_UTF8NoBOM; + // UTF-8 without BOM and with error detection. Same as the default encoding for StreamWriter. + private static Encoding UTF8NoBOM => s_UTF8NoBOM ??= new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); + internal const int DefaultBufferSize = 4096; public static StreamReader OpenText(string path) - { - if (path == null) - throw new ArgumentNullException(nameof(path)); - - return new StreamReader(path); - } + => new StreamReader(path ?? throw new ArgumentNullException(nameof(path))); public static StreamWriter CreateText(string path) - { - if (path == null) - throw new ArgumentNullException(nameof(path)); - - return new StreamWriter(path, append: false); - } + => new StreamWriter(path ?? throw new ArgumentNullException(nameof(path)), append: false); public static StreamWriter AppendText(string path) - { - if (path == null) - throw new ArgumentNullException(nameof(path)); - - return new StreamWriter(path, append: true); - } + => new StreamWriter(path ?? throw new ArgumentNullException(nameof(path)), append: true); /// /// Copies an existing file to a new file. @@ -86,9 +67,7 @@ public static void Copy(string sourceFileName, string destFileName, bool overwri // application until it has been closed. An IOException is thrown if the // directory specified doesn't exist. public static FileStream Create(string path) - { - return Create(path, DefaultBufferSize); - } + => Create(path, DefaultBufferSize); // Creates a file in a particular path. If the file exists, it is replaced. // The file is opened with ReadWrite access and cannot be opened by another @@ -107,12 +86,7 @@ public static FileStream Create(string path, int bufferSize, FileOptions options // On Windows, Delete will fail for a file that is open for normal I/O // or a file that is memory mapped. public static void Delete(string path) - { - if (path == null) - throw new ArgumentNullException(nameof(path)); - - FileSystem.DeleteFile(Path.GetFullPath(path)); - } + => FileSystem.DeleteFile(Path.GetFullPath(path ?? throw new ArgumentNullException(nameof(path)))); // Tests whether a file exists. The result is true if the file // given by the specified path exists; otherwise, the result is @@ -148,184 +122,88 @@ public static bool Exists([NotNullWhen(true)] string? path) } public static FileStream Open(string path, FileMode mode) - { - return Open(path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.None); - } + => Open(path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.None); public static FileStream Open(string path, FileMode mode, FileAccess access) - { - return Open(path, mode, access, FileShare.None); - } + => Open(path, mode, access, FileShare.None); public static FileStream Open(string path, FileMode mode, FileAccess access, FileShare share) - { - return new FileStream(path, mode, access, share); - } + => new FileStream(path, mode, access, share); + // File and Directory UTC APIs treat a DateTimeKind.Unspecified as UTC whereas + // ToUniversalTime treats this as local. internal static DateTimeOffset GetUtcDateTimeOffset(DateTime dateTime) - { - // File and Directory UTC APIs treat a DateTimeKind.Unspecified as UTC whereas - // ToUniversalTime treats this as local. - if (dateTime.Kind == DateTimeKind.Unspecified) - { - return DateTime.SpecifyKind(dateTime, DateTimeKind.Utc); - } - - return dateTime.ToUniversalTime(); - } + => dateTime.Kind == DateTimeKind.Unspecified + ? DateTime.SpecifyKind(dateTime, DateTimeKind.Utc) + : dateTime.ToUniversalTime(); public static void SetCreationTime(string path, DateTime creationTime) - { - string fullPath = Path.GetFullPath(path); - FileSystem.SetCreationTime(fullPath, creationTime, asDirectory: false); - } + => FileSystem.SetCreationTime(Path.GetFullPath(path), creationTime, asDirectory: false); public static void SetCreationTimeUtc(string path, DateTime creationTimeUtc) - { - string fullPath = Path.GetFullPath(path); - FileSystem.SetCreationTime(fullPath, GetUtcDateTimeOffset(creationTimeUtc), asDirectory: false); - } + => FileSystem.SetCreationTime(Path.GetFullPath(path), GetUtcDateTimeOffset(creationTimeUtc), asDirectory: false); public static DateTime GetCreationTime(string path) - { - string fullPath = Path.GetFullPath(path); - return FileSystem.GetCreationTime(fullPath).LocalDateTime; - } + => FileSystem.GetCreationTime(Path.GetFullPath(path)).LocalDateTime; public static DateTime GetCreationTimeUtc(string path) - { - string fullPath = Path.GetFullPath(path); - return FileSystem.GetCreationTime(fullPath).UtcDateTime; - } + => FileSystem.GetCreationTime(Path.GetFullPath(path)).UtcDateTime; public static void SetLastAccessTime(string path, DateTime lastAccessTime) - { - string fullPath = Path.GetFullPath(path); - FileSystem.SetLastAccessTime(fullPath, lastAccessTime, asDirectory: false); - } + => FileSystem.SetLastAccessTime(Path.GetFullPath(path), lastAccessTime, asDirectory: false); public static void SetLastAccessTimeUtc(string path, DateTime lastAccessTimeUtc) - { - string fullPath = Path.GetFullPath(path); - FileSystem.SetLastAccessTime(fullPath, GetUtcDateTimeOffset(lastAccessTimeUtc), asDirectory: false); - } + => FileSystem.SetLastAccessTime(Path.GetFullPath(path), GetUtcDateTimeOffset(lastAccessTimeUtc), asDirectory: false); public static DateTime GetLastAccessTime(string path) - { - string fullPath = Path.GetFullPath(path); - return FileSystem.GetLastAccessTime(fullPath).LocalDateTime; - } + => FileSystem.GetLastAccessTime(Path.GetFullPath(path)).LocalDateTime; public static DateTime GetLastAccessTimeUtc(string path) - { - string fullPath = Path.GetFullPath(path); - return FileSystem.GetLastAccessTime(fullPath).UtcDateTime; - } + => FileSystem.GetLastAccessTime(Path.GetFullPath(path)).UtcDateTime; public static void SetLastWriteTime(string path, DateTime lastWriteTime) - { - string fullPath = Path.GetFullPath(path); - FileSystem.SetLastWriteTime(fullPath, lastWriteTime, asDirectory: false); - } + => FileSystem.SetLastWriteTime(Path.GetFullPath(path), lastWriteTime, asDirectory: false); public static void SetLastWriteTimeUtc(string path, DateTime lastWriteTimeUtc) - { - string fullPath = Path.GetFullPath(path); - FileSystem.SetLastWriteTime(fullPath, GetUtcDateTimeOffset(lastWriteTimeUtc), asDirectory: false); - } + => FileSystem.SetLastWriteTime(Path.GetFullPath(path), GetUtcDateTimeOffset(lastWriteTimeUtc), asDirectory: false); public static DateTime GetLastWriteTime(string path) - { - string fullPath = Path.GetFullPath(path); - return FileSystem.GetLastWriteTime(fullPath).LocalDateTime; - } + => FileSystem.GetLastWriteTime(Path.GetFullPath(path)).LocalDateTime; public static DateTime GetLastWriteTimeUtc(string path) - { - string fullPath = Path.GetFullPath(path); - return FileSystem.GetLastWriteTime(fullPath).UtcDateTime; - } + => FileSystem.GetLastWriteTime(Path.GetFullPath(path)).UtcDateTime; public static FileAttributes GetAttributes(string path) - { - string fullPath = Path.GetFullPath(path); - return FileSystem.GetAttributes(fullPath); - } + => FileSystem.GetAttributes(Path.GetFullPath(path)); public static void SetAttributes(string path, FileAttributes fileAttributes) - { - string fullPath = Path.GetFullPath(path); - FileSystem.SetAttributes(fullPath, fileAttributes); - } + => FileSystem.SetAttributes(Path.GetFullPath(path), fileAttributes); public static FileStream OpenRead(string path) - { - return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); - } + => new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); public static FileStream OpenWrite(string path) - { - return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); - } + => new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); public static string ReadAllText(string path) - { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - - return InternalReadAllText(path, Encoding.UTF8); - } + => ReadAllText(path, Encoding.UTF8); public static string ReadAllText(string path, Encoding encoding) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); + Validate(path, encoding); - return InternalReadAllText(path, encoding); - } - - private static string InternalReadAllText(string path, Encoding encoding) - { - Debug.Assert(path != null); - Debug.Assert(encoding != null); - Debug.Assert(path.Length > 0); - - using (StreamReader sr = new StreamReader(path, encoding, detectEncodingFromByteOrderMarks: true)) - return sr.ReadToEnd(); + using StreamReader sr = new StreamReader(path, encoding, detectEncodingFromByteOrderMarks: true); + return sr.ReadToEnd(); } public static void WriteAllText(string path, string? contents) - { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - - using (StreamWriter sw = new StreamWriter(path)) - { - sw.Write(contents); - } - } + => WriteAllText(path, contents, UTF8NoBOM); public static void WriteAllText(string path, string? contents, Encoding encoding) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); + Validate(path, encoding); - using (StreamWriter sw = new StreamWriter(path, false, encoding)) - { - sw.Write(contents); - } + WriteToFile(path, FileMode.Create, contents, encoding); } public static byte[] ReadAllBytes(string path) @@ -333,18 +211,16 @@ public static byte[] ReadAllBytes(string path) // bufferSize == 1 used to avoid unnecessary buffer in FileStream using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1, FileOptions.SequentialScan)) { - long fileLength = fs.Length; - if (fileLength > int.MaxValue) + long fileLength = 0; + if (fs.CanSeek && (fileLength = fs.Length) > int.MaxValue) { throw new IOException(SR.IO_FileTooLong2GB); } - else if (fileLength == 0) + if (fileLength == 0) { -#if !MS_IO_REDIST - // Some file systems (e.g. procfs on Linux) return 0 for length even when there's content. + // Some file systems (e.g. procfs on Linux) return 0 for length even when there's content; also there is non-seekable file stream. // Thus we need to assume 0 doesn't mean empty. return ReadAllBytesUnknownLength(fs); -#endif } int index = 0; @@ -374,106 +250,54 @@ public static void WriteAllBytes(string path, byte[] bytes) if (bytes == null) throw new ArgumentNullException(nameof(bytes)); -#if MS_IO_REDIST - using FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read); - fs.Write(bytes, 0, bytes.Length); -#else using SafeFileHandle sfh = OpenHandle(path, FileMode.Create, FileAccess.Write, FileShare.Read); RandomAccess.WriteAtOffset(sfh, bytes, 0); -#endif } - public static string[] ReadAllLines(string path) - { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - return InternalReadAllLines(path, Encoding.UTF8); - } + public static string[] ReadAllLines(string path) + => ReadAllLines(path, Encoding.UTF8); public static string[] ReadAllLines(string path, Encoding encoding) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - - return InternalReadAllLines(path, encoding); - } - - private static string[] InternalReadAllLines(string path, Encoding encoding) - { - Debug.Assert(path != null); - Debug.Assert(encoding != null); - Debug.Assert(path.Length != 0); + Validate(path, encoding); string? line; List lines = new List(); - using (StreamReader sr = new StreamReader(path, encoding)) - while ((line = sr.ReadLine()) != null) - lines.Add(line); + using StreamReader sr = new StreamReader(path, encoding); + while ((line = sr.ReadLine()) != null) + { + lines.Add(line); + } return lines.ToArray(); } public static IEnumerable ReadLines(string path) - { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - - return ReadLinesIterator.CreateIterator(path, Encoding.UTF8); - } + => ReadLines(path, Encoding.UTF8); public static IEnumerable ReadLines(string path, Encoding encoding) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); + Validate(path, encoding); return ReadLinesIterator.CreateIterator(path, encoding); } public static void WriteAllLines(string path, string[] contents) - { - WriteAllLines(path, (IEnumerable)contents); - } + => WriteAllLines(path, (IEnumerable)contents); public static void WriteAllLines(string path, IEnumerable contents) - { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (contents == null) - throw new ArgumentNullException(nameof(contents)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - - InternalWriteAllLines(new StreamWriter(path), contents); - } + => WriteAllLines(path, contents, UTF8NoBOM); public static void WriteAllLines(string path, string[] contents, Encoding encoding) - { - WriteAllLines(path, (IEnumerable)contents, encoding); - } + => WriteAllLines(path, (IEnumerable)contents, encoding); public static void WriteAllLines(string path, IEnumerable contents, Encoding encoding) { - if (path == null) - throw new ArgumentNullException(nameof(path)); + Validate(path, encoding); + if (contents == null) throw new ArgumentNullException(nameof(contents)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); InternalWriteAllLines(new StreamWriter(path, false, encoding), contents); } @@ -493,63 +317,30 @@ private static void InternalWriteAllLines(TextWriter writer, IEnumerable } public static void AppendAllText(string path, string? contents) - { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - - using (StreamWriter sw = new StreamWriter(path, append: true)) - { - sw.Write(contents); - } - } + => AppendAllText(path, contents, UTF8NoBOM); public static void AppendAllText(string path, string? contents, Encoding encoding) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); + Validate(path, encoding); - using (StreamWriter sw = new StreamWriter(path, true, encoding)) - { - sw.Write(contents); - } + WriteToFile(path, FileMode.Append, contents, encoding); } public static void AppendAllLines(string path, IEnumerable contents) - { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (contents == null) - throw new ArgumentNullException(nameof(contents)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); - - InternalWriteAllLines(new StreamWriter(path, append: true), contents); - } + => AppendAllLines(path, contents, UTF8NoBOM); public static void AppendAllLines(string path, IEnumerable contents, Encoding encoding) { - if (path == null) - throw new ArgumentNullException(nameof(path)); + Validate(path, encoding); + if (contents == null) throw new ArgumentNullException(nameof(contents)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); InternalWriteAllLines(new StreamWriter(path, true, encoding), contents); } public static void Replace(string sourceFileName, string destinationFileName, string? destinationBackupFileName) - { - Replace(sourceFileName, destinationFileName, destinationBackupFileName, ignoreMetadataErrors: false); - } + => Replace(sourceFileName, destinationFileName, destinationBackupFileName, ignoreMetadataErrors: false); public static void Replace(string sourceFileName, string destinationFileName, string? destinationBackupFileName, bool ignoreMetadataErrors) { @@ -574,9 +365,7 @@ public static void Replace(string sourceFileName, string destinationFileName, st // permissions to destFileName. // public static void Move(string sourceFileName, string destFileName) - { - Move(sourceFileName, destFileName, false); - } + => Move(sourceFileName, destFileName, false); public static void Move(string sourceFileName, string destFileName, bool overwrite) { @@ -602,50 +391,30 @@ public static void Move(string sourceFileName, string destFileName, bool overwri [SupportedOSPlatform("windows")] public static void Encrypt(string path) - { - FileSystem.Encrypt(path ?? throw new ArgumentNullException(nameof(path))); - } + => FileSystem.Encrypt(path ?? throw new ArgumentNullException(nameof(path))); [SupportedOSPlatform("windows")] public static void Decrypt(string path) - { - FileSystem.Decrypt(path ?? throw new ArgumentNullException(nameof(path))); - } - - // UTF-8 without BOM and with error detection. Same as the default encoding for StreamWriter. - private static Encoding UTF8NoBOM => s_UTF8NoBOM ?? (s_UTF8NoBOM = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true)); + => FileSystem.Decrypt(path ?? throw new ArgumentNullException(nameof(path))); // If we use the path-taking constructors we will not have FileOptions.Asynchronous set and // we will have asynchronous file access faked by the thread pool. We want the real thing. private static StreamReader AsyncStreamReader(string path, Encoding encoding) - { - FileStream stream = new FileStream( - path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultBufferSize, - FileOptions.Asynchronous | FileOptions.SequentialScan); - - return new StreamReader(stream, encoding, detectEncodingFromByteOrderMarks: true); - } + => new StreamReader( + new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultBufferSize, FileOptions.Asynchronous | FileOptions.SequentialScan), + encoding, detectEncodingFromByteOrderMarks: true); private static StreamWriter AsyncStreamWriter(string path, Encoding encoding, bool append) - { - FileStream stream = new FileStream( - path, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.Read, DefaultBufferSize, - FileOptions.Asynchronous); - - return new StreamWriter(stream, encoding); - } + => new StreamWriter( + new FileStream(path, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.Read, DefaultBufferSize, FileOptions.Asynchronous), + encoding); public static Task ReadAllTextAsync(string path, CancellationToken cancellationToken = default(CancellationToken)) => ReadAllTextAsync(path, Encoding.UTF8, cancellationToken); public static Task ReadAllTextAsync(string path, Encoding encoding, CancellationToken cancellationToken = default(CancellationToken)) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); + Validate(path, encoding); return cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) @@ -666,11 +435,7 @@ private static async Task InternalReadAllTextAsync(string path, Encoding StringBuilder sb = new StringBuilder(); while (true) { -#if MS_IO_REDIST - int read = await sr.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); -#else int read = await sr.ReadAsync(new Memory(buffer), cancellationToken).ConfigureAwait(false); -#endif if (read == 0) { return sb.ToString(); @@ -694,25 +459,14 @@ private static async Task InternalReadAllTextAsync(string path, Encoding public static Task WriteAllTextAsync(string path, string? contents, Encoding encoding, CancellationToken cancellationToken = default(CancellationToken)) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); + Validate(path, encoding); if (cancellationToken.IsCancellationRequested) { return Task.FromCanceled(cancellationToken); } - if (string.IsNullOrEmpty(contents)) - { - new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read).Dispose(); - return Task.CompletedTask; - } - - return InternalWriteAllTextAsync(AsyncStreamWriter(path, encoding, append: false), contents, cancellationToken); + return WriteToFileAsync(path, FileMode.Create, contents, encoding, cancellationToken); } public static Task ReadAllBytesAsync(string path, CancellationToken cancellationToken = default(CancellationToken)) @@ -729,13 +483,11 @@ private static async Task InternalReadAllTextAsync(string path, Encoding bool returningInternalTask = false; try { - long fileLength = fs.Length; - if (fileLength > int.MaxValue) + long fileLength = 0L; + if (fs.CanSeek && (fileLength = fs.Length) > int.MaxValue) { var e = new IOException(SR.IO_FileTooLong2GB); -#if !MS_IO_REDIST ExceptionDispatchInfo.SetCurrentStackTrace(e); -#endif return Task.FromException(e); } @@ -761,11 +513,7 @@ private static async Task InternalReadAllBytesAsync(FileStream fs, int c byte[] bytes = new byte[count]; do { -#if MS_IO_REDIST - int n = await fs.ReadAsync(bytes, index, count - index, cancellationToken).ConfigureAwait(false); -#else int n = await fs.ReadAsync(new Memory(bytes, index, count - index), cancellationToken).ConfigureAwait(false); -#endif if (n == 0) { ThrowHelper.ThrowEndOfFileException(); @@ -804,11 +552,7 @@ private static async Task InternalReadAllBytesUnknownLengthAsync(FileStr } Debug.Assert(bytesRead < rentedArray.Length); -#if MS_IO_REDIST - int n = await fs.ReadAsync(rentedArray, bytesRead, rentedArray.Length - bytesRead, cancellationToken).ConfigureAwait(false); -#else int n = await fs.ReadAsync(rentedArray.AsMemory(bytesRead), cancellationToken).ConfigureAwait(false); -#endif if (n == 0) { return rentedArray.AsSpan(0, bytesRead).ToArray(); @@ -838,13 +582,8 @@ private static async Task InternalReadAllBytesUnknownLengthAsync(FileStr static async Task Core(string path, byte[] bytes, CancellationToken cancellationToken) { -#if MS_IO_REDIST - using FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, 1, FileOptions.Asynchronous); - await fs.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false); -#else using SafeFileHandle sfh = OpenHandle(path, FileMode.Create, FileAccess.Write, FileShare.Read, FileOptions.Asynchronous); await RandomAccess.WriteAtOffsetAsync(sfh, bytes, 0, cancellationToken).ConfigureAwait(false); -#endif } } @@ -853,12 +592,7 @@ static async Task Core(string path, byte[] bytes, CancellationToken cancellation public static Task ReadAllLinesAsync(string path, Encoding encoding, CancellationToken cancellationToken = default(CancellationToken)) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); + Validate(path, encoding); return cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) @@ -890,14 +624,10 @@ private static async Task InternalReadAllLinesAsync(string path, Encod public static Task WriteAllLinesAsync(string path, IEnumerable contents, Encoding encoding, CancellationToken cancellationToken = default(CancellationToken)) { - if (path == null) - throw new ArgumentNullException(nameof(path)); + Validate(path, encoding); + if (contents == null) throw new ArgumentNullException(nameof(contents)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); return cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) @@ -922,68 +652,19 @@ private static async Task InternalWriteAllLinesAsync(TextWriter writer, IEnumera } } - private static async Task InternalWriteAllTextAsync(StreamWriter sw, string contents, CancellationToken cancellationToken) - { -#if MS_IO_REDIST - char[]? buffer = null; - try - { - buffer = ArrayPool.Shared.Rent(DefaultBufferSize); - int count = contents.Length; - int index = 0; - while (index < count) - { - int batchSize = Math.Min(DefaultBufferSize, count - index); - contents.CopyTo(index, buffer, 0, batchSize); - await sw.WriteAsync(buffer, 0, batchSize).ConfigureAwait(false); - index += batchSize; - } - - cancellationToken.ThrowIfCancellationRequested(); - await sw.FlushAsync().ConfigureAwait(false); - } - finally - { - sw.Dispose(); - if (buffer != null) - { - ArrayPool.Shared.Return(buffer); - } - } -#else - using (sw) - { - await sw.WriteAsync(contents.AsMemory(), cancellationToken).ConfigureAwait(false); - await sw.FlushAsync().ConfigureAwait(false); - } -#endif - } - public static Task AppendAllTextAsync(string path, string? contents, CancellationToken cancellationToken = default(CancellationToken)) => AppendAllTextAsync(path, contents, UTF8NoBOM, cancellationToken); public static Task AppendAllTextAsync(string path, string? contents, Encoding encoding, CancellationToken cancellationToken = default(CancellationToken)) { - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); + Validate(path, encoding); if (cancellationToken.IsCancellationRequested) { return Task.FromCanceled(cancellationToken); } - if (string.IsNullOrEmpty(contents)) - { - // Just to throw exception if there is a problem opening the file. - new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read).Dispose(); - return Task.CompletedTask; - } - - return InternalWriteAllTextAsync(AsyncStreamWriter(path, encoding, append: true), contents, cancellationToken); + return WriteToFileAsync(path, FileMode.Append, contents, encoding, cancellationToken); } public static Task AppendAllLinesAsync(string path, IEnumerable contents, CancellationToken cancellationToken = default(CancellationToken)) @@ -991,14 +672,10 @@ private static async Task InternalWriteAllTextAsync(StreamWriter sw, string cont public static Task AppendAllLinesAsync(string path, IEnumerable contents, Encoding encoding, CancellationToken cancellationToken = default(CancellationToken)) { - if (path == null) - throw new ArgumentNullException(nameof(path)); + Validate(path, encoding); + if (contents == null) throw new ArgumentNullException(nameof(contents)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); return cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) @@ -1044,5 +721,15 @@ public static FileSystemInfo CreateSymbolicLink(string path, string pathToTarget FileSystem.VerifyValidPath(linkPath, nameof(linkPath)); return FileSystem.ResolveLinkTarget(linkPath, returnFinalTarget, isDirectory: false); } + + private static void Validate(string path, Encoding encoding) + { + if (path == null) + throw new ArgumentNullException(nameof(path)); + if (encoding == null) + throw new ArgumentNullException(nameof(encoding)); + if (path.Length == 0) + throw new ArgumentException(SR.Argument_EmptyPath, nameof(path)); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs index b5502ff9926cb..1e627dae59732 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs @@ -3,12 +3,18 @@ using System.Buffers; using System.Diagnostics; +using System.IO.Strategies; +using System.Text; +using System.Threading; +using System.Threading.Tasks; using Microsoft.Win32.SafeHandles; namespace System.IO { public static partial class File { + private const int ChunkSize = 8192; + /// /// Initializes a new instance of the class with the specified path, creation mode, read/write and sharing permission, the access other FileStreams can have to the same file, the buffer size, additional file options and the allocation size. /// @@ -48,7 +54,7 @@ public static partial class File public static SafeFileHandle OpenHandle(string path, FileMode mode = FileMode.Open, FileAccess access = FileAccess.Read, FileShare share = FileShare.Read, FileOptions options = FileOptions.None, long preallocationSize = 0) { - Strategies.FileStreamHelpers.ValidateArguments(path, mode, access, share, bufferSize: 0, options, preallocationSize); + FileStreamHelpers.ValidateArguments(path, mode, access, share, bufferSize: 0, options, preallocationSize); return SafeFileHandle.Open(Path.GetFullPath(path), mode, access, share, options, preallocationSize); } @@ -97,5 +103,131 @@ private static byte[] ReadAllBytesUnknownLength(FileStream fs) } } } + + private static void WriteToFile(string path, FileMode mode, string? contents, Encoding encoding) + { + ReadOnlySpan preamble = encoding.GetPreamble(); + int preambleSize = preamble.Length; + + using SafeFileHandle fileHandle = OpenHandle(path, mode, FileAccess.Write, FileShare.Read, FileOptions.None, GetPreallocationSize(mode, contents, encoding, preambleSize)); + long fileOffset = mode == FileMode.Append && fileHandle.CanSeek ? RandomAccess.GetLength(fileHandle) : 0; + + if (string.IsNullOrEmpty(contents)) + { + if (preambleSize > 0 // even if the content is empty, we want to store the preamble + && fileOffset == 0) // if we're appending to a file that already has data, don't write the preamble. + { + RandomAccess.WriteAtOffset(fileHandle, preamble, fileOffset); + } + return; + } + + int bytesNeeded = preambleSize + encoding.GetMaxByteCount(Math.Min(contents.Length, ChunkSize)); + byte[]? rentedBytes = null; + Span bytes = bytesNeeded <= 1024 ? stackalloc byte[1024] : (rentedBytes = ArrayPool.Shared.Rent(bytesNeeded)); + + try + { + if (fileOffset == 0) + { + preamble.CopyTo(bytes); + } + else + { + preambleSize = 0; // don't append preamble to a non-empty file + } + + Encoder encoder = encoding.GetEncoder(); + ReadOnlySpan remaining = contents; + while (!remaining.IsEmpty) + { + ReadOnlySpan toEncode = remaining.Slice(0, Math.Min(remaining.Length, ChunkSize)); + remaining = remaining.Slice(toEncode.Length); + int encoded = encoder.GetBytes(toEncode, bytes.Slice(preambleSize), flush: remaining.IsEmpty); + Span toStore = bytes.Slice(0, preambleSize + encoded); + + RandomAccess.WriteAtOffset(fileHandle, toStore, fileOffset); + + fileOffset += toStore.Length; + preambleSize = 0; + } + } + finally + { + if (rentedBytes is not null) + { + ArrayPool.Shared.Return(rentedBytes); + } + } + } + + private static async Task WriteToFileAsync(string path, FileMode mode, string? contents, Encoding encoding, CancellationToken cancellationToken) + { + ReadOnlyMemory preamble = encoding.GetPreamble(); + int preambleSize = preamble.Length; + + using SafeFileHandle fileHandle = OpenHandle(path, mode, FileAccess.Write, FileShare.Read, FileOptions.Asynchronous, GetPreallocationSize(mode, contents, encoding, preambleSize)); + long fileOffset = mode == FileMode.Append && fileHandle.CanSeek ? RandomAccess.GetLength(fileHandle) : 0; + + if (string.IsNullOrEmpty(contents)) + { + if (preambleSize > 0 // even if the content is empty, we want to store the preamble + && fileOffset == 0) // if we're appending to a file that already has data, don't write the preamble. + { + await RandomAccess.WriteAtOffsetAsync(fileHandle, preamble, fileOffset, cancellationToken).ConfigureAwait(false); + } + return; + } + + byte[] bytes = ArrayPool.Shared.Rent(preambleSize + encoding.GetMaxByteCount(Math.Min(contents.Length, ChunkSize))); + + try + { + if (fileOffset == 0) + { + preamble.CopyTo(bytes); + } + else + { + preambleSize = 0; // don't append preamble to a non-empty file + } + + Encoder encoder = encoding.GetEncoder(); + ReadOnlyMemory remaining = contents.AsMemory(); + while (!remaining.IsEmpty) + { + ReadOnlyMemory toEncode = remaining.Slice(0, Math.Min(remaining.Length, ChunkSize)); + remaining = remaining.Slice(toEncode.Length); + int encoded = encoder.GetBytes(toEncode.Span, bytes.AsSpan(preambleSize), flush: remaining.IsEmpty); + ReadOnlyMemory toStore = new ReadOnlyMemory(bytes, 0, preambleSize + encoded); + + await RandomAccess.WriteAtOffsetAsync(fileHandle, toStore, fileOffset, cancellationToken).ConfigureAwait(false); + + fileOffset += toStore.Length; + preambleSize = 0; + } + } + finally + { + ArrayPool.Shared.Return(bytes); + } + } + + private static long GetPreallocationSize(FileMode mode, string? contents, Encoding encoding, int preambleSize) + { + // for a single write operation, setting preallocationSize has no perf benefit, as it requires an additional sys-call + if (contents is null || contents.Length < ChunkSize) + { + return 0; + } + + // preallocationSize is ignored for Append mode, there is no need to spend cycles on GetByteCount + if (mode == FileMode.Append) + { + return 0; + } + + return preambleSize + encoding.GetByteCount(contents); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs index c7401018a8381..4f42c95ff454f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs @@ -7,11 +7,7 @@ using System.Text; using System.Runtime.Versioning; -#if MS_IO_REDIST -namespace Microsoft.IO -#else namespace System.IO -#endif { // Class for creating FileStream objects, and some basic file management // routines such as Delete, etc. diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Win32.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Win32.cs index 250b98bcc75a8..a9893cd1736c5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Win32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Win32.cs @@ -4,13 +4,7 @@ using System; using System.Runtime.InteropServices; -#if MS_IO_REDIST -using System.IO; - -namespace Microsoft.IO -#else namespace System.IO -#endif { internal static partial class FileSystem { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs index a233347d949ed..b94d7eeb74faf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs @@ -10,11 +10,7 @@ using System.Text; using System.Buffers; -#if MS_IO_REDIST -namespace Microsoft.IO -#else namespace System.IO -#endif { internal static partial class FileSystem { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.cs index a1d506e9218c8..09f6000326111 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.cs @@ -1,12 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if MS_IO_REDIST -using System; -namespace Microsoft.IO -#else namespace System.IO -#endif { internal static partial class FileSystem { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.Windows.cs index bb1440851733c..cadd69ce7e67a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.Windows.cs @@ -4,16 +4,9 @@ using System; using System.Diagnostics; using System.IO; - -#if MS_IO_REDIST -using Microsoft.IO.Enumeration; - -namespace Microsoft.IO -#else using System.IO.Enumeration; namespace System.IO -#endif { public partial class FileSystemInfo { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.cs index 3beed9e25635e..eb4111efee2b2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.cs @@ -5,11 +5,7 @@ using System.IO; using System.Runtime.Serialization; -#if MS_IO_REDIST -namespace Microsoft.IO -#else namespace System.IO -#endif { public abstract partial class FileSystemInfo : MarshalByRefObject, ISerializable { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/MatchCasing.cs b/src/libraries/System.Private.CoreLib/src/System/IO/MatchCasing.cs index 607ebe54c2813..0567042cdd7a1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/MatchCasing.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/MatchCasing.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if MS_IO_REDIST -namespace Microsoft.IO -#else namespace System.IO -#endif { /// Specifies the type of character casing to match. public enum MatchCasing diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/MatchType.cs b/src/libraries/System.Private.CoreLib/src/System/IO/MatchType.cs index 857796c938255..d157b13ad5ac4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/MatchType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/MatchType.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if MS_IO_REDIST -namespace Microsoft.IO -#else namespace System.IO -#endif { /// Specifies the type of wildcard matching to use. public enum MatchType diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Path.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Windows.cs index e0ad5c0c26af2..b10cedd4ecbdd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Path.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Windows.cs @@ -5,14 +5,7 @@ using System.Diagnostics.CodeAnalysis; using System.Text; -#if MS_IO_REDIST -using System; -using System.IO; - -namespace Microsoft.IO -#else namespace System.IO -#endif { public static partial class Path { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs index 49623b583e640..3732397f17ba0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs @@ -6,14 +6,7 @@ using System.Runtime.InteropServices; using System.Text; -#if MS_IO_REDIST -using System; -using System.IO; - -namespace Microsoft.IO -#else namespace System.IO -#endif { // Provides methods for processing file system strings in a cross-platform manner. // Most of the methods don't do a complete parsing (such as examining a UNC hostname), @@ -77,15 +70,9 @@ public static partial class Path } ReadOnlySpan subpath = path.AsSpan(0, subLength); -#if MS_IO_REDIST - return extension.Length != 0 && extension[0] == '.' ? - StringExtensions.Concat(subpath, extension.AsSpan()) : - StringExtensions.Concat(subpath, ".".AsSpan(), extension.AsSpan()); -#else return extension.StartsWith('.') ? string.Concat(subpath, extension) : string.Concat(subpath, ".", extension); -#endif } /// @@ -253,11 +240,7 @@ public static unsafe string GetRandomFileName() byte* pKey = stackalloc byte[KeyLength]; Interop.GetRandomBytes(pKey, KeyLength); -#if MS_IO_REDIST - return StringExtensions.Create( -#else return string.Create( -#endif 12, (IntPtr)pKey, (span, key) => // 12 == 8 + 1 (for period) + 3 Populate83FileNameFromRandomBytes((byte*)key, KeyLength, span)); } @@ -645,25 +628,9 @@ private static unsafe string JoinInternal(ReadOnlySpan first, ReadOnlySpan bool hasSeparator = PathInternal.IsDirectorySeparator(first[first.Length - 1]) || PathInternal.IsDirectorySeparator(second[0]); -#if !MS_IO_REDIST return hasSeparator ? string.Concat(first, second) : string.Concat(first, PathInternal.DirectorySeparatorCharAsString, second); -#else - fixed (char* f = &MemoryMarshal.GetReference(first), s = &MemoryMarshal.GetReference(second)) - { - return StringExtensions.Create( - first.Length + second.Length + (hasSeparator ? 0 : 1), - (First: (IntPtr)f, FirstLength: first.Length, Second: (IntPtr)s, SecondLength: second.Length), - static (destination, state) => - { - new Span((char*)state.First, state.FirstLength).CopyTo(destination); - if (destination.Length != (state.FirstLength + state.SecondLength)) - destination[state.FirstLength] = PathInternal.DirectorySeparatorChar; - new Span((char*)state.Second, state.SecondLength).CopyTo(destination.Slice(destination.Length - state.SecondLength)); - }); - } -#endif } private unsafe readonly struct Join3Payload @@ -702,11 +669,8 @@ private static unsafe string JoinInternal(ReadOnlySpan first, ReadOnlySpan var payload = new Join3Payload( f, first.Length, s, second.Length, t, third.Length, (byte)(firstNeedsSeparator | secondNeedsSeparator << 1)); -#if MS_IO_REDIST - return StringExtensions.Create( -#else + return string.Create( -#endif first.Length + second.Length + third.Length + firstNeedsSeparator + secondNeedsSeparator, (IntPtr)(&payload), static (destination, statePtr) => @@ -765,11 +729,8 @@ private static unsafe string JoinInternal(ReadOnlySpan first, ReadOnlySpan var payload = new Join4Payload( f, first.Length, s, second.Length, t, third.Length, u, fourth.Length, (byte)(firstNeedsSeparator | secondNeedsSeparator << 1 | thirdNeedsSeparator << 2)); -#if MS_IO_REDIST - return StringExtensions.Create( -#else + return string.Create( -#endif first.Length + second.Length + third.Length + fourth.Length + firstNeedsSeparator + secondNeedsSeparator + thirdNeedsSeparator, (IntPtr)(&payload), static (destination, statePtr) => diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs index 992dcc54f5be5..d922e89c13de5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs @@ -33,9 +33,30 @@ internal static unsafe int ReadAtOffset(SafeFileHandle handle, Span buffer // The Windows implementation uses ReadFile, which ignores the offset if the handle // isn't seekable. We do the same manually with PRead vs Read, in order to enable // the function to be used by FileStream for all the same situations. - int result = handle.CanSeek ? - Interop.Sys.PRead(handle, bufPtr, buffer.Length, fileOffset) : - Interop.Sys.Read(handle, bufPtr, buffer.Length); + int result; + if (handle.SupportsRandomAccess) + { + // Try pread for seekable files. + result = Interop.Sys.PRead(handle, bufPtr, buffer.Length, fileOffset); + if (result == -1) + { + // We need to fallback to the non-offset version for certain file types + // e.g: character devices (such as /dev/tty), pipes, and sockets. + Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); + + if (errorInfo.Error == Interop.Error.ENXIO || + errorInfo.Error == Interop.Error.ESPIPE) + { + handle.SupportsRandomAccess = false; + result = Interop.Sys.Read(handle, bufPtr, buffer.Length); + } + } + } + else + { + result = Interop.Sys.Read(handle, bufPtr, buffer.Length); + } + FileStreamHelpers.CheckFileCall(result, handle.Path); return result; } @@ -90,9 +111,29 @@ internal static unsafe void WriteAtOffset(SafeFileHandle handle, ReadOnlySpan(IReadOnlyList buffers, - THandler handler, out MemoryHandle[] handlesToDispose, out IntPtr segmentsPtr, out int totalBytes) - where THandler: struct, IMemoryHandler + THandler handler, [NotNullWhen(true)] out MemoryHandle[]? handlesToDispose, out IntPtr segmentsPtr, out int totalBytes) + where THandler : struct, IMemoryHandler { int pageSize = s_cachedPageSize; Debug.Assert(BitOperations.IsPow2(pageSize), "Page size is not a power of two."); @@ -447,13 +448,11 @@ private static unsafe bool TryPrepareScatterGatherBuffers(IReadOnly long alignedAtPageSizeMask = pageSize - 1; int buffersCount = buffers.Count; - handlesToDispose = new MemoryHandle[buffersCount]; + handlesToDispose = null; segmentsPtr = IntPtr.Zero; totalBytes = 0; - // "The array must contain enough elements to store nNumberOfBytesToWrite bytes of data, and one element for the terminating NULL. " - long* segments = (long*) NativeMemory.Alloc((nuint)(buffersCount + 1), sizeof(long)); - segments[buffersCount] = 0; + long* segments = null; bool success = false; try @@ -469,36 +468,55 @@ private static unsafe bool TryPrepareScatterGatherBuffers(IReadOnly return false; } - MemoryHandle handle = handlesToDispose[i] = handler.Pin(in buffer); - long ptr = segments[i] = (long)handle.Pointer; + MemoryHandle handle = handler.Pin(in buffer); + long ptr = (long)handle.Pointer; if ((ptr & alignedAtPageSizeMask) != 0) { + handle.Dispose(); return false; } + + // We avoid allocations if there are no + // buffers or the first one is unacceptable. + (handlesToDispose ??= new MemoryHandle[buffersCount])[i] = handle; + if (segments == null) + { + // "The array must contain enough elements to store nNumberOfBytesToWrite + // bytes of data, and one element for the terminating NULL." + segments = (long*)NativeMemory.Alloc((nuint)buffersCount + 1, sizeof(long)); + segments[buffersCount] = 0; + } + segments[i] = ptr; } segmentsPtr = (IntPtr)segments; totalBytes = (int)totalBytes64; success = true; - return true; + return handlesToDispose != null; } finally { if (!success) { - CleanupScatterGatherBuffers(handlesToDispose, (IntPtr) segments); + CleanupScatterGatherBuffers(handlesToDispose, (IntPtr)segments); } } } - private static unsafe void CleanupScatterGatherBuffers(MemoryHandle[] handlesToDispose, IntPtr segmentsPtr) + private static unsafe void CleanupScatterGatherBuffers(MemoryHandle[]? handlesToDispose, IntPtr segmentsPtr) { - foreach (MemoryHandle handle in handlesToDispose) + if (handlesToDispose != null) { - handle.Dispose(); + foreach (MemoryHandle handle in handlesToDispose) + { + handle.Dispose(); + } } - NativeMemory.Free((void*) segmentsPtr); + if (segmentsPtr != IntPtr.Zero) + { + NativeMemory.Free((void*)segmentsPtr); + } } private static ValueTask ReadScatterAtOffsetAsync(SafeFileHandle handle, IReadOnlyList> buffers, @@ -510,7 +528,7 @@ private static ValueTask ReadScatterAtOffsetAsync(SafeFileHandle handle, I } if (CanUseScatterGatherWindowsAPIs(handle) - && TryPrepareScatterGatherBuffers(buffers, default(MemoryHandler), out MemoryHandle[] handlesToDispose, out IntPtr segmentsPtr, out int totalBytes)) + && TryPrepareScatterGatherBuffers(buffers, default(MemoryHandler), out MemoryHandle[]? handlesToDispose, out IntPtr segmentsPtr, out int totalBytes)) { return ReadScatterAtOffsetSingleSyscallAsync(handle, handlesToDispose, segmentsPtr, fileOffset, totalBytes, cancellationToken); } @@ -607,7 +625,7 @@ private static ValueTask WriteGatherAtOffsetAsync(SafeFileHandle handle, IReadOn } if (CanUseScatterGatherWindowsAPIs(handle) - && TryPrepareScatterGatherBuffers(buffers, default(ReadOnlyMemoryHandler), out MemoryHandle[] handlesToDispose, out IntPtr segmentsPtr, out int totalBytes)) + && TryPrepareScatterGatherBuffers(buffers, default(ReadOnlyMemoryHandler), out MemoryHandle[]? handlesToDispose, out IntPtr segmentsPtr, out int totalBytes)) { return WriteGatherAtOffsetSingleSyscallAsync(handle, handlesToDispose, segmentsPtr, fileOffset, totalBytes, cancellationToken); } @@ -671,25 +689,26 @@ private static unsafe ValueTask WriteFileGatherAsync(SafeFileHandle handle, IntP private static async ValueTask WriteGatherAtOffsetMultipleSyscallsAsync(SafeFileHandle handle, IReadOnlyList> buffers, long fileOffset, CancellationToken cancellationToken) { - long bytesWritten = 0; int buffersCount = buffers.Count; for (int i = 0; i < buffersCount; i++) { ReadOnlyMemory rom = buffers[i]; - await WriteAtOffsetAsync(handle, rom, fileOffset + bytesWritten, cancellationToken).ConfigureAwait(false); - bytesWritten += rom.Length; + await WriteAtOffsetAsync(handle, rom, fileOffset, cancellationToken).ConfigureAwait(false); + fileOffset += rom.Length; } } - private static unsafe NativeOverlapped* GetNativeOverlappedForAsyncHandle(ThreadPoolBoundHandle threadPoolBinding, long fileOffset, CallbackResetEvent resetEvent) + private static unsafe NativeOverlapped* GetNativeOverlappedForAsyncHandle(SafeFileHandle handle, long fileOffset, CallbackResetEvent resetEvent) { // After SafeFileHandle is bound to ThreadPool, we need to use ThreadPoolBinding // to allocate a native overlapped and provide a valid callback. - NativeOverlapped* result = threadPoolBinding.AllocateNativeOverlapped(s_callback, resetEvent, null); + NativeOverlapped* result = handle.ThreadPoolBinding!.AllocateNativeOverlapped(s_callback, resetEvent, null); - // For pipes the offsets are ignored by the OS - result->OffsetLow = unchecked((int)fileOffset); - result->OffsetHigh = (int)(fileOffset >> 32); + if (handle.CanSeek) + { + result->OffsetLow = unchecked((int)fileOffset); + result->OffsetHigh = (int)(fileOffset >> 32); + } // From https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-getoverlappedresult: // "If the hEvent member of the OVERLAPPED structure is NULL, the system uses the state of the hFile handle to signal when the operation has been completed. diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/SearchOption.cs b/src/libraries/System.Private.CoreLib/src/System/IO/SearchOption.cs index c7fd2be70b68a..b37681889ada3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/SearchOption.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/SearchOption.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if MS_IO_REDIST -namespace Microsoft.IO -#else namespace System.IO -#endif { /// /// Enum describing whether the search operation should diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/SearchTarget.cs b/src/libraries/System.Private.CoreLib/src/System/IO/SearchTarget.cs index a1bed2ae7ff16..2b1bc9d89feac 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/SearchTarget.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/SearchTarget.cs @@ -1,11 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if MS_IO_REDIST -namespace Microsoft.IO -#else namespace System.IO -#endif { internal enum SearchTarget { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Windows.cs index 5ba493ca9ca21..b519b32a05ba2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Windows.cs @@ -14,9 +14,8 @@ namespace System.IO.Strategies // this type defines a set of stateless FileStream/FileStreamStrategy helper methods internal static partial class FileStreamHelpers { - // Async completion/return codes shared by: - // - AsyncWindowsFileStreamStrategy.ValueTaskSource - // - Net5CompatFileStreamStrategy.CompletionSource + // Async completion/return codes used by + // SafeFileHandle.OverlappedValueTaskSource internal static class TaskSourceCodes { internal const long NoResult = 0; @@ -338,7 +337,7 @@ internal static async Task AsyncModeCopyToAsync(SafeFileHandle handle, bool canS } } - /// Used by AsyncWindowsFileStreamStrategy and Net5CompatFileStreamStrategy CopyToAsync to enable awaiting the result of an overlapped I/O operation with minimal overhead. + /// Used by AsyncWindowsFileStreamStrategy.CopyToAsync to enable awaiting the result of an overlapped I/O operation with minimal overhead. private sealed unsafe class AsyncCopyToAwaitable : ICriticalNotifyCompletion { /// Sentinel object used to indicate that the I/O operation has completed before being awaited. diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.cs index 3db2174d3fbd1..e3b419e278973 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.cs @@ -11,15 +11,9 @@ internal static partial class FileStreamHelpers /// Caches whether Serialization Guard has been disabled for file writes private static int s_cachedSerializationSwitch; - internal static bool UseNet5CompatStrategy { get; } = AppContextConfigHelper.GetBooleanConfig("System.IO.UseNet5CompatFileStream", "DOTNET_SYSTEM_IO_USENET5COMPATFILESTREAM"); - internal static FileStreamStrategy ChooseStrategy(FileStream fileStream, SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) { - // The .NET 5 Compat strategy does not support bufferSize == 0. - // To minimize the risk of introducing bugs to it, we just pass 1 to disable the buffering. - - FileStreamStrategy strategy = UseNet5CompatStrategy ? - new Net5CompatFileStreamStrategy(handle, access, bufferSize == 0 ? 1 : bufferSize, isAsync) : + FileStreamStrategy strategy = EnableBufferingIfNeeded(ChooseStrategyCore(handle, access, isAsync), bufferSize); return WrapIfDerivedType(fileStream, strategy); @@ -27,8 +21,7 @@ internal static FileStreamStrategy ChooseStrategy(FileStream fileStream, SafeFil internal static FileStreamStrategy ChooseStrategy(FileStream fileStream, string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, long preallocationSize) { - FileStreamStrategy strategy = UseNet5CompatStrategy ? - new Net5CompatFileStreamStrategy(path, mode, access, share, bufferSize == 0 ? 1 : bufferSize, options, preallocationSize) : + FileStreamStrategy strategy = EnableBufferingIfNeeded(ChooseStrategyCore(path, mode, access, share, options, preallocationSize), bufferSize); return WrapIfDerivedType(fileStream, strategy); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/Net5CompatFileStreamStrategy.CompletionSource.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/Net5CompatFileStreamStrategy.CompletionSource.Windows.cs deleted file mode 100644 index 2c8a13feace0c..0000000000000 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/Net5CompatFileStreamStrategy.CompletionSource.Windows.cs +++ /dev/null @@ -1,250 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Buffers; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; -using TaskSourceCodes = System.IO.Strategies.FileStreamHelpers.TaskSourceCodes; - -namespace System.IO.Strategies -{ - internal sealed partial class Net5CompatFileStreamStrategy : FileStreamStrategy - { - // This is an internal object extending TaskCompletionSource with fields - // for all of the relevant data necessary to complete the IO operation. - // This is used by IOCallback and all of the async methods. - private unsafe class CompletionSource : TaskCompletionSource - { - internal static readonly unsafe IOCompletionCallback s_ioCallback = IOCallback; - - private static Action? s_cancelCallback; - - private readonly Net5CompatFileStreamStrategy _strategy; - private readonly int _numBufferedBytes; - private CancellationTokenRegistration _cancellationRegistration; -#if DEBUG - private bool _cancellationHasBeenRegistered; -#endif - private NativeOverlapped* _overlapped; // Overlapped class responsible for operations in progress when an appdomain unload occurs - private long _result; // Using long since this needs to be used in Interlocked APIs - - // Using RunContinuationsAsynchronously for compat reasons (old API used Task.Factory.StartNew for continuations) - internal CompletionSource(Net5CompatFileStreamStrategy strategy, PreAllocatedOverlapped? preallocatedOverlapped, - int numBufferedBytes, byte[]? bytes) : base(TaskCreationOptions.RunContinuationsAsynchronously) - { - _numBufferedBytes = numBufferedBytes; - _strategy = strategy; - _result = TaskSourceCodes.NoResult; - - // The _preallocatedOverlapped is null if the internal buffer was never created, so we check for - // a non-null bytes before using the stream's _preallocatedOverlapped - _overlapped = bytes != null && strategy.CompareExchangeCurrentOverlappedOwner(this, null) == null ? - strategy._fileHandle.ThreadPoolBinding!.AllocateNativeOverlapped(preallocatedOverlapped!) : // allocated when buffer was created, and buffer is non-null - strategy._fileHandle.ThreadPoolBinding!.AllocateNativeOverlapped(s_ioCallback, this, bytes); - Debug.Assert(_overlapped != null, "AllocateNativeOverlapped returned null"); - } - - internal NativeOverlapped* Overlapped => _overlapped; - - public void SetCompletedSynchronously(int numBytes) - { - ReleaseNativeResource(); - TrySetResult(numBytes + _numBufferedBytes); - } - - public void RegisterForCancellation(CancellationToken cancellationToken) - { -#if DEBUG - Debug.Assert(cancellationToken.CanBeCanceled); - Debug.Assert(!_cancellationHasBeenRegistered, "Cannot register for cancellation twice"); - _cancellationHasBeenRegistered = true; -#endif - - // Quick check to make sure the IO hasn't completed - if (_overlapped != null) - { - Action? cancelCallback = s_cancelCallback ??= Cancel; - - // Register the cancellation only if the IO hasn't completed - long packedResult = Interlocked.CompareExchange(ref _result, TaskSourceCodes.RegisteringCancellation, TaskSourceCodes.NoResult); - if (packedResult == TaskSourceCodes.NoResult) - { - _cancellationRegistration = cancellationToken.UnsafeRegister(cancelCallback, this); - - // Switch the result, just in case IO completed while we were setting the registration - packedResult = Interlocked.Exchange(ref _result, TaskSourceCodes.NoResult); - } - else if (packedResult != TaskSourceCodes.CompletedCallback) - { - // Failed to set the result, IO is in the process of completing - // Attempt to take the packed result - packedResult = Interlocked.Exchange(ref _result, TaskSourceCodes.NoResult); - } - - // If we have a callback that needs to be completed - if ((packedResult != TaskSourceCodes.NoResult) && (packedResult != TaskSourceCodes.CompletedCallback) && (packedResult != TaskSourceCodes.RegisteringCancellation)) - { - CompleteCallback((ulong)packedResult); - } - } - } - - internal virtual void ReleaseNativeResource() - { - // Ensure that cancellation has been completed and cleaned up. - _cancellationRegistration.Dispose(); - - // Free the overlapped. - // NOTE: The cancellation must *NOT* be running at this point, or it may observe freed memory - // (this is why we disposed the registration above). - if (_overlapped != null) - { - _strategy._fileHandle.ThreadPoolBinding!.FreeNativeOverlapped(_overlapped); - _overlapped = null; - } - - // Ensure we're no longer set as the current completion source (we may not have been to begin with). - // Only one operation at a time is eligible to use the preallocated overlapped, - _strategy.CompareExchangeCurrentOverlappedOwner(null, this); - } - - // When doing IO asynchronously (i.e. _isAsync==true), this callback is - // called by a free thread in the threadpool when the IO operation - // completes. - internal static void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* pOverlapped) - { - // Extract the completion source from the overlapped. The state in the overlapped - // will either be a FileStreamStrategy (in the case where the preallocated overlapped was used), - // in which case the operation being completed is its _currentOverlappedOwner, or it'll - // be directly the FileStreamCompletionSource that's completing (in the case where the preallocated - // overlapped was already in use by another operation). - object? state = ThreadPoolBoundHandle.GetNativeOverlappedState(pOverlapped); - Debug.Assert(state is Net5CompatFileStreamStrategy || state is CompletionSource); - CompletionSource completionSource = state switch - { - Net5CompatFileStreamStrategy strategy => strategy._currentOverlappedOwner!, // must be owned - _ => (CompletionSource)state - }; - Debug.Assert(completionSource != null); - Debug.Assert(completionSource._overlapped == pOverlapped, "Overlaps don't match"); - - // Handle reading from & writing to closed pipes. While I'm not sure - // this is entirely necessary anymore, maybe it's possible for - // an async read on a pipe to be issued and then the pipe is closed, - // returning this error. This may very well be necessary. - ulong packedResult; - if (errorCode != 0 && errorCode != Interop.Errors.ERROR_BROKEN_PIPE && errorCode != Interop.Errors.ERROR_NO_DATA) - { - packedResult = ((ulong)TaskSourceCodes.ResultError | errorCode); - } - else - { - packedResult = ((ulong)TaskSourceCodes.ResultSuccess | numBytes); - } - - // Stow the result so that other threads can observe it - // And, if no other thread is registering cancellation, continue - if (TaskSourceCodes.NoResult == Interlocked.Exchange(ref completionSource._result, (long)packedResult)) - { - // Successfully set the state, attempt to take back the callback - if (Interlocked.Exchange(ref completionSource._result, TaskSourceCodes.CompletedCallback) != TaskSourceCodes.NoResult) - { - // Successfully got the callback, finish the callback - completionSource.CompleteCallback(packedResult); - } - // else: Some other thread stole the result, so now it is responsible to finish the callback - } - // else: Some other thread is registering a cancellation, so it *must* finish the callback - } - - private void CompleteCallback(ulong packedResult) - { - // Free up the native resource and cancellation registration - CancellationToken cancellationToken = _cancellationRegistration.Token; // access before disposing registration - ReleaseNativeResource(); - - // Unpack the result and send it to the user - long result = (long)(packedResult & TaskSourceCodes.ResultMask); - if (result == TaskSourceCodes.ResultError) - { - int errorCode = unchecked((int)(packedResult & uint.MaxValue)); - if (errorCode == Interop.Errors.ERROR_OPERATION_ABORTED) - { - TrySetCanceled(cancellationToken.IsCancellationRequested ? cancellationToken : new CancellationToken(true)); - } - else - { - Exception e = Win32Marshal.GetExceptionForWin32Error(errorCode); - e.SetCurrentStackTrace(); - TrySetException(e); - } - } - else - { - Debug.Assert(result == TaskSourceCodes.ResultSuccess, "Unknown result"); - TrySetResult((int)(packedResult & uint.MaxValue) + _numBufferedBytes); - } - } - - private static void Cancel(object? state) - { - // WARNING: This may potentially be called under a lock (during cancellation registration) - - Debug.Assert(state is CompletionSource, "Unknown state passed to cancellation"); - CompletionSource completionSource = (CompletionSource)state; - Debug.Assert(completionSource._overlapped != null && !completionSource.Task.IsCompleted, "IO should not have completed yet"); - - // If the handle is still valid, attempt to cancel the IO - if (!completionSource._strategy._fileHandle.IsInvalid && - !Interop.Kernel32.CancelIoEx(completionSource._strategy._fileHandle, completionSource._overlapped)) - { - int errorCode = Marshal.GetLastPInvokeError(); - - // ERROR_NOT_FOUND is returned if CancelIoEx cannot find the request to cancel. - // This probably means that the IO operation has completed. - if (errorCode != Interop.Errors.ERROR_NOT_FOUND) - { - throw Win32Marshal.GetExceptionForWin32Error(errorCode); - } - } - } - - public static CompletionSource Create(Net5CompatFileStreamStrategy strategy, PreAllocatedOverlapped? preallocatedOverlapped, - int numBufferedBytesRead, ReadOnlyMemory memory) - { - // If the memory passed in is the strategy's internal buffer, we can use the base FileStreamCompletionSource, - // which has a PreAllocatedOverlapped with the memory already pinned. Otherwise, we use the derived - // MemoryFileStreamCompletionSource, which Retains the memory, which will result in less pinning in the case - // where the underlying memory is backed by pre-pinned buffers. - return preallocatedOverlapped != null && MemoryMarshal.TryGetArray(memory, out ArraySegment buffer) - && preallocatedOverlapped.IsUserObject(buffer.Array) // preallocatedOverlapped is allocated when BufferedStream|Net5CompatFileStreamStrategy allocates the buffer - ? new CompletionSource(strategy, preallocatedOverlapped, numBufferedBytesRead, buffer.Array) - : new MemoryFileStreamCompletionSource(strategy, numBufferedBytesRead, memory); - } - } - - /// - /// Extends with to support disposing of a - /// when the operation has completed. This should only be used - /// when memory doesn't wrap a byte[]. - /// - private sealed class MemoryFileStreamCompletionSource : CompletionSource - { - private MemoryHandle _handle; // mutable struct; do not make this readonly - - internal MemoryFileStreamCompletionSource(Net5CompatFileStreamStrategy strategy, int numBufferedBytes, ReadOnlyMemory memory) - : base(strategy, null, numBufferedBytes, null) // this type handles the pinning, so null is passed for bytes - { - _handle = memory.Pin(); - } - - internal override void ReleaseNativeResource() - { - _handle.Dispose(); - base.ReleaseNativeResource(); - } - } - } -} diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/Net5CompatFileStreamStrategy.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/Net5CompatFileStreamStrategy.Unix.cs deleted file mode 100644 index 2feffb5cb6be5..0000000000000 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/Net5CompatFileStreamStrategy.Unix.cs +++ /dev/null @@ -1,601 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.Win32.SafeHandles; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.Versioning; -using System.Threading; -using System.Threading.Tasks; - -namespace System.IO.Strategies -{ - /// Provides an implementation of a file stream for Unix files. - internal sealed partial class Net5CompatFileStreamStrategy : FileStreamStrategy - { - /// Advanced options requested when opening the file. - private FileOptions _options; - - /// If the file was opened with FileMode.Append, the length of the file when opened; otherwise, -1. - private long _appendStart = -1; - - /// - /// Extra state used by the file stream when _useAsyncIO is true. This includes - /// the semaphore used to serialize all operation, the buffer/offset/count provided by the - /// caller for ReadAsync/WriteAsync operations, and the last successful task returned - /// synchronously from ReadAsync which can be reused if the count matches the next request. - /// Only initialized when is true. - /// - private AsyncState? _asyncState; - - private void Init(FileMode mode, string originalPath, FileOptions options) - { - // FileStream performs most of the general argument validation. We can assume here that the arguments - // are all checked and consistent (e.g. non-null-or-empty path; valid enums in mode, access, share, and options; etc.) - // Store the arguments - _options = options; - - if (_useAsyncIO) - { - _asyncState = new AsyncState(); - } - - if (mode == FileMode.Append) - { - // Jump to the end of the file if opened as Append. - _appendStart = SeekCore(_fileHandle, 0, SeekOrigin.End); - } - - Debug.Assert(_fileHandle.IsAsync == _useAsyncIO); - } - - /// Initializes a stream from an already open file handle (file descriptor). - private void InitFromHandle(SafeFileHandle handle, FileAccess access, bool useAsyncIO) - { - if (useAsyncIO) - _asyncState = new AsyncState(); - - if (handle.CanSeek) - SeekCore(handle, 0, SeekOrigin.Current); - } - - public override bool CanSeek => _fileHandle.CanSeek; - - public override long Length - { - get - { - // Get the length of the file as reported by the OS - long length = RandomAccess.GetFileLength(_fileHandle); - - // But we may have buffered some data to be written that puts our length - // beyond what the OS is aware of. Update accordingly. - if (_writePos > 0 && _filePosition + _writePos > length) - { - length = _writePos + _filePosition; - } - - return length; - } - } - - /// Prevents other processes from reading from or writing to the FileStream. - /// The beginning of the range to lock. - /// The range to be locked. - internal override void Lock(long position, long length) => - FileStreamHelpers.Lock(_fileHandle, CanWrite, position, length); - - /// Allows access by other processes to all or part of a file that was previously locked. - /// The beginning of the range to unlock. - /// The range to be unlocked. - internal override void Unlock(long position, long length) => - FileStreamHelpers.Unlock(_fileHandle, position, length); - - /// Releases the unmanaged resources used by the stream. - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected override void Dispose(bool disposing) - { - try - { - if (_fileHandle != null && !_fileHandle.IsClosed) - { - // Flush any remaining data in the file - try - { - FlushWriteBuffer(); - } - catch (Exception e) when (!disposing && FileStreamHelpers.IsIoRelatedException(e)) - { - // On finalization, ignore failures from trying to flush the write buffer, - // e.g. if this stream is wrapping a pipe and the pipe is now broken. - } - - // Closing the file handle can fail, e.g. due to out of disk space - // Throw these errors as exceptions when disposing - if (_fileHandle != null && !_fileHandle.IsClosed && disposing) - { - SafeFileHandle.t_lastCloseErrorInfo = null; - - _fileHandle.Dispose(); - - if (SafeFileHandle.t_lastCloseErrorInfo != null) - { - throw Interop.GetExceptionForIoErrno(SafeFileHandle.t_lastCloseErrorInfo.GetValueOrDefault(), _fileHandle.Path, isDirectory: false); - } - } - } - } - finally - { - if (_fileHandle != null && !_fileHandle.IsClosed) - { - _fileHandle.Dispose(); - } - base.Dispose(disposing); - } - } - - public override ValueTask DisposeAsync() - { - // On Unix, we don't have any special support for async I/O, simply queueing writes - // rather than doing them synchronously. As such, if we're "using async I/O" and we - // have something to flush, queue the call to Dispose, so that we end up queueing whatever - // write work happens to flush the buffer. Otherwise, just delegate to the base implementation, - // which will synchronously invoke Dispose. We don't need to factor in the current type - // as we're using the virtual Dispose either way, and therefore factoring in whatever - // override may already exist on a derived type. - if (_useAsyncIO && _writePos > 0) - { - return new ValueTask(Task.Factory.StartNew(static s => ((Net5CompatFileStreamStrategy)s!).Dispose(), this, - CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default)); - } - - return base.DisposeAsync(); - } - - private void FlushWriteBufferForWriteByte() - { -#pragma warning disable CA1416 // Validate platform compatibility, issue: https://github.com/dotnet/runtime/issues/44542 - _asyncState?.Wait(); -#pragma warning restore CA1416 - try { FlushWriteBuffer(); } - finally { _asyncState?.Release(); } - } - - /// Writes any data in the write buffer to the underlying stream and resets the buffer. - private void FlushWriteBuffer(bool calledFromFinalizer = false) - { - AssertBufferInvariants(); - if (_writePos > 0) - { - WriteNative(new ReadOnlySpan(GetBuffer(), 0, _writePos)); - _writePos = 0; - } - } - - /// Sets the length of this stream to the given value. - /// The new length of the stream. - public override void SetLength(long value) - { - FlushInternalBuffer(); - - if (_appendStart != -1 && value < _appendStart) - { - throw new IOException(SR.IO_SetLengthAppendTruncate); - } - - VerifyOSHandlePosition(); - - CheckFileCall(Interop.Sys.FTruncate(_fileHandle, value)); - - // Set file pointer to end of file - if (_filePosition > value) - { - SeekCore(_fileHandle, 0, SeekOrigin.End); - } - } - - /// Reads a block of bytes from the stream and writes the data in a given buffer. - private int ReadSpan(Span destination) - { - PrepareForReading(); - - // Are there any bytes available in the read buffer? If yes, - // we can just return from the buffer. If the buffer is empty - // or has no more available data in it, we can either refill it - // (and then read from the buffer into the user's buffer) or - // we can just go directly into the user's buffer, if they asked - // for more data than we'd otherwise buffer. - int numBytesAvailable = _readLength - _readPos; - bool readFromOS = false; - if (numBytesAvailable == 0) - { - // If we're not able to seek, then we're not able to rewind the stream (i.e. flushing - // a read buffer), in which case we don't want to use a read buffer. Similarly, if - // the user has asked for more data than we can buffer, we also want to skip the buffer. - if (!CanSeek || (destination.Length >= _bufferLength)) - { - // Read directly into the user's buffer - _readPos = _readLength = 0; - return ReadNative(destination); - } - else - { - // Read into our buffer. - _readLength = numBytesAvailable = ReadNative(GetBuffer()); - _readPos = 0; - if (numBytesAvailable == 0) - { - return 0; - } - - // Note that we did an OS read as part of this Read, so that later - // we don't try to do one again if what's in the buffer doesn't - // meet the user's request. - readFromOS = true; - } - } - - // Now that we know there's data in the buffer, read from it into the user's buffer. - Debug.Assert(numBytesAvailable > 0, "Data must be in the buffer to be here"); - int bytesRead = Math.Min(numBytesAvailable, destination.Length); - new Span(GetBuffer(), _readPos, bytesRead).CopyTo(destination); - _readPos += bytesRead; - - // We may not have had enough data in the buffer to completely satisfy the user's request. - // While Read doesn't require that we return as much data as the user requested (any amount - // up to the requested count is fine), FileStream on Windows tries to do so by doing a - // subsequent read from the file if we tried to satisfy the request with what was in the - // buffer but the buffer contained less than the requested count. To be consistent with that - // behavior, we do the same thing here on Unix. Note that we may still get less the requested - // amount, as the OS may give us back fewer than we request, either due to reaching the end of - // file, or due to its own whims. - if (!readFromOS && bytesRead < destination.Length) - { - Debug.Assert(_readPos == _readLength, "bytesToRead should only be < destination.Length if numBytesAvailable < destination.Length"); - _readPos = _readLength = 0; // no data left in the read buffer - bytesRead += ReadNative(destination.Slice(bytesRead)); - } - - return bytesRead; - } - - /// Unbuffered, reads a block of bytes from the file handle into the given buffer. - /// The buffer into which data from the file is read. - /// - /// The total number of bytes read into the buffer. This might be less than the number of bytes requested - /// if that number of bytes are not currently available, or zero if the end of the stream is reached. - /// - private unsafe int ReadNative(Span buffer) - { - FlushWriteBuffer(); // we're about to read; dump the write buffer - - VerifyOSHandlePosition(); - - int bytesRead; - fixed (byte* bufPtr = &MemoryMarshal.GetReference(buffer)) - { - bytesRead = CheckFileCall(Interop.Sys.Read(_fileHandle, bufPtr, buffer.Length)); - Debug.Assert(bytesRead <= buffer.Length); - } - _filePosition += bytesRead; - return bytesRead; - } - - /// - /// Asynchronously reads a sequence of bytes from the current stream and advances - /// the position within the stream by the number of bytes read. - /// - /// The buffer to write the data into. - /// The token to monitor for cancellation requests. - /// If the operation completes synchronously, the number of bytes read. - /// A task that represents the asynchronous read operation. - private Task? ReadAsyncInternal(Memory destination, CancellationToken cancellationToken, out int synchronousResult) - { - Debug.Assert(_useAsyncIO); - Debug.Assert(_asyncState != null); - - if (!CanRead) // match Windows behavior; this gets thrown synchronously - { - ThrowHelper.ThrowNotSupportedException_UnreadableStream(); - } - - // Serialize operations using the semaphore. - Task waitTask = _asyncState.WaitAsync(); - - // If we got ownership immediately, and if there's enough data in our buffer - // to satisfy the full request of the caller, hand back the buffered data. - // While it would be a legal implementation of the Read contract, we don't - // hand back here less than the amount requested so as to match the behavior - // in ReadCore that will make a native call to try to fulfill the remainder - // of the request. - if (waitTask.Status == TaskStatus.RanToCompletion) - { - int numBytesAvailable = _readLength - _readPos; - if (numBytesAvailable >= destination.Length) - { - try - { - PrepareForReading(); - - new Span(GetBuffer(), _readPos, destination.Length).CopyTo(destination.Span); - _readPos += destination.Length; - - synchronousResult = destination.Length; - return null; - } - catch (Exception exc) - { - synchronousResult = 0; - return Task.FromException(exc); - } - finally - { - _asyncState.Release(); - } - } - } - - // Otherwise, issue the whole request asynchronously. - synchronousResult = 0; - _asyncState.Memory = destination; - return waitTask.ContinueWith(static (t, s) => - { - // The options available on Unix for writing asynchronously to an arbitrary file - // handle typically amount to just using another thread to do the synchronous write, - // which is exactly what this implementation does. This does mean there are subtle - // differences in certain FileStream behaviors between Windows and Unix when multiple - // asynchronous operations are issued against the stream to execute concurrently; on - // Unix the operations will be serialized due to the usage of a semaphore, but the - // position /length information won't be updated until after the write has completed, - // whereas on Windows it may happen before the write has completed. - - Debug.Assert(t.Status == TaskStatus.RanToCompletion); - var thisRef = (Net5CompatFileStreamStrategy)s!; - Debug.Assert(thisRef._asyncState != null); - try - { - Memory memory = thisRef._asyncState.Memory; - thisRef._asyncState.Memory = default; - return thisRef.ReadSpan(memory.Span); - } - finally { thisRef._asyncState.Release(); } - }, this, CancellationToken.None, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default); - } - - /// Reads from the file handle into the buffer, overwriting anything in it. - private int FillReadBufferForReadByte() - { -#pragma warning disable CA1416 // Validate platform compatibility, issue: https://github.com/dotnet/runtime/issues/44542 - _asyncState?.Wait(); -#pragma warning restore CA1416 - try { return ReadNative(_buffer); } - finally { _asyncState?.Release(); } - } - - /// Writes a block of bytes to the file stream. - /// The buffer containing data to write to the stream. - private void WriteSpan(ReadOnlySpan source) - { - PrepareForWriting(); - - // If no data is being written, nothing more to do. - if (source.Length == 0) - { - return; - } - - // If there's already data in our write buffer, then we need to go through - // our buffer to ensure data isn't corrupted. - if (_writePos > 0) - { - // If there's space remaining in the buffer, then copy as much as - // we can from the user's buffer into ours. - int spaceRemaining = _bufferLength - _writePos; - if (spaceRemaining >= source.Length) - { - source.CopyTo(GetBuffer().AsSpan(_writePos)); - _writePos += source.Length; - return; - } - else if (spaceRemaining > 0) - { - source.Slice(0, spaceRemaining).CopyTo(GetBuffer().AsSpan(_writePos)); - _writePos += spaceRemaining; - source = source.Slice(spaceRemaining); - } - - // At this point, the buffer is full, so flush it out. - FlushWriteBuffer(); - } - - // Our buffer is now empty. If using the buffer would slow things down (because - // the user's looking to write more data than we can store in the buffer), - // skip the buffer. Otherwise, put the remaining data into the buffer. - Debug.Assert(_writePos == 0); - if (source.Length >= _bufferLength) - { - WriteNative(source); - } - else - { - source.CopyTo(new Span(GetBuffer())); - _writePos = source.Length; - } - } - - /// Unbuffered, writes a block of bytes to the file stream. - /// The buffer containing data to write to the stream. - private unsafe void WriteNative(ReadOnlySpan source) - { - VerifyOSHandlePosition(); - - fixed (byte* bufPtr = &MemoryMarshal.GetReference(source)) - { - int offset = 0; - int count = source.Length; - while (count > 0) - { - int bytesWritten = CheckFileCall(Interop.Sys.Write(_fileHandle, bufPtr + offset, count)); - _filePosition += bytesWritten; - offset += bytesWritten; - count -= bytesWritten; - } - } - } - - /// - /// Asynchronously writes a sequence of bytes to the current stream, advances - /// the current position within this stream by the number of bytes written, and - /// monitors cancellation requests. - /// - /// The buffer to write data from. - /// The token to monitor for cancellation requests. - /// A task that represents the asynchronous write operation. - private ValueTask WriteAsyncInternal(ReadOnlyMemory source, CancellationToken cancellationToken) - { - Debug.Assert(_useAsyncIO); - Debug.Assert(_asyncState != null); - - if (cancellationToken.IsCancellationRequested) - return ValueTask.FromCanceled(cancellationToken); - - if (_fileHandle.IsClosed) - ThrowHelper.ThrowObjectDisposedException_FileClosed(); - - if (!CanWrite) // match Windows behavior; this gets thrown synchronously - { - ThrowHelper.ThrowNotSupportedException_UnwritableStream(); - } - - // Serialize operations using the semaphore. - Task waitTask = _asyncState.WaitAsync(cancellationToken); - - // If we got ownership immediately, and if there's enough space in our buffer - // to buffer the entire write request, then do so and we're done. - if (waitTask.Status == TaskStatus.RanToCompletion) - { - int spaceRemaining = _bufferLength - _writePos; - if (spaceRemaining >= source.Length) - { - try - { - PrepareForWriting(); - - source.Span.CopyTo(new Span(GetBuffer(), _writePos, source.Length)); - _writePos += source.Length; - - return default; - } - catch (Exception exc) - { - return ValueTask.FromException(exc); - } - finally - { - _asyncState.Release(); - } - } - } - - // Otherwise, issue the whole request asynchronously. - _asyncState.ReadOnlyMemory = source; - return new ValueTask(waitTask.ContinueWith(static (t, s) => - { - // The options available on Unix for writing asynchronously to an arbitrary file - // handle typically amount to just using another thread to do the synchronous write, - // which is exactly what this implementation does. This does mean there are subtle - // differences in certain FileStream behaviors between Windows and Unix when multiple - // asynchronous operations are issued against the stream to execute concurrently; on - // Unix the operations will be serialized due to the usage of a semaphore, but the - // position/length information won't be updated until after the write has completed, - // whereas on Windows it may happen before the write has completed. - - Debug.Assert(t.Status == TaskStatus.RanToCompletion); - var thisRef = (Net5CompatFileStreamStrategy)s!; - Debug.Assert(thisRef._asyncState != null); - try - { - ReadOnlyMemory readOnlyMemory = thisRef._asyncState.ReadOnlyMemory; - thisRef._asyncState.ReadOnlyMemory = default; - thisRef.WriteSpan(readOnlyMemory.Span); - } - finally { thisRef._asyncState.Release(); } - }, this, CancellationToken.None, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default)); - } - - /// Sets the current position of this stream to the given value. - /// The point relative to origin from which to begin seeking. - /// - /// Specifies the beginning, the end, or the current position as a reference - /// point for offset, using a value of type SeekOrigin. - /// - /// The new position in the stream. - public override long Seek(long offset, SeekOrigin origin) - { - if (origin < SeekOrigin.Begin || origin > SeekOrigin.End) - { - throw new ArgumentException(SR.Argument_InvalidSeekOrigin, nameof(origin)); - } - if (_fileHandle.IsClosed) - { - ThrowHelper.ThrowObjectDisposedException_FileClosed(); - } - if (!CanSeek) - { - ThrowHelper.ThrowNotSupportedException_UnseekableStream(); - } - - VerifyOSHandlePosition(); - - // Flush our write/read buffer. FlushWrite will output any write buffer we have and reset _bufferWritePos. - // We don't call FlushRead, as that will do an unnecessary seek to rewind the read buffer, and since we're - // about to seek and update our position, we can simply update the offset as necessary and reset our read - // position and length to 0. (In the future, for some simple cases we could potentially add an optimization - // here to just move data around in the buffer for short jumps, to avoid re-reading the data from disk.) - FlushWriteBuffer(); - if (origin == SeekOrigin.Current) - { - offset -= (_readLength - _readPos); - } - _readPos = _readLength = 0; - - // Keep track of where we were, in case we're in append mode and need to verify - long oldPos = 0; - if (_appendStart >= 0) - { - oldPos = SeekCore(_fileHandle, 0, SeekOrigin.Current); - } - - // Jump to the new location - long pos = SeekCore(_fileHandle, offset, origin); - - // Prevent users from overwriting data in a file that was opened in append mode. - if (_appendStart != -1 && pos < _appendStart) - { - SeekCore(_fileHandle, oldPos, SeekOrigin.Begin); - throw new IOException(SR.IO_SeekAppendOverwrite); - } - - // Return the new position - return pos; - } - - private int CheckFileCall(int result, bool ignoreNotSupported = false) - { - FileStreamHelpers.CheckFileCall(result, _fileHandle?.Path, ignoreNotSupported); - - return result; - } - - /// State used when the stream is in async mode. - private sealed class AsyncState : SemaphoreSlim - { - internal ReadOnlyMemory ReadOnlyMemory; - internal Memory Memory; - - /// Initialize the AsyncState. - internal AsyncState() : base(initialCount: 1, maxCount: 1) { } - } - } -} diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/Net5CompatFileStreamStrategy.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/Net5CompatFileStreamStrategy.Windows.cs deleted file mode 100644 index a2e7666114524..0000000000000 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/Net5CompatFileStreamStrategy.Windows.cs +++ /dev/null @@ -1,1104 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Win32.SafeHandles; - -/* - * Win32FileStream supports different modes of accessing the disk - async mode - * and sync mode. They are two completely different codepaths in the - * sync & async methods (i.e. Read/Write vs. ReadAsync/WriteAsync). File - * handles in NT can be opened in only sync or overlapped (async) mode, - * and we have to deal with this pain. Stream has implementations of - * the sync methods in terms of the async ones, so we'll - * call through to our base class to get those methods when necessary. - * - * Also buffering is added into Win32FileStream as well. Folded in the - * code from BufferedStream, so all the comments about it being mostly - * aggressive (and the possible perf improvement) apply to Win32FileStream as - * well. Also added some buffering to the async code paths. - * - * Class Invariants: - * The class has one buffer, shared for reading & writing. It can only be - * used for one or the other at any point in time - not both. The following - * should be true: - * 0 <= _readPos <= _readLen < _bufferSize - * 0 <= _writePos < _bufferSize - * _readPos == _readLen && _readPos > 0 implies the read buffer is valid, - * but we're at the end of the buffer. - * _readPos == _readLen == 0 means the read buffer contains garbage. - * Either _writePos can be greater than 0, or _readLen & _readPos can be - * greater than zero, but neither can be greater than zero at the same time. - * - */ - -namespace System.IO.Strategies -{ - internal sealed partial class Net5CompatFileStreamStrategy : FileStreamStrategy - { - private long _appendStart; // When appending, prevent overwriting file. - - private Task _activeBufferOperation = Task.CompletedTask; // tracks in-progress async ops using the buffer - private PreAllocatedOverlapped? _preallocatedOverlapped; // optimization for async ops to avoid per-op allocations - private CompletionSource? _currentOverlappedOwner; // async op currently using the preallocated overlapped - - private void Init(FileMode mode, string originalPath, FileOptions options) - { - Debug.Assert(!_useAsyncIO || _fileHandle.ThreadPoolBinding != null); - - // For Append mode... - if (mode == FileMode.Append) - { - _appendStart = SeekCore(_fileHandle, 0, SeekOrigin.End); - } - else - { - _appendStart = -1; - } - } - - private void InitFromHandle(SafeFileHandle handle, FileAccess access, bool useAsyncIO) - { -#if DEBUG - bool hadBinding = handle.ThreadPoolBinding != null; - - try - { -#endif - InitFromHandleImpl(handle, useAsyncIO); -#if DEBUG - } - catch - { - Debug.Assert(hadBinding || handle.ThreadPoolBinding == null, "We should never error out with a ThreadPoolBinding we've added"); - throw; - } -#endif - } - - private void InitFromHandleImpl(SafeFileHandle handle, bool useAsyncIO) - { - handle.EnsureThreadPoolBindingInitialized(); - - if (handle.CanSeek) - SeekCore(handle, 0, SeekOrigin.Current); - else - _filePosition = 0; - } - - private bool HasActiveBufferOperation => !_activeBufferOperation.IsCompleted; - - public override bool CanSeek => _fileHandle.CanSeek; - - public unsafe override long Length - { - get - { - long len = RandomAccess.GetFileLength(_fileHandle); - - // If we're writing near the end of the file, we must include our - // internal buffer in our Length calculation. Don't flush because - // we use the length of the file in our async write method. - if (_writePos > 0 && _filePosition + _writePos > len) - len = _writePos + _filePosition; - - return len; - } - } - - protected override void Dispose(bool disposing) - { - // Nothing will be done differently based on whether we are - // disposing vs. finalizing. This is taking advantage of the - // weak ordering between normal finalizable objects & critical - // finalizable objects, which I included in the SafeHandle - // design for Win32FileStream, which would often "just work" when - // finalized. - try - { - if (_fileHandle != null && !_fileHandle.IsClosed && _writePos > 0) - { - // Flush data to disk iff we were writing. After - // thinking about this, we also don't need to flush - // our read position, regardless of whether the handle - // was exposed to the user. They probably would NOT - // want us to do this. - try - { - FlushWriteBuffer(!disposing); - } - catch (Exception e) when (!disposing && FileStreamHelpers.IsIoRelatedException(e)) - { - // On finalization, ignore failures from trying to flush the write buffer, - // e.g. if this stream is wrapping a pipe and the pipe is now broken. - } - } - } - finally - { - if (_fileHandle != null && !_fileHandle.IsClosed) - { - _fileHandle.ThreadPoolBinding?.Dispose(); - _fileHandle.Dispose(); - } - - _preallocatedOverlapped?.Dispose(); - - // Don't set the buffer to null, to avoid a NullReferenceException - // when users have a race condition in their code (i.e. they call - // Close when calling another method on Stream like Read). - } - } - - public override async ValueTask DisposeAsync() - { - // Same logic as in Dispose(), except with async counterparts. - // TODO: https://github.com/dotnet/runtime/issues/27643: FlushAsync does synchronous work. - try - { - if (_fileHandle != null && !_fileHandle.IsClosed && _writePos > 0) - { - await FlushAsync(default).ConfigureAwait(false); - } - } - finally - { - if (_fileHandle != null && !_fileHandle.IsClosed) - { - _fileHandle.ThreadPoolBinding?.Dispose(); - _fileHandle.Dispose(); - } - - _preallocatedOverlapped?.Dispose(); - GC.SuppressFinalize(this); // the handle is closed; nothing further for the finalizer to do - } - } - - // Returns a task that flushes the internal write buffer - private Task FlushWriteAsync(CancellationToken cancellationToken) - { - Debug.Assert(_useAsyncIO); - Debug.Assert(_readPos == 0 && _readLength == 0, "FileStream: Read buffer must be empty in FlushWriteAsync!"); - - // If the buffer is already flushed, don't spin up the OS write - if (_writePos == 0) return Task.CompletedTask; - - Task flushTask = WriteAsyncInternalCore(new ReadOnlyMemory(GetBuffer(), 0, _writePos), cancellationToken); - _writePos = 0; - - // Update the active buffer operation - _activeBufferOperation = HasActiveBufferOperation ? - Task.WhenAll(_activeBufferOperation, flushTask) : - flushTask; - - return flushTask; - } - - private void FlushWriteBufferForWriteByte() => FlushWriteBuffer(); - - // Writes are buffered. Anytime the buffer fills up - // (_writePos + delta > _bufferSize) or the buffer switches to reading - // and there is left over data (_writePos > 0), this function must be called. - private void FlushWriteBuffer(bool calledFromFinalizer = false) - { - if (_writePos == 0) return; - Debug.Assert(_readPos == 0 && _readLength == 0, "FileStream: Read buffer must be empty in FlushWrite!"); - - if (_useAsyncIO) - { - Task writeTask = FlushWriteAsync(CancellationToken.None); - // With our Whidbey async IO & overlapped support for AD unloads, - // we don't strictly need to block here to release resources - // since that support takes care of the pinning & freeing the - // overlapped struct. We need to do this when called from - // Close so that the handle is closed when Close returns, but - // we don't need to call EndWrite from the finalizer. - // Additionally, if we do call EndWrite, we block forever - // because AD unloads prevent us from running the managed - // callback from the IO completion port. Blocking here when - // called from the finalizer during AD unload is clearly wrong, - // but we can't use any sort of test for whether the AD is - // unloading because if we weren't unloading, an AD unload - // could happen on a separate thread before we call EndWrite. - if (!calledFromFinalizer) - { - writeTask.GetAwaiter().GetResult(); - } - } - else - { - WriteCore(new ReadOnlySpan(GetBuffer(), 0, _writePos)); - } - - _writePos = 0; - } - - public override void SetLength(long value) - { - // Handle buffering updates. - if (_writePos > 0) - { - FlushWriteBuffer(); - } - else if (_readPos < _readLength) - { - FlushReadBuffer(); - } - _readPos = 0; - _readLength = 0; - - if (_appendStart != -1 && value < _appendStart) - throw new IOException(SR.IO_SetLengthAppendTruncate); - SetLengthCore(value); - } - - // We absolutely need this method broken out so that WriteInternalCoreAsync can call - // a method without having to go through buffering code that might call FlushWrite. - private unsafe void SetLengthCore(long value) - { - Debug.Assert(value >= 0, "value >= 0"); - VerifyOSHandlePosition(); - - FileStreamHelpers.SetFileLength(_fileHandle, value); - - if (_filePosition > value) - { - SeekCore(_fileHandle, 0, SeekOrigin.End); - } - } - - private int ReadSpan(Span destination) - { - Debug.Assert(!_useAsyncIO, "Must only be used when in synchronous mode"); - Debug.Assert((_readPos == 0 && _readLength == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLength), - "We're either reading or writing, but not both."); - - bool isBlocked = false; - int n = _readLength - _readPos; - // if the read buffer is empty, read into either user's array or our - // buffer, depending on number of bytes user asked for and buffer size. - if (n == 0) - { - if (!CanRead) ThrowHelper.ThrowNotSupportedException_UnreadableStream(); - if (_writePos > 0) FlushWriteBuffer(); - if (!CanSeek || (destination.Length >= _bufferLength)) - { - n = ReadNative(destination); - // Throw away read buffer. - _readPos = 0; - _readLength = 0; - return n; - } - n = ReadNative(GetBuffer()); - if (n == 0) return 0; - isBlocked = n < _bufferLength; - _readPos = 0; - _readLength = n; - } - // Now copy min of count or numBytesAvailable (i.e. near EOF) to array. - if (n > destination.Length) n = destination.Length; - new ReadOnlySpan(GetBuffer(), _readPos, n).CopyTo(destination); - _readPos += n; - - // We may have read less than the number of bytes the user asked - // for, but that is part of the Stream contract. Reading again for - // more data may cause us to block if we're using a device with - // no clear end of file, such as a serial port or pipe. If we - // blocked here & this code was used with redirected pipes for a - // process's standard output, this can lead to deadlocks involving - // two processes. But leave this here for files to avoid what would - // probably be a breaking change. -- - - // If we are reading from a device with no clear EOF like a - // serial port or a pipe, this will cause us to block incorrectly. - if (_fileHandle.CanSeek) - { - // If we hit the end of the buffer and didn't have enough bytes, we must - // read some more from the underlying stream. However, if we got - // fewer bytes from the underlying stream than we asked for (i.e. we're - // probably blocked), don't ask for more bytes. - if (n < destination.Length && !isBlocked) - { - Debug.Assert(_readPos == _readLength, "Read buffer should be empty!"); - int moreBytesRead = ReadNative(destination.Slice(n)); - n += moreBytesRead; - // We've just made our buffer inconsistent with our position - // pointer. We must throw away the read buffer. - _readPos = 0; - _readLength = 0; - } - } - - return n; - } - - [Conditional("DEBUG")] - private void AssertCanRead() - { - Debug.Assert(!_fileHandle.IsClosed, "!_fileHandle.IsClosed"); - Debug.Assert(CanRead, "CanRead"); - } - - /// Reads from the file handle into the buffer, overwriting anything in it. - private int FillReadBufferForReadByte() => - _useAsyncIO ? - ReadNativeAsync(new Memory(_buffer), 0, CancellationToken.None).GetAwaiter().GetResult() : - ReadNative(_buffer); - - private unsafe int ReadNative(Span buffer) - { - Debug.Assert(!_useAsyncIO, $"{nameof(ReadNative)} doesn't work on asynchronous file streams."); - AssertCanRead(); - - // Make sure we are reading from the right spot - VerifyOSHandlePosition(); - - int r = ReadFileNative(_fileHandle, buffer, null, out int errorCode); - - if (r == -1) - { - // For pipes, ERROR_BROKEN_PIPE is the normal end of the pipe. - if (errorCode == Interop.Errors.ERROR_BROKEN_PIPE) - { - r = 0; - } - else - { - if (errorCode == Interop.Errors.ERROR_INVALID_PARAMETER) - ThrowHelper.ThrowArgumentException_HandleNotSync(nameof(_fileHandle)); - - throw Win32Marshal.GetExceptionForWin32Error(errorCode, _fileHandle.Path); - } - } - Debug.Assert(r >= 0, "FileStream's ReadNative is likely broken."); - _filePosition += r; - - return r; - } - - public override long Seek(long offset, SeekOrigin origin) - { - if (origin < SeekOrigin.Begin || origin > SeekOrigin.End) - throw new ArgumentException(SR.Argument_InvalidSeekOrigin, nameof(origin)); - if (_fileHandle.IsClosed) ThrowHelper.ThrowObjectDisposedException_FileClosed(); - if (!CanSeek) ThrowHelper.ThrowNotSupportedException_UnseekableStream(); - - Debug.Assert((_readPos == 0 && _readLength == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLength), "We're either reading or writing, but not both."); - - // If we've got bytes in our buffer to write, write them out. - // If we've read in and consumed some bytes, we'll have to adjust - // our seek positions ONLY IF we're seeking relative to the current - // position in the stream. This simulates doing a seek to the new - // position, then a read for the number of bytes we have in our buffer. - if (_writePos > 0) - { - FlushWriteBuffer(); - } - else if (origin == SeekOrigin.Current) - { - // Don't call FlushRead here, which would have caused an infinite - // loop. Simply adjust the seek origin. This isn't necessary - // if we're seeking relative to the beginning or end of the stream. - offset -= (_readLength - _readPos); - } - _readPos = _readLength = 0; - - // Verify that internal position is in sync with the handle - VerifyOSHandlePosition(); - - long oldPos = _filePosition + (_readPos - _readLength); - long pos = SeekCore(_fileHandle, offset, origin); - - // Prevent users from overwriting data in a file that was opened in - // append mode. - if (_appendStart != -1 && pos < _appendStart) - { - SeekCore(_fileHandle, oldPos, SeekOrigin.Begin); - throw new IOException(SR.IO_SeekAppendOverwrite); - } - - // We now must update the read buffer. We can in some cases simply - // update _readPos within the buffer, copy around the buffer so our - // Position property is still correct, and avoid having to do more - // reads from the disk. Otherwise, discard the buffer's contents. - if (_readLength > 0) - { - // We can optimize the following condition: - // oldPos - _readPos <= pos < oldPos + _readLen - _readPos - if (oldPos == pos) - { - if (_readPos > 0) - { - Buffer.BlockCopy(GetBuffer(), _readPos, GetBuffer(), 0, _readLength - _readPos); - _readLength -= _readPos; - _readPos = 0; - } - // If we still have buffered data, we must update the stream's - // position so our Position property is correct. - if (_readLength > 0) - SeekCore(_fileHandle, _readLength, SeekOrigin.Current); - } - else if (oldPos - _readPos < pos && pos < oldPos + _readLength - _readPos) - { - int diff = (int)(pos - oldPos); - Buffer.BlockCopy(GetBuffer(), _readPos + diff, GetBuffer(), 0, _readLength - (_readPos + diff)); - _readLength -= (_readPos + diff); - _readPos = 0; - if (_readLength > 0) - SeekCore(_fileHandle, _readLength, SeekOrigin.Current); - } - else - { - // Lose the read buffer. - _readPos = 0; - _readLength = 0; - } - Debug.Assert(_readLength >= 0 && _readPos <= _readLength, "_readLen should be nonnegative, and _readPos should be less than or equal _readLen"); - Debug.Assert(pos == Position, "Seek optimization: pos != Position! Buffer math was mangled."); - } - return pos; - } - - partial void OnBufferAllocated() - { - Debug.Assert(_buffer != null); - Debug.Assert(_preallocatedOverlapped == null); - - if (_useAsyncIO) - _preallocatedOverlapped = PreAllocatedOverlapped.UnsafeCreate(CompletionSource.s_ioCallback, this, _buffer); - } - - private CompletionSource? CompareExchangeCurrentOverlappedOwner(CompletionSource? newSource, CompletionSource? existingSource) - => Interlocked.CompareExchange(ref _currentOverlappedOwner, newSource, existingSource); - - private void WriteSpan(ReadOnlySpan source) - { - Debug.Assert(!_useAsyncIO, "Must only be used when in synchronous mode"); - - if (_writePos == 0) - { - // Ensure we can write to the stream, and ready buffer for writing. - if (!CanWrite) ThrowHelper.ThrowNotSupportedException_UnwritableStream(); - if (_readPos < _readLength) FlushReadBuffer(); - _readPos = 0; - _readLength = 0; - } - - // If our buffer has data in it, copy data from the user's array into - // the buffer, and if we can fit it all there, return. Otherwise, write - // the buffer to disk and copy any remaining data into our buffer. - // The assumption here is memcpy is cheaper than disk (or net) IO. - // (10 milliseconds to disk vs. ~20-30 microseconds for a 4K memcpy) - // So the extra copying will reduce the total number of writes, in - // non-pathological cases (i.e. write 1 byte, then write for the buffer - // size repeatedly) - if (_writePos > 0) - { - int numBytes = _bufferLength - _writePos; // space left in buffer - if (numBytes > 0) - { - if (numBytes >= source.Length) - { - source.CopyTo(GetBuffer().AsSpan(_writePos)); - _writePos += source.Length; - return; - } - else - { - source.Slice(0, numBytes).CopyTo(GetBuffer().AsSpan(_writePos)); - _writePos += numBytes; - source = source.Slice(numBytes); - } - } - // Reset our buffer. We essentially want to call FlushWrite - // without calling Flush on the underlying Stream. - - WriteCore(new ReadOnlySpan(GetBuffer(), 0, _writePos)); - _writePos = 0; - } - - // If the buffer would slow writes down, avoid buffer completely. - if (source.Length >= _bufferLength) - { - Debug.Assert(_writePos == 0, "FileStream cannot have buffered data to write here! Your stream will be corrupted."); - WriteCore(source); - return; - } - else if (source.Length == 0) - { - return; // Don't allocate a buffer then call memcpy for 0 bytes. - } - - // Copy remaining bytes into buffer, to write at a later date. - source.CopyTo(GetBuffer().AsSpan(_writePos)); - _writePos = source.Length; - return; - } - - private unsafe void WriteCore(ReadOnlySpan source) - { - Debug.Assert(!_useAsyncIO); - Debug.Assert(!_fileHandle.IsClosed, "!_handle.IsClosed"); - Debug.Assert(CanWrite, "_parent.CanWrite"); - Debug.Assert(_readPos == _readLength, "_readPos == _readLen"); - - // Make sure we are writing to the position that we think we are - VerifyOSHandlePosition(); - - int r = WriteFileNative(_fileHandle, source, null, out int errorCode); - - if (r == -1) - { - // For pipes, ERROR_NO_DATA is not an error, but the pipe is closing. - if (errorCode == Interop.Errors.ERROR_NO_DATA) - { - r = 0; - } - else - { - // ERROR_INVALID_PARAMETER may be returned for writes - // where the position is too large or for synchronous writes - // to a handle opened asynchronously. - if (errorCode == Interop.Errors.ERROR_INVALID_PARAMETER) - throw new IOException(SR.IO_FileTooLongOrHandleNotSync); - throw Win32Marshal.GetExceptionForWin32Error(errorCode, _fileHandle.Path); - } - } - Debug.Assert(r >= 0, "FileStream's WriteCore is likely broken."); - _filePosition += r; - return; - } - - private Task? ReadAsyncInternal(Memory destination, CancellationToken cancellationToken, out int synchronousResult) - { - Debug.Assert(_useAsyncIO); - if (!CanRead) ThrowHelper.ThrowNotSupportedException_UnreadableStream(); - - Debug.Assert((_readPos == 0 && _readLength == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLength), "We're either reading or writing, but not both."); - - if (!_fileHandle.CanSeek) - { - // Pipes are tricky, at least when you have 2 different pipes - // that you want to use simultaneously. When redirecting stdout - // & stderr with the Process class, it's easy to deadlock your - // parent & child processes when doing writes 4K at a time. The - // OS appears to use a 4K buffer internally. If you write to a - // pipe that is full, you will block until someone read from - // that pipe. If you try reading from an empty pipe and - // Win32FileStream's ReadAsync blocks waiting for data to fill it's - // internal buffer, you will be blocked. In a case where a child - // process writes to stdout & stderr while a parent process tries - // reading from both, you can easily get into a deadlock here. - // To avoid this deadlock, don't buffer when doing async IO on - // pipes. But don't completely ignore buffered data either. - if (_readPos < _readLength) - { - int n = Math.Min(_readLength - _readPos, destination.Length); - new Span(GetBuffer(), _readPos, n).CopyTo(destination.Span); - _readPos += n; - synchronousResult = n; - return null; - } - else - { - Debug.Assert(_writePos == 0, "Win32FileStream must not have buffered write data here! Pipes should be unidirectional."); - synchronousResult = 0; - return ReadNativeAsync(destination, 0, cancellationToken); - } - } - - Debug.Assert(_fileHandle.CanSeek, "Should be seekable"); - - // Handle buffering. - if (_writePos > 0) FlushWriteBuffer(); - if (_readPos == _readLength) - { - // I can't see how to handle buffering of async requests when - // filling the buffer asynchronously, without a lot of complexity. - // The problems I see are issuing an async read, we do an async - // read to fill the buffer, then someone issues another read - // (either synchronously or asynchronously) before the first one - // returns. This would involve some sort of complex buffer locking - // that we probably don't want to get into, at least not in V1. - // If we did a sync read to fill the buffer, we could avoid the - // problem, and any async read less than 64K gets turned into a - // synchronous read by NT anyways... -- - - if (destination.Length < _bufferLength) - { - Task readTask = ReadNativeAsync(new Memory(GetBuffer()), 0, cancellationToken); - _readLength = readTask.GetAwaiter().GetResult(); - int n = Math.Min(_readLength, destination.Length); - new Span(GetBuffer(), 0, n).CopyTo(destination.Span); - _readPos = n; - - synchronousResult = n; - return null; - } - else - { - // Here we're making our position pointer inconsistent - // with our read buffer. Throw away the read buffer's contents. - _readPos = 0; - _readLength = 0; - synchronousResult = 0; - return ReadNativeAsync(destination, 0, cancellationToken); - } - } - else - { - int n = Math.Min(_readLength - _readPos, destination.Length); - new Span(GetBuffer(), _readPos, n).CopyTo(destination.Span); - _readPos += n; - - if (n == destination.Length) - { - // Return a completed task - synchronousResult = n; - return null; - } - else - { - // For streams with no clear EOF like serial ports or pipes - // we cannot read more data without causing an app to block - // incorrectly. Pipes don't go down this path - // though. This code needs to be fixed. - // Throw away read buffer. - _readPos = 0; - _readLength = 0; - synchronousResult = 0; - return ReadNativeAsync(destination.Slice(n), n, cancellationToken); - } - } - } - - private unsafe Task ReadNativeAsync(Memory destination, int numBufferedBytesRead, CancellationToken cancellationToken) - { - AssertCanRead(); - Debug.Assert(_useAsyncIO, "ReadNativeAsync doesn't work on synchronous file streams!"); - - // Create and store async stream class library specific data in the async result - CompletionSource completionSource = CompletionSource.Create(this, _preallocatedOverlapped, numBufferedBytesRead, destination); - NativeOverlapped* intOverlapped = completionSource.Overlapped; - - // Calculate position in the file we should be at after the read is done - if (CanSeek) - { - long len = Length; - - // Make sure we are reading from the position that we think we are - VerifyOSHandlePosition(); - - if (_filePosition + destination.Length > len) - { - if (_filePosition <= len) - { - destination = destination.Slice(0, (int)(len - _filePosition)); - } - else - { - destination = default; - } - } - - // Now set the position to read from in the NativeOverlapped struct - // For pipes, we should leave the offset fields set to 0. - intOverlapped->OffsetLow = unchecked((int)_filePosition); - intOverlapped->OffsetHigh = (int)(_filePosition >> 32); - - // When using overlapped IO, the OS is not supposed to - // touch the file pointer location at all. We will adjust it - // ourselves. This isn't threadsafe. - - // WriteFile should not update the file pointer when writing - // in overlapped mode, according to MSDN. But it does update - // the file pointer when writing to a UNC path! - // So changed the code below to seek to an absolute - // location, not a relative one. ReadFile seems consistent though. - SeekCore(_fileHandle, destination.Length, SeekOrigin.Current); - } - - // queue an async ReadFile operation and pass in a packed overlapped - int r = ReadFileNative(_fileHandle, destination.Span, intOverlapped, out int errorCode); - - // ReadFile, the OS version, will return 0 on failure. But - // my ReadFileNative wrapper returns -1. My wrapper will return - // the following: - // On error, r==-1. - // On async requests that are still pending, r==-1 w/ errorCode==ERROR_IO_PENDING - // on async requests that completed sequentially, r==0 - // You will NEVER RELIABLY be able to get the number of bytes - // read back from this call when using overlapped structures! You must - // not pass in a non-null lpNumBytesRead to ReadFile when using - // overlapped structures! This is by design NT behavior. - if (r == -1) - { - // For pipes, when they hit EOF, they will come here. - if (errorCode == Interop.Errors.ERROR_BROKEN_PIPE) - { - // Not an error, but EOF. AsyncFSCallback will NOT be - // called. Call the user callback here. - - // We clear the overlapped status bit for this special case. - // Failure to do so looks like we are freeing a pending overlapped later. - intOverlapped->InternalLow = IntPtr.Zero; - completionSource.SetCompletedSynchronously(0); - } - else if (errorCode != Interop.Errors.ERROR_IO_PENDING) - { - if (!_fileHandle.IsClosed && CanSeek) // Update Position - It could be anywhere. - { - SeekCore(_fileHandle, 0, SeekOrigin.Current); - } - - completionSource.ReleaseNativeResource(); - - if (errorCode == Interop.Errors.ERROR_HANDLE_EOF) - { - ThrowHelper.ThrowEndOfFileException(); - } - else - { - throw Win32Marshal.GetExceptionForWin32Error(errorCode, _fileHandle.Path); - } - } - else if (cancellationToken.CanBeCanceled) // ERROR_IO_PENDING - { - // Only once the IO is pending do we register for cancellation - completionSource.RegisterForCancellation(cancellationToken); - } - } - else - { - // Due to a workaround for a race condition in NT's ReadFile & - // WriteFile routines, we will always be returning 0 from ReadFileNative - // when we do async IO instead of the number of bytes read, - // irregardless of whether the operation completed - // synchronously or asynchronously. We absolutely must not - // set asyncResult._numBytes here, since will never have correct - // results. - } - - return completionSource.Task; - } - - private ValueTask WriteAsyncInternal(ReadOnlyMemory source, CancellationToken cancellationToken) - { - Debug.Assert(_useAsyncIO); - Debug.Assert((_readPos == 0 && _readLength == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLength), "We're either reading or writing, but not both."); - Debug.Assert(_fileHandle.CanSeek || (_readPos == 0 && _readLength == 0), "Win32FileStream must not have buffered data here! Pipes should be unidirectional."); - - if (!CanWrite) ThrowHelper.ThrowNotSupportedException_UnwritableStream(); - - bool writeDataStoredInBuffer = false; - if (_fileHandle.CanSeek) // avoid async buffering with non-seekable files (e.g. pipes), as doing so can lead to deadlocks (see comments in ReadInternalAsyncCore) - { - // Ensure the buffer is clear for writing - if (_writePos == 0) - { - if (_readPos < _readLength) - { - FlushReadBuffer(); - } - _readPos = 0; - _readLength = 0; - } - - // Determine how much space remains in the buffer - int remainingBuffer = _bufferLength - _writePos; - Debug.Assert(remainingBuffer >= 0); - - // Simple/common case: - // - The write is smaller than our buffer, such that it's worth considering buffering it. - // - There's no active flush operation, such that we don't have to worry about the existing buffer being in use. - // - And the data we're trying to write fits in the buffer, meaning it wasn't already filled by previous writes. - // In that case, just store it in the buffer. - if (source.Length < _bufferLength && !HasActiveBufferOperation && source.Length <= remainingBuffer) - { - source.Span.CopyTo(new Span(GetBuffer(), _writePos, source.Length)); - _writePos += source.Length; - writeDataStoredInBuffer = true; - - // There is one special-but-common case, common because devs often use - // byte[] sizes that are powers of 2 and thus fit nicely into our buffer, which is - // also a power of 2. If after our write the buffer still has remaining space, - // then we're done and can return a completed task now. But if we filled the buffer - // completely, we want to do the asynchronous flush/write as part of this operation - // rather than waiting until the next write that fills the buffer. - if (source.Length != remainingBuffer) - return default; - - Debug.Assert(_writePos == _bufferLength); - } - } - - // At this point, at least one of the following is true: - // 1. There was an active flush operation (it could have completed by now, though). - // 2. The data doesn't fit in the remaining buffer (or it's a pipe and we chose not to try). - // 3. We wrote all of the data to the buffer, filling it. - // - // If there's an active operation, we can't touch the current buffer because it's in use. - // That gives us a choice: we can either allocate a new buffer, or we can skip the buffer - // entirely (even if the data would otherwise fit in it). For now, for simplicity, we do - // the latter; it could also have performance wins due to OS-level optimizations, and we could - // potentially add support for PreAllocatedOverlapped due to having a single buffer. (We can - // switch to allocating a new buffer, potentially experimenting with buffer pooling, should - // performance data suggest it's appropriate.) - // - // If the data doesn't fit in the remaining buffer, it could be because it's so large - // it's greater than the entire buffer size, in which case we'd always skip the buffer, - // or it could be because there's more data than just the space remaining. For the latter - // case, we need to issue an asynchronous write to flush that data, which then turns this into - // the first case above with an active operation. - // - // If we already stored the data, then we have nothing additional to write beyond what - // we need to flush. - // - // In any of these cases, we have the same outcome: - // - If there's data in the buffer, flush it by writing it out asynchronously. - // - Then, if there's any data to be written, issue a write for it concurrently. - // We return a Task that represents one or both. - - // Flush the buffer asynchronously if there's anything to flush - Task? flushTask = null; - if (_writePos > 0) - { - flushTask = FlushWriteAsync(cancellationToken); - - // If we already copied all of the data into the buffer, - // simply return the flush task here. Same goes for if the task has - // already completed and was unsuccessful. - if (writeDataStoredInBuffer || - flushTask.IsFaulted || - flushTask.IsCanceled) - { - return new ValueTask(flushTask); - } - } - - Debug.Assert(!writeDataStoredInBuffer); - Debug.Assert(_writePos == 0); - - // Finally, issue the write asynchronously, and return a Task that logically - // represents the write operation, including any flushing done. - Task writeTask = WriteAsyncInternalCore(source, cancellationToken); - return new ValueTask( - (flushTask == null || flushTask.Status == TaskStatus.RanToCompletion) ? writeTask : - (writeTask.Status == TaskStatus.RanToCompletion) ? flushTask : - Task.WhenAll(flushTask, writeTask)); - } - - private unsafe Task WriteAsyncInternalCore(ReadOnlyMemory source, CancellationToken cancellationToken) - { - Debug.Assert(!_fileHandle.IsClosed, "!_handle.IsClosed"); - Debug.Assert(CanWrite, "_parent.CanWrite"); - Debug.Assert(_readPos == _readLength, "_readPos == _readLen"); - Debug.Assert(_useAsyncIO, "WriteInternalCoreAsync doesn't work on synchronous file streams!"); - - // Create and store async stream class library specific data in the async result - CompletionSource completionSource = CompletionSource.Create(this, _preallocatedOverlapped, 0, source); - NativeOverlapped* intOverlapped = completionSource.Overlapped; - - if (CanSeek) - { - // Make sure we set the length of the file appropriately. - long len = Length; - - // Make sure we are writing to the position that we think we are - VerifyOSHandlePosition(); - - if (_filePosition + source.Length > len) - { - SetLengthCore(_filePosition + source.Length); - } - - // Now set the position to read from in the NativeOverlapped struct - // For pipes, we should leave the offset fields set to 0. - intOverlapped->OffsetLow = (int)_filePosition; - intOverlapped->OffsetHigh = (int)(_filePosition >> 32); - - // When using overlapped IO, the OS is not supposed to - // touch the file pointer location at all. We will adjust it - // ourselves. This isn't threadsafe. - SeekCore(_fileHandle, source.Length, SeekOrigin.Current); - } - - // queue an async WriteFile operation and pass in a packed overlapped - int r = WriteFileNative(_fileHandle, source.Span, intOverlapped, out int errorCode); - - // WriteFile, the OS version, will return 0 on failure. But - // my WriteFileNative wrapper returns -1. My wrapper will return - // the following: - // On error, r==-1. - // On async requests that are still pending, r==-1 w/ errorCode==ERROR_IO_PENDING - // On async requests that completed sequentially, r==0 - // You will NEVER RELIABLY be able to get the number of bytes - // written back from this call when using overlapped IO! You must - // not pass in a non-null lpNumBytesWritten to WriteFile when using - // overlapped structures! This is ByDesign NT behavior. - if (r == -1) - { - // For pipes, when they are closed on the other side, they will come here. - if (errorCode == Interop.Errors.ERROR_NO_DATA) - { - // Not an error, but EOF. AsyncFSCallback will NOT be called. - // Completing TCS and return cached task allowing the GC to collect TCS. - completionSource.SetCompletedSynchronously(0); - return Task.CompletedTask; - } - else if (errorCode != Interop.Errors.ERROR_IO_PENDING) - { - if (!_fileHandle.IsClosed && CanSeek) // Update Position - It could be anywhere. - { - SeekCore(_fileHandle, 0, SeekOrigin.Current); - } - - completionSource.ReleaseNativeResource(); - - if (errorCode == Interop.Errors.ERROR_HANDLE_EOF) - { - ThrowHelper.ThrowEndOfFileException(); - } - else - { - throw Win32Marshal.GetExceptionForWin32Error(errorCode, _fileHandle.Path); - } - } - else if (cancellationToken.CanBeCanceled) // ERROR_IO_PENDING - { - // Only once the IO is pending do we register for cancellation - completionSource.RegisterForCancellation(cancellationToken); - } - } - else - { - // Due to a workaround for a race condition in NT's ReadFile & - // WriteFile routines, we will always be returning 0 from WriteFileNative - // when we do async IO instead of the number of bytes written, - // irregardless of whether the operation completed - // synchronously or asynchronously. We absolutely must not - // set asyncResult._numBytes here, since will never have correct - // results. - } - - return completionSource.Task; - } - - // __ConsoleStream also uses this code. - private unsafe int ReadFileNative(SafeFileHandle handle, Span bytes, NativeOverlapped* overlapped, out int errorCode) - { - Debug.Assert((_useAsyncIO && overlapped != null) || (!_useAsyncIO && overlapped == null), "Async IO and overlapped parameters inconsistent in call to ReadFileNative."); - - return FileStreamHelpers.ReadFileNative(handle, bytes, overlapped, out errorCode); - } - - private unsafe int WriteFileNative(SafeFileHandle handle, ReadOnlySpan buffer, NativeOverlapped* overlapped, out int errorCode) - { - Debug.Assert((_useAsyncIO && overlapped != null) || (!_useAsyncIO && overlapped == null), "Async IO and overlapped parameters inconsistent in call to WriteFileNative."); - - int numBytesWritten = 0; - int r; - - fixed (byte* p = &MemoryMarshal.GetReference(buffer)) - { - r = overlapped == null - ? Interop.Kernel32.WriteFile(handle, p, buffer.Length, out numBytesWritten, overlapped) - : Interop.Kernel32.WriteFile(handle, p, buffer.Length, IntPtr.Zero, overlapped); - } - - if (r == 0) - { - errorCode = FileStreamHelpers.GetLastWin32ErrorAndDisposeHandleIfInvalid(handle); - return -1; - } - else - { - errorCode = 0; - return numBytesWritten; - } - } - - public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) - { - // If we're in sync mode, just use the shared CopyToAsync implementation that does - // typical read/write looping. - if (!_useAsyncIO) - { - return base.CopyToAsync(destination, bufferSize, cancellationToken); - } - - // Fail if the file was closed - if (_fileHandle.IsClosed) - { - ThrowHelper.ThrowObjectDisposedException_FileClosed(); - } - if (!CanRead) - { - ThrowHelper.ThrowNotSupportedException_UnreadableStream(); - } - - // Bail early for cancellation if cancellation has been requested - if (cancellationToken.IsCancellationRequested) - { - return Task.FromCanceled(cancellationToken); - } - - // Do the async copy, with differing implementations based on whether the FileStream was opened as async or sync - Debug.Assert((_readPos == 0 && _readLength == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLength), "We're either reading or writing, but not both."); - return AsyncModeCopyToAsync(destination, bufferSize, cancellationToken); - } - - private async Task AsyncModeCopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) - { - Debug.Assert(_useAsyncIO, "This implementation is for async mode only"); - Debug.Assert(!_fileHandle.IsClosed, "!_handle.IsClosed"); - Debug.Assert(CanRead, "_parent.CanRead"); - - // Make sure any pending writes have been flushed before we do a read. - if (_writePos > 0) - { - await FlushWriteAsync(cancellationToken).ConfigureAwait(false); - } - - // Typically CopyToAsync would be invoked as the only "read" on the stream, but it's possible some reading is - // done and then the CopyToAsync is issued. For that case, see if we have any data available in the buffer. - if (GetBuffer() != null) - { - int bufferedBytes = _readLength - _readPos; - if (bufferedBytes > 0) - { - await destination.WriteAsync(new ReadOnlyMemory(GetBuffer(), _readPos, bufferedBytes), cancellationToken).ConfigureAwait(false); - _readPos = _readLength = 0; - } - } - - bool canSeek = CanSeek; - if (canSeek) - { - VerifyOSHandlePosition(); - } - - try - { - await FileStreamHelpers - .AsyncModeCopyToAsync(_fileHandle, canSeek, _filePosition, destination, bufferSize, cancellationToken) - .ConfigureAwait(false); - } - finally - { - // Make sure the stream's current position reflects where we ended up - if (!_fileHandle.IsClosed && CanSeek) - { - SeekCore(_fileHandle, 0, SeekOrigin.End); - } - } - } - - internal override void Lock(long position, long length) => FileStreamHelpers.Lock(_fileHandle, CanWrite, position, length); - - internal override void Unlock(long position, long length) => FileStreamHelpers.Unlock(_fileHandle, position, length); - } -} diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/Net5CompatFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/Net5CompatFileStreamStrategy.cs deleted file mode 100644 index 797f6f5e9c0ce..0000000000000 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/Net5CompatFileStreamStrategy.cs +++ /dev/null @@ -1,536 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Win32.SafeHandles; - -namespace System.IO.Strategies -{ - // This type is partial so we can avoid code duplication between Windows and Unix Net5Compat implementations - internal sealed partial class Net5CompatFileStreamStrategy : FileStreamStrategy - { - private byte[]? _buffer; - private readonly int _bufferLength; - private readonly SafeFileHandle _fileHandle; // only ever null if ctor throws - - /// Whether the file is opened for reading, writing, or both. - private readonly FileAccess _access; - - /// The next available byte to be read from the _buffer. - private int _readPos; - - /// The number of valid bytes in _buffer. - private int _readLength; - - /// The next location in which a write should occur to the buffer. - private int _writePos; - - /// - /// Whether asynchronous read/write/flush operations should be performed using async I/O. - /// On Windows FileOptions.Asynchronous controls how the file handle is configured, - /// and then as a result how operations are issued against that file handle. On Unix, - /// there isn't any distinction around how file descriptors are created for async vs - /// sync, but we still differentiate how the operations are issued in order to provide - /// similar behavioral semantics and performance characteristics as on Windows. On - /// Windows, if non-async, async read/write requests just delegate to the base stream, - /// and no attempt is made to synchronize between sync and async operations on the stream; - /// if async, then async read/write requests are implemented specially, and sync read/write - /// requests are coordinated with async ones by implementing the sync ones over the async - /// ones. On Unix, we do something similar. If non-async, async read/write requests just - /// delegate to the base stream, and no attempt is made to synchronize. If async, we use - /// a semaphore to coordinate both sync and async operations. - /// - private readonly bool _useAsyncIO; - - /// cached task for read ops that complete synchronously - private Task? _lastSynchronouslyCompletedTask; - - /// - /// Currently cached position in the stream. This should always mirror the underlying file's actual position, - /// and should only ever be out of sync if another stream with access to this same file manipulates it, at which - /// point we attempt to error out. - /// - private long _filePosition; - - /// Whether the file stream's handle has been exposed. - private bool _exposedHandle; - - internal Net5CompatFileStreamStrategy(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) - { - _exposedHandle = true; - _bufferLength = bufferSize; - - InitFromHandle(handle, access, isAsync); - - // Note: It would be cleaner to set the following fields in ValidateHandle, - // but we can't as they're readonly. - _access = access; - _useAsyncIO = isAsync; - - // As the handle was passed in, we must set the handle field at the very end to - // avoid the finalizer closing the handle when we throw errors. - _fileHandle = handle; - } - - internal Net5CompatFileStreamStrategy(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, long preallocationSize) - { - string fullPath = Path.GetFullPath(path); - - _access = access; - _bufferLength = bufferSize; - - if ((options & FileOptions.Asynchronous) != 0) - _useAsyncIO = true; - - _fileHandle = SafeFileHandle.Open(fullPath, mode, access, share, options, preallocationSize); - - try - { - Init(mode, path, options); - } - catch - { - // If anything goes wrong while setting up the stream, make sure we deterministically dispose - // of the opened handle. - _fileHandle.Dispose(); - _fileHandle = null!; - throw; - } - } - - ~Net5CompatFileStreamStrategy() => Dispose(false); // mandatory to Flush the write buffer - - internal override void DisposeInternal(bool disposing) => Dispose(disposing); - - public override Task FlushAsync(CancellationToken cancellationToken) - { - // TODO: https://github.com/dotnet/runtime/issues/27643 (stop doing this synchronous work!!). - // The always synchronous data transfer between the OS and the internal buffer is intentional - // because this is needed to allow concurrent async IO requests. Concurrent data transfer - // between the OS and the internal buffer will result in race conditions. Since FlushWrite and - // FlushRead modify internal state of the stream and transfer data between the OS and the - // internal buffer, they cannot be truly async. We will, however, flush the OS file buffers - // asynchronously because it doesn't modify any internal state of the stream and is potentially - // a long running process. - try - { - FlushInternalBuffer(); - } - catch (Exception e) - { - return Task.FromException(e); - } - - return Task.CompletedTask; - } - - public override int Read(byte[] buffer, int offset, int count) - { - return _useAsyncIO ? - ReadAsyncTask(buffer, offset, count, CancellationToken.None).GetAwaiter().GetResult() : - ReadSpan(new Span(buffer, offset, count)); - } - - public override int Read(Span buffer) - { - if (!_useAsyncIO) - { - if (_fileHandle.IsClosed) - { - ThrowHelper.ThrowObjectDisposedException_FileClosed(); - } - - return ReadSpan(buffer); - } - - // If the stream is in async mode, we can't call the synchronous ReadSpan, so we similarly call the base Read, - // which will turn delegate to Read(byte[],int,int), which will do the right thing if we're in async mode. - return base.Read(buffer); - } - - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - if (!_useAsyncIO) - { - // If we weren't opened for asynchronous I/O, we still call to the base implementation so that - // Read is invoked asynchronously. But we can do so using the base Stream's internal helper - // that bypasses delegating to BeginRead, since we already know this is FileStream rather - // than something derived from it and what our BeginRead implementation is going to do. - return BeginReadInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false); - } - - return ReadAsyncTask(buffer, offset, count, cancellationToken); - } - - public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) - { - if (!_useAsyncIO) - { - // If we weren't opened for asynchronous I/O, we still call to the base implementation so that - // Read is invoked asynchronously. But if we have a byte[], we can do so using the base Stream's - // internal helper that bypasses delegating to BeginRead, since we already know this is FileStream - // rather than something derived from it and what our BeginRead implementation is going to do. - return MemoryMarshal.TryGetArray(buffer, out ArraySegment segment) ? - new ValueTask(BeginReadInternal(segment.Array!, segment.Offset, segment.Count, null, null, serializeAsynchronously: true, apm: false)) : - base.ReadAsync(buffer, cancellationToken); - } - - Task? t = ReadAsyncInternal(buffer, cancellationToken, out int synchronousResult); - return t != null ? - new ValueTask(t) : - new ValueTask(synchronousResult); - } - - private Task ReadAsyncTask(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - Task? t = ReadAsyncInternal(new Memory(buffer, offset, count), cancellationToken, out int synchronousResult); - - if (t == null) - { - t = _lastSynchronouslyCompletedTask; - Debug.Assert(t == null || t.IsCompletedSuccessfully, "Cached task should have completed successfully"); - - if (t == null || t.Result != synchronousResult) - { - _lastSynchronouslyCompletedTask = t = Task.FromResult(synchronousResult); - } - } - - return t; - } - - public override void Write(byte[] buffer, int offset, int count) - { - if (_useAsyncIO) - { - WriteAsyncInternal(new ReadOnlyMemory(buffer, offset, count), CancellationToken.None).AsTask().GetAwaiter().GetResult(); - } - else - { - WriteSpan(new ReadOnlySpan(buffer, offset, count)); - } - } - - public override void Write(ReadOnlySpan buffer) - { - if (!_useAsyncIO) - { - if (_fileHandle.IsClosed) - { - ThrowHelper.ThrowObjectDisposedException_FileClosed(); - } - - WriteSpan(buffer); - } - else - { - // If the stream is in async mode, we can't call the synchronous WriteSpan, so we similarly call the base Write, - // which will turn delegate to Write(byte[],int,int), which will do the right thing if we're in async mode. - base.Write(buffer); - } - } - - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - if (!_useAsyncIO) - { - // If we weren't opened for asynchronous I/O, we still call to the base implementation so that - // Write is invoked asynchronously. But we can do so using the base Stream's internal helper - // that bypasses delegating to BeginWrite, since we already know this is FileStream rather - // than something derived from it and what our BeginWrite implementation is going to do. - return BeginWriteInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false); - } - - return WriteAsyncInternal(new ReadOnlyMemory(buffer, offset, count), cancellationToken).AsTask(); - } - - public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) - { - if (!_useAsyncIO) - { - // If we weren't opened for asynchronous I/O, we still call to the base implementation so that - // Write is invoked asynchronously. But if we have a byte[], we can do so using the base Stream's - // internal helper that bypasses delegating to BeginWrite, since we already know this is FileStream - // rather than something derived from it and what our BeginWrite implementation is going to do. - return MemoryMarshal.TryGetArray(buffer, out ArraySegment segment) ? - new ValueTask(BeginWriteInternal(segment.Array!, segment.Offset, segment.Count, null, null, serializeAsynchronously: true, apm: false)) : - base.WriteAsync(buffer, cancellationToken); - } - - return WriteAsyncInternal(buffer, cancellationToken); - } - - public override void Flush() => Flush(flushToDisk: false); - - internal override void Flush(bool flushToDisk) - { - FlushInternalBuffer(); - - if (flushToDisk && CanWrite) - { - FileStreamHelpers.FlushToDisk(_fileHandle); - } - } - - public override bool CanRead => !_fileHandle.IsClosed && (_access & FileAccess.Read) != 0; - - public override bool CanWrite => !_fileHandle.IsClosed && (_access & FileAccess.Write) != 0; - - internal override SafeFileHandle SafeFileHandle - { - get - { - Flush(); - _exposedHandle = true; - return _fileHandle; - } - } - - internal override string Name => _fileHandle.Path ?? SR.IO_UnknownFileName; - - internal override bool IsAsync => _useAsyncIO; - - /// - /// Verify that the actual position of the OS's handle equals what we expect it to. - /// This will fail if someone else moved the UnixFileStream's handle or if - /// our position updating code is incorrect. - /// - private void VerifyOSHandlePosition() - { - bool verifyPosition = _exposedHandle; // in release, only verify if we've given out the handle such that someone else could be manipulating it -#if DEBUG - verifyPosition = true; // in debug, always make sure our position matches what the OS says it should be -#endif - if (verifyPosition && CanSeek) - { - long oldPos = _filePosition; // SeekCore will override the current _position, so save it now - long curPos = SeekCore(_fileHandle, 0, SeekOrigin.Current); - if (oldPos != curPos) - { - // For reads, this is non-fatal but we still could have returned corrupted - // data in some cases, so discard the internal buffer. For writes, - // this is a problem; discard the buffer and error out. - _readPos = _readLength = 0; - if (_writePos > 0) - { - _writePos = 0; - throw new IOException(SR.IO_FileStreamHandlePosition); - } - } - } - } - - /// Verifies that state relating to the read/write buffer is consistent. - [Conditional("DEBUG")] - private void AssertBufferInvariants() - { - // Read buffer values must be in range: 0 <= _bufferReadPos <= _bufferReadLength <= _bufferLength - Debug.Assert(0 <= _readPos && _readPos <= _readLength && _readLength <= _bufferLength); - - // Write buffer values must be in range: 0 <= _bufferWritePos <= _bufferLength - Debug.Assert(0 <= _writePos && _writePos <= _bufferLength); - - // Read buffering and write buffering can't both be active - Debug.Assert((_readPos == 0 && _readLength == 0) || _writePos == 0); - } - - /// Validates that we're ready to read from the stream. - private void PrepareForReading() - { - if (_fileHandle.IsClosed) - ThrowHelper.ThrowObjectDisposedException_FileClosed(); - if (_readLength == 0 && !CanRead) - ThrowHelper.ThrowNotSupportedException_UnreadableStream(); - - AssertBufferInvariants(); - } - - /// Gets or sets the position within the current stream - public override long Position - { - get - { - AssertBufferInvariants(); - VerifyOSHandlePosition(); - - // We may have read data into our buffer from the handle, such that the handle position - // is artificially further along than the consumer's view of the stream's position. - // Thus, when reading, our position is really starting from the handle position negatively - // offset by the number of bytes in the buffer and positively offset by the number of - // bytes into that buffer we've read. When writing, both the read length and position - // must be zero, and our position is just the handle position offset positive by how many - // bytes we've written into the buffer. - return (_filePosition - _readLength) + _readPos + _writePos; - } - set - { - Seek(value, SeekOrigin.Begin); - } - } - - // This doesn't do argument checking. Necessary for SetLength, which must - // set the file pointer beyond the end of the file. This will update the - // internal position - private long SeekCore(SafeFileHandle fileHandle, long offset, SeekOrigin origin, bool closeInvalidHandle = false) - { - Debug.Assert(fileHandle.CanSeek, "fileHandle.CanSeek"); - - return _filePosition = FileStreamHelpers.Seek(fileHandle, offset, origin, closeInvalidHandle); - } - - internal override bool IsClosed => _fileHandle.IsClosed; - - /// - /// Gets the array used for buffering reading and writing. - /// If the array hasn't been allocated, this will lazily allocate it. - /// - /// The buffer. - private byte[] GetBuffer() - { - Debug.Assert(_buffer == null || _buffer.Length == _bufferLength); - if (_buffer == null) - { - _buffer = new byte[_bufferLength]; - OnBufferAllocated(); - } - - return _buffer; - } - - /// - /// Flushes the internal read/write buffer for this stream. If write data has been buffered, - /// that data is written out to the underlying file. Or if data has been buffered for - /// reading from the stream, the data is dumped and our position in the underlying file - /// is rewound as necessary. This does not flush the OS buffer. - /// - private void FlushInternalBuffer() - { - AssertBufferInvariants(); - if (_writePos > 0) - { - FlushWriteBuffer(); - } - else if (_readPos < _readLength && CanSeek) - { - FlushReadBuffer(); - } - } - - /// Dumps any read data in the buffer and rewinds our position in the stream, accordingly, as necessary. - private void FlushReadBuffer() - { - // Reading is done by blocks from the file, but someone could read - // 1 byte from the buffer then write. At that point, the OS's file - // pointer is out of sync with the stream's position. All write - // functions should call this function to preserve the position in the file. - - AssertBufferInvariants(); - Debug.Assert(_writePos == 0, "FileStream: Write buffer must be empty in FlushReadBuffer!"); - - int rewind = _readPos - _readLength; - if (rewind != 0) - { - Debug.Assert(CanSeek, "FileStream will lose buffered read data now."); - SeekCore(_fileHandle, rewind, SeekOrigin.Current); - } - _readPos = _readLength = 0; - } - - /// - /// Reads a byte from the file stream. Returns the byte cast to an int - /// or -1 if reading from the end of the stream. - /// - public override int ReadByte() - { - PrepareForReading(); - - byte[] buffer = GetBuffer(); - if (_readPos == _readLength) - { - FlushWriteBuffer(); - _readLength = FillReadBufferForReadByte(); - _readPos = 0; - if (_readLength == 0) - { - return -1; - } - } - - return buffer[_readPos++]; - } - - /// - /// Writes a byte to the current position in the stream and advances the position - /// within the stream by one byte. - /// - /// The byte to write to the stream. - public override void WriteByte(byte value) - { - PrepareForWriting(); - - // Flush the write buffer if it's full - if (_writePos == _bufferLength) - FlushWriteBufferForWriteByte(); - - // We now have space in the buffer. Store the byte. - GetBuffer()[_writePos++] = value; - } - - /// - /// Validates that we're ready to write to the stream, - /// including flushing a read buffer if necessary. - /// - private void PrepareForWriting() - { - if (_fileHandle.IsClosed) - ThrowHelper.ThrowObjectDisposedException_FileClosed(); - - // Make sure we're good to write. We only need to do this if there's nothing already - // in our write buffer, since if there is something in the buffer, we've already done - // this checking and flushing. - if (_writePos == 0) - { - if (!CanWrite) ThrowHelper.ThrowNotSupportedException_UnwritableStream(); - FlushReadBuffer(); - Debug.Assert(_bufferLength > 0, "_bufferSize > 0"); - } - } - - partial void OnBufferAllocated(); - - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) - { - if (!_useAsyncIO) - return base.BeginRead(buffer, offset, count, callback, state); - else - return TaskToApm.Begin(ReadAsyncTask(buffer, offset, count, CancellationToken.None), callback, state); - } - - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state) - { - if (!_useAsyncIO) - return base.BeginWrite(buffer, offset, count, callback, state); - else - return TaskToApm.Begin(WriteAsyncInternal(new ReadOnlyMemory(buffer, offset, count), CancellationToken.None).AsTask(), callback, state); - } - - public override int EndRead(IAsyncResult asyncResult) - { - if (!_useAsyncIO) - return base.EndRead(asyncResult); - else - return TaskToApm.End(asyncResult); - } - - public override void EndWrite(IAsyncResult asyncResult) - { - if (!_useAsyncIO) - base.EndWrite(asyncResult); - else - TaskToApm.End(asyncResult); - } - } -} diff --git a/src/libraries/System.Private.CoreLib/src/System/IParseable.cs b/src/libraries/System.Private.CoreLib/src/System/IParseable.cs index 77064639e368a..5a715cab0831a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IParseable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IParseable.cs @@ -12,7 +12,7 @@ namespace System { /// Defines a mechanism for parsing a string to a value. /// The type that implements this interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IParseable where TSelf : IParseable { diff --git a/src/libraries/System.Private.CoreLib/src/System/IShiftOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IShiftOperators.cs index 8ba4d810233dc..ad0af7155d4fb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IShiftOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IShiftOperators.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for shifting a value by another value. /// The type that implements this interface. /// The type that contains the result of shifting by . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IShiftOperators where TSelf : IShiftOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/ISpanParseable.cs b/src/libraries/System.Private.CoreLib/src/System/ISpanParseable.cs index 6264fe1580292..34dad1427db4a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ISpanParseable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ISpanParseable.cs @@ -11,7 +11,7 @@ namespace System { /// Defines a mechanism for parsing a span of characters to a value. /// The type that implements this interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface ISpanParseable : IParseable where TSelf : ISpanParseable { diff --git a/src/libraries/System.Private.CoreLib/src/System/ISubtractionOperators.cs b/src/libraries/System.Private.CoreLib/src/System/ISubtractionOperators.cs index f11da9d2f9812..5cbe1a634477f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ISubtractionOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ISubtractionOperators.cs @@ -13,7 +13,7 @@ namespace System /// The type that implements this interface. /// The type that will be subtracted from . /// The type that contains the difference of subtracted from . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface ISubtractionOperators where TSelf : ISubtractionOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IUnaryNegationOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IUnaryNegationOperators.cs index 686887ce9c8fd..5ccede089fe2c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IUnaryNegationOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IUnaryNegationOperators.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for computing the unary negation of a value. /// The type that implements this interface. /// The type that contains the result of negating . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IUnaryNegationOperators where TSelf : IUnaryNegationOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IUnaryPlusOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IUnaryPlusOperators.cs index a719ff5d0b11e..2d4dd964136d0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IUnaryPlusOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IUnaryPlusOperators.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for computing the unary plus of a value. /// The type that implements this interface. /// The type that contains the result of negating . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IUnaryPlusOperators where TSelf : IUnaryPlusOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/Int16.cs b/src/libraries/System.Private.CoreLib/src/System/Int16.cs index fe71b22401df8..df93c69690e7f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int16.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int16.cs @@ -288,11 +288,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IAdditionOperators.operator +(short left, short right) => (short)(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IAdditionOperators.operator +(short left, short right) // => checked((short)(left + right)); @@ -300,30 +300,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBinaryInteger.LeadingZeroCount(short value) => (short)(BitOperations.LeadingZeroCount((ushort)value) - 16); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBinaryInteger.PopCount(short value) => (short)BitOperations.PopCount((ushort)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBinaryInteger.RotateLeft(short value, int rotateAmount) => (short)((value << (rotateAmount & 15)) | ((ushort)value >> ((16 - rotateAmount) & 15))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBinaryInteger.RotateRight(short value, int rotateAmount) => (short)(((ushort)value >> (rotateAmount & 15)) | (value << ((16 - rotateAmount) & 15))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBinaryInteger.TrailingZeroCount(short value) => (byte)(BitOperations.TrailingZeroCount(value << 16) - 16); @@ -331,11 +331,11 @@ static short IBinaryInteger.TrailingZeroCount(short value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(short value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBinaryNumber.Log2(short value) { if (value < 0) @@ -349,19 +349,19 @@ static short IBinaryNumber.Log2(short value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBitwiseOperators.operator &(short left, short right) => (short)(left & right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBitwiseOperators.operator |(short left, short right) => (short)(left | right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBitwiseOperators.operator ^(short left, short right) => (short)(left ^ right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBitwiseOperators.operator ~(short value) => (short)(~value); @@ -369,19 +369,19 @@ static short IBinaryNumber.Log2(short value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(short left, short right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(short left, short right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(short left, short right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(short left, short right) => left >= right; @@ -389,11 +389,11 @@ static short IBinaryNumber.Log2(short value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IDecrementOperators.operator --(short value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IDecrementOperators.operator --(short value) // => checked(--value); @@ -401,11 +401,11 @@ static short IBinaryNumber.Log2(short value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IDivisionOperators.operator /(short left, short right) => (short)(left / right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IDivisionOperators.operator /(short left, short right) // => checked((short)(left / right)); @@ -413,11 +413,11 @@ static short IBinaryNumber.Log2(short value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(short left, short right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(short left, short right) => left != right; @@ -425,11 +425,11 @@ static short IBinaryNumber.Log2(short value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IIncrementOperators.operator ++(short value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IIncrementOperators.operator ++(short value) // => checked(++value); @@ -437,21 +437,21 @@ static short IBinaryNumber.Log2(short value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IModulusOperators.operator %(short left, short right) => (short)(left % right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IModulusOperators.operator %(short left, short right) // => checked((short)(left % right)); @@ -459,18 +459,18 @@ static short IBinaryNumber.Log2(short value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IMultiplyOperators.operator *(short left, short right) => (short)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IMultiplyOperators.operator *(short left, short right) // => checked((short)(left * right)); @@ -478,21 +478,21 @@ static short IBinaryNumber.Log2(short value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Abs(short value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Clamp(short value, short min, short max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static short INumber.Create(TOther value) { @@ -559,7 +559,7 @@ static short INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static short INumber.CreateSaturating(TOther value) { @@ -643,7 +643,7 @@ static short INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static short INumber.CreateTruncating(TOther value) { @@ -710,31 +710,31 @@ static short INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (short Quotient, short Remainder) INumber.DivRem(short left, short right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Max(short x, short y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Min(short x, short y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Sign(short value) => (short)Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out short result) { @@ -904,11 +904,11 @@ static bool INumber.TryCreate(TOther value, out short result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out short result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out short result) => TryParse(s, style, provider, out result); @@ -916,11 +916,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IF // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out short result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -928,15 +928,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IShiftOperators.operator <<(short value, int shiftAmount) => (short)(value << shiftAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IShiftOperators.operator >>(short value, int shiftAmount) => (short)(value >> shiftAmount); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static short IShiftOperators.operator >>>(short value, int shiftAmount) // => (short)((ushort)value >> shiftAmount); @@ -944,18 +944,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out short result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -963,11 +963,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short ISubtractionOperators.operator -(short left, short right) => (short)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short ISubtractionOperators.operator -(short left, short right) // => checked((short)(left - right)); @@ -975,11 +975,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IUnaryNegationOperators.operator -(short value) => (short)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IUnaryNegationOperators.operator -(short value) // => checked((short)(-value)); @@ -987,11 +987,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IUnaryPlusOperators.operator +(short value) => (short)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IUnaryPlusOperators.operator +(short value) // => checked((short)(+value)); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Int32.cs b/src/libraries/System.Private.CoreLib/src/System/Int32.cs index d52343097cc33..18295151f5fb4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int32.cs @@ -280,11 +280,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IAdditionOperators.operator +(int left, int right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IAdditionOperators.operator +(int left, int right) // => checked(left + right); @@ -292,30 +292,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBinaryInteger.LeadingZeroCount(int value) => BitOperations.LeadingZeroCount((uint)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBinaryInteger.PopCount(int value) => BitOperations.PopCount((uint)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBinaryInteger.RotateLeft(int value, int rotateAmount) => (int)BitOperations.RotateLeft((uint)value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBinaryInteger.RotateRight(int value, int rotateAmount) => (int)BitOperations.RotateRight((uint)value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBinaryInteger.TrailingZeroCount(int value) => BitOperations.TrailingZeroCount(value); @@ -323,11 +323,11 @@ static int IBinaryInteger.TrailingZeroCount(int value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(int value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBinaryNumber.Log2(int value) { if (value < 0) @@ -341,19 +341,19 @@ static int IBinaryNumber.Log2(int value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBitwiseOperators.operator &(int left, int right) => left & right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBitwiseOperators.operator |(int left, int right) => left | right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBitwiseOperators.operator ^(int left, int right) => left ^ right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBitwiseOperators.operator ~(int value) => ~value; @@ -361,19 +361,19 @@ static int IBinaryNumber.Log2(int value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(int left, int right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(int left, int right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(int left, int right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(int left, int right) => left >= right; @@ -381,11 +381,11 @@ static int IBinaryNumber.Log2(int value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IDecrementOperators.operator --(int value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IDecrementOperators.operator --(int value) // => checked(--value); @@ -393,11 +393,11 @@ static int IBinaryNumber.Log2(int value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IDivisionOperators.operator /(int left, int right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IDivisionOperators.operator /(int left, int right) // => checked(left / right); @@ -405,11 +405,11 @@ static int IBinaryNumber.Log2(int value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(int left, int right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(int left, int right) => left != right; @@ -417,11 +417,11 @@ static int IBinaryNumber.Log2(int value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IIncrementOperators.operator ++(int value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IIncrementOperators.operator ++(int value) // => checked(++value); @@ -429,21 +429,21 @@ static int IBinaryNumber.Log2(int value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IModulusOperators.operator %(int left, int right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IModulusOperators.operator %(int left, int right) // => checked(left % right); @@ -451,18 +451,18 @@ static int IBinaryNumber.Log2(int value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IMultiplyOperators.operator *(int left, int right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IMultiplyOperators.operator *(int left, int right) // => checked(left * right); @@ -470,21 +470,21 @@ static int IBinaryNumber.Log2(int value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Abs(int value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Clamp(int value, int min, int max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] internal static int Create(TOther value) where TOther : INumber { @@ -551,12 +551,12 @@ internal static int Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static int INumber.Create(TOther value) => Create(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static int INumber.CreateSaturating(TOther value) { @@ -636,7 +636,7 @@ static int INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static int INumber.CreateTruncating(TOther value) { @@ -703,31 +703,31 @@ static int INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (int Quotient, int Remainder) INumber.DivRem(int left, int right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Max(int x, int y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Min(int x, int y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Sign(int value) => Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out int result) { @@ -873,11 +873,11 @@ static bool INumber.TryCreate(TOther value, out int result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out int result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out int result) => TryParse(s, style, provider, out result); @@ -885,11 +885,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFor // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out int result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -897,15 +897,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvi // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IShiftOperators.operator <<(int value, int shiftAmount) => value << shiftAmount; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IShiftOperators.operator >>(int value, int shiftAmount) => value >> shiftAmount; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static int IShiftOperators.operator >>>(int value, int shiftAmount) // => (int)((uint)value >> shiftAmount); @@ -913,18 +913,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvi // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out int result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -932,11 +932,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int ISubtractionOperators.operator -(int left, int right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int ISubtractionOperators.operator -(int left, int right) // => checked(left - right); @@ -944,11 +944,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IUnaryNegationOperators.operator -(int value) => -value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IUnaryNegationOperators.operator -(int value) // => checked(-value); @@ -956,11 +956,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IUnaryPlusOperators.operator +(int value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IUnaryPlusOperators.operator +(int value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Int64.cs b/src/libraries/System.Private.CoreLib/src/System/Int64.cs index 5980d92925058..603fdcae8f46a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int64.cs @@ -267,11 +267,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IAdditionOperators.operator +(long left, long right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IAdditionOperators.operator +(long left, long right) // => checked(left + right); @@ -279,30 +279,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBinaryInteger.LeadingZeroCount(long value) => BitOperations.LeadingZeroCount((ulong)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBinaryInteger.PopCount(long value) => BitOperations.PopCount((ulong)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBinaryInteger.RotateLeft(long value, int rotateAmount) => (long)BitOperations.RotateLeft((ulong)value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBinaryInteger.RotateRight(long value, int rotateAmount) => (long)BitOperations.RotateRight((ulong)value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBinaryInteger.TrailingZeroCount(long value) => BitOperations.TrailingZeroCount(value); @@ -310,11 +310,11 @@ static long IBinaryInteger.TrailingZeroCount(long value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(long value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBinaryNumber.Log2(long value) { if (value < 0) @@ -328,19 +328,19 @@ static long IBinaryNumber.Log2(long value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBitwiseOperators.operator &(long left, long right) => left & right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBitwiseOperators.operator |(long left, long right) => left | right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBitwiseOperators.operator ^(long left, long right) => left ^ right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBitwiseOperators.operator ~(long value) => ~value; @@ -348,19 +348,19 @@ static long IBinaryNumber.Log2(long value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(long left, long right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(long left, long right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(long left, long right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(long left, long right) => left >= right; @@ -368,11 +368,11 @@ static long IBinaryNumber.Log2(long value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IDecrementOperators.operator --(long value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IDecrementOperators.operator --(long value) // => checked(--value); @@ -380,11 +380,11 @@ static long IBinaryNumber.Log2(long value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IDivisionOperators.operator /(long left, long right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IDivisionOperators.operator /(long left, long right) // => checked(left / right); @@ -392,11 +392,11 @@ static long IBinaryNumber.Log2(long value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(long left, long right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(long left, long right) => left != right; @@ -404,11 +404,11 @@ static long IBinaryNumber.Log2(long value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IIncrementOperators.operator ++(long value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IIncrementOperators.operator ++(long value) // => checked(++value); @@ -416,21 +416,21 @@ static long IBinaryNumber.Log2(long value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IModulusOperators.operator %(long left, long right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IModulusOperators.operator %(long left, long right) // => checked(left % right); @@ -438,18 +438,18 @@ static long IBinaryNumber.Log2(long value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IMultiplyOperators.operator *(long left, long right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IMultiplyOperators.operator *(long left, long right) // => checked(left * right); @@ -457,21 +457,21 @@ static long IBinaryNumber.Log2(long value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Abs(long value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Clamp(long value, long min, long max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static long INumber.Create(TOther value) { @@ -538,7 +538,7 @@ static long INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static long INumber.CreateSaturating(TOther value) { @@ -613,7 +613,7 @@ static long INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static long INumber.CreateTruncating(TOther value) { @@ -680,31 +680,31 @@ static long INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (long Quotient, long Remainder) INumber.DivRem(long left, long right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Max(long x, long y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Min(long x, long y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Sign(long value) => Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out long result) { @@ -826,11 +826,11 @@ static bool INumber.TryCreate(TOther value, out long result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out long result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out long result) => TryParse(s, style, provider, out result); @@ -838,11 +838,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFo // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out long result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -850,15 +850,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IShiftOperators.operator <<(long value, int shiftAmount) => value << (int)shiftAmount; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IShiftOperators.operator >>(long value, int shiftAmount) => value >> (int)shiftAmount; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static long IShiftOperators.operator >>>(long value, int shiftAmount) // => (long)((ulong)value >> (int)shiftAmount); @@ -866,18 +866,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out long result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -885,11 +885,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long ISubtractionOperators.operator -(long left, long right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long ISubtractionOperators.operator -(long left, long right) // => checked(left - right); @@ -897,11 +897,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IUnaryNegationOperators.operator -(long value) => -value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IUnaryNegationOperators.operator -(long value) // => checked(-value); @@ -909,11 +909,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IUnaryPlusOperators.operator +(long value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IUnaryPlusOperators.operator +(long value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs index f68ca4760e410..7fb1803d6f5ab 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs @@ -254,11 +254,11 @@ public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatPro // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IAdditionOperators.operator +(nint left, nint right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IAdditionOperators.operator +(nint left, nint right) // => checked(left + right); @@ -266,14 +266,14 @@ public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatPro // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBinaryInteger.LeadingZeroCount(nint value) { if (Environment.Is64BitProcess) @@ -286,7 +286,7 @@ static nint IBinaryInteger.LeadingZeroCount(nint value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBinaryInteger.PopCount(nint value) { if (Environment.Is64BitProcess) @@ -299,7 +299,7 @@ static nint IBinaryInteger.PopCount(nint value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBinaryInteger.RotateLeft(nint value, int rotateAmount) { if (Environment.Is64BitProcess) @@ -312,7 +312,7 @@ static nint IBinaryInteger.RotateLeft(nint value, int rotateAmount) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBinaryInteger.RotateRight(nint value, int rotateAmount) { @@ -326,7 +326,7 @@ static nint IBinaryInteger.RotateRight(nint value, int rotateAmount) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBinaryInteger.TrailingZeroCount(nint value) { if (Environment.Is64BitProcess) @@ -343,11 +343,11 @@ static nint IBinaryInteger.TrailingZeroCount(nint value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(nint value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBinaryNumber.Log2(nint value) { if (value < 0) @@ -369,19 +369,19 @@ static nint IBinaryNumber.Log2(nint value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBitwiseOperators.operator &(nint left, nint right) => left & right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBitwiseOperators.operator |(nint left, nint right) => left | right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBitwiseOperators.operator ^(nint left, nint right) => left ^ right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBitwiseOperators.operator ~(nint value) => ~value; @@ -389,19 +389,19 @@ static nint IBinaryNumber.Log2(nint value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(nint left, nint right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(nint left, nint right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(nint left, nint right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(nint left, nint right) => left >= right; @@ -409,11 +409,11 @@ static nint IBinaryNumber.Log2(nint value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IDecrementOperators.operator --(nint value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IDecrementOperators.operator --(nint value) // => checked(--value); @@ -421,11 +421,11 @@ static nint IBinaryNumber.Log2(nint value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IDivisionOperators.operator /(nint left, nint right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IDivisionOperators.operator /(nint left, nint right) // => checked(left / right); @@ -433,11 +433,11 @@ static nint IBinaryNumber.Log2(nint value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(nint left, nint right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(nint left, nint right) => left != right; @@ -445,11 +445,11 @@ static nint IBinaryNumber.Log2(nint value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IIncrementOperators.operator ++(nint value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IIncrementOperators.operator ++(nint value) // => checked(++value); @@ -457,21 +457,21 @@ static nint IBinaryNumber.Log2(nint value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IModulusOperators.operator %(nint left, nint right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IModulusOperators.operator %(nint left, nint right) // => checked(left % right); @@ -479,18 +479,18 @@ static nint IBinaryNumber.Log2(nint value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IMultiplyOperators.operator *(nint left, nint right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IMultiplyOperators.operator *(nint left, nint right) // => checked(left * right); @@ -498,21 +498,21 @@ static nint IBinaryNumber.Log2(nint value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Abs(nint value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Clamp(nint value, nint min, nint max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static nint INumber.Create(TOther value) { @@ -579,7 +579,7 @@ static nint INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static nint INumber.CreateSaturating(TOther value) { @@ -657,7 +657,7 @@ static nint INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static nint INumber.CreateTruncating(TOther value) { @@ -724,31 +724,31 @@ static nint INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (nint Quotient, nint Remainder) INumber.DivRem(nint left, nint right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Max(nint x, nint y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Min(nint x, nint y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Sign(nint value) => Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out nint result) { @@ -886,11 +886,11 @@ static bool INumber.TryCreate(TOther value, out nint result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out nint result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out nint result) => TryParse(s, style, provider, out result); @@ -898,11 +898,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFo // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out nint result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -910,15 +910,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IShiftOperators.operator <<(nint value, int shiftAmount) => value << (int)shiftAmount; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IShiftOperators.operator >>(nint value, int shiftAmount) => value >> (int)shiftAmount; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static nint IShiftOperators.operator >>>(nint value, int shiftAmount) // => (nint)((nuint)value >> (int)shiftAmount); @@ -926,18 +926,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out nint result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -945,11 +945,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint ISubtractionOperators.operator -(nint left, nint right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint ISubtractionOperators.operator -(nint left, nint right) // => checked(left - right); @@ -957,11 +957,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IUnaryNegationOperators.operator -(nint value) => -value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IUnaryNegationOperators.operator -(nint value) // => checked(-value); @@ -969,11 +969,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IUnaryPlusOperators.operator +(nint value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IUnaryPlusOperators.operator +(nint value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs index 408c83cb05058..f722e02810655 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs @@ -242,6 +242,8 @@ namespace System internal static partial class Number { internal const int DecimalPrecision = 29; // Decimal.DecCalc also uses this value + internal const string PreviewFeatureMessage = "Generic Math is in preview."; + internal const string PreviewFeatureUrl = "https://aka.ms/dotnet-warnings/generic-math-preview"; // SinglePrecision and DoublePrecision represent the maximum number of digits required // to guarantee that any given Single or Double can roundtrip. Some numbers may require diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.cs index 387e509997a2a..a94a0e19d0176 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.cs @@ -30,7 +30,7 @@ public static partial class RuntimeFeature /// /// Indicates that this version of runtime supports virtual static members of interfaces. /// - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public const string VirtualStaticsInInterfaces = nameof(VirtualStaticsInInterfaces); /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.PlatformNotSupported.cs index 2edfd97a518ad..626ea6d189dee 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.PlatformNotSupported.cs @@ -7,7 +7,7 @@ namespace System.Runtime.Intrinsics.X86 { [CLSCompliant(false)] - [RequiresPreviewFeatures] + [RequiresPreviewFeatures("AvxVnni is in preview.")] public abstract class AvxVnni : Avx2 { internal AvxVnni() { } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.cs index d6bb750ebc89a..fcefbeac02122 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.cs @@ -8,7 +8,7 @@ namespace System.Runtime.Intrinsics.X86 { [Intrinsic] [CLSCompliant(false)] - [RequiresPreviewFeatures] + [RequiresPreviewFeatures("AvxVnni is in preview.")] public abstract class AvxVnni : Avx2 { internal AvxVnni() { } diff --git a/src/libraries/System.Private.CoreLib/src/System/SByte.cs b/src/libraries/System.Private.CoreLib/src/System/SByte.cs index 759fc095b8365..1ccea1cca7061 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SByte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SByte.cs @@ -297,11 +297,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IAdditionOperators.operator +(sbyte left, sbyte right) => (sbyte)(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IAdditionOperators.operator +(sbyte left, sbyte right) // => checked((sbyte)(left + right)); @@ -309,30 +309,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBinaryInteger.LeadingZeroCount(sbyte value) => (sbyte)(BitOperations.LeadingZeroCount((byte)value) - 24); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBinaryInteger.PopCount(sbyte value) => (sbyte)BitOperations.PopCount((byte)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBinaryInteger.RotateLeft(sbyte value, int rotateAmount) => (sbyte)((value << (rotateAmount & 7)) | ((byte)value >> ((8 - rotateAmount) & 7))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBinaryInteger.RotateRight(sbyte value, int rotateAmount) => (sbyte)(((byte)value >> (rotateAmount & 7)) | (value << ((8 - rotateAmount) & 7))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBinaryInteger.TrailingZeroCount(sbyte value) => (sbyte)(BitOperations.TrailingZeroCount(value << 24) - 24); @@ -340,11 +340,11 @@ static sbyte IBinaryInteger.TrailingZeroCount(sbyte value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(sbyte value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBinaryNumber.Log2(sbyte value) { if (value < 0) @@ -358,19 +358,19 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBitwiseOperators.operator &(sbyte left, sbyte right) => (sbyte)(left & right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBitwiseOperators.operator |(sbyte left, sbyte right) => (sbyte)(left | right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBitwiseOperators.operator ^(sbyte left, sbyte right) => (sbyte)(left ^ right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBitwiseOperators.operator ~(sbyte value) => (sbyte)(~value); @@ -378,19 +378,19 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(sbyte left, sbyte right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(sbyte left, sbyte right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(sbyte left, sbyte right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(sbyte left, sbyte right) => left >= right; @@ -398,11 +398,11 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IDecrementOperators.operator --(sbyte value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IDecrementOperators.operator --(sbyte value) // => checked(--value); @@ -410,11 +410,11 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IDivisionOperators.operator /(sbyte left, sbyte right) => (sbyte)(left / right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IDivisionOperators.operator /(sbyte left, sbyte right) // => checked((sbyte)(left / right)); @@ -422,11 +422,11 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(sbyte left, sbyte right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(sbyte left, sbyte right) => left != right; @@ -434,11 +434,11 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IIncrementOperators.operator ++(sbyte value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IIncrementOperators.operator ++(sbyte value) // => checked(++value); @@ -446,21 +446,21 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IModulusOperators.operator %(sbyte left, sbyte right) => (sbyte)(left % right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IModulusOperators.operator %(sbyte left, sbyte right) // => checked((sbyte)(left % right)); @@ -468,18 +468,18 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IMultiplyOperators.operator *(sbyte left, sbyte right) => (sbyte)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IMultiplyOperators.operator *(sbyte left, sbyte right) // => checked((sbyte)(left * right)); @@ -487,21 +487,21 @@ static sbyte IBinaryNumber.Log2(sbyte value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Abs(sbyte value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Clamp(sbyte value, sbyte min, sbyte max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static sbyte INumber.Create(TOther value) { @@ -568,7 +568,7 @@ static sbyte INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static sbyte INumber.CreateSaturating(TOther value) { @@ -655,7 +655,7 @@ static sbyte INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static sbyte INumber.CreateTruncating(TOther value) { @@ -722,31 +722,31 @@ static sbyte INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (sbyte Quotient, sbyte Remainder) INumber.DivRem(sbyte left, sbyte right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Max(sbyte x, sbyte y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Min(sbyte x, sbyte y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Sign(sbyte value) => (sbyte)Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out sbyte result) { @@ -932,11 +932,11 @@ static bool INumber.TryCreate(TOther value, out sbyte result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out sbyte result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out sbyte result) => TryParse(s, style, provider, out result); @@ -944,11 +944,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IF // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out sbyte result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -956,15 +956,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IShiftOperators.operator <<(sbyte value, int shiftAmount) => (sbyte)(value << shiftAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IShiftOperators.operator >>(sbyte value, int shiftAmount) => (sbyte)(value >> shiftAmount); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static sbyte IShiftOperators.operator >>>(sbyte value, int shiftAmount) // => (sbyte)((byte)value >> shiftAmount); @@ -972,18 +972,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out sbyte result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -991,11 +991,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte ISubtractionOperators.operator -(sbyte left, sbyte right) => (sbyte)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte ISubtractionOperators.operator -(sbyte left, sbyte right) // => checked((sbyte)(left - right)); @@ -1003,11 +1003,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IUnaryNegationOperators.operator -(sbyte value) => (sbyte)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IUnaryNegationOperators.operator -(sbyte value) // => checked((sbyte)(-value)); @@ -1015,11 +1015,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IUnaryPlusOperators.operator +(sbyte value) => (sbyte)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IUnaryPlusOperators.operator +(sbyte value) // => checked((sbyte)(+value)); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Single.cs b/src/libraries/System.Private.CoreLib/src/System/Single.cs index 589cc26dcfdd1..35c6a1d8e7b16 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Single.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Single.cs @@ -448,11 +448,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IAdditionOperators.operator +(float left, float right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IAdditionOperators.operator +(float left, float right) // => checked(left + right); @@ -460,14 +460,14 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IAdditiveIdentity.AdditiveIdentity => 0.0f; // // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(float value) { uint bits = BitConverter.SingleToUInt32Bits(value); @@ -480,7 +480,7 @@ static bool IBinaryNumber.IsPow2(float value) && (significand == MinSignificand); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IBinaryNumber.Log2(float value) => MathF.Log2(value); @@ -488,28 +488,28 @@ static float IBinaryNumber.Log2(float value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IBitwiseOperators.operator &(float left, float right) { uint bits = BitConverter.SingleToUInt32Bits(left) & BitConverter.SingleToUInt32Bits(right); return BitConverter.UInt32BitsToSingle(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IBitwiseOperators.operator |(float left, float right) { uint bits = BitConverter.SingleToUInt32Bits(left) | BitConverter.SingleToUInt32Bits(right); return BitConverter.UInt32BitsToSingle(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IBitwiseOperators.operator ^(float left, float right) { uint bits = BitConverter.SingleToUInt32Bits(left) ^ BitConverter.SingleToUInt32Bits(right); return BitConverter.UInt32BitsToSingle(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IBitwiseOperators.operator ~(float value) { uint bits = ~BitConverter.SingleToUInt32Bits(value); @@ -520,19 +520,19 @@ static float IBinaryNumber.Log2(float value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(float left, float right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(float left, float right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(float left, float right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(float left, float right) => left >= right; @@ -540,11 +540,11 @@ static float IBinaryNumber.Log2(float value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IDecrementOperators.operator --(float value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IDecrementOperators.operator --(float value) // => checked(--value); @@ -552,11 +552,11 @@ static float IBinaryNumber.Log2(float value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IDivisionOperators.operator /(float left, float right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IDivisionOperators.operator /(float left, float right) // => checked(left / right); @@ -564,11 +564,11 @@ static float IBinaryNumber.Log2(float value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(float left, float right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(float left, float right) => left != right; @@ -576,200 +576,200 @@ static float IBinaryNumber.Log2(float value) // IFloatingPoint // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.E => MathF.E; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Epsilon => Epsilon; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.NaN => NaN; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.NegativeInfinity => NegativeInfinity; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.NegativeZero => -0.0f; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Pi => MathF.PI; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.PositiveInfinity => PositiveInfinity; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Tau => MathF.Tau; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Acos(float x) => MathF.Acos(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Acosh(float x) => MathF.Acosh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Asin(float x) => MathF.Asin(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Asinh(float x) => MathF.Asinh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Atan(float x) => MathF.Atan(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Atan2(float y, float x) => MathF.Atan2(y, x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Atanh(float x) => MathF.Atanh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.BitIncrement(float x) => MathF.BitIncrement(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.BitDecrement(float x) => MathF.BitDecrement(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Cbrt(float x) => MathF.Cbrt(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Ceiling(float x) => MathF.Ceiling(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.CopySign(float x, float y) => MathF.CopySign(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Cos(float x) => MathF.Cos(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Cosh(float x) => MathF.Cosh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Exp(float x) => MathF.Exp(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Floor(float x) => MathF.Floor(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.FusedMultiplyAdd(float left, float right, float addend) => MathF.FusedMultiplyAdd(left, right, addend); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.IEEERemainder(float left, float right) => MathF.IEEERemainder(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TInteger IFloatingPoint.ILogB(float x) => TInteger.Create(MathF.ILogB(x)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Log(float x) => MathF.Log(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Log(float x, float newBase) => MathF.Log(x, newBase); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Log2(float x) => MathF.Log2(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Log10(float x) => MathF.Log10(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.MaxMagnitude(float x, float y) => MathF.MaxMagnitude(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.MinMagnitude(float x, float y) => MathF.MinMagnitude(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Pow(float x, float y) => MathF.Pow(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Round(float x) => MathF.Round(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Round(float x, TInteger digits) => MathF.Round(x, int.Create(digits)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Round(float x, MidpointRounding mode) => MathF.Round(x, mode); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Round(float x, TInteger digits, MidpointRounding mode) => MathF.Round(x, int.Create(digits), mode); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.ScaleB(float x, TInteger n) => MathF.ScaleB(x, int.Create(n)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Sin(float x) => MathF.Sin(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Sinh(float x) => MathF.Sinh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Sqrt(float x) => MathF.Sqrt(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Tan(float x) => MathF.Tan(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Tanh(float x) => MathF.Tanh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Truncate(float x) => MathF.Truncate(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsFinite(float x) => IsFinite(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsInfinity(float x) => IsInfinity(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsNaN(float x) => IsNaN(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsNegative(float x) => IsNegative(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsNegativeInfinity(float x) => IsNegativeInfinity(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsNormal(float x) => IsNormal(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsPositiveInfinity(float x) => IsPositiveInfinity(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IFloatingPoint.IsSubnormal(float x) => IsSubnormal(x); // static float IFloatingPoint.AcosPi(float x) @@ -842,11 +842,11 @@ static float IFloatingPoint.Truncate(float x) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IIncrementOperators.operator ++(float value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IIncrementOperators.operator ++(float value) // => checked(++value); @@ -854,21 +854,21 @@ static float IFloatingPoint.Truncate(float x) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IModulusOperators.operator %(float left, float right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IModulusOperators.operator %(float left, float right) // => checked(left % right); @@ -876,18 +876,18 @@ static float IFloatingPoint.Truncate(float x) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IMultiplicativeIdentity.MultiplicativeIdentity => 1.0f; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IMultiplyOperators.operator *(float left, float right) => (float)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IMultiplyOperators.operator *(float left, float right) // => checked((float)(left * right)); @@ -895,21 +895,21 @@ static float IFloatingPoint.Truncate(float x) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.One => 1.0f; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Zero => 0.0f; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Abs(float value) => MathF.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Clamp(float value, float min, float max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static float INumber.Create(TOther value) { @@ -976,7 +976,7 @@ static float INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static float INumber.CreateSaturating(TOther value) { @@ -1043,7 +1043,7 @@ static float INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static float INumber.CreateTruncating(TOther value) { @@ -1110,31 +1110,31 @@ static float INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (float Quotient, float Remainder) INumber.DivRem(float left, float right) => (left / right, left % right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Max(float x, float y) => MathF.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Min(float x, float y) => MathF.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Sign(float value) => MathF.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out float result) { @@ -1216,11 +1216,11 @@ static bool INumber.TryCreate(TOther value, out float result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out float result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out float result) => TryParse(s, style, provider, out result); @@ -1228,11 +1228,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IF // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out float result) => TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, provider, out result); @@ -1240,18 +1240,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Float | NumberStyles.AllowThousands, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out float result) => TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, provider, out result); @@ -1259,11 +1259,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float ISubtractionOperators.operator -(float left, float right) => (float)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float ISubtractionOperators.operator -(float left, float right) // => checked((float)(left - right)); @@ -1271,20 +1271,20 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IUnaryNegationOperators.operator -(float value) => (float)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IUnaryNegationOperators.operator -(float value) => checked((float)(-value)); // // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IUnaryPlusOperators.operator +(float value) => (float)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IUnaryPlusOperators.operator +(float value) => checked((float)(+value)); #endif // FEATURE_GENERIC_MATH } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs index 54a7dc691cc0c..3f60a1cd7ff7c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs @@ -392,13 +392,24 @@ public bool TryReset() // to transition from canceled to non-canceled. if (_state == NotCanceledState) { - // If there is no timer, then we're free to reset. If there is a timer, then we need to first try - // to reset it to be infinite so that it won't fire, and then recognize that it could have already - // fired by the time we successfully changed it, and so check to see whether that's possibly the case. - // If we successfully reset it and it never fired, then we can be sure it won't trigger cancellation. - bool reset = - _timer is not TimerQueueTimer timer || - (timer.Change(Timeout.UnsignedInfinite, Timeout.UnsignedInfinite) && !timer._everQueued); + bool reset = false; + + try + { + // If there is no timer, then we're free to reset. If there is a timer, then we need to first try + // to reset it to be infinite so that it won't fire, and then recognize that it could have already + // fired by the time we successfully changed it, and so check to see whether that's possibly the case. + // If we successfully reset it and it never fired, then we can be sure it won't trigger cancellation. + reset = _timer is not TimerQueueTimer timer || + (timer.Change(Timeout.UnsignedInfinite, Timeout.UnsignedInfinite) && !timer._everQueued); + } + catch (ObjectDisposedException) + { + // Just eat the exception. There is no other way to tell that + // the timer has been disposed, and even if there were, there + // would not be a good way to deal with the observe/dispose + // race condition. + } if (reset) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs index ac42990b31d1a..72fd3feffff11 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs @@ -618,9 +618,6 @@ public Task ContinueWith(Action> continuationAction) /// /// The argument is null. /// - /// The provided CancellationToken - /// has already been disposed. - /// public Task ContinueWith(Action> continuationAction, CancellationToken cancellationToken) { return ContinueWith(continuationAction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None); @@ -722,9 +719,6 @@ public Task ContinueWith(Action> continuationAction, TaskContinuat /// /// The argument is null. /// - /// The provided CancellationToken - /// has already been disposed. - /// public Task ContinueWith(Action> continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { @@ -806,9 +800,6 @@ public Task ContinueWith(Action, object?> continuationAction, obje /// /// The argument is null. /// - /// The provided CancellationToken - /// has already been disposed. - /// public Task ContinueWith(Action, object?> continuationAction, object? state, CancellationToken cancellationToken) { return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None); @@ -913,9 +904,6 @@ public Task ContinueWith(Action, object?> continuationAction, obje /// /// The argument is null. /// - /// The provided CancellationToken - /// has already been disposed. - /// public Task ContinueWith(Action, object?> continuationAction, object? state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs index 458c914773cbc..7e8888f3e2dc9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs @@ -3553,9 +3553,6 @@ public Task ContinueWith(Action continuationAction) /// /// The argument is null. /// - /// The provided CancellationToken - /// has already been disposed. - /// public Task ContinueWith(Action continuationAction, CancellationToken cancellationToken) { return ContinueWith(continuationAction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None); @@ -3656,9 +3653,6 @@ public Task ContinueWith(Action continuationAction, TaskContinuationOption /// /// The argument is null. /// - /// The provided CancellationToken - /// has already been disposed. - /// public Task ContinueWith(Action continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { @@ -3738,9 +3732,6 @@ public Task ContinueWith(Action continuationAction, object? state /// /// The argument is null. /// - /// The provided CancellationToken - /// has already been disposed. - /// public Task ContinueWith(Action continuationAction, object? state, CancellationToken cancellationToken) { return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None); @@ -3844,9 +3835,6 @@ public Task ContinueWith(Action continuationAction, object? state /// /// The argument is null. /// - /// The provided CancellationToken - /// has already been disposed. - /// public Task ContinueWith(Action continuationAction, object? state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs b/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs index 05585e7ce612a..ee3d11925d0c3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs @@ -911,19 +911,19 @@ public string ToString(string? format, IFormatProvider? provider) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(TimeOnly left, TimeOnly right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(TimeOnly left, TimeOnly right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(TimeOnly left, TimeOnly right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(TimeOnly left, TimeOnly right) => left >= right; @@ -931,11 +931,11 @@ public string ToString(string? format, IFormatProvider? provider) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(TimeOnly left, TimeOnly right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(TimeOnly left, TimeOnly right) => left != right; @@ -943,11 +943,11 @@ public string ToString(string? format, IFormatProvider? provider) // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeOnly IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider, DateTimeStyles.None); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out TimeOnly result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -955,11 +955,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormat // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeOnly ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, provider, DateTimeStyles.None); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out TimeOnly result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -967,18 +967,18 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvi // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan ISubtractionOperators.operator -(TimeOnly left, TimeOnly right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan ISubtractionOperators.operator -(TimeOnly left, TimeOnly right) // => checked(left - right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeOnly IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeOnly IMinMaxValue.MaxValue => MaxValue; #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs b/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs index f117072b657d6..f7bcd46bd4691 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs @@ -509,11 +509,11 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IAdditionOperators.operator +(TimeSpan left, TimeSpan right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan IAdditionOperators.operator +(TimeSpan left, TimeSpan right) // => checked(left + right); @@ -521,26 +521,26 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IAdditiveIdentity.AdditiveIdentity => default; // // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(TimeSpan left, TimeSpan right) => left.operator <=(TimeSpan left, TimeSpan right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(TimeSpan left, TimeSpan right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(TimeSpan left, TimeSpan right) => left >= right; @@ -548,19 +548,19 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IDivisionOperators.operator /(TimeSpan left, double right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan IDivisionOperators.operator /(TimeSpan left, double right) // => checked(left / right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IDivisionOperators.operator /(TimeSpan left, TimeSpan right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IDivisionOperators.operator /(TimeSpan left, TimeSpan right) // => checked(left / right); @@ -568,11 +568,11 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(TimeSpan left, TimeSpan right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(TimeSpan left, TimeSpan right) => left != right; @@ -580,28 +580,28 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IMinMaxValue.MaxValue => MaxValue; // // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IMultiplicativeIdentity.MultiplicativeIdentity => 1.0; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IMultiplyOperators.operator *(TimeSpan left, double right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan IMultiplyOperators.operator *(TimeSpan left, double right) // => checked(left * right); @@ -609,11 +609,11 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out TimeSpan result) => TryParse(s, provider, out result); @@ -621,11 +621,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormat // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out TimeSpan result) => TryParse(s, provider, out result); @@ -633,11 +633,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvi // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan ISubtractionOperators.operator -(TimeSpan left, TimeSpan right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan ISubtractionOperators.operator -(TimeSpan left, TimeSpan right) // => checked(left - right); @@ -645,11 +645,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvi // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IUnaryNegationOperators.operator -(TimeSpan value) => -value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan IUnaryNegationOperators.operator -(TimeSpan value) // => checked(-value); @@ -657,11 +657,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvi // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IUnaryPlusOperators.operator +(TimeSpan value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan IUnaryPlusOperators.operator +(TimeSpan value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt16.cs b/src/libraries/System.Private.CoreLib/src/System/UInt16.cs index b6131418f26fd..43d64623218d8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt16.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt16.cs @@ -279,11 +279,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IAdditionOperators.operator +(ushort left, ushort right) => (ushort)(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IAdditionOperators.operator +(ushort left, ushort right) // => checked((ushort)(left + right)); @@ -291,30 +291,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBinaryInteger.LeadingZeroCount(ushort value) => (ushort)(BitOperations.LeadingZeroCount(value) - 16); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBinaryInteger.PopCount(ushort value) => (ushort)BitOperations.PopCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBinaryInteger.RotateLeft(ushort value, int rotateAmount) => (ushort)((value << (rotateAmount & 15)) | (value >> ((16 - rotateAmount) & 15))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBinaryInteger.RotateRight(ushort value, int rotateAmount) => (ushort)((value >> (rotateAmount & 15)) | (value << ((16 - rotateAmount) & 15))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBinaryInteger.TrailingZeroCount(ushort value) => (ushort)(BitOperations.TrailingZeroCount(value << 16) - 16); @@ -322,11 +322,11 @@ static ushort IBinaryInteger.TrailingZeroCount(ushort value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(ushort value) => BitOperations.IsPow2((uint)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBinaryNumber.Log2(ushort value) => (ushort)BitOperations.Log2(value); @@ -334,19 +334,19 @@ static ushort IBinaryNumber.Log2(ushort value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBitwiseOperators.operator &(ushort left, ushort right) => (ushort)(left & right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBitwiseOperators.operator |(ushort left, ushort right) => (ushort)(left | right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBitwiseOperators.operator ^(ushort left, ushort right) => (ushort)(left ^ right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBitwiseOperators.operator ~(ushort value) => (ushort)(~value); @@ -354,19 +354,19 @@ static ushort IBinaryNumber.Log2(ushort value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(ushort left, ushort right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(ushort left, ushort right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(ushort left, ushort right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(ushort left, ushort right) => left >= right; @@ -374,11 +374,11 @@ static ushort IBinaryNumber.Log2(ushort value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IDecrementOperators.operator --(ushort value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IDecrementOperators.operator --(ushort value) // => checked(--value); @@ -386,11 +386,11 @@ static ushort IBinaryNumber.Log2(ushort value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IDivisionOperators.operator /(ushort left, ushort right) => (ushort)(left / right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IDivisionOperators.operator /(ushort left, ushort right) // => checked((ushort)(left / right)); @@ -398,11 +398,11 @@ static ushort IBinaryNumber.Log2(ushort value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(ushort left, ushort right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(ushort left, ushort right) => left != right; @@ -410,11 +410,11 @@ static ushort IBinaryNumber.Log2(ushort value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IIncrementOperators.operator ++(ushort value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IIncrementOperators.operator ++(ushort value) // => checked(++value); @@ -422,21 +422,21 @@ static ushort IBinaryNumber.Log2(ushort value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IModulusOperators.operator %(ushort left, ushort right) => (ushort)(left % right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IModulusOperators.operator %(ushort left, ushort right) // => checked((ushort)(left % right)); @@ -444,18 +444,18 @@ static ushort IBinaryNumber.Log2(ushort value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IMultiplyOperators.operator *(ushort left, ushort right) => (ushort)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IMultiplyOperators.operator *(ushort left, ushort right) // => checked((ushort)(left * right)); @@ -463,21 +463,21 @@ static ushort IBinaryNumber.Log2(ushort value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Abs(ushort value) => value; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Clamp(ushort value, ushort min, ushort max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static ushort INumber.Create(TOther value) { @@ -544,7 +544,7 @@ static ushort INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static ushort INumber.CreateSaturating(TOther value) { @@ -628,7 +628,7 @@ static ushort INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static ushort INumber.CreateTruncating(TOther value) { @@ -695,31 +695,31 @@ static ushort INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (ushort Quotient, ushort Remainder) INumber.DivRem(ushort left, ushort right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Max(ushort x, ushort y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Min(ushort x, ushort y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Sign(ushort value) => (ushort)((value == 0) ? 0 : 1); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out ushort result) { @@ -889,11 +889,11 @@ static bool INumber.TryCreate(TOther value, out ushort result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out ushort result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out ushort result) => TryParse(s, style, provider, out result); @@ -901,11 +901,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, I // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out ushort result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -913,15 +913,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPr // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IShiftOperators.operator <<(ushort value, int shiftAmount) => (ushort)(value << shiftAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IShiftOperators.operator >>(ushort value, int shiftAmount) => (ushort)(value >> shiftAmount); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static ushort IShiftOperators.operator >>>(ushort value, int shiftAmount) // => (ushort)(value >> shiftAmount); @@ -929,11 +929,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPr // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out ushort result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -941,11 +941,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvide // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort ISubtractionOperators.operator -(ushort left, ushort right) => (ushort)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort ISubtractionOperators.operator -(ushort left, ushort right) // => checked((ushort)(left - right)); @@ -953,11 +953,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvide // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IUnaryNegationOperators.operator -(ushort value) => (ushort)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IUnaryNegationOperators.operator -(ushort value) // => checked((ushort)(-value)); @@ -965,11 +965,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvide // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IUnaryPlusOperators.operator +(ushort value) => (ushort)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IUnaryPlusOperators.operator +(ushort value) // => checked((ushort)(+value)); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt32.cs b/src/libraries/System.Private.CoreLib/src/System/UInt32.cs index 6d6e3ea446324..c470814fb9a27 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt32.cs @@ -265,11 +265,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IAdditionOperators.operator +(uint left, uint right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IAdditionOperators.operator +(uint left, uint right) // => checked(left + right); @@ -277,30 +277,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBinaryInteger.LeadingZeroCount(uint value) => (uint)BitOperations.LeadingZeroCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBinaryInteger.PopCount(uint value) => (uint)BitOperations.PopCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBinaryInteger.RotateLeft(uint value, int rotateAmount) => BitOperations.RotateLeft(value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBinaryInteger.RotateRight(uint value, int rotateAmount) => BitOperations.RotateRight(value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBinaryInteger.TrailingZeroCount(uint value) => (uint)BitOperations.TrailingZeroCount(value); @@ -308,11 +308,11 @@ static uint IBinaryInteger.TrailingZeroCount(uint value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(uint value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBinaryNumber.Log2(uint value) => (uint)BitOperations.Log2(value); @@ -320,19 +320,19 @@ static uint IBinaryNumber.Log2(uint value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBitwiseOperators.operator &(uint left, uint right) => left & right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBitwiseOperators.operator |(uint left, uint right) => left | right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBitwiseOperators.operator ^(uint left, uint right) => left ^ right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBitwiseOperators.operator ~(uint value) => ~value; @@ -340,19 +340,19 @@ static uint IBinaryNumber.Log2(uint value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(uint left, uint right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(uint left, uint right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(uint left, uint right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(uint left, uint right) => left >= right; @@ -360,11 +360,11 @@ static uint IBinaryNumber.Log2(uint value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IDecrementOperators.operator --(uint value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IDecrementOperators.operator --(uint value) // => checked(--value); @@ -372,11 +372,11 @@ static uint IBinaryNumber.Log2(uint value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IDivisionOperators.operator /(uint left, uint right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IDivisionOperators.operator /(uint left, uint right) // => checked(left / right); @@ -384,11 +384,11 @@ static uint IBinaryNumber.Log2(uint value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(uint left, uint right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(uint left, uint right) => left != right; @@ -396,11 +396,11 @@ static uint IBinaryNumber.Log2(uint value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IIncrementOperators.operator ++(uint value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IIncrementOperators.operator ++(uint value) // => checked(++value); @@ -408,21 +408,21 @@ static uint IBinaryNumber.Log2(uint value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IModulusOperators.operator %(uint left, uint right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IModulusOperators.operator %(uint left, uint right) // => checked(left % right); @@ -430,18 +430,18 @@ static uint IBinaryNumber.Log2(uint value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IMultiplyOperators.operator *(uint left, uint right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IMultiplyOperators.operator *(uint left, uint right) // => checked(left * right); @@ -449,21 +449,21 @@ static uint IBinaryNumber.Log2(uint value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Abs(uint value) => value; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Clamp(uint value, uint min, uint max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static uint INumber.Create(TOther value) { @@ -530,7 +530,7 @@ static uint INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static uint INumber.CreateSaturating(TOther value) { @@ -612,7 +612,7 @@ static uint INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static uint INumber.CreateTruncating(TOther value) { @@ -679,31 +679,31 @@ static uint INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (uint Quotient, uint Remainder) INumber.DivRem(uint left, uint right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Max(uint x, uint y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Min(uint x, uint y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Sign(uint value) => (uint)((value == 0) ? 0 : 1); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out uint result) { @@ -865,11 +865,11 @@ static bool INumber.TryCreate(TOther value, out uint result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out uint result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out uint result) => TryParse(s, style, provider, out result); @@ -877,11 +877,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFo // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out uint result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -889,15 +889,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IShiftOperators.operator <<(uint value, int shiftAmount) => value << (int)shiftAmount; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IShiftOperators.operator >>(uint value, int shiftAmount) => value >> (int)shiftAmount; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static uint IShiftOperators.operator >>>(uint value, int shiftAmount) // => value >> (int)shiftAmount; @@ -905,11 +905,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out uint result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -917,11 +917,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint ISubtractionOperators.operator -(uint left, uint right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint ISubtractionOperators.operator -(uint left, uint right) // => checked(left - right); @@ -929,11 +929,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IUnaryNegationOperators.operator -(uint value) => 0u - value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IUnaryNegationOperators.operator -(uint value) // => checked(0u - value); @@ -941,11 +941,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IUnaryPlusOperators.operator +(uint value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IUnaryPlusOperators.operator +(uint value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt64.cs b/src/libraries/System.Private.CoreLib/src/System/UInt64.cs index 93cf62ae2f140..23d4921e0e6b4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt64.cs @@ -264,11 +264,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IAdditionOperators.operator +(ulong left, ulong right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IAdditionOperators.operator +(ulong left, ulong right) // => checked(left + right); @@ -276,30 +276,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBinaryInteger.LeadingZeroCount(ulong value) => (ulong)BitOperations.LeadingZeroCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBinaryInteger.PopCount(ulong value) => (ulong)BitOperations.PopCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBinaryInteger.RotateLeft(ulong value, int rotateAmount) => BitOperations.RotateLeft(value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBinaryInteger.RotateRight(ulong value, int rotateAmount) => BitOperations.RotateRight(value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBinaryInteger.TrailingZeroCount(ulong value) => (ulong)BitOperations.TrailingZeroCount(value); @@ -307,11 +307,11 @@ static ulong IBinaryInteger.TrailingZeroCount(ulong value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(ulong value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBinaryNumber.Log2(ulong value) => (ulong)BitOperations.Log2(value); @@ -319,19 +319,19 @@ static ulong IBinaryNumber.Log2(ulong value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBitwiseOperators.operator &(ulong left, ulong right) => left & right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBitwiseOperators.operator |(ulong left, ulong right) => left | right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBitwiseOperators.operator ^(ulong left, ulong right) => left ^ right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBitwiseOperators.operator ~(ulong value) => ~value; @@ -339,19 +339,19 @@ static ulong IBinaryNumber.Log2(ulong value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(ulong left, ulong right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(ulong left, ulong right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(ulong left, ulong right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(ulong left, ulong right) => left >= right; @@ -359,11 +359,11 @@ static ulong IBinaryNumber.Log2(ulong value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IDecrementOperators.operator --(ulong value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IDecrementOperators.operator --(ulong value) // => checked(--value); @@ -371,11 +371,11 @@ static ulong IBinaryNumber.Log2(ulong value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IDivisionOperators.operator /(ulong left, ulong right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IDivisionOperators.operator /(ulong left, ulong right) // => checked(left / right); @@ -383,11 +383,11 @@ static ulong IBinaryNumber.Log2(ulong value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(ulong left, ulong right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(ulong left, ulong right) => left != right; @@ -395,11 +395,11 @@ static ulong IBinaryNumber.Log2(ulong value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IIncrementOperators.operator ++(ulong value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IIncrementOperators.operator ++(ulong value) // => checked(++value); @@ -407,21 +407,21 @@ static ulong IBinaryNumber.Log2(ulong value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IModulusOperators.operator %(ulong left, ulong right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IModulusOperators.operator %(ulong left, ulong right) // => checked(left % right); @@ -429,18 +429,18 @@ static ulong IBinaryNumber.Log2(ulong value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IMultiplyOperators.operator *(ulong left, ulong right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IMultiplyOperators.operator *(ulong left, ulong right) // => checked(left * right); @@ -448,21 +448,21 @@ static ulong IBinaryNumber.Log2(ulong value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Abs(ulong value) => value; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Clamp(ulong value, ulong min, ulong max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static ulong INumber.Create(TOther value) { @@ -529,7 +529,7 @@ static ulong INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static ulong INumber.CreateSaturating(TOther value) { @@ -607,7 +607,7 @@ static ulong INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static ulong INumber.CreateTruncating(TOther value) { @@ -674,31 +674,31 @@ static ulong INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (ulong Quotient, ulong Remainder) INumber.DivRem(ulong left, ulong right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Max(ulong x, ulong y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Min(ulong x, ulong y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Sign(ulong value) => (ulong)((value == 0) ? 0 : 1); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out ulong result) { @@ -844,11 +844,11 @@ static bool INumber.TryCreate(TOther value, out ulong result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out ulong result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out ulong result) => TryParse(s, style, provider, out result); @@ -856,11 +856,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IF // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out ulong result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -868,15 +868,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IShiftOperators.operator <<(ulong value, int shiftAmount) => value << (int)shiftAmount; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IShiftOperators.operator >>(ulong value, int shiftAmount) => value >> (int)shiftAmount; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static ulong IShiftOperators.operator >>>(ulong value, int shiftAmount) // => value >> (int)shiftAmount; @@ -884,11 +884,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out ulong result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -896,11 +896,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong ISubtractionOperators.operator -(ulong left, ulong right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong ISubtractionOperators.operator -(ulong left, ulong right) // => checked(left - right); @@ -908,11 +908,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IUnaryNegationOperators.operator -(ulong value) => 0UL - value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IUnaryNegationOperators.operator -(ulong value) // => checked(0UL - value); @@ -920,11 +920,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IUnaryPlusOperators.operator +(ulong value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IUnaryPlusOperators.operator +(ulong value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs index f0ff1620c7dcd..bc7859c0d18d9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs @@ -246,11 +246,11 @@ public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatPro // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IAdditionOperators.operator +(nuint left, nuint right) => (nuint)(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IAdditionOperators.operator +(nuint left, nuint right) // => checked((nuint)(left + right)); @@ -258,14 +258,14 @@ public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatPro // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBinaryInteger.LeadingZeroCount(nuint value) { if (Environment.Is64BitProcess) @@ -278,7 +278,7 @@ static nuint IBinaryInteger.LeadingZeroCount(nuint value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBinaryInteger.PopCount(nuint value) { if (Environment.Is64BitProcess) @@ -291,7 +291,7 @@ static nuint IBinaryInteger.PopCount(nuint value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBinaryInteger.RotateLeft(nuint value, int rotateAmount) { if (Environment.Is64BitProcess) @@ -304,7 +304,7 @@ static nuint IBinaryInteger.RotateLeft(nuint value, int rotateAmount) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBinaryInteger.RotateRight(nuint value, int rotateAmount) { if (Environment.Is64BitProcess) @@ -317,7 +317,7 @@ static nuint IBinaryInteger.RotateRight(nuint value, int rotateAmount) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBinaryInteger.TrailingZeroCount(nuint value) { if (Environment.Is64BitProcess) @@ -334,7 +334,7 @@ static nuint IBinaryInteger.TrailingZeroCount(nuint value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(nuint value) { if (Environment.Is64BitProcess) @@ -347,7 +347,7 @@ static bool IBinaryNumber.IsPow2(nuint value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBinaryNumber.Log2(nuint value) { if (Environment.Is64BitProcess) @@ -364,19 +364,19 @@ static nuint IBinaryNumber.Log2(nuint value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBitwiseOperators.operator &(nuint left, nuint right) => left & right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBitwiseOperators.operator |(nuint left, nuint right) => left | right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBitwiseOperators.operator ^(nuint left, nuint right) => left ^ right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBitwiseOperators.operator ~(nuint value) => ~value; @@ -384,19 +384,19 @@ static nuint IBinaryNumber.Log2(nuint value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(nuint left, nuint right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(nuint left, nuint right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(nuint left, nuint right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(nuint left, nuint right) => left >= right; @@ -404,11 +404,11 @@ static nuint IBinaryNumber.Log2(nuint value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IDecrementOperators.operator --(nuint value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IDecrementOperators.operator --(nuint value) // => checked(--value); @@ -416,11 +416,11 @@ static nuint IBinaryNumber.Log2(nuint value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IDivisionOperators.operator /(nuint left, nuint right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IDivisionOperators.operator /(nuint left, nuint right) // => checked(left / right); @@ -428,11 +428,11 @@ static nuint IBinaryNumber.Log2(nuint value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(nuint left, nuint right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(nuint left, nuint right) => left != right; @@ -440,11 +440,11 @@ static nuint IBinaryNumber.Log2(nuint value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IIncrementOperators.operator ++(nuint value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IIncrementOperators.operator ++(nuint value) // => checked(++value); @@ -452,21 +452,21 @@ static nuint IBinaryNumber.Log2(nuint value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IModulusOperators.operator %(nuint left, nuint right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IModulusOperators.operator %(nuint left, nuint right) // => checked(left % right); @@ -474,18 +474,18 @@ static nuint IBinaryNumber.Log2(nuint value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IMultiplyOperators.operator *(nuint left, nuint right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IMultiplyOperators.operator *(nuint left, nuint right) // => checked(left * right); @@ -493,21 +493,21 @@ static nuint IBinaryNumber.Log2(nuint value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Abs(nuint value) => value; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Clamp(nuint value, nuint min, nuint max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static nuint INumber.Create(TOther value) { @@ -574,7 +574,7 @@ static nuint INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static nuint INumber.CreateSaturating(TOther value) { @@ -655,7 +655,7 @@ static nuint INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static nuint INumber.CreateTruncating(TOther value) { @@ -722,31 +722,31 @@ static nuint INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (nuint Quotient, nuint Remainder) INumber.DivRem(nuint left, nuint right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Max(nuint x, nuint y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Min(nuint x, nuint y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Sign(nuint value) => (nuint)((value == 0) ? 0 : 1); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out nuint result) { @@ -900,11 +900,11 @@ static bool INumber.TryCreate(TOther value, out nuint result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out nuint result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out nuint result) => TryParse(s, style, provider, out result); @@ -912,11 +912,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IF // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out nuint result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -924,15 +924,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IShiftOperators.operator <<(nuint value, int shiftAmount) => value << (int)shiftAmount; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IShiftOperators.operator >>(nuint value, int shiftAmount) => value >> (int)shiftAmount; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static nuint IShiftOperators.operator >>>(nuint value, int shiftAmount) // => value >> (int)shiftAmount; @@ -940,11 +940,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out nuint result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -952,11 +952,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint ISubtractionOperators.operator -(nuint left, nuint right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint ISubtractionOperators.operator -(nuint left, nuint right) // => checked(left - right); @@ -964,11 +964,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IUnaryNegationOperators.operator -(nuint value) => (nuint)0 - value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IUnaryNegationOperators.operator -(nuint value) // => checked((nuint)0 - value); @@ -976,11 +976,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IUnaryPlusOperators.operator +(nuint value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IUnaryPlusOperators.operator +(nuint value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs index b70e07511c485..101ce90eaa272 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs @@ -283,7 +283,7 @@ public static void BindStaticMethod() { HelperMarshal._intValue = 0; Runtime.InvokeJS(@$" - var invoke_int = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); + var invoke_int = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); invoke_int (200); "); @@ -295,7 +295,7 @@ public static void BindIntPtrStaticMethod() { HelperMarshal._intPtrValue = IntPtr.Zero; Runtime.InvokeJS(@$" - var invoke_int_ptr = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeIntPtr""); + var invoke_int_ptr = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeIntPtr""); invoke_int_ptr (42); "); Assert.Equal(42, (int)HelperMarshal._intPtrValue); @@ -306,7 +306,7 @@ public static void MarshalIntPtrToJS() { HelperMarshal._marshaledIntPtrValue = IntPtr.Zero; Runtime.InvokeJS(@$" - var invokeMarshalIntPtr = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeMarshalIntPtr""); + var invokeMarshalIntPtr = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeMarshalIntPtr""); var r = invokeMarshalIntPtr (); if (r != 42) throw `Invalid int_ptr value`; @@ -319,7 +319,7 @@ public static void InvokeStaticMethod() { HelperMarshal._intValue = 0; Runtime.InvokeJS(@$" - Module.mono_call_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"", [ 300 ]); + INTERNAL.call_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt"", [ 300 ]); "); Assert.Equal(300, HelperMarshal._intValue); @@ -330,7 +330,7 @@ public static void ResolveMethod() { HelperMarshal._intValue = 0; Runtime.InvokeJS(@$" - var invoke_int = Module.mono_method_resolve (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); + var invoke_int = INTERNAL.mono_method_resolve (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); App.call_test_method (""InvokeInt"", [ invoke_int ]); "); @@ -629,7 +629,7 @@ public static void BoundStaticMethodMissingArgs() HelperMarshal._intValue = 1; Runtime.InvokeJS(@$" - var invoke_int = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); + var invoke_int = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); invoke_int (); "); Assert.Equal(0, HelperMarshal._intValue); @@ -640,7 +640,7 @@ public static void BoundStaticMethodExtraArgs() { HelperMarshal._intValue = 0; Runtime.InvokeJS(@$" - var invoke_int = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); + var invoke_int = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); invoke_int (200, 400); "); Assert.Equal(200, HelperMarshal._intValue); @@ -654,13 +654,13 @@ public static void BoundStaticMethodArgumentTypeCoercion() HelperMarshal._intValue = 0; Runtime.InvokeJS(@$" - var invoke_int = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); + var invoke_int = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); invoke_int (""200""); "); Assert.Equal(200, HelperMarshal._intValue); Runtime.InvokeJS(@$" - var invoke_int = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); + var invoke_int = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); invoke_int (400.5); "); Assert.Equal(400, HelperMarshal._intValue); @@ -671,14 +671,14 @@ public static void BoundStaticMethodUnpleasantArgumentTypeCoercion() { HelperMarshal._intValue = 100; Runtime.InvokeJS(@$" - var invoke_int = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); + var invoke_int = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); invoke_int (""hello""); "); Assert.Equal(0, HelperMarshal._intValue); // In this case at the very least, the leading "7" is not turned into the number 7 Runtime.InvokeJS(@$" - var invoke_int = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); + var invoke_int = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeInt""); invoke_int (""7apples""); "); Assert.Equal(0, HelperMarshal._intValue); @@ -689,7 +689,7 @@ public static void PassUintArgument() { HelperMarshal._uintValue = 0; Runtime.InvokeJS(@$" - var invoke_uint = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeUInt""); + var invoke_uint = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeUInt""); invoke_uint (0xFFFFFFFE); "); @@ -702,9 +702,9 @@ public static void ReturnUintEnum () HelperMarshal._uintValue = 0; HelperMarshal._enumValue = TestEnum.BigValue; Runtime.InvokeJS(@$" - var get_value = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}GetEnumValue""); + var get_value = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}GetEnumValue""); var e = get_value (); - var invoke_uint = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeUInt""); + var invoke_uint = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}InvokeUInt""); invoke_uint (e); "); Assert.Equal((uint)TestEnum.BigValue, HelperMarshal._uintValue); @@ -715,7 +715,7 @@ public static void PassUintEnumByValue () { HelperMarshal._enumValue = TestEnum.Zero; Runtime.InvokeJS(@$" - var set_enum = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}SetEnumValue"", ""j""); + var set_enum = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}SetEnumValue"", ""j""); set_enum (0xFFFFFFFE); "); Assert.Equal(TestEnum.BigValue, HelperMarshal._enumValue); @@ -728,7 +728,7 @@ public static void PassUintEnumByValueMasqueradingAsInt () // HACK: We're explicitly telling the bindings layer to pass an int here, not an enum // Because we know the enum is : uint, this is compatible, so it works. Runtime.InvokeJS(@$" - var set_enum = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}SetEnumValue"", ""i""); + var set_enum = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}SetEnumValue"", ""i""); set_enum (0xFFFFFFFE); "); Assert.Equal(TestEnum.BigValue, HelperMarshal._enumValue); @@ -740,7 +740,7 @@ public static void PassUintEnumByNameIsNotImplemented () HelperMarshal._enumValue = TestEnum.Zero; var exc = Assert.Throws( () => Runtime.InvokeJS(@$" - var set_enum = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}SetEnumValue"", ""j""); + var set_enum = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}SetEnumValue"", ""j""); set_enum (""BigValue""); ") ); @@ -752,7 +752,7 @@ public static void CannotUnboxUint64 () { var exc = Assert.Throws( () => Runtime.InvokeJS(@$" - var get_u64 = Module.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}GetUInt64"", """"); + var get_u64 = INTERNAL.mono_bind_static_method (""{HelperMarshal.INTEROP_CLASS}GetUInt64"", """"); var u64 = get_u64(); ") ); @@ -806,7 +806,7 @@ public static void ManuallyInternString() { HelperMarshal._stringResource = HelperMarshal._stringResource2 = null; Runtime.InvokeJS(@" - var sym = BINDING.mono_intern_string(""interned string 3""); + var sym = INTERNAL.mono_intern_string(""interned string 3""); App.call_test_method (""InvokeString"", [ sym ], ""s""); App.call_test_method (""InvokeString2"", [ sym ], ""s""); "); @@ -823,7 +823,7 @@ public static void LargeStringsAreNotAutomaticallyLocatedInInternTable() var s = ""long interned string""; for (var i = 0; i < 1024; i++) s += String(i % 10); - var sym = BINDING.mono_intern_string(s); + var sym = INTERNAL.mono_intern_string(s); App.call_test_method (""InvokeString"", [ sym ], ""S""); App.call_test_method (""InvokeString2"", [ sym ], ""s""); "); @@ -837,7 +837,7 @@ public static void CanInternVeryManyStrings() HelperMarshal._stringResource = null; Runtime.InvokeJS(@" for (var i = 0; i < 10240; i++) - BINDING.mono_intern_string('s' + i); + INTERNAL.mono_intern_string('s' + i); App.call_test_method (""InvokeString"", [ 's5000' ], ""S""); "); Assert.Equal("s5000", HelperMarshal._stringResource); @@ -864,8 +864,8 @@ public static void InternedStringReturnValuesWork() HelperMarshal._stringResource = HelperMarshal._stringResource2 = null; var fqn = "[System.Private.Runtime.InteropServices.JavaScript.Tests]System.Runtime.InteropServices.JavaScript.Tests.HelperMarshal:StoreArgumentAndReturnLiteral"; Runtime.InvokeJS( - $"var a = BINDING.bind_static_method('{fqn}')('test');\r\n" + - $"var b = BINDING.bind_static_method('{fqn}')(a);\r\n" + + $"var a = INTERNAL.mono_bind_static_method('{fqn}')('test');\r\n" + + $"var b = INTERNAL.mono_bind_static_method('{fqn}')(a);\r\n" + "App.call_test_method ('InvokeString2', [ b ]);" ); Assert.Equal("s: 1 length: 1", HelperMarshal._stringResource); diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 54f6ca00bc33a..c645b921b9792 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -3,7 +3,6 @@ // ------------------------------------------------------------------------------ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ -using System.Runtime.Versioning; namespace System.Runtime.Intrinsics { @@ -3653,7 +3652,7 @@ internal X64() { } } [System.CLSCompliantAttribute(false)] - [RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("AvxVnni is in preview.")] public abstract class AvxVnni : System.Runtime.Intrinsics.X86.Avx2 { internal AvxVnni() { } diff --git a/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj b/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj index 7e938de2925ef..d61ea2546b168 100644 --- a/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj +++ b/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj @@ -7,12 +7,12 @@ - + @@ -30,5 +30,6 @@ + diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs index d27244837a089..671f4af2699be 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; @@ -15,9 +16,6 @@ namespace System.Numerics private const int kcbitUint = 32; private const int kcbitUlong = 64; private const int DecimalScaleFactorMask = 0x00FF0000; - private const int DecimalSignMask = unchecked((int)0x80000000); - - internal const int StackallocUInt32Limit = 64; // For values int.MinValue < n <= int.MaxValue, the value is stored in sign // and _bits is null. For all other values, sign is +1 or -1 and the bits are in _bits @@ -213,6 +211,7 @@ public BigInteger(decimal value) Debug.Assert(bits.Length == 4 && (bits[3] & DecimalScaleFactorMask) == 0); + const int signMask = unchecked((int)kuMaskHighBit); int size = 3; while (size > 0 && bits[size - 1] == 0) size--; @@ -225,7 +224,7 @@ public BigInteger(decimal value) // bits[0] is the absolute value of this decimal // if bits[0] < 0 then it is too large to be packed into _sign _sign = bits[0]; - _sign *= ((bits[3] & DecimalSignMask) != 0) ? -1 : +1; + _sign *= ((bits[3] & signMask) != 0) ? -1 : +1; _bits = null; } else @@ -241,7 +240,7 @@ public BigInteger(decimal value) _bits[2] = (uint)bits[2]; } - _sign = ((bits[3] & DecimalSignMask) != 0) ? -1 : +1; + _sign = ((bits[3] & signMask) != 0) ? -1 : +1; } AssertValid(); } @@ -473,67 +472,51 @@ internal BigInteger(int n, uint[]? rgu) /// /// Constructor used during bit manipulation and arithmetic. - /// When possible the span will be packed into _sign to conserve space. + /// When possible the value will be packed into _sign to conserve space. /// /// The absolute value of the number - /// An array, identical in contents to , for which ownership can be transferred; null if no such array was available. /// The bool indicating the sign of the value. - private BigInteger(ReadOnlySpan value, uint[]? valueArray, bool negative) + private BigInteger(ReadOnlySpan value, bool negative) { - Debug.Assert(valueArray is null || value.SequenceEqual(valueArray)); + int len; - // Try to conserve space as much as possible by checking for wasted leading uint entries - // (sometimes the span has leading zeros from bit manipulation operations & and ^). - if (!value.IsEmpty && value[^1] == 0) - { - int len = value.Length - 1; - while (len > 0 && value[len - 1] == 0) - { - len--; - } - value = value.Slice(0, len); - valueArray = null; - } + // Try to conserve space as much as possible by checking for wasted leading span entries + // sometimes the span has leading zeros from bit manipulation operations & and ^ + for (len = value.Length; len > 0 && value[len - 1] == 0; len--); - if (value.IsEmpty) + if (len == 0) { this = s_bnZeroInt; } - else if (value.Length == 1 && value[0] < kuMaskHighBit) + else if (len == 1 && value[0] < kuMaskHighBit) { - // Values like (Int32.MaxValue+1) are stored as "0x80000000" and as such cannot be packed into _sign. + // Values like (Int32.MaxValue+1) are stored as "0x80000000" and as such cannot be packed into _sign _sign = negative ? -(int)value[0] : (int)value[0]; _bits = null; if (_sign == int.MinValue) { - // Although Int32.MinValue fits in _sign, we represent this case differently for negate. + // Although Int32.MinValue fits in _sign, we represent this case differently for negate this = s_bnMinInt; } } else { _sign = negative ? -1 : +1; - _bits = valueArray ?? value.ToArray(); + _bits = value.Slice(0, len).ToArray(); } - AssertValid(); } /// - /// Create a BigInteger from a little-endian twos-complement UInt32 array. - /// When possible, value is assigned directly to this._bits without an array copy - /// so use this ctor with care. + /// Create a BigInteger from a little-endian twos-complement UInt32 span. /// /// - private BigInteger(uint[] value) + private BigInteger(Span value) { - if (value == null) - throw new ArgumentNullException(nameof(value)); - int dwordCount = value.Length; - bool isNegative = dwordCount > 0 && ((value[dwordCount - 1] & 0x80000000) == 0x80000000); + bool isNegative = dwordCount > 0 && ((value[dwordCount - 1] & kuMaskHighBit) == kuMaskHighBit); - // Try to conserve space as much as possible by checking for wasted leading uint[] entries + // Try to conserve space as much as possible by checking for wasted leading span entries while (dwordCount > 0 && value[dwordCount - 1] == 0) dwordCount--; if (dwordCount == 0) @@ -568,18 +551,9 @@ private BigInteger(uint[] value) if (!isNegative) { // Handle the simple positive value cases where the input is already in sign magnitude - if (dwordCount != value.Length) - { - _sign = +1; - _bits = new uint[dwordCount]; - Array.Copy(value, _bits, dwordCount); - } - // No trimming is possible. Assign value directly to _bits. - else - { - _sign = +1; - _bits = value; - } + _sign = +1; + value = value.Slice(0, dwordCount); + _bits = value.ToArray(); AssertValid(); return; } @@ -608,29 +582,20 @@ private BigInteger(uint[] value) _bits = null; } } - // The number is represented by multiple dwords. - // Trim off any wasted uint values when possible. - else if (len != value.Length) - { - _sign = -1; - _bits = new uint[len]; - Array.Copy(value, _bits, len); - } - // No trimming is possible. Assign value directly to _bits. else { _sign = -1; - _bits = value; + _bits = value.Slice(0, len).ToArray(); } AssertValid(); return; } - public static BigInteger Zero => s_bnZeroInt; + public static BigInteger Zero { get { return s_bnZeroInt; } } - public static BigInteger One => s_bnOneInt; + public static BigInteger One { get { return s_bnOneInt; } } - public static BigInteger MinusOne => s_bnMinusOneInt; + public static BigInteger MinusOne { get { return s_bnMinusOneInt; } } public bool IsPowerOfTwo { @@ -639,12 +604,12 @@ public bool IsPowerOfTwo AssertValid(); if (_bits == null) - return (_sign & (_sign - 1)) == 0 && _sign != 0; + return BitOperations.IsPow2(_sign); if (_sign != 1) return false; int iu = _bits.Length - 1; - if ((_bits[iu] & (_bits[iu] - 1)) != 0) + if (!BitOperations.IsPow2(_bits[iu])) return false; while (--iu >= 0) { @@ -774,10 +739,26 @@ public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out Big if (trivialDivisor) { uint rest; - uint[] bits = BigIntegerCalculator.Divide(dividend._bits, NumericsHelpers.Abs(divisor._sign), out rest); - remainder = dividend._sign < 0 ? -1 * rest : rest; - return new BigInteger(bits, bits, (dividend._sign < 0) ^ (divisor._sign < 0)); + uint[]? bitsFromPool = null; + int size = dividend._bits.Length; + Span quotient = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + + try + { + // may throw DivideByZeroException + BigIntegerCalculator.Divide(dividend._bits, NumericsHelpers.Abs(divisor._sign), quotient, out rest); + + remainder = dividend._sign < 0 ? -1 * rest : rest; + return new BigInteger(quotient, (dividend._sign < 0) ^ (divisor._sign < 0)); + } + finally + { + if (bitsFromPool != null) + ArrayPool.Shared.Return(bitsFromPool); + } } Debug.Assert(divisor._bits != null); @@ -789,11 +770,30 @@ public static BigInteger DivRem(BigInteger dividend, BigInteger divisor, out Big } else { - uint[] rest; - uint[] bits = BigIntegerCalculator.Divide(dividend._bits, divisor._bits, out rest); + uint[]? remainderFromPool = null; + int size = dividend._bits.Length; + Span rest = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : remainderFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); - remainder = new BigInteger(rest, rest, dividend._sign < 0); - return new BigInteger(bits, bits, (dividend._sign < 0) ^ (divisor._sign < 0)); + uint[]? quotientFromPool = null; + size = dividend._bits.Length - divisor._bits.Length + 1; + Span quotient = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : quotientFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + + BigIntegerCalculator.Divide(dividend._bits, divisor._bits, quotient, rest); + + remainder = new BigInteger(rest, dividend._sign < 0); + var result = new BigInteger(quotient, (dividend._sign < 0) ^ (divisor._sign < 0)); + + if (remainderFromPool != null) + ArrayPool.Shared.Return(remainderFromPool); + + if (quotientFromPool != null) + ArrayPool.Shared.Return(quotientFromPool); + + return result; } } @@ -823,7 +823,7 @@ public static double Log(BigInteger value, double baseValue) ulong l = value._bits.Length > 2 ? value._bits[value._bits.Length - 3] : 0; // Measure the exact bit count - int c = NumericsHelpers.CbitHighZero((uint)h); + int c = BitOperations.LeadingZeroCount((uint)h); long b = (long)value._bits.Length * 32 - c; // Extract most significant bits @@ -857,7 +857,7 @@ public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right Debug.Assert(right._bits != null); return left._sign != 0 ? BigIntegerCalculator.Gcd(right._bits, NumericsHelpers.Abs(left._sign)) - : new BigInteger(right._bits, null, negative: false); + : new BigInteger(right._bits, negative: false); } if (trivialRight) @@ -865,7 +865,7 @@ public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right Debug.Assert(left._bits != null); return right._sign != 0 ? BigIntegerCalculator.Gcd(left._bits, NumericsHelpers.Abs(right._sign)) - : new BigInteger(left._bits, null, negative: false); + : new BigInteger(left._bits, negative: false); } Debug.Assert(left._bits != null && right._bits != null); @@ -880,29 +880,46 @@ public static BigInteger GreatestCommonDivisor(BigInteger left, BigInteger right } } - private static BigInteger GreatestCommonDivisor(uint[] leftBits, uint[] rightBits) + private static BigInteger GreatestCommonDivisor(ReadOnlySpan leftBits, ReadOnlySpan rightBits) { Debug.Assert(BigIntegerCalculator.Compare(leftBits, rightBits) >= 0); + uint[]? bitsFromPool = null; + BigInteger result; + // Short circuits to spare some allocations... if (rightBits.Length == 1) { uint temp = BigIntegerCalculator.Remainder(leftBits, rightBits[0]); - return BigIntegerCalculator.Gcd(rightBits[0], temp); + result = BigIntegerCalculator.Gcd(rightBits[0], temp); } - - if (rightBits.Length == 2) + else if (rightBits.Length == 2) { - uint[] tempBits = BigIntegerCalculator.Remainder(leftBits, rightBits); + Span bits = (leftBits.Length <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(leftBits.Length)).Slice(0, leftBits.Length); + + BigIntegerCalculator.Remainder(leftBits, rightBits, bits); ulong left = ((ulong)rightBits[1] << 32) | rightBits[0]; - ulong right = ((ulong)tempBits[1] << 32) | tempBits[0]; + ulong right = ((ulong)bits[1] << 32) | bits[0]; + + result = BigIntegerCalculator.Gcd(left, right); + } + else + { + Span bits = (leftBits.Length <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(leftBits.Length)).Slice(0, leftBits.Length); - return BigIntegerCalculator.Gcd(left, right); + BigIntegerCalculator.Gcd(leftBits, rightBits, bits); + result = new BigInteger(bits, negative: false); } - uint[] bits = BigIntegerCalculator.Gcd(leftBits, rightBits); - return new BigInteger(bits, bits, negative: false); + if (bitsFromPool != null) + ArrayPool.Shared.Return(bitsFromPool); + + return result; } public static BigInteger Max(BigInteger left, BigInteger right) @@ -932,6 +949,8 @@ public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigIntege bool trivialExponent = exponent._bits == null; bool trivialModulus = modulus._bits == null; + BigInteger result; + if (trivialModulus) { uint bits = trivialValue && trivialExponent ? BigIntegerCalculator.Pow(NumericsHelpers.Abs(value._sign), NumericsHelpers.Abs(exponent._sign), NumericsHelpers.Abs(modulus._sign)) : @@ -939,17 +958,43 @@ public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigIntege trivialExponent ? BigIntegerCalculator.Pow(value._bits!, NumericsHelpers.Abs(exponent._sign), NumericsHelpers.Abs(modulus._sign)) : BigIntegerCalculator.Pow(value._bits!, exponent._bits!, NumericsHelpers.Abs(modulus._sign)); - return value._sign < 0 && !exponent.IsEven ? -1 * bits : bits; + result = value._sign < 0 && !exponent.IsEven ? -1 * bits : bits; } else { - uint[] bits = trivialValue && trivialExponent ? BigIntegerCalculator.Pow(NumericsHelpers.Abs(value._sign), NumericsHelpers.Abs(exponent._sign), modulus._bits!) : - trivialValue ? BigIntegerCalculator.Pow(NumericsHelpers.Abs(value._sign), exponent._bits!, modulus._bits!) : - trivialExponent ? BigIntegerCalculator.Pow(value._bits!, NumericsHelpers.Abs(exponent._sign), modulus._bits!) : - BigIntegerCalculator.Pow(value._bits!, exponent._bits!, modulus._bits!); + int size = (modulus._bits?.Length ?? 1) << 1; + uint[]? bitsFromPool = null; + Span bits = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + bits.Clear(); + if (trivialValue) + { + if (trivialExponent) + { + BigIntegerCalculator.Pow(NumericsHelpers.Abs(value._sign), NumericsHelpers.Abs(exponent._sign), modulus._bits!, bits); + } + else + { + BigIntegerCalculator.Pow(NumericsHelpers.Abs(value._sign), exponent._bits!, modulus._bits!, bits); + } + } + else if (trivialExponent) + { + BigIntegerCalculator.Pow(value._bits!, NumericsHelpers.Abs(exponent._sign), modulus._bits!, bits); + } + else + { + BigIntegerCalculator.Pow(value._bits!, exponent._bits!, modulus._bits!, bits); + } + + result = new BigInteger(bits, value._sign < 0 && !exponent.IsEven); - return new BigInteger(bits, bits, value._sign < 0 && !exponent.IsEven); + if (bitsFromPool != null) + ArrayPool.Shared.Return(bitsFromPool); } + + return result; } public static BigInteger Pow(BigInteger value, int exponent) @@ -966,6 +1011,10 @@ public static BigInteger Pow(BigInteger value, int exponent) bool trivialValue = value._bits == null; + uint power = NumericsHelpers.Abs(exponent); + uint[]? bitsFromPool = null; + BigInteger result; + if (trivialValue) { if (value._sign == 1) @@ -974,34 +1023,54 @@ public static BigInteger Pow(BigInteger value, int exponent) return (exponent & 1) != 0 ? value : s_bnOneInt; if (value._sign == 0) return value; + + int size = BigIntegerCalculator.PowBound(power, 1); + Span bits = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + bits.Clear(); + + BigIntegerCalculator.Pow(NumericsHelpers.Abs(value._sign), power, bits); + result = new BigInteger(bits, value._sign < 0 && (exponent & 1) != 0); + } + else + { + int size = BigIntegerCalculator.PowBound(power, value._bits!.Length); + Span bits = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + bits.Clear(); + + BigIntegerCalculator.Pow(value._bits, power, bits); + result = new BigInteger(bits, value._sign < 0 && (exponent & 1) != 0); } - uint[] bits = trivialValue - ? BigIntegerCalculator.Pow(NumericsHelpers.Abs(value._sign), NumericsHelpers.Abs(exponent)) - : BigIntegerCalculator.Pow(value._bits!, NumericsHelpers.Abs(exponent)); + if (bitsFromPool != null) + ArrayPool.Shared.Return(bitsFromPool); - return new BigInteger(bits, bits, value._sign < 0 && (exponent & 1) != 0); + return result; } public override int GetHashCode() { AssertValid(); - if (_bits == null) + if (_bits is null) return _sign; + int hash = _sign; for (int iv = _bits.Length; --iv >= 0;) - hash = NumericsHelpers.CombineHash(hash, unchecked((int)_bits[iv])); + hash = unchecked((int)CombineHash((uint)hash, _bits[iv])); return hash; + + static uint CombineHash(uint u1, uint u2) => ((u1 << 7) | (u1 >> 25)) ^ u2; } public override bool Equals([NotNullWhen(true)] object? obj) { AssertValid(); - if (!(obj is BigInteger)) - return false; - return Equals((BigInteger)obj); + return obj is BigInteger other && Equals(other); } public bool Equals(long other) @@ -1124,9 +1193,9 @@ public int CompareTo(object? obj) { if (obj == null) return 1; - if (!(obj is BigInteger)) + if (obj is not BigInteger bigInt) throw new ArgumentException(SR.Argument_MustBeBigInt, nameof(obj)); - return CompareTo((BigInteger)obj); + return CompareTo(bigInt); } /// @@ -1424,79 +1493,59 @@ private enum GetBytesMode { AllocateArray, Count, Span } } /// - /// Return the value of this BigInteger as a little-endian twos-complement - /// uint span, using the fewest number of uints possible. If the value is zero, - /// return a span of one uint whose element is 0. + /// Converts the value of this BigInteger to a little-endian twos-complement + /// uint span allocated by the caller using the fewest number of uints possible. /// - private ReadOnlySpan ToUInt32Span(Span scratch) + /// Pre-allocated buffer by the caller. + /// The actual number of copied elements. + private int WriteTo(Span buffer) { - Debug.Assert(!scratch.IsEmpty); - - if (_bits == null && _sign == 0) - { - scratch[0] = 0; - return scratch.Slice(0, 1); - } + Debug.Assert(_bits is null || _sign == 0 ? buffer.Length == 2 : buffer.Length >= _bits.Length + 1); - Span dwords = scratch; - bool dwordsIsScratch = true; uint highDWord; - if (_bits == null) + if (_bits is null) { - dwords[0] = unchecked((uint)_sign); - dwords = dwords.Slice(0, 1); + buffer[0] = unchecked((uint)_sign); highDWord = (_sign < 0) ? uint.MaxValue : 0; } - else if (_sign == -1) + else { - if (dwords.Length >= _bits.Length) + _bits.CopyTo(buffer); + buffer = buffer.Slice(0, _bits.Length + 1); + if (_sign == -1) { - _bits.AsSpan().CopyTo(dwords); - dwords = dwords.Slice(0, _bits.Length); + NumericsHelpers.DangerousMakeTwosComplement(buffer.Slice(0, buffer.Length - 1)); // Mutates dwords + highDWord = uint.MaxValue; } else - { - dwords = (uint[])_bits.Clone(); - } - NumericsHelpers.DangerousMakeTwosComplement(dwords); // Mutates dwords - highDWord = uint.MaxValue; - } - else - { - dwords = _bits; - highDWord = 0; - dwordsIsScratch = false; + highDWord = 0; } // Find highest significant byte and ensure high bit is 0 if positive, 1 if negative - int msb; - for (msb = dwords.Length - 1; msb > 0 && dwords[msb] == highDWord; msb--); - bool needExtraByte = (dwords[msb] & 0x80000000) != (highDWord & 0x80000000); - - int length = msb + 1 + (needExtraByte ? 1 : 0); - bool copyDwordsToScratch = true; - if (length <= scratch.Length) - { - scratch = scratch.Slice(0, length); - copyDwordsToScratch = !dwordsIsScratch; - } - else + int msb = buffer.Length - 2; + while (msb > 0 && buffer[msb] == highDWord) { - scratch = new uint[length]; + msb--; } - if (copyDwordsToScratch) - { - dwords.Slice(0, msb + 1).CopyTo(scratch); - } + // Ensure high bit is 0 if positive, 1 if negative + bool needExtraByte = (buffer[msb] & 0x80000000) != (highDWord & 0x80000000); + int count; if (needExtraByte) { - scratch[^1] = highDWord; + count = msb + 2; + buffer = buffer.Slice(0, count); + buffer[buffer.Length - 1] = highDWord; + } + else + { + count = msb + 1; + buffer = buffer.Slice(0, count); } - return scratch; + return count; } public override string ToString() @@ -1524,42 +1573,72 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan return BigNumber.TryFormatBigInteger(this, format, NumberFormatInfo.GetInstance(provider), destination, out charsWritten); } - private static BigInteger Add(uint[]? leftBits, int leftSign, uint[]? rightBits, int rightSign) + private static BigInteger Add(ReadOnlySpan leftBits, int leftSign, ReadOnlySpan rightBits, int rightSign) { - bool trivialLeft = leftBits == null; - bool trivialRight = rightBits == null; + bool trivialLeft = leftBits.IsEmpty; + bool trivialRight = rightBits.IsEmpty; if (trivialLeft && trivialRight) { return (long)leftSign + rightSign; } + BigInteger result; + uint[]? bitsFromPool = null; + if (trivialLeft) { - Debug.Assert(rightBits != null); - uint[] bits = BigIntegerCalculator.Add(rightBits, NumericsHelpers.Abs(leftSign)); - return new BigInteger(bits, bits, leftSign < 0); - } + Debug.Assert(!rightBits.IsEmpty); - if (trivialRight) - { - Debug.Assert(leftBits != null); - uint[] bits = BigIntegerCalculator.Add(leftBits, NumericsHelpers.Abs(rightSign)); - return new BigInteger(bits, bits, leftSign < 0); + int size = rightBits.Length + 1; + Span bits = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + + BigIntegerCalculator.Add(rightBits, NumericsHelpers.Abs(leftSign), bits); + result = new BigInteger(bits, leftSign < 0); } + else if (trivialRight) + { + Debug.Assert(!leftBits.IsEmpty); - Debug.Assert(leftBits != null && rightBits != null); + int size = leftBits.Length + 1; + Span bits = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); - if (leftBits.Length < rightBits.Length) + BigIntegerCalculator.Add(leftBits, NumericsHelpers.Abs(rightSign), bits); + result = new BigInteger(bits, leftSign < 0); + } + else if (leftBits.Length < rightBits.Length) { - uint[] bits = BigIntegerCalculator.Add(rightBits, leftBits); - return new BigInteger(bits, bits, leftSign < 0); + Debug.Assert(!leftBits.IsEmpty && !rightBits.IsEmpty); + + int size = rightBits.Length + 1; + Span bits = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + + BigIntegerCalculator.Add(rightBits, leftBits, bits); + result = new BigInteger(bits, leftSign < 0); } else { - uint[] bits = BigIntegerCalculator.Add(leftBits, rightBits); - return new BigInteger(bits, bits, leftSign < 0); + Debug.Assert(!leftBits.IsEmpty && !rightBits.IsEmpty); + + int size = leftBits.Length + 1; + Span bits = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + + BigIntegerCalculator.Add(leftBits, rightBits, bits); + result = new BigInteger(bits, leftSign < 0); } + + if (bitsFromPool != null) + ArrayPool.Shared.Return(bitsFromPool); + + return result; } public static BigInteger operator -(BigInteger left, BigInteger right) @@ -1572,42 +1651,70 @@ private static BigInteger Add(uint[]? leftBits, int leftSign, uint[]? rightBits, return Subtract(left._bits, left._sign, right._bits, right._sign); } - private static BigInteger Subtract(uint[]? leftBits, int leftSign, uint[]? rightBits, int rightSign) + private static BigInteger Subtract(ReadOnlySpan leftBits, int leftSign, ReadOnlySpan rightBits, int rightSign) { - bool trivialLeft = leftBits == null; - bool trivialRight = rightBits == null; + bool trivialLeft = leftBits.IsEmpty; + bool trivialRight = rightBits.IsEmpty; if (trivialLeft && trivialRight) { return (long)leftSign - rightSign; } + BigInteger result; + uint[]? bitsFromPool = null; + if (trivialLeft) { - Debug.Assert(rightBits != null); - uint[] bits = BigIntegerCalculator.Subtract(rightBits, NumericsHelpers.Abs(leftSign)); - return new BigInteger(bits, bits, leftSign >= 0); - } + Debug.Assert(!rightBits.IsEmpty); - if (trivialRight) - { - Debug.Assert(leftBits != null); - uint[] bits = BigIntegerCalculator.Subtract(leftBits, NumericsHelpers.Abs(rightSign)); - return new BigInteger(bits, bits, leftSign < 0); + int size = rightBits.Length; + Span bits = (size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + + BigIntegerCalculator.Subtract(rightBits, NumericsHelpers.Abs(leftSign), bits); + result = new BigInteger(bits, leftSign >= 0); } + else if (trivialRight) + { + Debug.Assert(!leftBits.IsEmpty); - Debug.Assert(leftBits != null && rightBits != null); + int size = leftBits.Length; + Span bits = (size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); - if (BigIntegerCalculator.Compare(leftBits, rightBits) < 0) + BigIntegerCalculator.Subtract(leftBits, NumericsHelpers.Abs(rightSign), bits); + result = new BigInteger(bits, leftSign < 0); + } + else if (BigIntegerCalculator.Compare(leftBits, rightBits) < 0) { - uint[] bits = BigIntegerCalculator.Subtract(rightBits, leftBits); - return new BigInteger(bits, bits, leftSign >= 0); + int size = rightBits.Length; + Span bits = (size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + + BigIntegerCalculator.Subtract(rightBits, leftBits, bits); + result = new BigInteger(bits, leftSign >= 0); } else { - uint[] bits = BigIntegerCalculator.Subtract(leftBits, rightBits); - return new BigInteger(bits, bits, leftSign < 0); + Debug.Assert(!leftBits.IsEmpty && !rightBits.IsEmpty); + + int size = leftBits.Length; + Span bits = (size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + + BigIntegerCalculator.Subtract(leftBits, rightBits, bits); + result = new BigInteger(bits, leftSign < 0); } + + if (bitsFromPool != null) + ArrayPool.Shared.Return(bitsFromPool); + + return result; } public static implicit operator BigInteger(byte value) @@ -1822,7 +1929,7 @@ public static explicit operator double(BigInteger value) ulong m = length > 1 ? bits[length - 2] : 0; ulong l = length > 2 ? bits[length - 3] : 0; - int z = NumericsHelpers.CbitHighZero((uint)h); + int z = BitOperations.LeadingZeroCount((uint)h); int exp = (length - 2) * 32 - z; ulong man = (h << 32 + z) | (m << z) | (l >> 32 - z); @@ -1858,24 +1965,53 @@ public static explicit operator decimal(BigInteger value) return Zero; } - if (left._bits == null && right._bits == null) + if (left._bits is null && right._bits is null) { return left._sign & right._sign; } - ReadOnlySpan x = left.ToUInt32Span(stackalloc uint[StackallocUInt32Limit / 2]); - ReadOnlySpan y = right.ToUInt32Span(stackalloc uint[StackallocUInt32Limit / 2]); - uint[] z = new uint[Math.Max(x.Length, y.Length)]; uint xExtend = (left._sign < 0) ? uint.MaxValue : 0; uint yExtend = (right._sign < 0) ? uint.MaxValue : 0; + uint[]? leftBufferFromPool = null; + int size = (left._bits?.Length ?? 1) + 1; + Span x = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : leftBufferFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + x = x.Slice(0, left.WriteTo(x)); + + uint[]? rightBufferFromPool = null; + size = (right._bits?.Length ?? 1) + 1; + Span y = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : rightBufferFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + y = y.Slice(0, right.WriteTo(y)); + + uint[]? resultBufferFromPool = null; + size = Math.Max(x.Length, y.Length); + Span z = (size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : resultBufferFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + for (int i = 0; i < z.Length; i++) { - uint xu = (i < x.Length) ? x[i] : xExtend; - uint yu = (i < y.Length) ? y[i] : yExtend; + uint xu = ((uint)i < (uint)x.Length) ? x[i] : xExtend; + uint yu = ((uint)i < (uint)y.Length) ? y[i] : yExtend; z[i] = xu & yu; } - return new BigInteger(z); + + if (leftBufferFromPool != null) + ArrayPool.Shared.Return(leftBufferFromPool); + + if (rightBufferFromPool != null) + ArrayPool.Shared.Return(rightBufferFromPool); + + var result = new BigInteger(z); + + if (resultBufferFromPool != null) + ArrayPool.Shared.Return(resultBufferFromPool); + + return result; } public static BigInteger operator |(BigInteger left, BigInteger right) @@ -1885,47 +2021,104 @@ public static explicit operator decimal(BigInteger value) if (right.IsZero) return left; - if (left._bits == null && right._bits == null) + if (left._bits is null && right._bits is null) { return left._sign | right._sign; } - ReadOnlySpan x = left.ToUInt32Span(stackalloc uint[StackallocUInt32Limit / 2]); - ReadOnlySpan y = right.ToUInt32Span(stackalloc uint[StackallocUInt32Limit / 2]); - uint[] z = new uint[Math.Max(x.Length, y.Length)]; uint xExtend = (left._sign < 0) ? uint.MaxValue : 0; uint yExtend = (right._sign < 0) ? uint.MaxValue : 0; + uint[]? leftBufferFromPool = null; + int size = (left._bits?.Length ?? 1) + 1; + Span x = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : leftBufferFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + x = x.Slice(0, left.WriteTo(x)); + + uint[]? rightBufferFromPool = null; + size = (right._bits?.Length ?? 1) + 1; + Span y = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : rightBufferFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + y = y.Slice(0, right.WriteTo(y)); + + uint[]? resultBufferFromPool = null; + size = Math.Max(x.Length, y.Length); + Span z = (size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : resultBufferFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + for (int i = 0; i < z.Length; i++) { - uint xu = (i < x.Length) ? x[i] : xExtend; - uint yu = (i < y.Length) ? y[i] : yExtend; + uint xu = ((uint)i < (uint)x.Length) ? x[i] : xExtend; + uint yu = ((uint)i < (uint)y.Length) ? y[i] : yExtend; z[i] = xu | yu; } - return new BigInteger(z); + + if (leftBufferFromPool != null) + ArrayPool.Shared.Return(leftBufferFromPool); + + if (rightBufferFromPool != null) + ArrayPool.Shared.Return(rightBufferFromPool); + + var result = new BigInteger(z); + + if (resultBufferFromPool != null) + ArrayPool.Shared.Return(resultBufferFromPool); + + return result; } public static BigInteger operator ^(BigInteger left, BigInteger right) { - if (left._bits == null && right._bits == null) + if (left._bits is null && right._bits is null) { return left._sign ^ right._sign; } - ReadOnlySpan x = left.ToUInt32Span(stackalloc uint[StackallocUInt32Limit / 2]); - ReadOnlySpan y = right.ToUInt32Span(stackalloc uint[StackallocUInt32Limit / 2]); - uint[] z = new uint[Math.Max(x.Length, y.Length)]; uint xExtend = (left._sign < 0) ? uint.MaxValue : 0; uint yExtend = (right._sign < 0) ? uint.MaxValue : 0; + uint[]? leftBufferFromPool = null; + int size = (left._bits?.Length ?? 1) + 1; + Span x = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : leftBufferFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + x = x.Slice(0, left.WriteTo(x)); + + uint[]? rightBufferFromPool = null; + size = (right._bits?.Length ?? 1) + 1; + Span y = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : rightBufferFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + y = y.Slice(0, right.WriteTo(y)); + + uint[]? resultBufferFromPool = null; + size = Math.Max(x.Length, y.Length); + Span z = (size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : resultBufferFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + for (int i = 0; i < z.Length; i++) { - uint xu = (i < x.Length) ? x[i] : xExtend; - uint yu = (i < y.Length) ? y[i] : yExtend; + uint xu = ((uint)i < (uint)x.Length) ? x[i] : xExtend; + uint yu = ((uint)i < (uint)y.Length) ? y[i] : yExtend; z[i] = xu ^ yu; } - return new BigInteger(z); + if (leftBufferFromPool != null) + ArrayPool.Shared.Return(leftBufferFromPool); + + if (rightBufferFromPool != null) + ArrayPool.Shared.Return(rightBufferFromPool); + + var result = new BigInteger(z); + + if (resultBufferFromPool != null) + ArrayPool.Shared.Return(resultBufferFromPool); + + return result; } public static BigInteger operator <<(BigInteger value, int shift) @@ -1934,28 +2127,26 @@ public static explicit operator decimal(BigInteger value) return value; if (shift == int.MinValue) - return (value >> int.MaxValue) >> 1; + return ((value >> int.MaxValue) >> 1); if (shift < 0) return value >> -shift; (int digitShift, int smallShift) = Math.DivRem(shift, kcbitUint); - Span xd = stackalloc uint[1]; - bool negx = GetPartsForBitManipulation(ref value, ref xd); + uint[]? xdFromPool = null; + int xl = value._bits?.Length ?? 1; + Span xd = (xl <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : xdFromPool = ArrayPool.Shared.Rent(xl)).Slice(0, xl); + bool negx = value.GetPartsForBitManipulation(xd); - int zl = xd.Length + digitShift + 1; - uint[]? zdArray = null; - Span zd = stackalloc uint[0]; - if (zl <= StackallocUInt32Limit) - { - zd = stackalloc uint[StackallocUInt32Limit].Slice(0, zl); - zd.Slice(0, digitShift).Clear(); - } - else - { - zd = zdArray = new uint[zl]; - } + int zl = xl + digitShift + 1; + uint[]? zdFromPool = null; + Span zd = ((uint)zl <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : zdFromPool = ArrayPool.Shared.Rent(zl)).Slice(0, zl); + zd.Clear(); uint carry = 0; if (smallShift == 0) @@ -1968,16 +2159,25 @@ public static explicit operator decimal(BigInteger value) else { int carryShift = kcbitUint - smallShift; - for (int i = 0; i < xd.Length; i++) + int i; + for (i = 0; i < xd.Length; i++) { uint rot = xd[i]; zd[i + digitShift] = rot << smallShift | carry; carry = rot >> carryShift; } } - zd[^1] = carry; - return new BigInteger(zd, zdArray, negx); + zd[zd.Length - 1] = carry; + + var result = new BigInteger(zd, negx); + + if (xdFromPool != null) + ArrayPool.Shared.Return(xdFromPool); + if (zdFromPool != null) + ArrayPool.Shared.Return(zdFromPool); + + return result; } public static BigInteger operator >>(BigInteger value, int shift) @@ -1986,38 +2186,30 @@ public static explicit operator decimal(BigInteger value) return value; if (shift == int.MinValue) - return value << int.MaxValue << 1; + return ((value << int.MaxValue) << 1); if (shift < 0) return value << -shift; (int digitShift, int smallShift) = Math.DivRem(shift, kcbitUint); - Span stackallocedXd = stackalloc uint[1]; - Span xd = stackallocedXd; - bool negx = GetPartsForBitManipulation(ref value, ref xd); + BigInteger result; + + uint[]? xdFromPool = null; + int xl = value._bits?.Length ?? 1; + Span xd = (xl <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : xdFromPool = ArrayPool.Shared.Rent(xl)).Slice(0, xl); + + bool negx = value.GetPartsForBitManipulation(xd); bool trackSignBit = false; if (negx) { if (shift >= (kcbitUint * xd.Length)) { - return MinusOne; - } - - if (xd != stackallocedXd) - { - // make a copy of the part extracted from GetPartsForBitManipulation - if (xd.Length <= StackallocUInt32Limit) - { - stackallocedXd = stackalloc uint[StackallocUInt32Limit].Slice(0, xd.Length); - xd.CopyTo(stackallocedXd); - xd = stackallocedXd; - } - else - { - xd = xd.ToArray(); - } + result = MinusOne; + goto exit; } NumericsHelpers.DangerousMakeTwosComplement(xd); // Mutates xd @@ -2028,18 +2220,15 @@ public static explicit operator decimal(BigInteger value) // After a 32 bit right shift, it becomes [0x00, 0x00] which is [0x00, 0x00] when converted back. // The expected result is [0x00, 0x00, 0xFFFFFFFF] (2's complement) or [0x00, 0x00, 0x01] when converted back // If the 2's component's last element is a 0, we will track the sign externally - trackSignBit = smallShift == 0 && xd[^1] == 0; + trackSignBit = smallShift == 0 && xd[xd.Length - 1] == 0; } - int zl = xd.Length - digitShift + (trackSignBit ? 1: 0); - uint[]? zdArray = null; - Span zd = stackalloc uint[0]; - if (zl > 0) - { - zd = zl <= StackallocUInt32Limit ? - stackalloc uint[StackallocUInt32Limit].Slice(0, zl) : - zdArray = new uint[zl]; - } + uint[]? zdFromPool = null; + int zl = Math.Max(xl - digitShift, 0) + (trackSignBit ? 1 : 0); + Span zd = ((uint)zl <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : zdFromPool = ArrayPool.Shared.Rent(zl)).Slice(0, zl); + zd.Clear(); if (smallShift == 0) { @@ -2063,17 +2252,25 @@ stackalloc uint[StackallocUInt32Limit].Slice(0, zl) : carry = rot << carryShift; } } + if (negx) { // Set the tracked sign to the last element if (trackSignBit) - { - zd[^1] = 0xFFFFFFFF; - } + zd[zd.Length - 1] = 0xFFFFFFFF; + NumericsHelpers.DangerousMakeTwosComplement(zd); // Mutates zd } - return new BigInteger(zd, zdArray, negx); + result = new BigInteger(zd, negx); + + if (zdFromPool != null) + ArrayPool.Shared.Return(zdFromPool); + exit: + if (xdFromPool != null) + ArrayPool.Shared.Return(xdFromPool); + + return result; } public static BigInteger operator ~(BigInteger value) @@ -2118,46 +2315,87 @@ stackalloc uint[StackallocUInt32Limit].Slice(0, zl) : left.AssertValid(); right.AssertValid(); - bool trivialLeft = left._bits == null; - bool trivialRight = right._bits == null; + return Multiply(left._bits, left._sign, right._bits, right._sign); + } + + private static BigInteger Multiply(ReadOnlySpan left, int leftSign, ReadOnlySpan right, int rightSign) + { + bool trivialLeft = left.IsEmpty; + bool trivialRight = right.IsEmpty; if (trivialLeft && trivialRight) { - return (long)left._sign * right._sign; + return (long)leftSign * rightSign; } + BigInteger result; + uint[]? bitsFromPool = null; + if (trivialLeft) { - Debug.Assert(right._bits != null); - uint[] bits = BigIntegerCalculator.Multiply(right._bits, NumericsHelpers.Abs(left._sign)); - return new BigInteger(bits, bits, (left._sign < 0) ^ (right._sign < 0)); - } + Debug.Assert(!right.IsEmpty); - if (trivialRight) - { - Debug.Assert(left._bits != null); - uint[] bits = BigIntegerCalculator.Multiply(left._bits, NumericsHelpers.Abs(right._sign)); - return new BigInteger(bits, bits, (left._sign < 0) ^ (right._sign < 0)); + int size = right.Length + 1; + Span bits = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + + BigIntegerCalculator.Multiply(right, NumericsHelpers.Abs(leftSign), bits); + result = new BigInteger(bits, (leftSign < 0) ^ (rightSign < 0)); } + else if (trivialRight) + { + Debug.Assert(!left.IsEmpty); - Debug.Assert(left._bits != null && right._bits != null); + int size = left.Length + 1; + Span bits = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); - if (left._bits == right._bits) - { - uint[] bits = BigIntegerCalculator.Square(left._bits); - return new BigInteger(bits, bits, (left._sign < 0) ^ (right._sign < 0)); + BigIntegerCalculator.Multiply(left, NumericsHelpers.Abs(rightSign), bits); + result = new BigInteger(bits, (leftSign < 0) ^ (rightSign < 0)); } + else if (left == right) + { + int size = left.Length + right.Length; + Span bits = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); - if (left._bits.Length < right._bits.Length) + BigIntegerCalculator.Square(left, bits); + result = new BigInteger(bits, negative: false); + } + else if (left.Length < right.Length) { - uint[] bits = BigIntegerCalculator.Multiply(right._bits, left._bits); - return new BigInteger(bits, bits, (left._sign < 0) ^ (right._sign < 0)); + Debug.Assert(!left.IsEmpty && !right.IsEmpty); + + int size = left.Length + right.Length; + Span bits = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + bits.Clear(); + + BigIntegerCalculator.Multiply(right, left, bits); + result = new BigInteger(bits, (leftSign < 0) ^ (rightSign < 0)); } else { - uint[] bits = BigIntegerCalculator.Multiply(left._bits, right._bits); - return new BigInteger(bits, bits, (left._sign < 0) ^ (right._sign < 0)); + Debug.Assert(!left.IsEmpty && !right.IsEmpty); + + int size = left.Length + right.Length; + Span bits = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + bits.Clear(); + + BigIntegerCalculator.Multiply(left, right, bits); + result = new BigInteger(bits, (leftSign < 0) ^ (rightSign < 0)); } + + if (bitsFromPool != null) + ArrayPool.Shared.Return(bitsFromPool); + + return result; } public static BigInteger operator /(BigInteger dividend, BigInteger divisor) @@ -2180,11 +2418,28 @@ stackalloc uint[StackallocUInt32Limit].Slice(0, zl) : return s_bnZeroInt; } + uint[]? quotientFromPool = null; + if (trivialDivisor) { Debug.Assert(dividend._bits != null); - uint[] bits = BigIntegerCalculator.Divide(dividend._bits, NumericsHelpers.Abs(divisor._sign)); - return new BigInteger(bits, bits, (dividend._sign < 0) ^ (divisor._sign < 0)); + + int size = dividend._bits.Length; + Span quotient = ((uint)size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : quotientFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + + try + { + //may throw DivideByZeroException + BigIntegerCalculator.Divide(dividend._bits, NumericsHelpers.Abs(divisor._sign), quotient); + return new BigInteger(quotient, (dividend._sign < 0) ^ (divisor._sign < 0)); + } + finally + { + if (quotientFromPool != null) + ArrayPool.Shared.Return(quotientFromPool); + } } Debug.Assert(dividend._bits != null && divisor._bits != null); @@ -2195,8 +2450,18 @@ stackalloc uint[StackallocUInt32Limit].Slice(0, zl) : } else { - uint[] bits = BigIntegerCalculator.Divide(dividend._bits, divisor._bits); - return new BigInteger(bits, bits, (dividend._sign < 0) ^ (divisor._sign < 0)); + int size = dividend._bits.Length - divisor._bits.Length + 1; + Span quotient = ((uint)size < BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : quotientFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + + BigIntegerCalculator.Divide(dividend._bits, divisor._bits, quotient); + var result = new BigInteger(quotient, (dividend._sign < 0) ^ (divisor._sign < 0)); + + if (quotientFromPool != null) + ArrayPool.Shared.Return(quotientFromPool); + + return result; } } @@ -2233,8 +2498,20 @@ stackalloc uint[StackallocUInt32Limit].Slice(0, zl) : { return dividend; } - uint[] bits = BigIntegerCalculator.Remainder(dividend._bits, divisor._bits); - return new BigInteger(bits, bits, dividend._sign < 0); + + uint[]? bitsFromPool = null; + int size = dividend._bits.Length; + Span bits = (size <= BigIntegerCalculator.StackAllocThreshold ? + stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : bitsFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + + BigIntegerCalculator.Remainder(dividend._bits, divisor._bits, bits); + var result = new BigInteger(bits, dividend._sign < 0); + + if (bitsFromPool != null) + ArrayPool.Shared.Return(bitsFromPool); + + return result; } public static bool operator <(BigInteger left, BigInteger right) @@ -2451,28 +2728,26 @@ public long GetBitLength() /// Encapsulate the logic of normalizing the "small" and "large" forms of BigInteger /// into the "large" form so that Bit Manipulation algorithms can be simplified. /// - /// /// - /// The UInt32 span containing the entire big integer in "large" (denormalized) form. + /// The UInt32 array containing the entire big integer in "large" (denormalized) form. /// E.g., the number one (1) and negative one (-1) are both stored as 0x00000001 /// BigInteger values Int32.MinValue < x <= Int32.MaxValue are converted to this - /// format for convenience. Expecting to be passed a writeable span of length 1. + /// format for convenience. /// /// True for negative numbers. - private static bool GetPartsForBitManipulation(ref BigInteger x, ref Span xd) + private bool GetPartsForBitManipulation(Span xd) { - Debug.Assert(xd.Length == 1); + Debug.Assert(_bits is null ? xd.Length == 1 : xd.Length == _bits.Length); - if (x._bits == null) + if (_bits is null) { - xd[0] = (uint)(x._sign < 0 ? -x._sign : x._sign); + xd[0] = (uint)(_sign < 0 ? -_sign : _sign); } else { - xd = x._bits; + _bits.CopyTo(xd); } - - return x._sign < 0; + return _sign < 0; } internal static int GetDiffLength(uint[] rgu1, uint[] rgu2, int cu) @@ -2506,4 +2781,4 @@ private void AssertValid() } } } -} +} \ No newline at end of file diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.AddSub.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.AddSub.cs index 4439d67346de6..c2ac712ec9e67 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.AddSub.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.AddSub.cs @@ -2,112 +2,89 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Security; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.Numerics { internal static partial class BigIntegerCalculator { - public static uint[] Add(uint[] left, uint right) + public static void Add(ReadOnlySpan left, uint right, Span bits) { - Debug.Assert(left != null); Debug.Assert(left.Length >= 1); + Debug.Assert(bits.Length == left.Length + 1); // Executes the addition for one big and one 32-bit integer. // Thus, we've similar code than below, but there is no loop for // processing the 32-bit integer, since it's a single element. - uint[] bits = new uint[left.Length + 1]; + long carry = right; - long digit = (long)left[0] + right; - bits[0] = unchecked((uint)digit); - long carry = digit >> 32; - - for (int i = 1; i < left.Length; i++) + for (int i = 0; i < left.Length; i++) { - digit = left[i] + carry; + long digit = left[i] + carry; bits[i] = unchecked((uint)digit); carry = digit >> 32; } - bits[left.Length] = (uint)carry; - return bits; + bits[left.Length] = (uint)carry; } - public static unsafe uint[] Add(uint[] left, uint[] right) + public static void Add(ReadOnlySpan left, ReadOnlySpan right, Span bits) { - Debug.Assert(left != null); - Debug.Assert(right != null); Debug.Assert(left.Length >= right.Length); + Debug.Assert(bits.Length == left.Length + 1); - // Switching to unsafe pointers helps sparing - // some nasty index calculations... - - uint[] bits = new uint[left.Length + 1]; - - fixed (uint* l = left, r = right, b = &bits[0]) - { - Add(l, left.Length, - r, right.Length, - b, bits.Length); - } - - return bits; - } + int i = 0; + long carry = 0L; - private static unsafe void Add(uint* left, int leftLength, - uint* right, int rightLength, - uint* bits, int bitsLength) - { - Debug.Assert(leftLength >= 0); - Debug.Assert(rightLength >= 0); - Debug.Assert(leftLength >= rightLength); - Debug.Assert(bitsLength == leftLength + 1); + // Switching to managed references helps eliminating + // index bounds check... + ref uint leftPtr = ref MemoryMarshal.GetReference(left); + ref uint resultPtr = ref MemoryMarshal.GetReference(bits); // Executes the "grammar-school" algorithm for computing z = a + b. // While calculating z_i = a_i + b_i we take care of overflow: // Since a_i + b_i + c <= 2(2^32 - 1) + 1 = 2^33 - 1, our carry c // has always the value 1 or 0; hence, we're safe here. - int i = 0; - long carry = 0L; - - for (; i < rightLength; i++) + for ( ; i < right.Length; i++) { - long digit = (left[i] + carry) + right[i]; - bits[i] = unchecked((uint)digit); + long digit = (Unsafe.Add(ref leftPtr, i) + carry) + right[i]; + Unsafe.Add(ref resultPtr, i) = unchecked((uint)digit); carry = digit >> 32; } - for (; i < leftLength; i++) + for ( ; i < left.Length; i++) { long digit = left[i] + carry; - bits[i] = unchecked((uint)digit); + Unsafe.Add(ref resultPtr, i) = unchecked((uint)digit); carry = digit >> 32; } - bits[i] = (uint)carry; + Unsafe.Add(ref resultPtr, i) = (uint)carry; } - private static unsafe void AddSelf(uint* left, int leftLength, - uint* right, int rightLength) + private static void AddSelf(Span left, ReadOnlySpan right) { - Debug.Assert(leftLength >= 0); - Debug.Assert(rightLength >= 0); - Debug.Assert(leftLength >= rightLength); + Debug.Assert(left.Length >= right.Length); + + int i = 0; + long carry = 0L; + + // Switching to managed references helps eliminating + // index bounds check... + ref uint leftPtr = ref MemoryMarshal.GetReference(left); // Executes the "grammar-school" algorithm for computing z = a + b. // Same as above, but we're writing the result directly to a and // stop execution, if we're out of b and c is already 0. - int i = 0; - long carry = 0L; - - for (; i < rightLength; i++) + for ( ; i < right.Length; i++) { - long digit = (left[i] + carry) + right[i]; - left[i] = unchecked((uint)digit); + long digit = (Unsafe.Add(ref leftPtr, i) + carry) + right[i]; + Unsafe.Add(ref leftPtr, i) = unchecked((uint)digit); carry = digit >> 32; } - for (; carry != 0 && i < leftLength; i++) + for ( ; carry != 0 && i < left.Length; i++) { long digit = left[i] + carry; left[i] = (uint)digit; @@ -117,110 +94,84 @@ private static unsafe void AddSelf(uint* left, int leftLength, Debug.Assert(carry == 0); } - public static uint[] Subtract(uint[] left, uint right) + public static void Subtract(ReadOnlySpan left, uint right, Span bits) { - Debug.Assert(left != null); Debug.Assert(left.Length >= 1); Debug.Assert(left[0] >= right || left.Length >= 2); + Debug.Assert(bits.Length == left.Length); // Executes the subtraction for one big and one 32-bit integer. // Thus, we've similar code than below, but there is no loop for // processing the 32-bit integer, since it's a single element. - uint[] bits = new uint[left.Length]; + long carry = -right; - long digit = (long)left[0] - right; - bits[0] = unchecked((uint)digit); - long carry = digit >> 32; - - for (int i = 1; i < left.Length; i++) + for (int i = 0; i < left.Length; i++) { - digit = left[i] + carry; + long digit = left[i] + carry; bits[i] = unchecked((uint)digit); carry = digit >> 32; } - - return bits; } - public static unsafe uint[] Subtract(uint[] left, uint[] right) + public static void Subtract(ReadOnlySpan left, ReadOnlySpan right, Span bits) { - Debug.Assert(left != null); - Debug.Assert(right != null); Debug.Assert(left.Length >= right.Length); Debug.Assert(Compare(left, right) >= 0); + Debug.Assert(bits.Length == left.Length); - // Switching to unsafe pointers helps sparing - // some nasty index calculations... - - uint[] bits = new uint[left.Length]; - - fixed (uint* l = left, r = right, b = bits) - { - Subtract(l, left.Length, - r, right.Length, - b, bits.Length); - } - - return bits; - } + int i = 0; + long carry = 0L; - private static unsafe void Subtract(uint* left, int leftLength, - uint* right, int rightLength, - uint* bits, int bitsLength) - { - Debug.Assert(leftLength >= 0); - Debug.Assert(rightLength >= 0); - Debug.Assert(leftLength >= rightLength); - Debug.Assert(Compare(left, leftLength, right, rightLength) >= 0); - Debug.Assert(bitsLength == leftLength); + // Switching to managed references helps eliminating + // index bounds check... + ref uint leftPtr = ref MemoryMarshal.GetReference(left); + ref uint resultPtr = ref MemoryMarshal.GetReference(bits); // Executes the "grammar-school" algorithm for computing z = a - b. // While calculating z_i = a_i - b_i we take care of overflow: // Since a_i - b_i doesn't need any additional bit, our carry c // has always the value -1 or 0; hence, we're safe here. - int i = 0; - long carry = 0L; - - for (; i < rightLength; i++) + for ( ; i < right.Length; i++) { - long digit = (left[i] + carry) - right[i]; - bits[i] = unchecked((uint)digit); + long digit = (Unsafe.Add(ref leftPtr, i) + carry) - right[i]; + Unsafe.Add(ref resultPtr, i) = unchecked((uint)digit); carry = digit >> 32; } - for (; i < leftLength; i++) + for ( ; i < left.Length; i++) { long digit = left[i] + carry; - bits[i] = (uint)digit; + Unsafe.Add(ref resultPtr, i) = (uint)digit; carry = digit >> 32; } Debug.Assert(carry == 0); } - private static unsafe void SubtractSelf(uint* left, int leftLength, - uint* right, int rightLength) + private static void SubtractSelf(Span left, ReadOnlySpan right) { - Debug.Assert(leftLength >= 0); - Debug.Assert(rightLength >= 0); - Debug.Assert(leftLength >= rightLength); - Debug.Assert(Compare(left, leftLength, right, rightLength) >= 0); + Debug.Assert(left.Length >= right.Length); + Debug.Assert(Compare(left, right) >= 0); + + int i = 0; + long carry = 0L; + + // Switching to managed references helps eliminating + // index bounds check... + ref uint leftPtr = ref MemoryMarshal.GetReference(left); // Executes the "grammar-school" algorithm for computing z = a - b. // Same as above, but we're writing the result directly to a and // stop execution, if we're out of b and c is already 0. - int i = 0; - long carry = 0L; - - for (; i < rightLength; i++) + for (; i < right.Length; i++) { - long digit = (left[i] + carry) - right[i]; - left[i] = unchecked((uint)digit); + long digit = (Unsafe.Add(ref leftPtr, i) + carry) - right[i]; + Unsafe.Add(ref leftPtr, i) = unchecked((uint)digit); carry = digit >> 32; } - for (; carry != 0 && i < leftLength; i++) + for (; carry != 0 && i < left.Length; i++) { long digit = left[i] + carry; left[i] = (uint)digit; @@ -229,48 +180,5 @@ private static unsafe void SubtractSelf(uint* left, int leftLength, Debug.Assert(carry == 0); } - - public static int Compare(uint[] left, uint[] right) - { - Debug.Assert(left != null); - Debug.Assert(right != null); - - if (left.Length < right.Length) - return -1; - if (left.Length > right.Length) - return 1; - - for (int i = left.Length - 1; i >= 0; i--) - { - if (left[i] < right[i]) - return -1; - if (left[i] > right[i]) - return 1; - } - - return 0; - } - - private static unsafe int Compare(uint* left, int leftLength, - uint* right, int rightLength) - { - Debug.Assert(leftLength >= 0); - Debug.Assert(rightLength >= 0); - - if (leftLength < rightLength) - return -1; - if (leftLength > rightLength) - return 1; - - for (int i = leftLength - 1; i >= 0; i--) - { - if (left[i] < right[i]) - return -1; - if (left[i] > right[i]) - return 1; - } - - return 0; - } } } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.BitsBuffer.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.BitsBuffer.cs deleted file mode 100644 index ec05118f03007..0000000000000 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.BitsBuffer.cs +++ /dev/null @@ -1,215 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Security; - -namespace System.Numerics -{ - // ATTENTION: always pass BitsBuffer by reference, - // it's a structure for performance reasons. Furthermore - // it's a mutable one, so use it only with care! - - internal static partial class BigIntegerCalculator - { - // To spare memory allocations a buffer helps reusing memory! - // We just create the target array twice and switch between every - // operation. In order to not compute unnecessarily with all those - // leading zeros we take care of the current actual length. - - internal struct BitsBuffer - { - private uint[] _bits; - private int _length; - - public BitsBuffer(int size, uint value) - { - Debug.Assert(size >= 1); - - _bits = new uint[size]; - _length = value != 0 ? 1 : 0; - - _bits[0] = value; - } - - public BitsBuffer(int size, uint[] value) - { - Debug.Assert(value != null); - Debug.Assert(size >= ActualLength(value)); - - _bits = new uint[size]; - _length = ActualLength(value); - - Array.Copy(value, _bits, _length); - } - - public unsafe void MultiplySelf(ref BitsBuffer value, - ref BitsBuffer temp) - { - Debug.Assert(temp._length == 0); - Debug.Assert(_length + value._length <= temp._bits.Length); - - // Executes a multiplication for this and value, writes the - // result to temp. Switches this and temp arrays afterwards. - - fixed (uint* b = _bits, v = value._bits, t = temp._bits) - { - if (_length < value._length) - { - Multiply(v, value._length, - b, _length, - t, _length + value._length); - } - else - { - Multiply(b, _length, - v, value._length, - t, _length + value._length); - } - } - - Apply(ref temp, _length + value._length); - } - - public unsafe void SquareSelf(ref BitsBuffer temp) - { - Debug.Assert(temp._length == 0); - Debug.Assert(_length + _length <= temp._bits.Length); - - // Executes a square for this, writes the result to temp. - // Switches this and temp arrays afterwards. - - fixed (uint* b = _bits, t = temp._bits) - { - Square(b, _length, - t, _length + _length); - } - - Apply(ref temp, _length + _length); - } - - public void Reduce(ref FastReducer reducer) - { - // Executes a modulo operation using an optimized reducer. - // Thus, no need of any switching here, happens in-line. - - _length = reducer.Reduce(_bits, _length); - } - - public unsafe void Reduce(uint[] modulus) - { - Debug.Assert(modulus != null); - - // Executes a modulo operation using the divide operation. - // Thus, no need of any switching here, happens in-line. - - if (_length >= modulus.Length) - { - fixed (uint* b = _bits, m = modulus) - { - Divide(b, _length, - m, modulus.Length, - null, 0); - } - - _length = ActualLength(_bits, modulus.Length); - } - } - - public unsafe void Reduce(ref BitsBuffer modulus) - { - // Executes a modulo operation using the divide operation. - // Thus, no need of any switching here, happens in-line. - - if (_length >= modulus._length) - { - fixed (uint* b = _bits, m = modulus._bits) - { - Divide(b, _length, - m, modulus._length, - null, 0); - } - - _length = ActualLength(_bits, modulus._length); - } - } - - public void Overwrite(ulong value) - { - Debug.Assert(_bits.Length >= 2); - - if (_length > 2) - { - // Ensure leading zeros - Array.Clear(_bits, 2, _length - 2); - } - - uint lo = unchecked((uint)value); - uint hi = (uint)(value >> 32); - - _bits[0] = lo; - _bits[1] = hi; - _length = hi != 0 ? 2 : lo != 0 ? 1 : 0; - } - - public void Overwrite(uint value) - { - Debug.Assert(_bits.Length >= 1); - - if (_length > 1) - { - // Ensure leading zeros - Array.Clear(_bits, 1, _length - 1); - } - - _bits[0] = value; - _length = value != 0 ? 1 : 0; - } - - public uint[] GetBits() - { - return _bits; - } - - public int GetSize() - { - return _bits.Length; - } - - public int GetLength() - { - return _length; - } - - public void Refresh(int maxLength) - { - Debug.Assert(_bits.Length >= maxLength); - - if (_length > maxLength) - { - // Ensure leading zeros - Array.Clear(_bits, maxLength, _length - maxLength); - } - - _length = ActualLength(_bits, maxLength); - } - - private void Apply(ref BitsBuffer temp, int maxLength) - { - Debug.Assert(temp._length == 0); - Debug.Assert(maxLength <= temp._bits.Length); - - // Resets this and switches this and temp afterwards. - // The caller assumed an empty temp, the next will too. - - Array.Clear(_bits, 0, _length); - - uint[] t = temp._bits; - temp._bits = _bits; - _bits = t; - - _length = ActualLength(_bits, maxLength); - } - } - } -} diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs index bb75e77a228d0..9ca65e0813e25 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs @@ -1,26 +1,24 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; using System.Diagnostics; -using System.Security; namespace System.Numerics { internal static partial class BigIntegerCalculator { - public static uint[] Divide(uint[] left, uint right, - out uint remainder) + public static void Divide(ReadOnlySpan left, uint right, Span quotient, out uint remainder) { - Debug.Assert(left != null); Debug.Assert(left.Length >= 1); + Debug.Assert(quotient.Length == left.Length); // Executes the division for one big and one 32-bit integer. // Thus, we've similar code than below, but there is no loop for // processing the 32-bit integer, since it's a single element. - uint[] quotient = new uint[left.Length]; - ulong carry = 0UL; + for (int i = left.Length - 1; i >= 0; i--) { ulong value = (carry << 32) | left[i]; @@ -29,19 +27,15 @@ public static uint[] Divide(uint[] left, uint right, carry = value - digit * right; } remainder = (uint)carry; - - return quotient; } - public static uint[] Divide(uint[] left, uint right) + public static void Divide(ReadOnlySpan left, uint right, Span quotient) { - Debug.Assert(left != null); Debug.Assert(left.Length >= 1); + Debug.Assert(quotient.Length == left.Length); // Same as above, but only computing the quotient. - uint[] quotient = new uint[left.Length]; - ulong carry = 0UL; for (int i = left.Length - 1; i >= 0; i--) { @@ -50,17 +44,13 @@ public static uint[] Divide(uint[] left, uint right) quotient[i] = (uint)digit; carry = value - digit * right; } - - return quotient; } - public static uint Remainder(uint[] left, uint right) + public static uint Remainder(ReadOnlySpan left, uint right) { - Debug.Assert(left != null); Debug.Assert(left.Length >= 1); // Same as above, but only computing the remainder. - ulong carry = 0UL; for (int i = left.Length - 1; i >= 0; i--) { @@ -71,115 +61,79 @@ public static uint Remainder(uint[] left, uint right) return (uint)carry; } - public static unsafe uint[] Divide(uint[] left, uint[] right, - out uint[] remainder) + public static void Divide(ReadOnlySpan left, ReadOnlySpan right, Span quotient, Span remainder) { - Debug.Assert(left != null); - Debug.Assert(right != null); Debug.Assert(left.Length >= 1); Debug.Assert(right.Length >= 1); Debug.Assert(left.Length >= right.Length); + Debug.Assert(quotient.Length == left.Length - right.Length + 1); + Debug.Assert(remainder.Length == left.Length); - // Switching to unsafe pointers helps sparing - // some nasty index calculations... - - uint[] localLeft = left.AsSpan().ToArray(); // left will get overwritten, we need a local copy - uint[] bits = new uint[left.Length - right.Length + 1]; - - fixed (uint* l = &localLeft[0], r = &right[0], b = &bits[0]) - { - Divide(l, localLeft.Length, - r, right.Length, - b, bits.Length); - } - - remainder = localLeft; - - return bits; + left.CopyTo(remainder); + Divide(remainder, right, quotient); } - public static unsafe uint[] Divide(uint[] left, uint[] right) + public static void Divide(ReadOnlySpan left, ReadOnlySpan right, Span quotient) { - Debug.Assert(left != null); - Debug.Assert(right != null); Debug.Assert(left.Length >= 1); Debug.Assert(right.Length >= 1); Debug.Assert(left.Length >= right.Length); + Debug.Assert(quotient.Length == left.Length - right.Length + 1); // Same as above, but only returning the quotient. - // left will get overwritten, we need a local copy - Span localLeft = stackalloc uint[0]; - if (left.Length <= BigInteger.StackallocUInt32Limit) - { - localLeft = stackalloc uint[BigInteger.StackallocUInt32Limit].Slice(0, left.Length); - left.AsSpan().CopyTo(localLeft); - } - else - { - localLeft = left.AsSpan().ToArray(); - } + uint[]? leftCopyFromPool = null; - uint[] bits = new uint[left.Length - right.Length + 1]; + // NOTE: left will get overwritten, we need a local copy + // However, mutated left is not used afterwards, so use array pooling or stack alloc + Span leftCopy = (left.Length <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : leftCopyFromPool = ArrayPool.Shared.Rent(left.Length)).Slice(0, left.Length); + left.CopyTo(leftCopy); - fixed (uint* l = &localLeft[0], r = &right[0], b = &bits[0]) - { - Divide(l, localLeft.Length, - r, right.Length, - b, bits.Length); - } + Divide(leftCopy, right, quotient); - return bits; + if (leftCopyFromPool != null) + ArrayPool.Shared.Return(leftCopyFromPool); } - public static unsafe uint[] Remainder(uint[] left, uint[] right) + public static void Remainder(ReadOnlySpan left, ReadOnlySpan right, Span remainder) { - Debug.Assert(left != null); - Debug.Assert(right != null); Debug.Assert(left.Length >= 1); Debug.Assert(right.Length >= 1); Debug.Assert(left.Length >= right.Length); + Debug.Assert(remainder.Length >= left.Length); // Same as above, but only returning the remainder. - uint[] localLeft = left.AsSpan().ToArray(); // left will get overwritten, we need a local copy - - fixed (uint* l = &localLeft[0], r = &right[0]) - { - Divide(l, localLeft.Length, - r, right.Length, - null, 0); - } - - return localLeft; + left.CopyTo(remainder); + Divide(remainder, right, default); } - private static unsafe void Divide(uint* left, int leftLength, - uint* right, int rightLength, - uint* bits, int bitsLength) + private static void Divide(Span left, ReadOnlySpan right, Span bits) { - Debug.Assert(leftLength >= 1); - Debug.Assert(rightLength >= 1); - Debug.Assert(leftLength >= rightLength); - Debug.Assert(bitsLength == leftLength - rightLength + 1 - || bitsLength == 0); + Debug.Assert(left.Length >= 1); + Debug.Assert(right.Length >= 1); + Debug.Assert(left.Length >= right.Length); + Debug.Assert(bits.Length == left.Length - right.Length + 1 + || bits.Length == 0); // Executes the "grammar-school" algorithm for computing q = a / b. // Before calculating q_i, we get more bits into the highest bit // block of the divisor. Thus, guessing digits of the quotient // will be more precise. Additionally we'll get r = a % b. - uint divHi = right[rightLength - 1]; - uint divLo = rightLength > 1 ? right[rightLength - 2] : 0; + uint divHi = right[right.Length - 1]; + uint divLo = right.Length > 1 ? right[right.Length - 2] : 0; // We measure the leading zeros of the divisor - int shift = LeadingZeros(divHi); + int shift = BitOperations.LeadingZeroCount(divHi); int backShift = 32 - shift; // And, we make sure the most significant bit is set if (shift > 0) { - uint divNx = rightLength > 2 ? right[rightLength - 3] : 0; + uint divNx = right.Length > 2 ? right[right.Length - 3] : 0; divHi = (divHi << shift) | (divLo >> backShift); divLo = (divLo << shift) | (divNx >> backShift); @@ -187,10 +141,10 @@ private static unsafe void Divide(uint* left, int leftLength, // Then, we divide all of the bits as we would do it using // pen and paper: guessing the next digit, subtracting, ... - for (int i = leftLength; i >= rightLength; i--) + for (int i = left.Length; i >= right.Length; i--) { - int n = i - rightLength; - uint t = i < leftLength ? left[i] : 0; + int n = i - right.Length; + uint t = (uint)i < (uint)left.Length ? left[i] : 0; ulong valHi = ((ulong)t << 32) | left[i - 1]; uint valLo = i > 1 ? left[i - 2] : 0; @@ -217,15 +171,13 @@ private static unsafe void Divide(uint* left, int leftLength, if (digit > 0) { // Now it's time to subtract our current quotient - uint carry = SubtractDivisor(left + n, leftLength - n, - right, rightLength, digit); + uint carry = SubtractDivisor(left.Slice(n), right, digit); if (carry != t) { Debug.Assert(carry == t + 1); // Our guess was still exactly one too high - carry = AddDivisor(left + n, leftLength - n, - right, rightLength); + carry = AddDivisor(left.Slice(n), right); --digit; Debug.Assert(carry == 1); @@ -233,41 +185,36 @@ private static unsafe void Divide(uint* left, int leftLength, } // We have the digit! - if (bitsLength != 0) + if ((uint)n < (uint)bits.Length) bits[n] = (uint)digit; - if (i < leftLength) + + if ((uint)i < (uint)left.Length) left[i] = 0; } } - private static unsafe uint AddDivisor(uint* left, int leftLength, - uint* right, int rightLength) + private static uint AddDivisor(Span left, ReadOnlySpan right) { - Debug.Assert(leftLength >= 0); - Debug.Assert(rightLength >= 0); - Debug.Assert(leftLength >= rightLength); + Debug.Assert(left.Length >= right.Length); // Repairs the dividend, if the last subtract was too much ulong carry = 0UL; - for (int i = 0; i < rightLength; i++) + for (int i = 0; i < right.Length; i++) { - ulong digit = (left[i] + carry) + right[i]; - left[i] = unchecked((uint)digit); + ref uint leftElement = ref left[i]; + ulong digit = (leftElement + carry) + right[i]; + leftElement = unchecked((uint)digit); carry = digit >> 32; } return (uint)carry; } - private static unsafe uint SubtractDivisor(uint* left, int leftLength, - uint* right, int rightLength, - ulong q) + private static uint SubtractDivisor(Span left, ReadOnlySpan right, ulong q) { - Debug.Assert(leftLength >= 0); - Debug.Assert(rightLength >= 0); - Debug.Assert(leftLength >= rightLength); + Debug.Assert(left.Length >= right.Length); Debug.Assert(q <= 0xFFFFFFFF); // Combines a subtract and a multiply operation, which is naturally @@ -275,14 +222,15 @@ private static unsafe uint SubtractDivisor(uint* left, int leftLength, ulong carry = 0UL; - for (int i = 0; i < rightLength; i++) + for (int i = 0; i < right.Length; i++) { carry += right[i] * q; uint digit = unchecked((uint)carry); carry = carry >> 32; - if (left[i] < digit) + ref uint leftElement = ref left[i]; + if (leftElement < digit) ++carry; - left[i] = unchecked(left[i] - digit); + leftElement = unchecked(leftElement - digit); } return (uint)carry; @@ -316,39 +264,5 @@ private static bool DivideGuessTooBig(ulong q, ulong valHi, uint valLo, return false; } - - private static int LeadingZeros(uint value) - { - if (value == 0) - return 32; - - int count = 0; - if ((value & 0xFFFF0000) == 0) - { - count += 16; - value = value << 16; - } - if ((value & 0xFF000000) == 0) - { - count += 8; - value = value << 8; - } - if ((value & 0xF0000000) == 0) - { - count += 4; - value = value << 4; - } - if ((value & 0xC0000000) == 0) - { - count += 2; - value = value << 2; - } - if ((value & 0x80000000) == 0) - { - count += 1; - } - - return count; - } } } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.FastReducer.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.FastReducer.cs index 8731794b40299..0b56d2b52e245 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.FastReducer.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.FastReducer.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Security; namespace System.Numerics { @@ -14,135 +13,114 @@ internal static partial class BigIntegerCalculator // see https://en.wikipedia.org/wiki/Barrett_reduction - internal readonly struct FastReducer + private readonly ref struct FastReducer { - private readonly uint[] _modulus; - private readonly uint[] _mu; - private readonly uint[] _q1; - private readonly uint[] _q2; + private readonly ReadOnlySpan _modulus; + private readonly ReadOnlySpan _mu; + private readonly Span _q1; + private readonly Span _q2; - private readonly int _muLength; - - public FastReducer(uint[] modulus) + public FastReducer(ReadOnlySpan modulus, Span r, Span mu, Span q1, Span q2) { - Debug.Assert(modulus != null); + Debug.Assert(!modulus.IsEmpty); + Debug.Assert(r.Length == modulus.Length * 2 + 1); + Debug.Assert(mu.Length == r.Length - modulus.Length + 1); + Debug.Assert(q1.Length == modulus.Length * 2 + 2); + Debug.Assert(q2.Length == modulus.Length * 2 + 2); // Let r = 4^k, with 2^k > m - uint[] r = new uint[modulus.Length * 2 + 1]; r[r.Length - 1] = 1; // Let mu = 4^k / m - _mu = Divide(r, modulus); + Divide(r, modulus, mu); _modulus = modulus; - // Allocate memory for quotients once - _q1 = new uint[modulus.Length * 2 + 2]; - _q2 = new uint[modulus.Length * 2 + 1]; + _q1 = q1; + _q2 = q2; - _muLength = ActualLength(_mu); + _mu = mu.Slice(0, ActualLength(mu)); } - public int Reduce(uint[] value, int length) + public int Reduce(Span value) { - Debug.Assert(value != null); - Debug.Assert(length <= value.Length); Debug.Assert(value.Length <= _modulus.Length * 2); // Trivial: value is shorter - if (length < _modulus.Length) - return length; + if (value.Length < _modulus.Length) + return value.Length; // Let q1 = v/2^(k-1) * mu - int l1 = DivMul(value, length, _mu, _muLength, - _q1, _modulus.Length - 1); + _q1.Clear(); + int l1 = DivMul(value, _mu, _q1, _modulus.Length - 1); // Let q2 = q1/2^(k+1) * m - int l2 = DivMul(_q1, l1, _modulus, _modulus.Length, - _q2, _modulus.Length + 1); + _q2.Clear(); + int l2 = DivMul(_q1.Slice(0, l1), _modulus, _q2, _modulus.Length + 1); // Let v = (v - q2) % 2^(k+1) - i*m - return SubMod(value, length, _q2, l2, - _modulus, _modulus.Length + 1); + var length = SubMod(value, _q2.Slice(0, l2), _modulus, _modulus.Length + 1); + value = value.Slice(length); + value.Clear(); + + return length; } - private static unsafe int DivMul(uint[] left, int leftLength, - uint[] right, int rightLength, - uint[] bits, int k) + private static int DivMul(ReadOnlySpan left, ReadOnlySpan right, Span bits, int k) { - Debug.Assert(left != null); - Debug.Assert(left.Length >= leftLength); - Debug.Assert(right != null); - Debug.Assert(right.Length >= rightLength); - Debug.Assert(bits != null); - Debug.Assert(bits.Length + k >= leftLength + rightLength); + Debug.Assert(!right.IsEmpty); + Debug.Assert(!bits.IsEmpty); + Debug.Assert(bits.Length + k >= left.Length + right.Length); // Executes the multiplication algorithm for left and right, // but skips the first k limbs of left, which is equivalent to // preceding division by 2^(32*k). To spare memory allocations // we write the result to an already allocated memory. - Array.Clear(bits); - - if (leftLength > k) + if (left.Length > k) { - leftLength -= k; + left = left.Slice(k); - fixed (uint* l = left, r = right, b = bits) + if (left.Length < right.Length) { - if (leftLength < rightLength) - { - Multiply(r, rightLength, - l + k, leftLength, - b, leftLength + rightLength); - } - else - { - Multiply(l + k, leftLength, - r, rightLength, - b, leftLength + rightLength); - } + Multiply(right, + left, + bits.Slice(0, left.Length + right.Length)); + } + else + { + Multiply(left, + right, + bits.Slice(0, left.Length + right.Length)); } - return ActualLength(bits, leftLength + rightLength); + return ActualLength(bits.Slice(0, left.Length + right.Length)); } return 0; } - private static unsafe int SubMod(uint[] left, int leftLength, - uint[] right, int rightLength, - uint[] modulus, int k) + private static int SubMod(Span left, ReadOnlySpan right, ReadOnlySpan modulus, int k) { - Debug.Assert(left != null); - Debug.Assert(left.Length >= leftLength); - Debug.Assert(right != null); - Debug.Assert(right.Length >= rightLength); - // Executes the subtraction algorithm for left and right, // but considers only the first k limbs, which is equivalent to // preceding reduction by 2^(32*k). Furthermore, if left is // still greater than modulus, further subtractions are used. - if (leftLength > k) - leftLength = k; - if (rightLength > k) - rightLength = k; + if (left.Length > k) + left = left.Slice(0, k); + if (right.Length > k) + right = right.Slice(0, k); - fixed (uint* l = left, r = right, m = modulus) - { - SubtractSelf(l, leftLength, r, rightLength); - leftLength = ActualLength(left, leftLength); + SubtractSelf(left, right); + left = left.Slice(0, ActualLength(left)); - while (Compare(l, leftLength, m, modulus.Length) >= 0) - { - SubtractSelf(l, leftLength, m, modulus.Length); - leftLength = ActualLength(left, leftLength); - } + while (Compare(left, modulus) >= 0) + { + SubtractSelf(left, modulus); + left = left.Slice(0, ActualLength(left)); } - Array.Clear(left, leftLength, left.Length - leftLength); - - return leftLength; + return left.Length; } } } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.GcdInv.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.GcdInv.cs index d984912ec6246..c9944c1ba95bb 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.GcdInv.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.GcdInv.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; using System.Diagnostics; namespace System.Numerics @@ -40,9 +41,8 @@ public static ulong Gcd(ulong left, ulong right) return left; } - public static uint Gcd(uint[] left, uint right) + public static uint Gcd(ReadOnlySpan left, uint right) { - Debug.Assert(left != null); Debug.Assert(left.Length >= 1); Debug.Assert(right != 0); @@ -54,27 +54,34 @@ public static uint Gcd(uint[] left, uint right) return Gcd(right, temp); } - public static uint[] Gcd(uint[] left, uint[] right) + public static void Gcd(ReadOnlySpan left, ReadOnlySpan right, Span result) { - Debug.Assert(left != null); Debug.Assert(left.Length >= 2); - Debug.Assert(right != null); Debug.Assert(right.Length >= 2); Debug.Assert(Compare(left, right) >= 0); + Debug.Assert(result.Length == left.Length); - BitsBuffer leftBuffer = new BitsBuffer(left.Length, left); - BitsBuffer rightBuffer = new BitsBuffer(right.Length, right); + left.CopyTo(result); - Gcd(ref leftBuffer, ref rightBuffer); + uint[]? rightCopyFromPool = null; + Span rightCopy = (right.Length <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : rightCopyFromPool = ArrayPool.Shared.Rent(right.Length)).Slice(0, right.Length); + right.CopyTo(rightCopy); - return leftBuffer.GetBits(); + Gcd(result, rightCopy); + + if (rightCopyFromPool != null) + ArrayPool.Shared.Return(rightCopyFromPool); } - private static void Gcd(ref BitsBuffer left, ref BitsBuffer right) + private static void Gcd(Span left, Span right) { - Debug.Assert(left.GetLength() >= 2); - Debug.Assert(right.GetLength() >= 2); - Debug.Assert(left.GetLength() >= right.GetLength()); + Debug.Assert(left.Length >= 2); + Debug.Assert(right.Length >= 2); + Debug.Assert(left.Length >= right.Length); + + Span result = left; //keep result buffer untouched during computation // Executes Lehmer's gcd algorithm, but uses the most // significant bits to work with 64-bit (not 32-bit) values. @@ -83,11 +90,11 @@ private static void Gcd(ref BitsBuffer left, ref BitsBuffer right) // http://cacr.uwaterloo.ca/hac/about/chap14.pdf (see 14.4.2) // ftp://ftp.risc.uni-linz.ac.at/pub/techreports/1992/92-69.ps.gz - while (right.GetLength() > 2) + while (right.Length > 2) { ulong x, y; - ExtractDigits(ref left, ref right, out x, out y); + ExtractDigits(left, right, out x, out y); uint a = 1U, b = 0U; uint c = 0U, d = 1U; @@ -149,85 +156,112 @@ private static void Gcd(ref BitsBuffer left, ref BitsBuffer right) if (b == 0) { // Euclid's step - left.Reduce(ref right); + left = left.Slice(0, Reduce(left, right)); - BitsBuffer temp = left; + Span temp = left; left = right; right = temp; } else { // Lehmer's step - LehmerCore(ref left, ref right, a, b, c, d); + var count = LehmerCore(left, right, a, b, c, d); + left = left.Slice(0, Refresh(left, count)); + right = right.Slice(0, Refresh(right, count)); if (iteration % 2 == 1) { // Ensure left is larger than right - BitsBuffer temp = left; + Span temp = left; left = right; right = temp; } } } - if (right.GetLength() > 0) + if (right.Length > 0) { // Euclid's step - left.Reduce(ref right); + Reduce(left, right); - uint[] xBits = right.GetBits(); - uint[] yBits = left.GetBits(); + ulong x = ((ulong)right[1] << 32) | right[0]; + ulong y = ((ulong)left[1] << 32) | left[0]; - ulong x = ((ulong)xBits[1] << 32) | xBits[0]; - ulong y = ((ulong)yBits[1] << 32) | yBits[0]; + left = left.Slice(0, Overwrite(left, Gcd(x, y))); + Overwrite(right, 0U); + } + + left.CopyTo(result); + } - left.Overwrite(Gcd(x, y)); - right.Overwrite(0); + private static int Overwrite(Span buffer, ulong value) + { + Debug.Assert(buffer.Length >= 2); + + if (buffer.Length > 2) + { + // Ensure leading zeros in little-endian + buffer.Slice(2).Clear(); } + + uint lo = unchecked((uint)value); + uint hi = (uint)(value >> 32); + + buffer[1] = hi; + buffer[0] = lo; + return hi != 0 ? 2 : lo != 0 ? 1 : 0; } - private static void ExtractDigits(ref BitsBuffer xBuffer, - ref BitsBuffer yBuffer, + private static int Overwrite(Span bits, uint value) + { + Debug.Assert(bits.Length >= 1); + + if (bits.Length > 1) + { + // Ensure leading zeros in little-endian + bits.Slice(1).Clear(); + } + + bits[0] = value; + return value != 0 ? 1 : 0; + } + + private static void ExtractDigits(ReadOnlySpan xBuffer, + ReadOnlySpan yBuffer, out ulong x, out ulong y) { - Debug.Assert(xBuffer.GetLength() >= 3); - Debug.Assert(yBuffer.GetLength() >= 3); - Debug.Assert(xBuffer.GetLength() >= yBuffer.GetLength()); + Debug.Assert(xBuffer.Length >= 3); + Debug.Assert(yBuffer.Length >= 3); + Debug.Assert(xBuffer.Length >= yBuffer.Length); // Extracts the most significant bits of x and y, // but ensures the quotient x / y does not change! - uint[] xBits = xBuffer.GetBits(); - int xLength = xBuffer.GetLength(); - - uint[] yBits = yBuffer.GetBits(); - int yLength = yBuffer.GetLength(); - - ulong xh = xBits[xLength - 1]; - ulong xm = xBits[xLength - 2]; - ulong xl = xBits[xLength - 3]; + ulong xh = xBuffer[xBuffer.Length - 1]; + ulong xm = xBuffer[xBuffer.Length - 2]; + ulong xl = xBuffer[xBuffer.Length - 3]; ulong yh, ym, yl; // arrange the bits - switch (xLength - yLength) + switch (xBuffer.Length - yBuffer.Length) { case 0: - yh = yBits[yLength - 1]; - ym = yBits[yLength - 2]; - yl = yBits[yLength - 3]; + yh = yBuffer[yBuffer.Length - 1]; + ym = yBuffer[yBuffer.Length - 2]; + yl = yBuffer[yBuffer.Length - 3]; break; case 1: yh = 0UL; - ym = yBits[yLength - 1]; - yl = yBits[yLength - 2]; + ym = yBuffer[yBuffer.Length - 1]; + yl = yBuffer[yBuffer.Length - 2]; break; case 2: yh = 0UL; ym = 0UL; - yl = yBits[yLength - 1]; + yl = yBuffer[yBuffer.Length - 1]; break; default: @@ -238,7 +272,7 @@ private static void ExtractDigits(ref BitsBuffer xBuffer, } // Use all the bits but one, see [hac] 14.58 (ii) - int z = LeadingZeros((uint)xh); + int z = BitOperations.LeadingZeroCount((uint)xh); x = ((xh << 32 + z) | (xm << z) | (xl >> 32 - z)) >> 1; y = ((yh << 32 + z) | (ym << z) | (yl >> 32 - z)) >> 1; @@ -246,23 +280,20 @@ private static void ExtractDigits(ref BitsBuffer xBuffer, Debug.Assert(x >= y); } - private static void LehmerCore(ref BitsBuffer xBuffer, - ref BitsBuffer yBuffer, - long a, long b, - long c, long d) + private static int LehmerCore(Span x, + Span y, + long a, long b, + long c, long d) { - Debug.Assert(xBuffer.GetLength() >= 1); - Debug.Assert(yBuffer.GetLength() >= 1); - Debug.Assert(xBuffer.GetLength() >= yBuffer.GetLength()); + Debug.Assert(x.Length >= 1); + Debug.Assert(y.Length >= 1); + Debug.Assert(x.Length >= y.Length); Debug.Assert(a <= 0x7FFFFFFF && b <= 0x7FFFFFFF); Debug.Assert(c <= 0x7FFFFFFF && d <= 0x7FFFFFFF); // Executes the combined calculation of Lehmer's step. - uint[] x = xBuffer.GetBits(); - uint[] y = yBuffer.GetBits(); - - int length = yBuffer.GetLength(); + int length = y.Length; long xCarry = 0L, yCarry = 0L; for (int i = 0; i < length; i++) @@ -275,8 +306,20 @@ private static void LehmerCore(ref BitsBuffer xBuffer, y[i] = unchecked((uint)yDigit); } - xBuffer.Refresh(length); - yBuffer.Refresh(length); + return length; + } + + private static int Refresh(Span bits, int maxLength) + { + Debug.Assert(bits.Length >= maxLength); + + if (bits.Length > maxLength) + { + // Ensure leading zeros + bits.Slice(maxLength).Clear(); + } + + return ActualLength(bits.Slice(0, maxLength)); } } } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.PowMod.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.PowMod.cs index c646173430275..0407feff54fe3 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.PowMod.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.PowMod.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; using System.Diagnostics; namespace System.Numerics @@ -12,50 +13,104 @@ internal static partial class BigIntegerCalculator // https://en.wikipedia.org/wiki/Exponentiation_by_squaring - public static uint[] Pow(uint value, uint power) + public static void Pow(uint value, uint power, Span bits) { - // The basic pow method for a 32-bit integer. - // To spare memory allocations we first roughly - // estimate an upper bound for our buffers. + Pow(value != 0U ? stackalloc uint[1] { value } : default, power, bits); + } - int size = PowBound(power, 1, 1); - BitsBuffer v = new BitsBuffer(size, value); - return PowCore(power, ref v); + public static void Pow(ReadOnlySpan value, uint power, Span bits) + { + Debug.Assert(bits.Length == PowBound(power, value.Length)); + + uint[]? tempFromPool = null; + Span temp = (bits.Length <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : tempFromPool = ArrayPool.Shared.Rent(bits.Length)).Slice(0, bits.Length); + temp.Clear(); + + uint[]? valueCopyFromPool = null; + Span valueCopy = (bits.Length <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : valueCopyFromPool = ArrayPool.Shared.Rent(bits.Length)).Slice(0, bits.Length); + value.CopyTo(valueCopy); + valueCopy.Slice(value.Length).Clear(); + + PowCore(valueCopy, value.Length, temp, power, bits).CopyTo(bits); + + if (tempFromPool != null) + ArrayPool.Shared.Return(tempFromPool); + if (valueCopyFromPool != null) + ArrayPool.Shared.Return(valueCopyFromPool); } - public static uint[] Pow(uint[] value, uint power) + private static Span PowCore(Span value, int valueLength, Span temp, uint power, Span result) { - Debug.Assert(value != null); + Debug.Assert(value.Length >= valueLength); + Debug.Assert(temp.Length == result.Length); + Debug.Assert(value.Length == temp.Length); + + result[0] = 1; + int bitsLength = 1; - // The basic pow method for a big integer. - // To spare memory allocations we first roughly - // estimate an upper bound for our buffers. + // The basic pow algorithm using square-and-multiply. + while (power != 0) + { + if ((power & 1) == 1) + bitsLength = MultiplySelf(ref result, bitsLength, value.Slice(0, valueLength), ref temp); + if (power != 1) + valueLength = SquareSelf(ref value, valueLength, ref temp); + power = power >> 1; + } - int size = PowBound(power, value.Length, 1); - BitsBuffer v = new BitsBuffer(size, value); - return PowCore(power, ref v); + return result; } - private static uint[] PowCore(uint power, ref BitsBuffer value) + private static int MultiplySelf(ref Span left, int leftLength, ReadOnlySpan right, ref Span temp) { - // Executes the basic pow algorithm. + Debug.Assert(leftLength <= left.Length); - int size = value.GetSize(); + int resultLength = leftLength + right.Length; - BitsBuffer temp = new BitsBuffer(size, 0); - BitsBuffer result = new BitsBuffer(size, 1); + if (leftLength >= right.Length) + { + Multiply(left.Slice(0, leftLength), right, temp.Slice(0, resultLength)); + } + else + { + Multiply(right, left.Slice(0, leftLength), temp.Slice(0, resultLength)); + } + + left.Clear(); + //switch buffers + Span t = left; + left = temp; + temp = t; + return ActualLength(left.Slice(0, resultLength)); + } - PowCore(power, ref value, ref result, ref temp); + private static int SquareSelf(ref Span value, int valueLength, ref Span temp) + { + Debug.Assert(valueLength <= value.Length); + Debug.Assert(temp.Length >= valueLength + valueLength); - return result.GetBits(); + int resultLength = valueLength + valueLength; + + Square(value.Slice(0, valueLength), temp.Slice(0, resultLength)); + + value.Clear(); + //switch buffers + Span t = value; + value = temp; + temp = t; + return ActualLength(value.Slice(0, resultLength)); } - private static int PowBound(uint power, int valueLength, - int resultLength) + public static int PowBound(uint power, int valueLength) { // The basic pow algorithm, but instead of squaring // and multiplying we just sum up the lengths. + int resultLength = 1; while (power != 0) { checked @@ -71,64 +126,41 @@ private static int PowBound(uint power, int valueLength, return resultLength; } - private static void PowCore(uint power, ref BitsBuffer value, - ref BitsBuffer result, ref BitsBuffer temp) - { - // The basic pow algorithm using square-and-multiply. - - while (power != 0) - { - if ((power & 1) == 1) - result.MultiplySelf(ref value, ref temp); - if (power != 1) - value.SquareSelf(ref temp); - power = power >> 1; - } - } - public static uint Pow(uint value, uint power, uint modulus) { // The 32-bit modulus pow method for a 32-bit integer // raised by a 32-bit integer... - return PowCore(power, modulus, value, 1); + return PowCore(value, power, modulus, 1); } - public static uint Pow(uint[] value, uint power, uint modulus) + public static uint Pow(ReadOnlySpan value, uint power, uint modulus) { - Debug.Assert(value != null); - // The 32-bit modulus pow method for a big integer // raised by a 32-bit integer... uint v = Remainder(value, modulus); - return PowCore(power, modulus, v, 1); + return PowCore(v, power, modulus, 1); } - public static uint Pow(uint value, uint[] power, uint modulus) + public static uint Pow(uint value, ReadOnlySpan power, uint modulus) { - Debug.Assert(power != null); - // The 32-bit modulus pow method for a 32-bit integer // raised by a big integer... - return PowCore(power, modulus, value, 1); + return PowCore(value, power, modulus, 1); } - public static uint Pow(uint[] value, uint[] power, uint modulus) + public static uint Pow(ReadOnlySpan value, ReadOnlySpan power, uint modulus) { - Debug.Assert(value != null); - Debug.Assert(power != null); - // The 32-bit modulus pow method for a big integer // raised by a big integer... uint v = Remainder(value, modulus); - return PowCore(power, modulus, v, 1); + return PowCore(v, power, modulus, 1); } - private static uint PowCore(uint[] power, uint modulus, - ulong value, ulong result) + private static uint PowCore(ulong value, ReadOnlySpan power, uint modulus, ulong result) { // The 32-bit modulus pow algorithm for all but // the last power limb using square-and-multiply. @@ -145,11 +177,10 @@ private static uint PowCore(uint[] power, uint modulus, } } - return PowCore(power[power.Length - 1], modulus, value, result); + return PowCore(value, power[power.Length - 1], modulus, result); } - private static uint PowCore(uint power, uint modulus, - ulong value, ulong result) + private static uint PowCore(ulong value, uint power, uint modulus, ulong result) { // The 32-bit modulus pow algorithm for the last or // the only power limb using square-and-multiply. @@ -166,116 +197,221 @@ private static uint PowCore(uint power, uint modulus, return (uint)(result % modulus); } - public static uint[] Pow(uint value, uint power, uint[] modulus) + public static void Pow(uint value, uint power, + ReadOnlySpan modulus, Span bits) { - Debug.Assert(modulus != null); - - // The big modulus pow method for a 32-bit integer - // raised by a 32-bit integer... - - int size = modulus.Length + modulus.Length; - BitsBuffer v = new BitsBuffer(size, value); - return PowCore(power, modulus, ref v); + Pow(value != 0U ? stackalloc uint[1] { value } : default, power, modulus, bits); } - public static uint[] Pow(uint[] value, uint power, uint[] modulus) + public static void Pow(ReadOnlySpan value, uint power, + ReadOnlySpan modulus, Span bits) { - Debug.Assert(value != null); - Debug.Assert(modulus != null); + Debug.Assert(!modulus.IsEmpty); + Debug.Assert(bits.Length == modulus.Length + modulus.Length); // The big modulus pow method for a big integer // raised by a 32-bit integer... + uint[]? valueCopyFromPool = null; + int size = Math.Max(value.Length, bits.Length); + Span valueCopy = (size <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : valueCopyFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + valueCopy.Clear(); + if (value.Length > modulus.Length) - value = Remainder(value, modulus); + { + Remainder(value, modulus, valueCopy); + } + else + { + value.CopyTo(valueCopy); + } - int size = modulus.Length + modulus.Length; - BitsBuffer v = new BitsBuffer(size, value); - return PowCore(power, modulus, ref v); - } + uint[]? tempFromPool = null; + Span temp = (bits.Length <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : tempFromPool = ArrayPool.Shared.Rent(bits.Length)).Slice(0, bits.Length); + temp.Clear(); - public static uint[] Pow(uint value, uint[] power, uint[] modulus) - { - Debug.Assert(power != null); - Debug.Assert(modulus != null); + PowCore(valueCopy, ActualLength(valueCopy), power, modulus, temp, bits); - // The big modulus pow method for a 32-bit integer - // raised by a big integer... + if (valueCopyFromPool != null) + ArrayPool.Shared.Return(valueCopyFromPool); + if (tempFromPool != null) + ArrayPool.Shared.Return(tempFromPool); + } - int size = modulus.Length + modulus.Length; - BitsBuffer v = new BitsBuffer(size, value); - return PowCore(power, modulus, ref v); + public static void Pow(uint value, ReadOnlySpan power, + ReadOnlySpan modulus, Span bits) + { + Pow(value != 0U ? stackalloc uint[1] { value } : default, power, modulus, bits); } - public static uint[] Pow(uint[] value, uint[] power, uint[] modulus) + public static void Pow(ReadOnlySpan value, ReadOnlySpan power, + ReadOnlySpan modulus, Span bits) { - Debug.Assert(value != null); - Debug.Assert(power != null); - Debug.Assert(modulus != null); + Debug.Assert(!modulus.IsEmpty); + Debug.Assert(bits.Length == modulus.Length + modulus.Length); // The big modulus pow method for a big integer // raised by a big integer... + int size = Math.Max(value.Length, bits.Length); + uint[]? valueCopyFromPool = null; + Span valueCopy = (size <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : valueCopyFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + valueCopy.Clear(); + if (value.Length > modulus.Length) - value = Remainder(value, modulus); + { + Remainder(value, modulus, valueCopy); + } + else + { + value.CopyTo(valueCopy); + } + + uint[]? tempFromPool = null; + Span temp = (bits.Length <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : tempFromPool = ArrayPool.Shared.Rent(bits.Length)).Slice(0, bits.Length); + temp.Clear(); + + PowCore(valueCopy, ActualLength(valueCopy), power, modulus, temp, bits); - int size = modulus.Length + modulus.Length; - BitsBuffer v = new BitsBuffer(size, value); - return PowCore(power, modulus, ref v); + if (valueCopyFromPool != null) + ArrayPool.Shared.Return(valueCopyFromPool); + if (tempFromPool != null) + ArrayPool.Shared.Return(tempFromPool); } +#if DEBUG // Mutable for unit testing... - private static int ReducerThreshold = 32; - - private static uint[] PowCore(uint[] power, uint[] modulus, - ref BitsBuffer value) + private static +#else + private const +#endif + int ReducerThreshold = 32; + + private static void PowCore(Span value, int valueLength, + ReadOnlySpan power, ReadOnlySpan modulus, + Span temp, Span bits) { // Executes the big pow algorithm. - int size = value.GetSize(); - - BitsBuffer temp = new BitsBuffer(size, 0); - BitsBuffer result = new BitsBuffer(size, 1); + bits[0] = 1; if (modulus.Length < ReducerThreshold) { - PowCore(power, modulus, ref value, ref result, ref temp); + PowCore(value, valueLength, power, modulus, bits, 1, temp).CopyTo(bits); } else { - FastReducer reducer = new FastReducer(modulus); - PowCore(power, ref reducer, ref value, ref result, ref temp); + int size = modulus.Length * 2 + 1; + uint[]? rFromPool = null; + Span r = ((uint)size <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : rFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + r.Clear(); + + size = r.Length - modulus.Length + 1; + uint[]? muFromPool = null; + Span mu = ((uint)size <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : muFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + mu.Clear(); + + size = modulus.Length * 2 + 2; + uint[]? q1FromPool = null; + Span q1 = ((uint)size <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : q1FromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + q1.Clear(); + + uint[]? q2FromPool = null; + Span q2 = ((uint)size <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : q2FromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + q2.Clear(); + + FastReducer reducer = new FastReducer(modulus, r, mu, q1, q2); + + if (rFromPool != null) + ArrayPool.Shared.Return(rFromPool); + + PowCore(value, valueLength, power, reducer, bits, 1, temp).CopyTo(bits); + + if (muFromPool != null) + ArrayPool.Shared.Return(muFromPool); + if (q1FromPool != null) + ArrayPool.Shared.Return(q1FromPool); + if (q2FromPool != null) + ArrayPool.Shared.Return(q2FromPool); } - - return result.GetBits(); } - private static uint[] PowCore(uint power, uint[] modulus, - ref BitsBuffer value) + private static void PowCore(Span value, int valueLength, + uint power, ReadOnlySpan modulus, + Span temp, Span bits) { // Executes the big pow algorithm. - - int size = value.GetSize(); - - BitsBuffer temp = new BitsBuffer(size, 0); - BitsBuffer result = new BitsBuffer(size, 1); + bits[0] = 1; if (modulus.Length < ReducerThreshold) { - PowCore(power, modulus, ref value, ref result, ref temp); + PowCore(value, valueLength, power, modulus, bits, 1, temp).CopyTo(bits); } else { - FastReducer reducer = new FastReducer(modulus); - PowCore(power, ref reducer, ref value, ref result, ref temp); + int size = modulus.Length * 2 + 1; + uint[]? rFromPool = null; + Span r = ((uint)size <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : rFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + r.Clear(); + + size = r.Length - modulus.Length + 1; + uint[]? muFromPool = null; + Span mu = ((uint)size <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : muFromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + mu.Clear(); + + size = modulus.Length * 2 + 2; + uint[]? q1FromPool = null; + Span q1 = ((uint)size <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : q1FromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + q1.Clear(); + + uint[]? q2FromPool = null; + Span q2 = ((uint)size <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : q2FromPool = ArrayPool.Shared.Rent(size)).Slice(0, size); + q2.Clear(); + + FastReducer reducer = new FastReducer(modulus, r, mu, q1, q2); + + if (rFromPool != null) + ArrayPool.Shared.Return(rFromPool); + + PowCore(value, valueLength, power, reducer, bits, 1, temp).CopyTo(bits); + + if (muFromPool != null) + ArrayPool.Shared.Return(muFromPool); + if (q1FromPool != null) + ArrayPool.Shared.Return(q1FromPool); + if (q2FromPool != null) + ArrayPool.Shared.Return(q2FromPool); } - - return result.GetBits(); } - private static void PowCore(uint[] power, uint[] modulus, - ref BitsBuffer value, ref BitsBuffer result, - ref BitsBuffer temp) + private static Span PowCore(Span value, int valueLength, + ReadOnlySpan power, ReadOnlySpan modulus, + Span result, int resultLength, + Span temp) { // The big modulus pow algorithm for all but // the last power limb using square-and-multiply. @@ -290,22 +426,22 @@ private static void PowCore(uint[] power, uint[] modulus, { if ((p & 1) == 1) { - result.MultiplySelf(ref value, ref temp); - result.Reduce(modulus); + resultLength = MultiplySelf(ref result, resultLength, value.Slice(0, valueLength), ref temp); + resultLength = Reduce(result.Slice(0, resultLength), modulus); } - value.SquareSelf(ref temp); - value.Reduce(modulus); + valueLength = SquareSelf(ref value, valueLength, ref temp); + valueLength = Reduce(value.Slice(0, valueLength), modulus); p = p >> 1; } } - PowCore(power[power.Length - 1], modulus, ref value, ref result, - ref temp); + return PowCore(value, valueLength, power[power.Length - 1], modulus, result, resultLength, temp); } - private static void PowCore(uint power, uint[] modulus, - ref BitsBuffer value, ref BitsBuffer result, - ref BitsBuffer temp) + private static Span PowCore(Span value, int valueLength, + uint power, ReadOnlySpan modulus, + Span result, int resultLength, + Span temp) { // The big modulus pow algorithm for the last or // the only power limb using square-and-multiply. @@ -317,21 +453,24 @@ private static void PowCore(uint power, uint[] modulus, { if ((power & 1) == 1) { - result.MultiplySelf(ref value, ref temp); - result.Reduce(modulus); + resultLength = MultiplySelf(ref result, resultLength, value.Slice(0, valueLength), ref temp); + resultLength = Reduce(result.Slice(0, resultLength), modulus); } if (power != 1) { - value.SquareSelf(ref temp); - value.Reduce(modulus); + valueLength = SquareSelf(ref value, valueLength, ref temp); + valueLength = Reduce(value.Slice(0, valueLength), modulus); } power = power >> 1; } + + return result.Slice(0, resultLength); } - private static void PowCore(uint[] power, ref FastReducer reducer, - ref BitsBuffer value, ref BitsBuffer result, - ref BitsBuffer temp) + private static Span PowCore(Span value, int valueLength, + ReadOnlySpan power, in FastReducer reducer, + Span result, int resultLength, + Span temp) { // The big modulus pow algorithm for all but // the last power limb using square-and-multiply. @@ -346,22 +485,22 @@ private static void PowCore(uint[] power, ref FastReducer reducer, { if ((p & 1) == 1) { - result.MultiplySelf(ref value, ref temp); - result.Reduce(ref reducer); + resultLength = MultiplySelf(ref result, resultLength, value.Slice(0, valueLength), ref temp); + resultLength = reducer.Reduce(result.Slice(0, resultLength)); } - value.SquareSelf(ref temp); - value.Reduce(ref reducer); + valueLength = SquareSelf(ref value, valueLength, ref temp); + valueLength = reducer.Reduce(value.Slice(0, valueLength)); p = p >> 1; } } - PowCore(power[power.Length - 1], ref reducer, ref value, ref result, - ref temp); + return PowCore(value, valueLength, power[power.Length - 1], reducer, result, resultLength, temp); } - private static void PowCore(uint power, ref FastReducer reducer, - ref BitsBuffer value, ref BitsBuffer result, - ref BitsBuffer temp) + private static Span PowCore(Span value, int valueLength, + uint power, in FastReducer reducer, + Span result, int resultLength, + Span temp) { // The big modulus pow algorithm for the last or // the only power limb using square-and-multiply. @@ -373,34 +512,18 @@ private static void PowCore(uint power, ref FastReducer reducer, { if ((power & 1) == 1) { - result.MultiplySelf(ref value, ref temp); - result.Reduce(ref reducer); + resultLength = MultiplySelf(ref result, resultLength, value.Slice(0, valueLength), ref temp); + resultLength = reducer.Reduce(result.Slice(0, resultLength)); } if (power != 1) { - value.SquareSelf(ref temp); - value.Reduce(ref reducer); + valueLength = SquareSelf(ref value, valueLength, ref temp); + valueLength = reducer.Reduce(value.Slice(0, valueLength)); } power = power >> 1; } - } - - private static int ActualLength(uint[] value) - { - // Since we're reusing memory here, the actual length - // of a given value may be less then the array's length - - return ActualLength(value, value.Length); - } - - private static int ActualLength(uint[] value, int length) - { - Debug.Assert(value != null); - Debug.Assert(length <= value.Length); - while (length > 0 && value[length - 1] == 0) - --length; - return length; + return result; } } } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.SquMul.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.SquMul.cs index f77d02f37ccb3..4aeae650e76e6 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.SquMul.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.SquMul.cs @@ -1,40 +1,26 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; using System.Diagnostics; -using System.Security; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.Numerics { internal static partial class BigIntegerCalculator { - public static unsafe uint[] Square(uint[] value) - { - Debug.Assert(value != null); - - // Switching to unsafe pointers helps sparing - // some nasty index calculations... - - uint[] bits = new uint[value.Length + value.Length]; - - fixed (uint* v = value, b = bits) - { - Square(v, value.Length, - b, bits.Length); - } - - return bits; - } - +#if DEBUG // Mutable for unit testing... - private static int SquareThreshold = 32; - private static int AllocationThreshold = 256; + private static +#else + private const +#endif + int SquareThreshold = 32; - private static unsafe void Square(uint* value, int valueLength, - uint* bits, int bitsLength) + public static void Square(ReadOnlySpan value, Span bits) { - Debug.Assert(valueLength >= 0); - Debug.Assert(bitsLength == valueLength + valueLength); + Debug.Assert(bits.Length == value.Length + value.Length); // Executes different algorithms for computing z = a * a // based on the actual length of a. If a is "small" enough @@ -45,8 +31,12 @@ private static unsafe void Square(uint* value, int valueLength, // NOTE: useful thresholds needs some "empirical" testing, // which are smaller in DEBUG mode for testing purpose. - if (valueLength < SquareThreshold) + if (value.Length < SquareThreshold) { + // Switching to managed references helps eliminating + // index bounds check... + ref uint resultPtr = ref MemoryMarshal.GetReference(bits); + // Squares the bits using the "grammar-school" method. // Envisioning the "rhombus" of a pen-and-paper calculation // we see that computing z_i+j += a_j * a_i can be optimized @@ -58,20 +48,20 @@ private static unsafe void Square(uint* value, int valueLength, // = 2^64 - 1 (which perfectly matches with ulong!). But // here we would need an UInt65... Hence, we split these // operation and do some extra shifts. - - for (int i = 0; i < valueLength; i++) + for (int i = 0; i < value.Length; i++) { ulong carry = 0UL; + uint v = value[i]; for (int j = 0; j < i; j++) { - ulong digit1 = bits[i + j] + carry; - ulong digit2 = (ulong)value[j] * value[i]; - bits[i + j] = unchecked((uint)(digit1 + (digit2 << 1))); + ulong digit1 = Unsafe.Add(ref resultPtr, i + j) + carry; + ulong digit2 = (ulong)value[j] * v; + Unsafe.Add(ref resultPtr, i + j) = unchecked((uint)(digit1 + (digit2 << 1))); carry = (digit2 + (digit1 >> 1)) >> 31; } - ulong digits = (ulong)value[i] * value[i] + carry; - bits[i + i] = unchecked((uint)digits); - bits[i + i + 1] = (uint)(digits >> 32); + ulong digits = (ulong)v * v + carry; + Unsafe.Add(ref resultPtr, i + i) = unchecked((uint)digits); + Unsafe.Add(ref resultPtr, i + i + 1) = (uint)(digits >> 32); } } else @@ -88,81 +78,59 @@ private static unsafe void Square(uint* value, int valueLength, // Say we want to compute z = a * a ... // ... we need to determine our new length (just the half) - int n = valueLength >> 1; + int n = value.Length >> 1; int n2 = n << 1; // ... split value like a = (a_1 << n) + a_0 - uint* valueLow = value; - int valueLowLength = n; - uint* valueHigh = value + n; - int valueHighLength = valueLength - n; + ReadOnlySpan valueLow = value.Slice(0, n); + ReadOnlySpan valueHigh = value.Slice(n); // ... prepare our result array (to reuse its memory) - uint* bitsLow = bits; - int bitsLowLength = n2; - uint* bitsHigh = bits + n2; - int bitsHighLength = bitsLength - n2; + Span bitsLow = bits.Slice(0, n2); + Span bitsHigh = bits.Slice(n2); // ... compute z_0 = a_0 * a_0 (squaring again!) - Square(valueLow, valueLowLength, - bitsLow, bitsLowLength); + Square(valueLow, bitsLow); // ... compute z_2 = a_1 * a_1 (squaring again!) - Square(valueHigh, valueHighLength, - bitsHigh, bitsHighLength); + Square(valueHigh, bitsHigh); + + int foldLength = valueHigh.Length + 1; + uint[]? foldFromPool = null; + Span fold = ((uint)foldLength <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : foldFromPool = ArrayPool.Shared.Rent(foldLength)).Slice(0, foldLength); + fold.Clear(); - int foldLength = valueHighLength + 1; int coreLength = foldLength + foldLength; + uint[]? coreFromPool = null; + Span core = ((uint)coreLength <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : coreFromPool = ArrayPool.Shared.Rent(coreLength)).Slice(0, coreLength); + core.Clear(); - if (coreLength < AllocationThreshold) - { - uint* fold = stackalloc uint[foldLength]; - new Span(fold, foldLength).Clear(); - uint* core = stackalloc uint[coreLength]; - new Span(core, coreLength).Clear(); - - // ... compute z_a = a_1 + a_0 (call it fold...) - Add(valueHigh, valueHighLength, - valueLow, valueLowLength, - fold, foldLength); - - // ... compute z_1 = z_a * z_a - z_0 - z_2 - Square(fold, foldLength, - core, coreLength); - SubtractCore(bitsHigh, bitsHighLength, - bitsLow, bitsLowLength, - core, coreLength); - - // ... and finally merge the result! :-) - AddSelf(bits + n, bitsLength - n, core, coreLength); - } - else - { - fixed (uint* fold = new uint[foldLength], - core = new uint[coreLength]) - { - // ... compute z_a = a_1 + a_0 (call it fold...) - Add(valueHigh, valueHighLength, - valueLow, valueLowLength, - fold, foldLength); - - // ... compute z_1 = z_a * z_a - z_0 - z_2 - Square(fold, foldLength, - core, coreLength); - SubtractCore(bitsHigh, bitsHighLength, - bitsLow, bitsLowLength, - core, coreLength); - - // ... and finally merge the result! :-) - AddSelf(bits + n, bitsLength - n, core, coreLength); - } - } + // ... compute z_a = a_1 + a_0 (call it fold...) + Add(valueHigh, valueLow, fold); + + // ... compute z_1 = z_a * z_a - z_0 - z_2 + Square(fold, core); + + if (foldFromPool != null) + ArrayPool.Shared.Return(foldFromPool); + + SubtractCore(bitsHigh, bitsLow, core); + + // ... and finally merge the result! :-) + AddSelf(bits.Slice(n), core); + + if (coreFromPool != null) + ArrayPool.Shared.Return(coreFromPool); } } - public static uint[] Multiply(uint[] left, uint right) + public static void Multiply(ReadOnlySpan left, uint right, Span bits) { - Debug.Assert(left != null); + Debug.Assert(bits.Length == left.Length + 1); // Executes the multiplication for one big and one 32-bit integer. // Since every step holds the already slightly familiar equation @@ -171,51 +139,28 @@ public static uint[] Multiply(uint[] left, uint right) int i = 0; ulong carry = 0UL; - uint[] bits = new uint[left.Length + 1]; - for (; i < left.Length; i++) + for ( ; i < left.Length; i++) { ulong digits = (ulong)left[i] * right + carry; bits[i] = unchecked((uint)digits); carry = digits >> 32; } bits[i] = (uint)carry; - - return bits; - } - - public static unsafe uint[] Multiply(uint[] left, uint[] right) - { - Debug.Assert(left != null); - Debug.Assert(right != null); - Debug.Assert(left.Length >= right.Length); - - // Switching to unsafe pointers helps sparing - // some nasty index calculations... - - uint[] bits = new uint[left.Length + right.Length]; - - fixed (uint* l = left, r = right, b = bits) - { - Multiply(l, left.Length, - r, right.Length, - b, bits.Length); - } - - return bits; } +#if DEBUG // Mutable for unit testing... - private static int MultiplyThreshold = 32; + private static +#else + private const +#endif + int MultiplyThreshold = 32; - private static unsafe void Multiply(uint* left, int leftLength, - uint* right, int rightLength, - uint* bits, int bitsLength) + public static void Multiply(ReadOnlySpan left, ReadOnlySpan right, Span bits) { - Debug.Assert(leftLength >= 0); - Debug.Assert(rightLength >= 0); - Debug.Assert(leftLength >= rightLength); - Debug.Assert(bitsLength == leftLength + rightLength); + Debug.Assert(left.Length >= right.Length); + Debug.Assert(bits.Length == left.Length + right.Length); // Executes different algorithms for computing z = a * b // based on the actual length of b. If b is "small" enough @@ -226,8 +171,12 @@ private static unsafe void Multiply(uint* left, int leftLength, // NOTE: useful thresholds needs some "empirical" testing, // which are smaller in DEBUG mode for testing purpose. - if (rightLength < MultiplyThreshold) + if (right.Length < MultiplyThreshold) { + // Switching to managed references helps eliminating + // index bounds check... + ref uint resultPtr = ref MemoryMarshal.GetReference(bits); + // Multiplies the bits using the "grammar-school" method. // Envisioning the "rhombus" of a pen-and-paper calculation // should help getting the idea of these two loops... @@ -235,17 +184,17 @@ private static unsafe void Multiply(uint* left, int leftLength, // z_i+j + a_j * b_i + c <= 2(2^32 - 1) + (2^32 - 1)^2 = // = 2^64 - 1 (which perfectly matches with ulong!). - for (int i = 0; i < rightLength; i++) + for (int i = 0; i < right.Length; i++) { ulong carry = 0UL; - for (int j = 0; j < leftLength; j++) + for (int j = 0; j < left.Length; j++) { - ulong digits = bits[i + j] + carry - + (ulong)left[j] * right[i]; - bits[i + j] = unchecked((uint)digits); + ref uint elementPtr = ref Unsafe.Add(ref resultPtr, i + j); + ulong digits = elementPtr + carry + (ulong)left[j] * right[i]; + elementPtr = unchecked((uint)digits); carry = digits >> 32; } - bits[i + leftLength] = (uint)carry; + Unsafe.Add(ref resultPtr, i + left.Length) = (uint)carry; } } else @@ -262,111 +211,77 @@ private static unsafe void Multiply(uint* left, int leftLength, // Say we want to compute z = a * b ... // ... we need to determine our new length (just the half) - int n = rightLength >> 1; + int n = right.Length >> 1; int n2 = n << 1; // ... split left like a = (a_1 << n) + a_0 - uint* leftLow = left; - int leftLowLength = n; - uint* leftHigh = left + n; - int leftHighLength = leftLength - n; + ReadOnlySpan leftLow = left.Slice(0, n); + ReadOnlySpan leftHigh = left.Slice(n); // ... split right like b = (b_1 << n) + b_0 - uint* rightLow = right; - int rightLowLength = n; - uint* rightHigh = right + n; - int rightHighLength = rightLength - n; + ReadOnlySpan rightLow = right.Slice(0, n); + ReadOnlySpan rightHigh = right.Slice(n); // ... prepare our result array (to reuse its memory) - uint* bitsLow = bits; - int bitsLowLength = n2; - uint* bitsHigh = bits + n2; - int bitsHighLength = bitsLength - n2; + Span bitsLow = bits.Slice(0, n2); + Span bitsHigh = bits.Slice(n2); // ... compute z_0 = a_0 * b_0 (multiply again) - Multiply(leftLow, leftLowLength, - rightLow, rightLowLength, - bitsLow, bitsLowLength); + Multiply(leftLow, rightLow, bitsLow); // ... compute z_2 = a_1 * b_1 (multiply again) - Multiply(leftHigh, leftHighLength, - rightHigh, rightHighLength, - bitsHigh, bitsHighLength); + Multiply(leftHigh, rightHigh, bitsHigh); + + int leftFoldLength = leftHigh.Length + 1; + uint[]? leftFoldFromPool = null; + Span leftFold = ((uint)leftFoldLength <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : leftFoldFromPool = ArrayPool.Shared.Rent(leftFoldLength)).Slice(0, leftFoldLength); + leftFold.Clear(); + + int rightFoldLength = rightHigh.Length + 1; + uint[]? rightFoldFromPool = null; + Span rightFold = ((uint)rightFoldLength <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : rightFoldFromPool = ArrayPool.Shared.Rent(rightFoldLength)).Slice(0, rightFoldLength); + rightFold.Clear(); - int leftFoldLength = leftHighLength + 1; - int rightFoldLength = rightHighLength + 1; int coreLength = leftFoldLength + rightFoldLength; + uint[]? coreFromPool = null; + Span core = ((uint)coreLength <= StackAllocThreshold ? + stackalloc uint[StackAllocThreshold] + : coreFromPool = ArrayPool.Shared.Rent(coreLength)).Slice(0, coreLength); + core.Clear(); - if (coreLength < AllocationThreshold) - { - uint* leftFold = stackalloc uint[leftFoldLength]; - new Span(leftFold, leftFoldLength).Clear(); - uint* rightFold = stackalloc uint[rightFoldLength]; - new Span(rightFold, rightFoldLength).Clear(); - uint* core = stackalloc uint[coreLength]; - new Span(core, coreLength).Clear(); - - // ... compute z_a = a_1 + a_0 (call it fold...) - Add(leftHigh, leftHighLength, - leftLow, leftLowLength, - leftFold, leftFoldLength); - - // ... compute z_b = b_1 + b_0 (call it fold...) - Add(rightHigh, rightHighLength, - rightLow, rightLowLength, - rightFold, rightFoldLength); - - // ... compute z_1 = z_a * z_b - z_0 - z_2 - Multiply(leftFold, leftFoldLength, - rightFold, rightFoldLength, - core, coreLength); - SubtractCore(bitsHigh, bitsHighLength, - bitsLow, bitsLowLength, - core, coreLength); - - // ... and finally merge the result! :-) - AddSelf(bits + n, bitsLength - n, core, coreLength); - } - else - { - fixed (uint* leftFold = new uint[leftFoldLength], - rightFold = new uint[rightFoldLength], - core = new uint[coreLength]) - { - // ... compute z_a = a_1 + a_0 (call it fold...) - Add(leftHigh, leftHighLength, - leftLow, leftLowLength, - leftFold, leftFoldLength); - - // ... compute z_b = b_1 + b_0 (call it fold...) - Add(rightHigh, rightHighLength, - rightLow, rightLowLength, - rightFold, rightFoldLength); - - // ... compute z_1 = z_a * z_b - z_0 - z_2 - Multiply(leftFold, leftFoldLength, - rightFold, rightFoldLength, - core, coreLength); - SubtractCore(bitsHigh, bitsHighLength, - bitsLow, bitsLowLength, - core, coreLength); - - // ... and finally merge the result! :-) - AddSelf(bits + n, bitsLength - n, core, coreLength); - } - } + // ... compute z_a = a_1 + a_0 (call it fold...) + Add(leftHigh, leftLow, leftFold); + + // ... compute z_b = b_1 + b_0 (call it fold...) + Add(rightHigh, rightLow, rightFold); + + // ... compute z_1 = z_a * z_b - z_0 - z_2 + Multiply(leftFold, rightFold, core); + + if (leftFoldFromPool != null) + ArrayPool.Shared.Return(leftFoldFromPool); + + if (rightFoldFromPool != null) + ArrayPool.Shared.Return(rightFoldFromPool); + + SubtractCore(bitsHigh, bitsLow, core); + + // ... and finally merge the result! :-) + AddSelf(bits.Slice(n), core); + + if (coreFromPool != null) + ArrayPool.Shared.Return(coreFromPool); } } - private static unsafe void SubtractCore(uint* left, int leftLength, - uint* right, int rightLength, - uint* core, int coreLength) + private static void SubtractCore(ReadOnlySpan left, ReadOnlySpan right, Span core) { - Debug.Assert(leftLength >= 0); - Debug.Assert(rightLength >= 0); - Debug.Assert(coreLength >= 0); - Debug.Assert(leftLength >= rightLength); - Debug.Assert(coreLength >= leftLength); + Debug.Assert(left.Length >= right.Length); + Debug.Assert(core.Length >= left.Length); // Executes a special subtraction algorithm for the multiplication, // which needs to subtract two different values from a core value, @@ -378,19 +293,26 @@ private static unsafe void SubtractCore(uint* left, int leftLength, int i = 0; long carry = 0L; - for (; i < rightLength; i++) + // Switching to managed references helps eliminating + // index bounds check... + ref uint leftPtr = ref MemoryMarshal.GetReference(left); + ref uint corePtr = ref MemoryMarshal.GetReference(core); + + for ( ; i < right.Length; i++) { - long digit = (core[i] + carry) - left[i] - right[i]; - core[i] = unchecked((uint)digit); + long digit = (Unsafe.Add(ref corePtr, i) + carry) - Unsafe.Add(ref leftPtr, i) - right[i]; + Unsafe.Add(ref corePtr, i) = unchecked((uint)digit); carry = digit >> 32; } - for (; i < leftLength; i++) + + for ( ; i < left.Length; i++) { - long digit = (core[i] + carry) - left[i]; - core[i] = unchecked((uint)digit); + long digit = (Unsafe.Add(ref corePtr, i) + carry) - left[i]; + Unsafe.Add(ref corePtr, i) = unchecked((uint)digit); carry = digit >> 32; } - for (; carry != 0 && i < coreLength; i++) + + for ( ; carry != 0 && i < core.Length; i++) { long digit = core[i] + carry; core[i] = (uint)digit; diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.Utils.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.Utils.cs new file mode 100644 index 0000000000000..37d4ae7596568 --- /dev/null +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.Utils.cs @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Numerics +{ + internal static partial class BigIntegerCalculator + { +#if DEBUG + // Mutable for unit testing... + internal static +#else + internal const +#endif + int StackAllocThreshold = 64; + + public static int Compare(ReadOnlySpan left, ReadOnlySpan right) + { + if (left.Length < right.Length) + return -1; + if (left.Length > right.Length) + return 1; + + for (int i = left.Length - 1; i >= 0; i--) + { + uint leftElement = left[i]; + uint rightElement = right[i]; + if (leftElement < rightElement) + return -1; + if (leftElement > rightElement) + return 1; + } + + return 0; + } + + private static int ActualLength(ReadOnlySpan value) + { + // Since we're reusing memory here, the actual length + // of a given value may be less then the array's length + + int length = value.Length; + + while (length > 0 && value[length - 1] == 0) + --length; + return length; + } + + private static int Reduce(Span bits, ReadOnlySpan modulus) + { + // Executes a modulo operation using the divide operation. + + if (bits.Length >= modulus.Length) + { + Divide(bits, modulus, default); + + return ActualLength(bits.Slice(0, modulus.Length)); + } + return bits.Length; + } + } +} \ No newline at end of file diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs index 5ce7919e830bf..2d7395e2e83dd 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs @@ -410,11 +410,11 @@ private static bool HexNumberToBigInteger(ref BigNumberBuffer number, out BigInt bool isNegative = HexConverter.FromChar(number.digits[0]) >= 8; uint partialValue = (isNegative && partialDigitCount > 0) ? 0xFFFFFFFFu : 0; - int[]? arrayFromPool = null; + uint[]? arrayFromPool = null; - Span bitsBuffer = (blockCount <= BigInteger.StackallocUInt32Limit) - ? stackalloc uint[blockCount] - : MemoryMarshal.Cast((arrayFromPool = ArrayPool.Shared.Rent(blockCount)).AsSpan(0, blockCount)); + Span bitsBuffer = ((uint)blockCount <= BigIntegerCalculator.StackAllocThreshold + ? stackalloc uint[BigIntegerCalculator.StackAllocThreshold] + : arrayFromPool = ArrayPool.Shared.Rent(blockCount)).Slice(0, blockCount); int bitsBufferPos = blockCount - 1; @@ -489,14 +489,14 @@ private static bool HexNumberToBigInteger(ref BigNumberBuffer number, out BigInt { if (arrayFromPool != null) { - ArrayPool.Shared.Return(arrayFromPool); + ArrayPool.Shared.Return(arrayFromPool); } } } private static bool NumberToBigInteger(ref BigNumberBuffer number, out BigInteger result) { - Span stackBuffer = stackalloc uint[BigInteger.StackallocUInt32Limit]; + Span stackBuffer = stackalloc uint[BigIntegerCalculator.StackAllocThreshold]; Span currentBuffer = stackBuffer; int currentBufferSize = 0; int[]? arrayFromPool = null; diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs index 9325be0d806c2..d2f207229e313 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Globalization; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; @@ -851,4 +850,4 @@ public static explicit operator Complex(decimal value) return new Complex((double)value, 0.0); } } -} +} \ No newline at end of file diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/NumericsHelpers.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/NumericsHelpers.cs index e89bc4acd13e8..ff9d263edcb51 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/NumericsHelpers.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/NumericsHelpers.cs @@ -59,7 +59,7 @@ public static double GetDoubleFromParts(int sign, int exp, ulong man) else { // Normalize so that 0x0010 0000 0000 0000 is the highest bit set. - int cbitShift = CbitHighZero(man) - 11; + int cbitShift = BitOperations.LeadingZeroCount(man) - 11; if (cbitShift < 0) man >>= -cbitShift; else @@ -108,11 +108,12 @@ public static double GetDoubleFromParts(int sign, int exp, ulong man) // a mutation and needs to be used with care for immutable types. public static void DangerousMakeTwosComplement(Span d) { - if (d != null && d.Length > 0) + if (d.Length > 0) { d[0] = unchecked(~d[0] + 1); int i = 1; + // first do complement and +1 as long as carry is needed for (; d[i - 1] == 0 && i < d.Length; i++) { @@ -139,53 +140,5 @@ public static uint Abs(int a) return ((uint)a ^ mask) - mask; } } - - public static uint CombineHash(uint u1, uint u2) - { - return ((u1 << 7) | (u1 >> 25)) ^ u2; - } - - public static int CombineHash(int n1, int n2) - { - return unchecked((int)CombineHash((uint)n1, (uint)n2)); - } - - public static int CbitHighZero(uint u) - { - if (u == 0) - return 32; - - int cbit = 0; - if ((u & 0xFFFF0000) == 0) - { - cbit += 16; - u <<= 16; - } - if ((u & 0xFF000000) == 0) - { - cbit += 8; - u <<= 8; - } - if ((u & 0xF0000000) == 0) - { - cbit += 4; - u <<= 4; - } - if ((u & 0xC0000000) == 0) - { - cbit += 2; - u <<= 2; - } - if ((u & 0x80000000) == 0) - cbit += 1; - return cbit; - } - - public static int CbitHighZero(ulong uu) - { - if ((uu & 0xFFFFFFFF00000000) == 0) - return 32 + CbitHighZero((uint)uu); - return CbitHighZero((uint)(uu >> 32)); - } } } diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/BigIntTools.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/BigIntTools.cs index 519b1d9e5b397..33d6614483717 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/BigIntTools.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/BigIntTools.cs @@ -59,6 +59,9 @@ public static void RunWithFakeThreshold(string name, int value, Action action) return; // Internal frame types are not reflectable on AoT platforms. Skip the test. FieldInfo field = internalCalculator.GetDeclaredField(name); + if (field is null || field.IsLiteral) + return; // in Release config the field may be const + int lastValue = (int)field.GetValue(null); field.SetValue(null, value); try diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/multiply.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/multiply.cs index 72be36c581923..a2646d5bd6cb8 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/multiply.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/multiply.cs @@ -44,7 +44,7 @@ public static void RunMultiply_TwoLargeBigIntegers_Threshold() // Again, with lower threshold BigIntTools.Utils.RunWithFakeThreshold("SquareThreshold", 8, () => BigIntTools.Utils.RunWithFakeThreshold("MultiplyThreshold", 8, () => - BigIntTools.Utils.RunWithFakeThreshold("AllocationThreshold", 8, RunMultiply_TwoLargeBigIntegers) + BigIntTools.Utils.RunWithFakeThreshold("StackAllocThreshold", 8, RunMultiply_TwoLargeBigIntegers) ) ); } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index ecd536be23436..12c702153c292 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -754,130 +754,130 @@ public static void SetByte(System.Array array, int index, byte value) { } public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Byte result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IAdditionOperators.operator +(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBinaryInteger.LeadingZeroCount(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBinaryInteger.PopCount(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBinaryInteger.RotateLeft(byte value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBinaryInteger.RotateRight(byte value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBinaryInteger.TrailingZeroCount(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBinaryNumber.Log2(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBitwiseOperators.operator &(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBitwiseOperators.operator |(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBitwiseOperators.operator ^(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBitwiseOperators.operator ~(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IDecrementOperators.operator --(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IDivisionOperators.operator /(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IIncrementOperators.operator ++(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IModulusOperators.operator %(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IMultiplyOperators.operator *(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Abs(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Clamp(byte value, byte min, byte max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (byte Quotient, byte Remainder) INumber.DivRem(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Max(byte x, byte y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Min(byte x, byte y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Sign(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out byte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out byte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out byte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out byte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IShiftOperators.operator <<(byte value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IShiftOperators.operator >>(byte value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out byte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte ISubtractionOperators.operator -(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IUnaryNegationOperators.operator -(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IUnaryPlusOperators.operator +(byte value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -974,130 +974,130 @@ public CannotUnloadAppDomainException(string? message, System.Exception? innerEx string System.IFormattable.ToString(string? format, IFormatProvider? formatProvider) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IAdditionOperators.operator +(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBinaryInteger.LeadingZeroCount(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBinaryInteger.PopCount(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBinaryInteger.RotateLeft(char value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBinaryInteger.RotateRight(char value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBinaryInteger.TrailingZeroCount(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBinaryNumber.Log2(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBitwiseOperators.operator &(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBitwiseOperators.operator |(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBitwiseOperators.operator ^(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBitwiseOperators.operator ~(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IDecrementOperators.operator --(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IDivisionOperators.operator /(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IIncrementOperators.operator ++(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IModulusOperators.operator %(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IMultiplyOperators.operator *(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Abs(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Clamp(char value, char min, char max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (char Quotient, char Remainder) INumber.DivRem(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Max(char x, char y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Min(char x, char y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Sign(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out char result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out char result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out char result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out char result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IShiftOperators.operator <<(char value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures, System.Runtime.CompilerServices.SpecialNameAttribute] + [System.Runtime.Versioning.RequiresPreviewFeatures("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview"), System.Runtime.CompilerServices.SpecialNameAttribute] static char IShiftOperators.operator >>(char value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out char result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char ISubtractionOperators.operator -(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IUnaryNegationOperators.operator -(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IUnaryPlusOperators.operator +(char value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -1656,33 +1656,33 @@ public static partial class Convert public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider? provider = null) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateOnly IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateOnly IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.DateOnly left, System.DateOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.DateOnly left, System.DateOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.DateOnly left, System.DateOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.DateOnly left, System.DateOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.DateOnly left, System.DateOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.DateOnly left, System.DateOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateOnly IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.DateOnly result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateOnly ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.DateOnly result) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -1820,44 +1820,44 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateTime result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTime IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTime IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTime IAdditionOperators.operator +(System.DateTime left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.DateTime left, System.DateTime right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.DateTime left, System.DateTime right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.DateTime left, System.DateTime right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.DateTime left, System.DateTime right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.DateTime left, System.DateTime right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.DateTime left, System.DateTime right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTime IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.DateTime result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTime ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.DateTime result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTime ISubtractionOperators.operator -(System.DateTime left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan ISubtractionOperators.operator -(System.DateTime left, System.DateTime right) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -1972,44 +1972,44 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? input, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTimeOffset IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTimeOffset IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTimeOffset IAdditionOperators.operator +(System.DateTimeOffset left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTimeOffset IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.DateTimeOffset result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTimeOffset ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.DateTimeOffset result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTimeOffset ISubtractionOperators.operator -(System.DateTimeOffset left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan ISubtractionOperators.operator -(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -2195,103 +2195,103 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Decimal result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IAdditionOperators.operator +(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IDecrementOperators.operator --(decimal value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IDivisionOperators.operator /(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IIncrementOperators.operator ++(decimal value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IModulusOperators.operator %(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IMultiplyOperators.operator *(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Abs(decimal value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Clamp(decimal value, decimal min, decimal max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (decimal Quotient, decimal Remainder) INumber.DivRem(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Max(decimal x, decimal y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Min(decimal x, decimal y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Sign(decimal value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out decimal result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out decimal result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out decimal result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out decimal result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out decimal result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal ISubtractionOperators.operator -(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IUnaryNegationOperators.operator -(decimal value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IUnaryPlusOperators.operator +(decimal value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -2407,226 +2407,226 @@ public DivideByZeroException(string? message, System.Exception? innerException) public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Double result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.E { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Epsilon { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.NaN { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.NegativeInfinity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.NegativeZero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Pi { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.PositiveInfinity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Tau { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IAdditionOperators.operator +(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IBinaryNumber.Log2(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IBitwiseOperators.operator &(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IBitwiseOperators.operator |(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IBitwiseOperators.operator ^(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IBitwiseOperators.operator ~(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IDecrementOperators.operator --(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IDivisionOperators.operator /(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Acos(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Acosh(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Asin(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Asinh(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Atan(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Atan2(double y, double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Atanh(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.BitIncrement(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.BitDecrement(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Cbrt(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Ceiling(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.CopySign(double x, double y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Cos(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Cosh(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Exp(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Floor(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.FusedMultiplyAdd(double left, double right, double addend) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.IEEERemainder(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static TInteger IFloatingPoint.ILogB(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Log(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Log(double x, double newBase) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Log2(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Log10(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.MaxMagnitude(double x, double y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.MinMagnitude(double x, double y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Pow(double x, double y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Round(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Round(double x, TInteger digits) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Round(double x, System.MidpointRounding mode) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Round(double x, TInteger digits, System.MidpointRounding mode) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.ScaleB(double x, TInteger n) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Sin(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Sinh(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Sqrt(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Tan(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Tanh(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Truncate(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsFinite(double d) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsInfinity(double d) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsNaN(double d) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsNegative(double d) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsNegativeInfinity(double d) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsNormal(double d) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsPositiveInfinity(double d) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsSubnormal(double d) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IIncrementOperators.operator ++(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IModulusOperators.operator %(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IMultiplyOperators.operator *(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Abs(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Clamp(double value, double min, double max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (double Quotient, double Remainder) INumber.DivRem(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Max(double x, double y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Min(double x, double y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Sign(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out double result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out double result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out double result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out double result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out double result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double ISubtractionOperators.operator -(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IUnaryNegationOperators.operator -(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IUnaryPlusOperators.operator +(double value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -3062,28 +3062,28 @@ public GopherStyleUriParser() { } bool System.ISpanFormattable.TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format, System.IFormatProvider? provider) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.Guid left, System.Guid right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.Guid left, System.Guid right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.Guid left, System.Guid right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.Guid left, System.Guid right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.Guid left, System.Guid right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.Guid left, System.Guid right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Guid IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.Guid result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Guid ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.Guid result) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -3141,226 +3141,226 @@ public GopherStyleUriParser() { } public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.Half result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.E { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Epsilon { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.NaN { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.NegativeInfinity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.NegativeZero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Pi { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.PositiveInfinity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Tau { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IAdditionOperators.operator +(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IBinaryNumber.Log2(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IBitwiseOperators.operator &(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IBitwiseOperators.operator |(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IBitwiseOperators.operator ^(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IBitwiseOperators.operator ~(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IDecrementOperators.operator --(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IDivisionOperators.operator /(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Acos(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Acosh(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Asin(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Asinh(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Atan(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Atan2(System.Half y, System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Atanh(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.BitIncrement(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.BitDecrement(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Cbrt(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Ceiling(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.CopySign(System.Half x, System.Half y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Cos(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Cosh(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Exp(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Floor(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.FusedMultiplyAdd(System.Half left, System.Half right, System.Half addend) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.IEEERemainder(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static TInteger IFloatingPoint.ILogB(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Log(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Log(System.Half x, System.Half newBase) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Log2(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Log10(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.MaxMagnitude(System.Half x, System.Half y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.MinMagnitude(System.Half x, System.Half y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Pow(System.Half x, System.Half y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Round(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Round(System.Half x, TInteger digits) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Round(System.Half x, System.MidpointRounding mode) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Round(System.Half x, TInteger digits, System.MidpointRounding mode) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.ScaleB(System.Half x, TInteger n) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Sin(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Sinh(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Sqrt(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Tan(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Tanh(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Truncate(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsFinite(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsInfinity(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsNaN(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsNegative(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsNegativeInfinity(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsNormal(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsPositiveInfinity(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsSubnormal(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IIncrementOperators.operator ++(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IModulusOperators.operator %(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IMultiplyOperators.operator *(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Abs(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Clamp(System.Half value, System.Half min, System.Half max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (System.Half Quotient, System.Half Remainder) INumber.DivRem(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Max(System.Half x, System.Half y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Min(System.Half x, System.Half y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Sign(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out System.Half result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Half result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Half result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.Half result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.Half result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half ISubtractionOperators.operator -(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IUnaryNegationOperators.operator -(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IUnaryPlusOperators.operator +(System.Half value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -3391,24 +3391,24 @@ public partial class HttpStyleUriParser : System.UriParser public HttpStyleUriParser() { } } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IAdditionOperators where TSelf : System.IAdditionOperators { static abstract TResult operator +(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IAdditiveIdentity where TSelf : System.IAdditiveIdentity { static abstract TResult AdditiveIdentity { get; } } -[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] +[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IBinaryFloatingPoint : System.IBinaryNumber, System.IFloatingPoint where TSelf : IBinaryFloatingPoint { } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IBinaryInteger : System.IBinaryNumber, System.IShiftOperators where TSelf : IBinaryInteger { @@ -3418,14 +3418,14 @@ public partial interface IBinaryInteger : System.IBinaryNumber, Sy static abstract TSelf RotateRight(TSelf value, int rotateAmount); static abstract TSelf TrailingZeroCount(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IBinaryNumber : System.IBitwiseOperators, System.INumber where TSelf : IBinaryNumber { static abstract bool IsPow2(TSelf value); static abstract TSelf Log2(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IBitwiseOperators where TSelf : System.IBitwiseOperators { @@ -3434,7 +3434,7 @@ public partial interface IBitwiseOperators static abstract TResult operator ^(TSelf left, TOther right); static abstract TResult operator ~(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IComparisonOperators : System.IComparable, System.IComparable, System.IEqualityOperators where TSelf : IComparisonOperators { @@ -3443,26 +3443,26 @@ public partial interface IComparisonOperators : System.IComparabl static abstract bool operator >(TSelf left, TOther right); static abstract bool operator >=(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IDecrementOperators where TSelf : System.IDecrementOperators { static abstract TSelf operator --(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IDivisionOperators where TSelf : System.IDivisionOperators { static abstract TResult operator /(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IEqualityOperators : IEquatable where TSelf : System.IEqualityOperators { static abstract bool operator ==(TSelf left, TOther right); static abstract bool operator !=(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IFloatingPoint : System.ISignedNumber where TSelf : System.IFloatingPoint { @@ -3520,38 +3520,38 @@ public partial interface IFloatingPoint : System.ISignedNumber static abstract TSelf Tanh(TSelf x); static abstract TSelf Truncate(TSelf x); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IIncrementOperators where TSelf : System.IIncrementOperators { static abstract TSelf operator ++(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IMinMaxValue where TSelf : System.IMinMaxValue { static abstract TSelf MinValue { get; } static abstract TSelf MaxValue { get; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IModulusOperators where TSelf : System.IModulusOperators { static abstract TResult operator %(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IMultiplicativeIdentity where TSelf : System.IMultiplicativeIdentity { static abstract TResult MultiplicativeIdentity { get; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IMultiplyOperators where TSelf : System.IMultiplyOperators { static abstract TResult operator *(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface INumber : System.IAdditionOperators, System.IAdditiveIdentity, System.IComparable, System.IComparable, System.IComparisonOperators, System.IDecrementOperators, System.IDivisionOperators, System.IEquatable, System.IEqualityOperators, System.IFormattable, System.IIncrementOperators, System.IModulusOperators, System.IMultiplicativeIdentity, System.IMultiplyOperators, System.IParseable, System.ISpanFormattable, System.ISpanParseable, System.ISubtractionOperators, System.IUnaryNegationOperators, System.IUnaryPlusOperators where TSelf : System.INumber { @@ -3572,52 +3572,52 @@ public partial interface INumber : System.IAdditionOperators s, System.Globalization.NumberStyles style, IFormatProvider? provider, out TSelf result); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IParseable where TSelf : System.IParseable { static abstract TSelf Parse(string s, System.IFormatProvider? provider); static abstract bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out TSelf result); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IShiftOperators where TSelf : System.IShiftOperators { static abstract TResult operator <<(TSelf value, int shiftAmount); static abstract TResult operator >>(TSelf value, int shiftAmount); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface ISignedNumber : System.INumber, System.IUnaryNegationOperators where TSelf : System.ISignedNumber { static abstract TSelf NegativeOne { get; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface ISpanParseable : System.IParseable where TSelf : System.ISpanParseable { static abstract TSelf Parse(System.ReadOnlySpan s, System.IFormatProvider? provider); static abstract bool TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out TSelf result); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface ISubtractionOperators where TSelf : System.ISubtractionOperators { static abstract TResult operator -(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IUnaryNegationOperators where TSelf : System.IUnaryNegationOperators { static abstract TResult operator -(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IUnaryPlusOperators where TSelf : System.IUnaryPlusOperators { static abstract TResult operator +(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IUnsignedNumber : System.INumber where TSelf : IUnsignedNumber { @@ -3771,133 +3771,133 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.Int16 result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IAdditionOperators.operator +(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBinaryInteger.LeadingZeroCount(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBinaryInteger.PopCount(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBinaryInteger.RotateLeft(short value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBinaryInteger.RotateRight(short value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBinaryInteger.TrailingZeroCount(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBinaryNumber.Log2(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBitwiseOperators.operator &(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBitwiseOperators.operator |(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBitwiseOperators.operator ^(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBitwiseOperators.operator ~(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IDecrementOperators.operator --(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IDivisionOperators.operator /(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IIncrementOperators.operator ++(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IModulusOperators.operator %(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IMultiplyOperators.operator *(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Abs(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Clamp(short value, short min, short max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (short Quotient, short Remainder) INumber.DivRem(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Max(short x, short y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Min(short x, short y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Sign(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out short result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out short result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out short result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out short result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IShiftOperators.operator <<(short value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IShiftOperators.operator >>(short value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out short result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short ISubtractionOperators.operator -(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IUnaryNegationOperators.operator -(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IUnaryPlusOperators.operator +(short value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -3950,133 +3950,133 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.Int32 result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IAdditionOperators.operator +(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBinaryInteger.LeadingZeroCount(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBinaryInteger.PopCount(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBinaryInteger.RotateLeft(int value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBinaryInteger.RotateRight(int value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBinaryInteger.TrailingZeroCount(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBinaryNumber.Log2(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBitwiseOperators.operator &(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBitwiseOperators.operator |(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBitwiseOperators.operator ^(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBitwiseOperators.operator ~(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IDecrementOperators.operator --(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IDivisionOperators.operator /(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IIncrementOperators.operator ++(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IModulusOperators.operator %(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IMultiplyOperators.operator *(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Abs(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Clamp(int value, int min, int max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (int Quotient, int Remainder) INumber.DivRem(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Max(int x, int y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Min(int x, int y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Sign(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out int result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out int result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out int result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out int result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IShiftOperators.operator <<(int value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IShiftOperators.operator >>(int value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out int result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int ISubtractionOperators.operator -(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IUnaryNegationOperators.operator -(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IUnaryPlusOperators.operator +(int value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -4129,133 +4129,133 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.Int64 result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IAdditionOperators.operator +(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBinaryInteger.LeadingZeroCount(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBinaryInteger.PopCount(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBinaryInteger.RotateLeft(long value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBinaryInteger.RotateRight(long value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBinaryInteger.TrailingZeroCount(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBinaryNumber.Log2(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBitwiseOperators.operator &(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBitwiseOperators.operator |(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBitwiseOperators.operator ^(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBitwiseOperators.operator ~(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IDecrementOperators.operator --(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IDivisionOperators.operator /(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IIncrementOperators.operator ++(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IModulusOperators.operator %(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IMultiplyOperators.operator *(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Abs(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Clamp(long value, long min, long max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (long Quotient, long Remainder) INumber.DivRem(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Max(long x, long y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Min(long x, long y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Sign(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out long result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out long result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out long result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out long result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IShiftOperators.operator <<(long value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IShiftOperators.operator >>(long value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out long result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long ISubtractionOperators.operator -(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IUnaryNegationOperators.operator -(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IUnaryPlusOperators.operator +(long value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -4317,133 +4317,133 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.IntPtr result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IAdditionOperators.operator +(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBinaryInteger.LeadingZeroCount(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBinaryInteger.PopCount(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBinaryInteger.RotateLeft(nint value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBinaryInteger.RotateRight(nint value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBinaryInteger.TrailingZeroCount(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBinaryNumber.Log2(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBitwiseOperators.operator &(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBitwiseOperators.operator |(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBitwiseOperators.operator ^(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBitwiseOperators.operator ~(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IDecrementOperators.operator --(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IDivisionOperators.operator /(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IIncrementOperators.operator ++(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IModulusOperators.operator %(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IMultiplyOperators.operator *(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Abs(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Clamp(nint value, nint min, nint max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (nint Quotient, nint Remainder) INumber.DivRem(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Max(nint x, nint y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Min(nint x, nint y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Sign(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out nint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out nint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out nint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out nint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IShiftOperators.operator <<(nint value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IShiftOperators.operator >>(nint value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out nint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint ISubtractionOperators.operator -(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IUnaryNegationOperators.operator -(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IUnaryPlusOperators.operator +(nint value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -5282,133 +5282,133 @@ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, S public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.SByte result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IAdditionOperators.operator +(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBinaryInteger.LeadingZeroCount(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBinaryInteger.PopCount(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBinaryInteger.RotateLeft(sbyte value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBinaryInteger.RotateRight(sbyte value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBinaryInteger.TrailingZeroCount(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBinaryNumber.Log2(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBitwiseOperators.operator &(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBitwiseOperators.operator |(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBitwiseOperators.operator ^(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBitwiseOperators.operator ~(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IDecrementOperators.operator --(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IDivisionOperators.operator /(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IIncrementOperators.operator ++(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IModulusOperators.operator %(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IMultiplyOperators.operator *(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Abs(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Clamp(sbyte value, sbyte min, sbyte max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (sbyte Quotient, sbyte Remainder) INumber.DivRem(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Max(sbyte x, sbyte y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Min(sbyte x, sbyte y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Sign(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out sbyte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out sbyte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out sbyte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out sbyte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IShiftOperators.operator <<(sbyte value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IShiftOperators.operator >>(sbyte value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out sbyte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte ISubtractionOperators.operator -(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IUnaryNegationOperators.operator -(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IUnaryPlusOperators.operator +(sbyte value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -5483,226 +5483,226 @@ public SerializableAttribute() { } public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.Single result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.E { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Epsilon { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.NaN { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.NegativeInfinity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.NegativeZero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Pi { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.PositiveInfinity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Tau { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IAdditionOperators.operator +(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IBinaryNumber.Log2(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IBitwiseOperators.operator &(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IBitwiseOperators.operator |(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IBitwiseOperators.operator ^(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IBitwiseOperators.operator ~(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IDecrementOperators.operator --(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IDivisionOperators.operator /(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Acos(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Acosh(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Asin(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Asinh(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Atan(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Atan2(float y, float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Atanh(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.BitIncrement(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.BitDecrement(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Cbrt(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Ceiling(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.CopySign(float x, float y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Cos(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Cosh(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Exp(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Floor(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.FusedMultiplyAdd(float left, float right, float addend) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.IEEERemainder(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static TInteger IFloatingPoint.ILogB(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Log(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Log(float x, float newBase) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Log2(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Log10(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.MaxMagnitude(float x, float y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.MinMagnitude(float x, float y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Pow(float x, float y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Round(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Round(float x, TInteger digits) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Round(float x, System.MidpointRounding mode) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Round(float x, TInteger digits, System.MidpointRounding mode) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.ScaleB(float x, TInteger n) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Sin(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Sinh(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Sqrt(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Tan(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Tanh(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Truncate(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsFinite(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsInfinity(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsNaN(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsNegative(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsNegativeInfinity(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsNormal(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsPositiveInfinity(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IFloatingPoint.IsSubnormal(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IIncrementOperators.operator ++(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IModulusOperators.operator %(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IMultiplyOperators.operator *(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Abs(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Clamp(float value, float min, float max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (float Quotient, float Remainder) INumber.DivRem(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Max(float x, float y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Min(float x, float y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Sign(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out float result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out float result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out float result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out float result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out float result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float ISubtractionOperators.operator -(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IUnaryNegationOperators.operator -(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IUnaryPlusOperators.operator +(float value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -6087,36 +6087,36 @@ public ThreadStaticAttribute() { } public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider? provider = null) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.TimeOnly left, System.TimeOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.TimeOnly left, System.TimeOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.TimeOnly left, System.TimeOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.TimeOnly left, System.TimeOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.TimeOnly left, System.TimeOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.TimeOnly left, System.TimeOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeOnly IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.TimeOnly result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeOnly ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.TimeOnly result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan ISubtractionOperators.operator -(System.TimeOnly left, System.TimeOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeOnly IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeOnly IMinMaxValue.MaxValue { get { throw null; } } #endif // FEATURE_GENERIC_MATH } @@ -6230,59 +6230,59 @@ public TimeoutException(string? message, System.Exception? innerException) { } public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? input, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? formatProvider, out System.TimeSpan result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IAdditionOperators.operator +(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IDivisionOperators.operator /(System.TimeSpan left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IDivisionOperators.operator /(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IMultiplyOperators.operator *(System.TimeSpan left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.TimeSpan result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.TimeSpan result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan ISubtractionOperators.operator -(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IUnaryNegationOperators.operator -(System.TimeSpan value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IUnaryPlusOperators.operator +(System.TimeSpan value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -7017,130 +7017,130 @@ public TypeUnloadedException(string? message, System.Exception? innerException) public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.UInt16 result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IAdditionOperators.operator +(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBinaryInteger.LeadingZeroCount(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBinaryInteger.PopCount(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBinaryInteger.RotateLeft(ushort value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBinaryInteger.RotateRight(ushort value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBinaryInteger.TrailingZeroCount(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBinaryNumber.Log2(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBitwiseOperators.operator &(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBitwiseOperators.operator |(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBitwiseOperators.operator ^(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBitwiseOperators.operator ~(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IDecrementOperators.operator --(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IDivisionOperators.operator /(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IIncrementOperators.operator ++(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IModulusOperators.operator %(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IMultiplyOperators.operator *(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Abs(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Clamp(ushort value, ushort min, ushort max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (ushort Quotient, ushort Remainder) INumber.DivRem(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Max(ushort x, ushort y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Min(ushort x, ushort y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Sign(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out ushort result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out ushort result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out ushort result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out ushort result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IShiftOperators.operator <<(ushort value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IShiftOperators.operator >>(ushort value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out ushort result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort ISubtractionOperators.operator -(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IUnaryNegationOperators.operator -(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IUnaryPlusOperators.operator +(ushort value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -7194,130 +7194,130 @@ public TypeUnloadedException(string? message, System.Exception? innerException) public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.UInt32 result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IAdditionOperators.operator +(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBinaryInteger.LeadingZeroCount(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBinaryInteger.PopCount(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBinaryInteger.RotateLeft(uint value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBinaryInteger.RotateRight(uint value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBinaryInteger.TrailingZeroCount(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBinaryNumber.Log2(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBitwiseOperators.operator &(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBitwiseOperators.operator |(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBitwiseOperators.operator ^(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBitwiseOperators.operator ~(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IDecrementOperators.operator --(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IDivisionOperators.operator /(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IIncrementOperators.operator ++(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IModulusOperators.operator %(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IMultiplyOperators.operator *(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Abs(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Clamp(uint value, uint min, uint max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (uint Quotient, uint Remainder) INumber.DivRem(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Max(uint x, uint y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Min(uint x, uint y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Sign(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out uint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out uint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out uint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out uint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IShiftOperators.operator <<(uint value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IShiftOperators.operator >>(uint value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out uint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint ISubtractionOperators.operator -(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IUnaryNegationOperators.operator -(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IUnaryPlusOperators.operator +(uint value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -7371,130 +7371,130 @@ public TypeUnloadedException(string? message, System.Exception? innerException) public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.UInt64 result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IAdditionOperators.operator +(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBinaryInteger.LeadingZeroCount(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBinaryInteger.PopCount(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBinaryInteger.RotateLeft(ulong value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBinaryInteger.RotateRight(ulong value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBinaryInteger.TrailingZeroCount(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBinaryNumber.Log2(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBitwiseOperators.operator &(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBitwiseOperators.operator |(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBitwiseOperators.operator ^(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBitwiseOperators.operator ~(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IDecrementOperators.operator --(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IDivisionOperators.operator /(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IIncrementOperators.operator ++(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IModulusOperators.operator %(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IMultiplyOperators.operator *(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Abs(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Clamp(ulong value, ulong min, ulong max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (ulong Quotient, ulong Remainder) INumber.DivRem(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Max(ulong x, ulong y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Min(ulong x, ulong y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Sign(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out ulong result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out ulong result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out ulong result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out ulong result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IShiftOperators.operator <<(ulong value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IShiftOperators.operator >>(ulong value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out ulong result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong ISubtractionOperators.operator -(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IUnaryNegationOperators.operator -(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IUnaryPlusOperators.operator +(ulong value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -7553,129 +7553,129 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.UIntPtr result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IAdditionOperators.operator +(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBinaryInteger.LeadingZeroCount(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBinaryInteger.PopCount(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBinaryInteger.RotateLeft(nuint value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBinaryInteger.RotateRight(nuint value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBinaryInteger.TrailingZeroCount(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBinaryNumber.Log2(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBitwiseOperators.operator &(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBitwiseOperators.operator |(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBitwiseOperators.operator ^(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBitwiseOperators.operator ~(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IDecrementOperators.operator --(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IDivisionOperators.operator /(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IIncrementOperators.operator ++(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IModulusOperators.operator %(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IMultiplyOperators.operator *(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Abs(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Clamp(nuint value, nuint min, nuint max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (nuint Quotient, nuint Remainder) INumber.DivRem(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Max(nuint x, nuint y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] - static nuint INumber.Min(nuint x, nuint y) { throw null; }[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static nuint INumber.Min(nuint x, nuint y) { throw null; }[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Sign(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out nuint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out nuint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out nuint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out nuint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IShiftOperators.operator <<(nuint value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IShiftOperators.operator >>(nuint value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out nuint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint ISubtractionOperators.operator -(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IUnaryNegationOperators.operator -(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IUnaryPlusOperators.operator +(nuint value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -13097,7 +13097,7 @@ public static partial class RuntimeFeature public const string DefaultImplementationsOfInterfaces = "DefaultImplementationsOfInterfaces"; public const string UnmanagedSignatureCallingConvention = "UnmanagedSignatureCallingConvention"; public const string PortablePdb = "PortablePdb"; - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public const string VirtualStaticsInInterfaces = "VirtualStaticsInInterfaces"; public static bool IsDynamicCodeCompiled { get { throw null; } } public static bool IsDynamicCodeSupported { get { throw null; } } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/AesImplementation.Unix.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/AesImplementation.Unix.cs index f20436697be6a..649e22dea891e 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/AesImplementation.Unix.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/AesImplementation.Unix.cs @@ -21,7 +21,7 @@ private static UniversalCryptoTransform CreateTransformCore( // The algorithm pointer is a static pointer, so not having any cleanup code is correct. IntPtr algorithm = GetAlgorithm(key.Length * 8, feedback * 8, cipherMode); - BasicSymmetricCipher cipher = new OpenSslCipher(algorithm, cipherMode, blockSize, paddingSize, key, 0, iv, encrypting); + BasicSymmetricCipher cipher = new OpenSslCipher(algorithm, cipherMode, blockSize, paddingSize, key, iv, encrypting); return UniversalCryptoTransform.Create(paddingMode, cipher, encrypting); } @@ -35,7 +35,7 @@ private static ILiteSymmetricCipher CreateLiteCipher( bool encrypting) { IntPtr algorithm = GetAlgorithm(key.Length * 8, feedback * 8, cipherMode); - return new OpenSslCipherLite(algorithm, cipherMode, blockSize, paddingSize, key, 0, iv, encrypting); + return new OpenSslCipherLite(algorithm, cipherMode, blockSize, paddingSize, key, iv, encrypting); } private static IntPtr GetAlgorithm(int keySize, int feedback, CipherMode cipherMode) => diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/DesImplementation.Android.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/DesImplementation.Android.cs index f2b460be7be68..2e33599225238 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/DesImplementation.Android.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/DesImplementation.Android.cs @@ -22,7 +22,7 @@ private static UniversalCryptoTransform CreateTransformCore( // The algorithm pointer is a static pointer, so not having any cleanup code is correct. IntPtr algorithm = GetAlgorithm(cipherMode, feedbackSize); - BasicSymmetricCipher cipher = new OpenSslCipher(algorithm, cipherMode, blockSize, paddingSize, key, 0, iv, encrypting); + BasicSymmetricCipher cipher = new OpenSslCipher(algorithm, cipherMode, blockSize, paddingSize, key, iv, encrypting); return UniversalCryptoTransform.Create(paddingMode, cipher, encrypting); } @@ -38,7 +38,7 @@ private static ILiteSymmetricCipher CreateLiteCipher( { // The algorithm pointer is a static pointer, so not having any cleanup code is correct. IntPtr algorithm = GetAlgorithm(cipherMode, feedbackSize); - return new OpenSslCipherLite(algorithm, cipherMode, blockSize, paddingSize, key, effectiveKeyLength: 0, iv, encrypting); + return new OpenSslCipherLite(algorithm, cipherMode, blockSize, paddingSize, key, iv, encrypting); } private static IntPtr GetAlgorithm(CipherMode cipherMode, int feedbackSize) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/DesImplementation.Unix.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/DesImplementation.Unix.cs index f1d795d75b4ef..b22a1da6cf18a 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/DesImplementation.Unix.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/DesImplementation.Unix.cs @@ -24,7 +24,7 @@ private static UniversalCryptoTransform CreateTransformCore( Interop.Crypto.EnsureLegacyAlgorithmsRegistered(); - BasicSymmetricCipher cipher = new OpenSslCipher(algorithm, cipherMode, blockSize, paddingSize, key, 0, iv, encrypting); + BasicSymmetricCipher cipher = new OpenSslCipher(algorithm, cipherMode, blockSize, paddingSize, key, iv, encrypting); return UniversalCryptoTransform.Create(paddingMode, cipher, encrypting); } @@ -42,7 +42,7 @@ private static ILiteSymmetricCipher CreateLiteCipher( IntPtr algorithm = GetAlgorithm(cipherMode, feedbackSize); Interop.Crypto.EnsureLegacyAlgorithmsRegistered(); - return new OpenSslCipherLite(algorithm, cipherMode, blockSize, paddingSize, key, effectiveKeyLength: 0, iv, encrypting); + return new OpenSslCipherLite(algorithm, cipherMode, blockSize, paddingSize, key, iv, encrypting); } private static IntPtr GetAlgorithm(CipherMode cipherMode, int feedbackSize) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipher.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipher.cs index c5231afbc7be2..e02f2e670dde4 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipher.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipher.cs @@ -11,7 +11,7 @@ internal sealed class OpenSslCipher : BasicSymmetricCipher { private readonly OpenSslCipherLite _cipherLite; - public OpenSslCipher(IntPtr algorithm, CipherMode cipherMode, int blockSizeInBytes, int paddingSizeInBytes, byte[] key, int effectiveKeyLength, byte[]? iv, bool encrypting) + public OpenSslCipher(IntPtr algorithm, CipherMode cipherMode, int blockSizeInBytes, int paddingSizeInBytes, byte[] key, byte[]? iv, bool encrypting) : base(cipherMode.GetCipherIv(iv), blockSizeInBytes, paddingSizeInBytes) { _cipherLite = new OpenSslCipherLite( @@ -20,7 +20,6 @@ public OpenSslCipher(IntPtr algorithm, CipherMode cipherMode, int blockSizeInByt blockSizeInBytes, paddingSizeInBytes, key, - effectiveKeyLength, iv, encrypting); } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipherLite.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipherLite.cs index 7b06900f5961a..82b4c38d3bb75 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipherLite.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipherLite.cs @@ -28,7 +28,6 @@ public OpenSslCipherLite( int blockSizeInBytes, int paddingSizeInBytes, ReadOnlySpan key, - int effectiveKeyLength, ReadOnlySpan iv, bool encrypting) { @@ -40,7 +39,6 @@ public OpenSslCipherLite( algorithm, ref MemoryMarshal.GetReference(key), key.Length * 8, - effectiveKeyLength, ref MemoryMarshal.GetReference(iv), encrypting ? 1 : 0); diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Android.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Android.cs index 2f45df779c2a8..c1fb5a95f453a 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Android.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Android.cs @@ -13,7 +13,6 @@ private static UniversalCryptoTransform CreateTransformCore( CipherMode cipherMode, PaddingMode paddingMode, byte[] key, - int effectiveKeyLength, byte[]? iv, int blockSize, int feedbackSizeInBytes, @@ -27,7 +26,6 @@ private static ILiteSymmetricCipher CreateLiteCipher( CipherMode cipherMode, PaddingMode paddingMode, ReadOnlySpan key, - int effectiveKeyLength, ReadOnlySpan iv, int blockSize, int feedbackSizeInBytes, diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.OSX.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.OSX.cs index a9f040285be46..e8076d8325cc1 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.OSX.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.OSX.cs @@ -12,7 +12,6 @@ private static UniversalCryptoTransform CreateTransformCore( CipherMode cipherMode, PaddingMode paddingMode, byte[] key, - int effectiveKeyLength, byte[]? iv, int blockSize, int feedbackSizeInBytes, @@ -36,7 +35,6 @@ private static ILiteSymmetricCipher CreateLiteCipher( CipherMode cipherMode, PaddingMode paddingMode, ReadOnlySpan key, - int effectiveKeyLength, ReadOnlySpan iv, int blockSize, int feedbackSizeInBytes, diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Unix.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Unix.cs index ea59ac37ceb17..b479d91533001 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Unix.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Unix.cs @@ -13,7 +13,6 @@ private static UniversalCryptoTransform CreateTransformCore( CipherMode cipherMode, PaddingMode paddingMode, byte[] key, - int effectiveKeyLength, byte[]? iv, int blockSize, int feedbackSize, @@ -25,7 +24,7 @@ private static UniversalCryptoTransform CreateTransformCore( Interop.Crypto.EnsureLegacyAlgorithmsRegistered(); - BasicSymmetricCipher cipher = new OpenSslCipher(algorithm, cipherMode, blockSize, paddingSize, key, effectiveKeyLength, iv, encrypting); + BasicSymmetricCipher cipher = new OpenSslCipher(algorithm, cipherMode, blockSize, paddingSize, key, iv, encrypting); return UniversalCryptoTransform.Create(paddingMode, cipher, encrypting); } @@ -33,7 +32,6 @@ private static ILiteSymmetricCipher CreateLiteCipher( CipherMode cipherMode, PaddingMode paddingMode, ReadOnlySpan key, - int effectiveKeyLength, ReadOnlySpan iv, int blockSize, int feedbackSizeInBytes, @@ -44,7 +42,7 @@ private static ILiteSymmetricCipher CreateLiteCipher( IntPtr algorithm = GetAlgorithm(cipherMode); Interop.Crypto.EnsureLegacyAlgorithmsRegistered(); - return new OpenSslCipherLite(algorithm, cipherMode, blockSize, paddingSize, key, effectiveKeyLength, iv, encrypting); + return new OpenSslCipherLite(algorithm, cipherMode, blockSize, paddingSize, key, iv, encrypting); } private static IntPtr GetAlgorithm(CipherMode cipherMode) => cipherMode switch diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Windows.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Windows.cs index bb33fd7da352b..20d0e04e88ac1 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Windows.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.Windows.cs @@ -14,14 +14,13 @@ private static UniversalCryptoTransform CreateTransformCore( CipherMode cipherMode, PaddingMode paddingMode, byte[] key, - int effectiveKeyLength, byte[]? iv, int blockSize, int feedbackSize, int paddingSize, bool encrypting) { - using (SafeAlgorithmHandle algorithm = RC2BCryptModes.GetHandle(cipherMode, effectiveKeyLength)) + using (SafeAlgorithmHandle algorithm = RC2BCryptModes.GetHandle(cipherMode, key.Length * 8)) { // The BasicSymmetricCipherBCrypt ctor will increase algorithm reference count and take ownership. BasicSymmetricCipher cipher = new BasicSymmetricCipherBCrypt(algorithm, cipherMode, blockSize, paddingSize, key, true, iv, encrypting); @@ -33,14 +32,13 @@ private static ILiteSymmetricCipher CreateLiteCipher( CipherMode cipherMode, PaddingMode paddingMode, ReadOnlySpan key, - int effectiveKeyLength, ReadOnlySpan iv, int blockSize, int feedbackSizeInBytes, int paddingSize, bool encrypting) { - using (SafeAlgorithmHandle algorithm = RC2BCryptModes.GetHandle(cipherMode, effectiveKeyLength)) + using (SafeAlgorithmHandle algorithm = RC2BCryptModes.GetHandle(cipherMode, key.Length * 8)) { // The BasicSymmetricCipherBCrypt ctor will increase algorithm reference count and take ownership. return new BasicSymmetricCipherLiteBCrypt( diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.cs index 6f2734fb22f5c..5353006e0989c 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/RC2Implementation.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics; using System.Security.Cryptography; namespace Internal.Cryptography @@ -76,8 +77,8 @@ private ICryptoTransform CreateTransform(byte[] rgbKey, byte[]? rgbIV, bool encr ValidateCFBFeedbackSize(FeedbackSize); } - int effectiveKeySize = EffectiveKeySizeValue == 0 ? keySize : EffectiveKeySize; - return CreateTransformCore(Mode, Padding, rgbKey, effectiveKeySize, rgbIV, BlockSize / BitsPerByte, FeedbackSize / BitsPerByte, GetPaddingSize(), encrypting); + Debug.Assert(EffectiveKeySize == KeySize); + return CreateTransformCore(Mode, Padding, rgbKey, rgbIV, BlockSize / BitsPerByte, FeedbackSize / BitsPerByte, GetPaddingSize(), encrypting); } protected override bool TryDecryptEcbCore( @@ -89,12 +90,11 @@ protected override bool TryDecryptEcbCore( if (!ValidKeySize(Key.Length, out int keySize)) throw new InvalidOperationException(SR.Cryptography_InvalidKeySize); - int effectiveKeySize = EffectiveKeySizeValue == 0 ? keySize : EffectiveKeySize; + Debug.Assert(EffectiveKeySize == KeySize); ILiteSymmetricCipher cipher = CreateLiteCipher( CipherMode.ECB, paddingMode, Key, - effectiveKeyLength: effectiveKeySize, iv: null, blockSize: BlockSize / BitsPerByte, 0, /*feedback size */ @@ -116,12 +116,11 @@ protected override bool TryEncryptEcbCore( if (!ValidKeySize(Key.Length, out int keySize)) throw new InvalidOperationException(SR.Cryptography_InvalidKeySize); - int effectiveKeySize = EffectiveKeySizeValue == 0 ? keySize : EffectiveKeySize; + Debug.Assert(EffectiveKeySize == KeySize); ILiteSymmetricCipher cipher = CreateLiteCipher( CipherMode.ECB, paddingMode, Key, - effectiveKeyLength: effectiveKeySize, iv: default, blockSize: BlockSize / BitsPerByte, 0, /*feedback size */ @@ -144,12 +143,11 @@ protected override bool TryEncryptCbcCore( if (!ValidKeySize(Key.Length, out int keySize)) throw new InvalidOperationException(SR.Cryptography_InvalidKeySize); - int effectiveKeySize = EffectiveKeySizeValue == 0 ? keySize : EffectiveKeySize; + Debug.Assert(EffectiveKeySize == KeySize); ILiteSymmetricCipher cipher = CreateLiteCipher( CipherMode.CBC, paddingMode, Key, - effectiveKeyLength: effectiveKeySize, iv, blockSize: BlockSize / BitsPerByte, 0, /*feedback size */ @@ -172,12 +170,11 @@ protected override bool TryDecryptCbcCore( if (!ValidKeySize(Key.Length, out int keySize)) throw new InvalidOperationException(SR.Cryptography_InvalidKeySize); - int effectiveKeySize = EffectiveKeySizeValue == 0 ? keySize : EffectiveKeySize; + Debug.Assert(EffectiveKeySize == KeySize); ILiteSymmetricCipher cipher = CreateLiteCipher( CipherMode.CBC, paddingMode, Key, - effectiveKeyLength: effectiveKeySize, iv, blockSize: BlockSize / BitsPerByte, 0, /*feedback size */ diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/TripleDesImplementation.Unix.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/TripleDesImplementation.Unix.cs index 6c877be845720..475ca6d31809c 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/TripleDesImplementation.Unix.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/TripleDesImplementation.Unix.cs @@ -21,7 +21,7 @@ private static UniversalCryptoTransform CreateTransformCore( // The algorithm pointer is a static pointer, so not having any cleanup code is correct. IntPtr algorithm = GetAlgorithm(cipherMode, feedbackSize); - BasicSymmetricCipher cipher = new OpenSslCipher(algorithm, cipherMode, blockSize, paddingSize, key, 0, iv, encrypting); + BasicSymmetricCipher cipher = new OpenSslCipher(algorithm, cipherMode, blockSize, paddingSize, key, iv, encrypting); return UniversalCryptoTransform.Create(paddingMode, cipher, encrypting); } @@ -44,7 +44,6 @@ private static ILiteSymmetricCipher CreateLiteCipher( blockSize, paddingSize, key, - effectiveKeyLength: 0, iv, encrypting); } diff --git a/src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/BasicSymmetricCipherCsp.cs b/src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/BasicSymmetricCipherCsp.cs index 892df2169b88c..5d97658ab644c 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/BasicSymmetricCipherCsp.cs +++ b/src/libraries/System.Security.Cryptography.Csp/src/Internal/Cryptography/BasicSymmetricCipherCsp.cs @@ -16,7 +16,7 @@ internal sealed class BasicSymmetricCipherCsp : BasicSymmetricCipher private SafeProvHandle _hProvider; private SafeKeyHandle _hKey; - public BasicSymmetricCipherCsp(int algId, CipherMode cipherMode, int blockSizeInBytes, byte[] key, int effectiveKeyLength, bool addNoSaltFlag, byte[]? iv, bool encrypting, int feedbackSize, int paddingSizeInBytes) + public BasicSymmetricCipherCsp(int algId, CipherMode cipherMode, int blockSizeInBytes, byte[] key, bool addNoSaltFlag, byte[]? iv, bool encrypting, int feedbackSize, int paddingSizeInBytes) : base(cipherMode.GetCipherIv(iv), blockSizeInBytes, paddingSizeInBytes) { _encrypting = encrypting; @@ -36,9 +36,9 @@ public BasicSymmetricCipherCsp(int algId, CipherMode cipherMode, int blockSizeIn SetKeyParameter(_hKey, CryptGetKeyParamQueryType.KP_IV, currentIv); } - if (effectiveKeyLength != 0) + if (algId == CapiHelper.CALG_RC2) { - SetKeyParameter(_hKey, CryptGetKeyParamQueryType.KP_EFFECTIVE_KEYLEN, effectiveKeyLength); + SetKeyParameter(_hKey, CryptGetKeyParamQueryType.KP_EFFECTIVE_KEYLEN, key.Length * 8); } } diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DESCryptoServiceProvider.Windows.cs b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DESCryptoServiceProvider.Windows.cs index 2bdd859a691e2..5829aa05f0355 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DESCryptoServiceProvider.Windows.cs +++ b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/DESCryptoServiceProvider.Windows.cs @@ -100,7 +100,6 @@ private ICryptoTransform CreateTransform(byte[] rgbKey, byte[]? rgbIV, bool encr Mode, BlockSize / BitsPerByte, rgbKey, - effectiveKeyLength: 0, addNoSaltFlag: false, rgbIV, encrypting, diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RC2CryptoServiceProvider.Windows.cs b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RC2CryptoServiceProvider.Windows.cs index 2255c53b1157c..b76119432af1b 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RC2CryptoServiceProvider.Windows.cs +++ b/src/libraries/System.Security.Cryptography.Csp/src/System/Security/Cryptography/RC2CryptoServiceProvider.Windows.cs @@ -4,6 +4,7 @@ using Internal.Cryptography; using Internal.NativeCrypto; using System.ComponentModel; +using System.Diagnostics; using System.Runtime.Versioning; namespace System.Security.Cryptography @@ -101,8 +102,8 @@ private ICryptoTransform CreateTransform(byte[] rgbKey, byte[]? rgbIV, bool encr throw new CryptographicException(SR.Cryptography_InvalidIVSize); } - int effectiveKeySize = EffectiveKeySizeValue == 0 ? (int)keySize : EffectiveKeySize; - BasicSymmetricCipher cipher = new BasicSymmetricCipherCsp(CapiHelper.CALG_RC2, Mode, BlockSize / BitsPerByte, rgbKey, effectiveKeySize, !UseSalt, rgbIV, encrypting, 0, 0); + Debug.Assert(EffectiveKeySize == KeySize); + BasicSymmetricCipher cipher = new BasicSymmetricCipherCsp(CapiHelper.CALG_RC2, Mode, BlockSize / BitsPerByte, rgbKey, !UseSalt, rgbIV, encrypting, 0, 0); return UniversalCryptoTransform.Create(Padding, cipher, encrypting); } } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.netcoreapp.cs b/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.netcoreapp.cs index d92fd4fbbd86b..0f53e8d734e9f 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.netcoreapp.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/ref/System.Security.Cryptography.Pkcs.netcoreapp.cs @@ -15,7 +15,9 @@ public CmsRecipient(System.Security.Cryptography.Pkcs.SubjectIdentifierType reci public sealed partial class CmsSigner { public CmsSigner(System.Security.Cryptography.Pkcs.SubjectIdentifierType signerIdentifierType, System.Security.Cryptography.X509Certificates.X509Certificate2? certificate, System.Security.Cryptography.AsymmetricAlgorithm? privateKey) { } + public CmsSigner(System.Security.Cryptography.Pkcs.SubjectIdentifierType signerIdentifierType, System.Security.Cryptography.X509Certificates.X509Certificate2? certificate, System.Security.Cryptography.RSA? privateKey, System.Security.Cryptography.RSASignaturePadding? signaturePadding) { } public System.Security.Cryptography.AsymmetricAlgorithm? PrivateKey { get { throw null; } set { } } + public System.Security.Cryptography.RSASignaturePadding? SignaturePadding { get { throw null; } set { } } } public sealed partial class ContentInfo { diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/CompatibilitySuppressions.xml b/src/libraries/System.Security.Cryptography.Pkcs/src/CompatibilitySuppressions.xml index daad0d31168c6..459caaa3038b2 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/CompatibilitySuppressions.xml @@ -1,5 +1,23 @@  + + CP0002 + M:System.Security.Cryptography.Pkcs.CmsSigner.get_SignaturePadding + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net462/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.CmsSigner.set_SignaturePadding(System.Security.Cryptography.RSASignaturePadding) + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net462/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.CmsSigner.#ctor(System.Security.Cryptography.Pkcs.SubjectIdentifierType,System.Security.Cryptography.X509Certificates.X509Certificate2,System.Security.Cryptography.RSA,System.Security.Cryptography.RSASignaturePadding) + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net462/System.Security.Cryptography.Pkcs.dll + CP0002 M:System.Security.Cryptography.Pkcs.CmsSigner.get_PrivateKey @@ -184,4 +202,4 @@ runtimes/win/lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll true - \ No newline at end of file + diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/MatchingRefApiCompatBaseline.netstandard2.0.txt b/src/libraries/System.Security.Cryptography.Pkcs/src/MatchingRefApiCompatBaseline.netstandard2.0.txt index f9e2c1a544038..e644784de848a 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/MatchingRefApiCompatBaseline.netstandard2.0.txt +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/MatchingRefApiCompatBaseline.netstandard2.0.txt @@ -5,8 +5,11 @@ MembersMustExist : Member 'public void System.Security.Cryptography.Pkcs.Algorit MembersMustExist : Member 'public System.Boolean System.Security.Cryptography.Pkcs.CmsRecipientCollection.IsSynchronized.get()' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public System.Object System.Security.Cryptography.Pkcs.CmsRecipientCollection.SyncRoot.get()' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public void System.Security.Cryptography.Pkcs.CmsSigner..ctor(System.Security.Cryptography.Pkcs.SubjectIdentifierType, System.Security.Cryptography.X509Certificates.X509Certificate2, System.Security.Cryptography.AsymmetricAlgorithm)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public void System.Security.Cryptography.Pkcs.CmsSigner..ctor(System.Security.Cryptography.Pkcs.SubjectIdentifierType, System.Security.Cryptography.X509Certificates.X509Certificate2, System.Security.Cryptography.RSA, System.Security.Cryptography.RSASignaturePadding)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public System.Security.Cryptography.AsymmetricAlgorithm System.Security.Cryptography.Pkcs.CmsSigner.PrivateKey.get()' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public void System.Security.Cryptography.Pkcs.CmsSigner.PrivateKey.set(System.Security.Cryptography.AsymmetricAlgorithm)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Security.Cryptography.RSASignaturePadding System.Security.Cryptography.Pkcs.CmsSigner.SignaturePadding.get()' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public void System.Security.Cryptography.Pkcs.CmsSigner.SignaturePadding.set(System.Security.Cryptography.RSASignaturePadding)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public System.Security.Cryptography.Oid System.Security.Cryptography.Pkcs.ContentInfo.GetContentType(System.ReadOnlySpan)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public void System.Security.Cryptography.Pkcs.EnvelopedCms.Decode(System.ReadOnlySpan)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public void System.Security.Cryptography.Pkcs.EnvelopedCms.Decrypt(System.Security.Cryptography.Pkcs.RecipientInfo, System.Security.Cryptography.AsymmetricAlgorithm)' does not exist in the reference but it does exist in the implementation. diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx index dad16b2a82a28..0b0701deadb05 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx @@ -76,6 +76,9 @@ Value was invalid. + + The RSA padding must be Pkcs1 or Pss. + Index was out of range. Must be non-negative and less than the size of the collection. diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj index 0abd0890f6e1e..f91940deada37 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj @@ -1,4 +1,4 @@ - + true true @@ -159,7 +159,6 @@ System.Security.Cryptography.Pkcs.EnvelopedCms - @@ -193,6 +192,8 @@ System.Security.Cryptography.Pkcs.EnvelopedCms Link="Common\Interop\Windows\Crypt32\Interop.CertContextPropId.cs" /> + null; + internal DSACmsSignature(string? signatureAlgorithm, HashAlgorithmName expectedDigest) { _signatureAlgorithm = signatureAlgorithm; @@ -109,9 +111,11 @@ protected override bool Sign( AsymmetricAlgorithm? key, bool silent, [NotNullWhen(true)] out string? signatureAlgorithm, - [NotNullWhen(true)] out byte[]? signatureValue) + [NotNullWhen(true)] out byte[]? signatureValue, + out byte[]? signatureParameters) { Debug.Assert(Helpers.IsDSASupported); + signatureParameters = null; // If there's no private key, fall back to the public key for a "no private key" exception. DSA? dsa = key as DSA ?? diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs index cac04b086150e..5fc08e0870e9b 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.ECDsa.cs @@ -25,6 +25,8 @@ private sealed partial class ECDsaCmsSignature : CmsSignature private readonly HashAlgorithmName _expectedDigest; private readonly string? _signatureAlgorithm; + internal override RSASignaturePadding? SignaturePadding => null; + internal ECDsaCmsSignature(string? signatureAlgorithm, HashAlgorithmName expectedDigest) { _signatureAlgorithm = signatureAlgorithm; @@ -108,8 +110,10 @@ protected override bool Sign( AsymmetricAlgorithm? certKey, bool silent, [NotNullWhen(true)] out string? signatureAlgorithm, - [NotNullWhen(true)] out byte[]? signatureValue) + [NotNullWhen(true)] out byte[]? signatureValue, + out byte[]? signatureParameters) { + signatureParameters = null; // If there's no private key, fall back to the public key for a "no private key" exception. ECDsa? key = certKey as ECDsa ?? PkcsPal.Instance.GetPrivateKeyForSigning(certificate, silent) ?? diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs index 7873de050dd81..2f26c108e8087 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.RSA.cs @@ -90,39 +90,8 @@ protected abstract RSASignaturePadding GetSignaturePadding( string? digestAlgorithmOid, HashAlgorithmName digestAlgorithmName, int digestValueLength); - } - - private sealed class RSAPkcs1CmsSignature : RSACmsSignature - { - public RSAPkcs1CmsSignature(string? signatureAlgorithm, HashAlgorithmName? expectedDigest) - : base(signatureAlgorithm, expectedDigest) - { - } - - protected override RSASignaturePadding GetSignaturePadding( - ReadOnlyMemory? signatureParameters, - string? digestAlgorithmOid, - HashAlgorithmName digestAlgorithmName, - int digestValueLength) - { - if (signatureParameters == null) - { - return RSASignaturePadding.Pkcs1; - } - - Span expectedParameters = stackalloc byte[2]; - expectedParameters[0] = 0x05; - expectedParameters[1] = 0x00; - - if (expectedParameters.SequenceEqual(signatureParameters.Value.Span)) - { - return RSASignaturePadding.Pkcs1; - } - throw new CryptographicException(SR.Cryptography_Pkcs_InvalidSignatureParameters); - } - - protected override bool Sign( + private protected bool SignCore( #if NETCOREAPP || NETSTANDARD2_1 ReadOnlySpan dataHash, #else @@ -132,7 +101,7 @@ protected override bool Sign( X509Certificate2 certificate, AsymmetricAlgorithm? key, bool silent, - [NotNullWhen(true)] out string? signatureAlgorithm, + RSASignaturePadding signaturePadding, [NotNullWhen(true)] out byte[]? signatureValue) { RSA certPublicKey = certificate.GetRSAPublicKey()!; @@ -142,15 +111,12 @@ protected override bool Sign( PkcsPal.Instance.GetPrivateKeyForSigning(certificate, silent) ?? certPublicKey; - if (privateKey == null) + if (privateKey is null) { - signatureAlgorithm = null; signatureValue = null; return false; } - signatureAlgorithm = Oids.Rsa; - #if NETCOREAPP || NETSTANDARD2_1 byte[] signature = new byte[privateKey.KeySize / 8]; @@ -158,14 +124,14 @@ protected override bool Sign( dataHash, signature, hashAlgorithmName, - RSASignaturePadding.Pkcs1, + signaturePadding, out int bytesWritten); if (signed && signature.Length == bytesWritten) { signatureValue = signature; - if (key != null && !certPublicKey.VerifyHash(dataHash, signatureValue, hashAlgorithmName, RSASignaturePadding.Pkcs1)) + if (key is not null && !certPublicKey.VerifyHash(dataHash, signatureValue, hashAlgorithmName, signaturePadding)) { // key did not match certificate signatureValue = null; @@ -182,9 +148,9 @@ protected override bool Sign( dataHash, #endif hashAlgorithmName, - RSASignaturePadding.Pkcs1); + signaturePadding); - if (key != null && !certPublicKey.VerifyHash(dataHash, signatureValue, hashAlgorithmName, RSASignaturePadding.Pkcs1)) + if (key is not null && !certPublicKey.VerifyHash(dataHash, signatureValue, hashAlgorithmName, signaturePadding)) { // key did not match certificate signatureValue = null; @@ -195,8 +161,128 @@ protected override bool Sign( } } + private sealed class RSAPkcs1CmsSignature : RSACmsSignature + { + internal override RSASignaturePadding? SignaturePadding => RSASignaturePadding.Pkcs1; + + public RSAPkcs1CmsSignature(string? signatureAlgorithm, HashAlgorithmName? expectedDigest) + : base(signatureAlgorithm, expectedDigest) + { + } + + protected override RSASignaturePadding GetSignaturePadding( + ReadOnlyMemory? signatureParameters, + string? digestAlgorithmOid, + HashAlgorithmName digestAlgorithmName, + int digestValueLength) + { + if (signatureParameters == null) + { + return RSASignaturePadding.Pkcs1; + } + + Span expectedParameters = stackalloc byte[2]; + expectedParameters[0] = 0x05; + expectedParameters[1] = 0x00; + + if (expectedParameters.SequenceEqual(signatureParameters.Value.Span)) + { + return RSASignaturePadding.Pkcs1; + } + + throw new CryptographicException(SR.Cryptography_Pkcs_InvalidSignatureParameters); + } + + protected override bool Sign( +#if NETCOREAPP || NETSTANDARD2_1 + ReadOnlySpan dataHash, +#else + byte[] dataHash, +#endif + HashAlgorithmName hashAlgorithmName, + X509Certificate2 certificate, + AsymmetricAlgorithm? key, + bool silent, + [NotNullWhen(true)] out string? signatureAlgorithm, + [NotNullWhen(true)] out byte[]? signatureValue, + out byte[]? signatureParameters) + { + bool result = SignCore( + dataHash, + hashAlgorithmName, + certificate, + key, + silent, + RSASignaturePadding.Pkcs1, + out signatureValue); + + signatureAlgorithm = result ? Oids.Rsa : null; + signatureParameters = null; + return result; + } + } + private sealed class RSAPssCmsSignature : RSACmsSignature { + // SEQUENCE + private static readonly byte[] s_rsaPssSha1Parameters = new byte[] { 0x30, 0x00 }; + + // SEQUENCE + // [0] + // SEQUENCE + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 + // [1] + // SEQUENCE + // OBJECT IDENTIFIER 1.2.840.113549.1.1.8 + // SEQUENCE + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 + // [2] + // INTEGER 32 + private static readonly byte[] s_rsaPssSha256Parameters = new byte[] { + 0x30, 0x30, 0xA0, 0x0D, 0x30, 0x0B, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, + 0x01, 0xA1, 0x1A, 0x30, 0x18, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x08, + 0x30, 0x0B, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0xA2, 0x03, 0x02, + 0x01, 0x20, + }; + + // SEQUENCE + // [0] + // SEQUENCE + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.2 + // [1] + // SEQUENCE + // OBJECT IDENTIFIER 1.2.840.113549.1.1.8 + // SEQUENCE + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.2 + // [2] + // INTEGER 48 + private static readonly byte[] s_rsaPssSha384Parameters = new byte[] { + 0x30, 0x30, 0xA0, 0x0D, 0x30, 0x0B, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, + 0x02, 0xA1, 0x1A, 0x30, 0x18, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x08, + 0x30, 0x0B, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0xA2, 0x03, 0x02, + 0x01, 0x30, + }; + + // SEQUENCE + // [0] + // SEQUENCE + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.3 + // [1] + // SEQUENCE + // OBJECT IDENTIFIER 1.2.840.113549.1.1.8 + // SEQUENCE + // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.3 + // [2] + // INTEGER 64 + private static readonly byte[] s_rsaPssSha512Parameters = new byte[] { + 0x30, 0x30, 0xA0, 0x0D, 0x30, 0x0B, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, + 0x03, 0xA1, 0x1A, 0x30, 0x18, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x08, + 0x30, 0x0B, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0xA2, 0x03, 0x02, + 0x01, 0x40, + }; + + internal override RSASignaturePadding? SignaturePadding => RSASignaturePadding.Pss; + public RSAPssCmsSignature() : base(null, null) { } @@ -276,11 +362,56 @@ protected override bool Sign( X509Certificate2 certificate, AsymmetricAlgorithm? key, bool silent, - out string signatureAlgorithm, - out byte[] signatureValue) + [NotNullWhen(true)] out string? signatureAlgorithm, + [NotNullWhen(true)] out byte[]? signatureValue, + out byte[]? signatureParameters) { - Debug.Fail("RSA-PSS requires building parameters, which has no API."); - throw new CryptographicException(); + bool result = SignCore( + dataHash, + hashAlgorithmName, + certificate, + key, + silent, + RSASignaturePadding.Pss, + out signatureValue); + + if (result) + { + signatureAlgorithm = Oids.RsaPss; + + if (hashAlgorithmName == HashAlgorithmName.SHA1) + { + signatureParameters = s_rsaPssSha1Parameters; + } + else if (hashAlgorithmName == HashAlgorithmName.SHA256) + { + signatureParameters = s_rsaPssSha256Parameters; + } + else if (hashAlgorithmName == HashAlgorithmName.SHA384) + { + signatureParameters = s_rsaPssSha384Parameters; + } + else if (hashAlgorithmName == HashAlgorithmName.SHA512) + { + signatureParameters = s_rsaPssSha512Parameters; + } + else + { + // The only hash algorithm we don't support is MD5. + // We shouldn't get here with anything other than MD5. + Debug.Assert(hashAlgorithmName == HashAlgorithmName.MD5, $"Unsupported digest algorithm '{hashAlgorithmName.Name}'"); + signatureAlgorithm = null; + signatureParameters = null; + return false; + } + } + else + { + signatureAlgorithm = null; + signatureParameters = null; + } + + return result; } } } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs index bb6680465d93d..7cf3436b54aa6 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSignature.cs @@ -26,6 +26,7 @@ static CmsSignature() static partial void PrepareRegistrationDsa(Dictionary lookup); static partial void PrepareRegistrationECDsa(Dictionary lookup); + internal abstract RSASignaturePadding? SignaturePadding { get; } protected abstract bool VerifyKeyType(AsymmetricAlgorithm key); internal abstract bool VerifySignature( @@ -52,12 +53,53 @@ protected abstract bool Sign( AsymmetricAlgorithm? key, bool silent, [NotNullWhen(true)] out string? signatureAlgorithm, - [NotNullWhen(true)] out byte[]? signatureValue); + [NotNullWhen(true)] out byte[]? signatureValue, + out byte[]? signatureParameters); - internal static CmsSignature? ResolveAndVerifyKeyType(string signatureAlgorithmOid, AsymmetricAlgorithm? key) + internal static CmsSignature? ResolveAndVerifyKeyType( + string signatureAlgorithmOid, + AsymmetricAlgorithm? key, + RSASignaturePadding? rsaSignaturePadding) { + // Rules: + // RSASignaturePadding 'wins' if specified if the signatureAlgorithmOid is any RSA OID. + // if there is no rsaSignaturePadding, the OID is used. + // If the rsaSignaturePadding is specified and the signatureAlgorithm OID is not any + // RSA OID, this is invalid, so null. if (s_lookup.TryGetValue(signatureAlgorithmOid, out CmsSignature? processor)) { + // We have a padding that might override the OID. + if (rsaSignaturePadding is not null) + { + // The processor does not support RSA signature padding + if (processor.SignaturePadding is null) + { + // We were given an RSA signature padding, but the processor is not any known RSA. + // We won't override a non-RSA OID (like ECDSA) to RSA based on the padding, so return null. + return null; + } + + // The processor is RSA, but does not agree with the specified signature padding, so override. + if (processor.SignaturePadding != rsaSignaturePadding) + { + if (rsaSignaturePadding == RSASignaturePadding.Pkcs1) + { + processor = s_lookup[Oids.Rsa]; + Debug.Assert(processor is not null); + } + else if (rsaSignaturePadding == RSASignaturePadding.Pss) + { + processor = s_lookup[Oids.RsaPss]; + Debug.Assert(processor is not null); + } + else + { + Debug.Fail("Unhandled RSA signature padding."); + return null; + } + } + } + if (key != null && !processor.VerifyKeyType(key)) { return null; @@ -79,21 +121,33 @@ internal static bool Sign( X509Certificate2 certificate, AsymmetricAlgorithm? key, bool silent, + RSASignaturePadding? rsaSignaturePadding, out string? oid, - out ReadOnlyMemory signatureValue) + out ReadOnlyMemory signatureValue, + out ReadOnlyMemory signatureParameters) { - CmsSignature? processor = ResolveAndVerifyKeyType(certificate.GetKeyAlgorithm(), key); + CmsSignature? processor = ResolveAndVerifyKeyType(certificate.GetKeyAlgorithm(), key, rsaSignaturePadding); if (processor == null) { oid = null; signatureValue = default; + signatureParameters = default; return false; } - bool signed = processor.Sign(dataHash, hashAlgorithmName, certificate, key, silent, out oid, out byte[]? signature); + bool signed = processor.Sign( + dataHash, + hashAlgorithmName, + certificate, + key, + silent, + out oid, + out byte[]? signature, + out byte[]? parameters); signatureValue = signature; + signatureParameters = parameters; return signed; } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs index cd94142c6d0cf..8b9a401a81b36 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/CmsSigner.cs @@ -17,6 +17,7 @@ public sealed class CmsSigner private static readonly Oid s_defaultAlgorithm = Oids.Sha256Oid; private SubjectIdentifierType _signerIdentifierType; + private RSASignaturePadding? _signaturePadding; public X509Certificate2? Certificate { get; set; } public AsymmetricAlgorithm? PrivateKey { get; set; } @@ -26,6 +27,25 @@ public sealed class CmsSigner public CryptographicAttributeObjectCollection SignedAttributes { get; private set; } = new CryptographicAttributeObjectCollection(); public CryptographicAttributeObjectCollection UnsignedAttributes { get; private set; } = new CryptographicAttributeObjectCollection(); + /// + /// Gets or sets the RSA signature padding to use. + /// + /// The RSA signature padding to use. + public RSASignaturePadding? SignaturePadding + { + get => _signaturePadding; + set + { + if (value is not null && + value != RSASignaturePadding.Pkcs1 && value != RSASignaturePadding.Pss) + { + throw new ArgumentException(SR.Argument_InvalidRsaSignaturePadding, nameof(value)); + } + + _signaturePadding = value; + } + } + public SubjectIdentifierType SignerIdentifierType { get { return _signerIdentifierType; } @@ -62,7 +82,48 @@ public CmsSigner(SubjectIdentifierType signerIdentifierType, X509Certificate2? c } public CmsSigner(SubjectIdentifierType signerIdentifierType, X509Certificate2? certificate, AsymmetricAlgorithm? privateKey) + : this(signerIdentifierType, certificate, privateKey, signaturePadding: null) { + } + + /// + /// Initializes a new instance of the CmsSigner class with a specified signer + /// certificate, subject identifier type, private key object, and RSA signature padding. + /// + /// + /// One of the enumeration values that specifies the scheme to use for identifying + /// which signing certificate was used. + /// + /// + /// The certificate whose private key will be used to sign a message. + /// + /// + /// The private key object to use when signing the message. + /// + /// + /// The RSA signature padding to use. + /// + public CmsSigner( + SubjectIdentifierType signerIdentifierType, + X509Certificate2? certificate, + RSA? privateKey, + RSASignaturePadding? signaturePadding) + : this(signerIdentifierType, certificate, (AsymmetricAlgorithm?)privateKey, signaturePadding) + { + } + + private CmsSigner( + SubjectIdentifierType signerIdentifierType, + X509Certificate2? certificate, + AsymmetricAlgorithm? privateKey, + RSASignaturePadding? signaturePadding) + { + if (signaturePadding is not null && + signaturePadding != RSASignaturePadding.Pkcs1 && signaturePadding != RSASignaturePadding.Pss) + { + throw new ArgumentException(SR.Argument_InvalidRsaSignaturePadding, nameof(signaturePadding)); + } + switch (signerIdentifierType) { case SubjectIdentifierType.Unknown: @@ -90,6 +151,7 @@ public CmsSigner(SubjectIdentifierType signerIdentifierType, X509Certificate2? c Certificate = certificate; DigestAlgorithm = s_defaultAlgorithm.CopyOid(); PrivateKey = privateKey; + _signaturePadding = signaturePadding; } internal void CheckCertificateValue() @@ -212,6 +274,7 @@ internal SignerInfoAsn Sign( bool signed; string? signatureAlgorithm; ReadOnlyMemory signatureValue; + ReadOnlyMemory signatureParameters = default; if (SignerIdentifierType == SubjectIdentifierType.NoSignature) { @@ -227,8 +290,10 @@ internal SignerInfoAsn Sign( Certificate!, PrivateKey, silent, + SignaturePadding, out signatureAlgorithm, - out signatureValue); + out signatureValue, + out signatureParameters); } if (!signed) @@ -239,6 +304,11 @@ internal SignerInfoAsn Sign( newSignerInfo.SignatureValue = signatureValue; newSignerInfo.SignatureAlgorithm.Algorithm = signatureAlgorithm!; + if (!signatureParameters.IsEmpty) + { + newSignerInfo.SignatureAlgorithm.Parameters = signatureParameters; + } + X509Certificate2Collection certs = new X509Certificate2Collection(); certs.AddRange(Certificates); diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs index af5714360543a..9c7874b451c42 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System/Security/Cryptography/Pkcs/SignerInfo.cs @@ -690,7 +690,11 @@ private void Verify( X509Certificate2 certificate, bool verifySignatureOnly) { - CmsSignature? signatureProcessor = CmsSignature.ResolveAndVerifyKeyType(SignatureAlgorithm.Value!, key: null); + // SignatureAlgorithm always 'wins' so we don't need to pass in an rsaSignaturePadding + CmsSignature? signatureProcessor = CmsSignature.ResolveAndVerifyKeyType( + SignatureAlgorithm.Value!, + key: null, + rsaSignaturePadding: null); if (signatureProcessor == null) { diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/Oids.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/Oids.cs index 0fae7af2c5822..eded07b0913eb 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/Oids.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/Oids.cs @@ -22,6 +22,7 @@ internal static class Oids public const string RsaPkcs1Sha256 = "1.2.840.113549.1.1.11"; public const string RsaPkcs1Sha384 = "1.2.840.113549.1.1.12"; public const string RsaPkcs1Sha512 = "1.2.840.113549.1.1.13"; + public const string RsaPss = "1.2.840.113549.1.1.10"; public const string Esdh = "1.2.840.113549.1.9.16.3.5"; public const string Dh = "1.2.840.10046.2.1"; public const string EcdsaSha256 = "1.2.840.10045.4.3.2"; diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/CmsSignerTests.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/CmsSignerTests.cs index 4c73ecc54f354..a99d2f8d4dde9 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/CmsSignerTests.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/CmsSignerTests.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Reflection; using Xunit; namespace System.Security.Cryptography.Pkcs.Tests @@ -19,5 +20,43 @@ public static void SignerIdentifierType_InvalidValues(SubjectIdentifierType inva expectedParamName: null, () => signer.SignerIdentifierType = invalidType); } + +#if NETCOREAPP + [Fact] + public static void SignaturePadding_InvalidValue() + { + RSASignaturePaddingMode badMode = (RSASignaturePaddingMode)(-1); + + // Currently we support all RSASignaturePaddings. However we want to make sure we fail properly + // if an unsupported one is added later, so construct a bogus padding. + RSASignaturePadding badPadding = (RSASignaturePadding)typeof(RSASignaturePadding) + .GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, new Type[] { typeof(RSASignaturePaddingMode)}) + .Invoke(new object[] { badMode }); + + // Test setter + CmsSigner signer = new CmsSigner(); + AssertExtensions.Throws("value", () => signer.SignaturePadding = badPadding); + + // Test ctor + AssertExtensions.Throws("signaturePadding", () => new CmsSigner( + SubjectIdentifierType.IssuerAndSerialNumber, + certificate: null, + privateKey: null, + badPadding)); + } + + [Fact] + public static void SignaturePadding_Null() + { + CmsSigner signer = new CmsSigner(); + signer.SignaturePadding = null; // Assert.NoThrow + + _ = new CmsSigner( + SubjectIdentifierType.IssuerAndSerialNumber, + certificate: null, + privateKey: null, + signaturePadding: null); // Assert.NoThrow + } +#endif } } diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs index cfa17458204e5..de363e3873897 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs @@ -479,6 +479,124 @@ public static void CreateSignature_DigestAlgorithmWithSignatureOid_Prohibited() } } + [Theory] + [InlineData(Oids.Sha256, true)] + [InlineData(Oids.Sha384, true)] + [InlineData(Oids.Sha512, true)] + [InlineData(Oids.Sha1, true)] + [InlineData(Oids.Sha256, false)] + [InlineData(Oids.Sha384, false)] + [InlineData(Oids.Sha512, false)] + [InlineData(Oids.Sha1, false)] + public static void CreateSignature_RsaPss(string digestOid, bool assignByConstructor) + { + ContentInfo content = new ContentInfo(new byte[] { 1, 2, 3 }); + SignedCms cms = new SignedCms(content); + byte[] cmsBytes; + + using (X509Certificate2 cert = Certificates.RSA2048SignatureOnly.TryGetCertificateWithPrivateKey()) + { + CmsSigner signer; + + if (assignByConstructor) + { + signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert, null, RSASignaturePadding.Pss); + } + else + { + signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert); + signer.SignaturePadding = RSASignaturePadding.Pss; + } + + signer.DigestAlgorithm = new Oid(digestOid, null); + cms.ComputeSignature(signer); + cmsBytes = cms.Encode(); + } + + cms = new SignedCms(); + cms.Decode(cmsBytes); + cms.CheckSignature(true); // Assert.NoThrow + Assert.Single(cms.SignerInfos); + + SignerInfo signerInfo = cms.SignerInfos[0]; + Assert.Equal(Oids.RsaPss, signerInfo.SignatureAlgorithm.Value); + } + + [Fact] + public static void CreateSignature_RsaPss_SeparateKey() + { + ContentInfo content = new ContentInfo(new byte[] { 1, 2, 3 }); + SignedCms cms = new SignedCms(content); + byte[] cmsBytes; + + using (X509Certificate2 cert = Certificates.RSA2048SignatureOnly.TryGetCertificateWithPrivateKey()) + using (X509Certificate2 pubOnly = new X509Certificate2(cert.RawDataMemory.Span)) + using (RSA rsa = cert.GetRSAPrivateKey()) + { + CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, pubOnly, rsa, RSASignaturePadding.Pss); + cms.ComputeSignature(signer); + cmsBytes = cms.Encode(); + } + + cms = new SignedCms(); + cms.Decode(cmsBytes); + cms.CheckSignature(true); // Assert.NoThrow + Assert.Single(cms.SignerInfos); + + SignerInfo signerInfo = cms.SignerInfos[0]; + Assert.Equal(Oids.RsaPss, signerInfo.SignatureAlgorithm.Value); + } + + [Fact] + public static void CreateSignature_RsaPss_Md5NotSupported() + { + ContentInfo content = new ContentInfo(new byte[] { 1, 2, 3 }); + SignedCms cms = new SignedCms(content); + + using (X509Certificate2 cert = Certificates.RSA2048SignatureOnly.TryGetCertificateWithPrivateKey()) + { + CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert, null, RSASignaturePadding.Pss); + signer.DigestAlgorithm = new Oid(Oids.Md5, null); + Assert.ThrowsAny(() => cms.ComputeSignature(signer)); + } + } + + [Fact] + public static void CreateSignature_RsaPadding_DefaultToPkcs1() + { + ContentInfo content = new ContentInfo(new byte[] { 1, 2, 3 }); + SignedCms cms = new SignedCms(content); + byte[] cmsBytes; + + using (X509Certificate2 cert = Certificates.RSA2048SignatureOnly.TryGetCertificateWithPrivateKey()) + { + CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert, null, null); + cms.ComputeSignature(signer); + cmsBytes = cms.Encode(); + } + + cms = new SignedCms(); + cms.Decode(cmsBytes); + cms.CheckSignature(true); // Assert.NoThrow + Assert.Single(cms.SignerInfos); + + SignerInfo signerInfo = cms.SignerInfos[0]; + Assert.Equal(Oids.Rsa, signerInfo.SignatureAlgorithm.Value); + } + + [Fact] + public static void CreateSignature_Ecdsa_ThrowsWithRsaSignaturePadding() + { + ContentInfo content = new ContentInfo(new byte[] { 1, 2, 3 }); + SignedCms cms = new SignedCms(content); + + using (X509Certificate2 cert = Certificates.ECDsaP256Win.TryGetCertificateWithPrivateKey()) + { + CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert, null, RSASignaturePadding.Pss); + Assert.ThrowsAny(() => cms.ComputeSignature(signer)); + } + } + private static void VerifyWithExplicitPrivateKey(X509Certificate2 cert, AsymmetricAlgorithm key) { using (var pubCert = new X509Certificate2(cert.RawData)) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.ExportPal.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.ExportPal.cs index ef28cdf69f8e2..b98ed82966316 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.ExportPal.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/StorePal.ExportPal.cs @@ -39,7 +39,6 @@ protected override byte[] ExportPkcs7() } } - Debug.Assert(certHandles.Length > 0); return Interop.AndroidCrypto.X509ExportPkcs7(certHandles); } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/CollectionTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/CollectionTests.cs index da647d19ad5ef..ac92a40e6d947 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/CollectionTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/CollectionTests.cs @@ -1583,7 +1583,6 @@ public static void ExportCertificatePems_SingleCert() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/59777", TestPlatforms.Android)] public static void ExportCertificatePems_MultiCert() { const string MultiPem = "-----BEGIN CERTIFICATE-----\n" + @@ -1745,7 +1744,9 @@ static void AssertPem(X509Certificate2Collection expected, ReadOnlySpan pe using (ImportedCollection imported = Cert.Import(data)) { - Assert.Equal(expected.ToArray(), imported.Collection.ToArray(), new X509Certificate2EqualityComparer()); + X509Certificate2[] expectedCollection = expected.OrderBy(c => c.Thumbprint).ToArray(); + X509Certificate2[] actualCollection = imported.Collection.OrderBy(c => c.Thumbprint).ToArray(); + Assert.Equal(expectedCollection, actualCollection, new X509Certificate2EqualityComparer()); } } diff --git a/src/libraries/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs b/src/libraries/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs index c2af5df2f7059..247d600b86c76 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/tests/ServiceBaseTests.cs @@ -20,6 +20,7 @@ public class ServiceBaseTests : IDisposable private static readonly Lazy s_isElevated = new Lazy(() => AdminHelpers.IsProcessElevated()); protected static bool IsProcessElevated => s_isElevated.Value; protected static bool IsElevatedAndSupportsEventLogs => IsProcessElevated && PlatformDetection.IsNotWindowsNanoServer; + protected static bool IsElevatedAndWindows10OrLater => IsProcessElevated && PlatformDetection.IsWindows10OrLater; private bool _disposed; @@ -81,7 +82,7 @@ public void TestOnStartThenStop() controller.WaitForStatus(ServiceControllerStatus.Stopped); } - [ConditionalFact(nameof(IsProcessElevated))] + [ConditionalFact(nameof(IsElevatedAndWindows10OrLater))] // flaky on Windows 8.1 public void TestOnStartWithArgsThenStop() { ServiceController controller = ConnectToServer(); diff --git a/src/libraries/System.Text.Json/Common/ReflectionExtensions.cs b/src/libraries/System.Text.Json/Common/ReflectionExtensions.cs index 8a1a58a97a2cb..09ecc45077fe0 100644 --- a/src/libraries/System.Text.Json/Common/ReflectionExtensions.cs +++ b/src/libraries/System.Text.Json/Common/ReflectionExtensions.cs @@ -310,5 +310,18 @@ public static bool TryGetDeserializationConstructor( deserializationCtor = ctorWithAttribute ?? publicParameterlessCtor ?? lonePublicCtor; return true; } + + public static object? GetDefaultValue(this ParameterInfo parameterInfo) + { + object? defaultValue = parameterInfo.DefaultValue; + + // DBNull.Value is sometimes used as the default value (returned by reflection) of nullable params in place of null. + if (defaultValue == DBNull.Value && parameterInfo.ParameterType != typeof(DBNull)) + { + return null; + } + + return defaultValue; + } } } diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs index c17eb09a805e7..ec6124a8222be 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs @@ -804,14 +804,19 @@ private string GenerateCtorParamMetadataInitFunc(TypeGenerationSpec typeGenerati { ParameterInfo reflectionInfo = parameters[i].ParameterInfo; + string parameterTypeRef = reflectionInfo.ParameterType.GetCompilableName(); + + object? defaultValue = reflectionInfo.GetDefaultValue(); + string defaultValueAsStr = GetParamDefaultValueAsString(defaultValue, parameterTypeRef); + sb.Append(@$" {InfoVarName} = new() {{ Name = ""{reflectionInfo.Name!}"", - ParameterType = typeof({reflectionInfo.ParameterType.GetCompilableName()}), + ParameterType = typeof({parameterTypeRef}), Position = {reflectionInfo.Position}, HasDefaultValue = {ToCSharpKeyword(reflectionInfo.HasDefaultValue)}, - DefaultValue = {GetParamDefaultValueAsString(reflectionInfo.DefaultValue)} + DefaultValue = {defaultValueAsStr} }}; {parametersVarName}[{i}] = {InfoVarName}; "); @@ -1313,12 +1318,12 @@ private static string GetNumberHandlingAsStr(JsonNumberHandling? numberHandling) private static string ToCSharpKeyword(bool value) => value.ToString().ToLowerInvariant(); - private static string GetParamDefaultValueAsString(object? value) + private static string GetParamDefaultValueAsString(object? value, string objectTypeAsStr) { switch (value) { case null: - return "null"; + return $"default({objectTypeAsStr})"; case bool boolVal: return ToCSharpKeyword(boolVal); default: diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs index bbdd17bddb8c2..2785e66c7cd3a 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs @@ -26,6 +26,7 @@ private sealed class Parser private const string SystemTextJsonNamespace = "System.Text.Json"; private const string JsonConverterAttributeFullName = "System.Text.Json.Serialization.JsonConverterAttribute"; private const string JsonConverterFactoryFullName = "System.Text.Json.Serialization.JsonConverterFactory"; + private const string JsonConverterOfTFullName = "System.Text.Json.Serialization.JsonConverter`1"; private const string JsonArrayFullName = "System.Text.Json.Nodes.JsonArray"; private const string JsonElementFullName = "System.Text.Json.JsonElement"; private const string JsonExtensionDataAttributeFullName = "System.Text.Json.Serialization.JsonExtensionDataAttribute"; @@ -101,6 +102,9 @@ private sealed class Parser private readonly Type? _dateOnlyType; private readonly Type? _timeOnlyType; + // Needed for converter validation + private readonly Type _jsonConverterOfTType; + private readonly HashSet _numberTypes = new(); private readonly HashSet _knownTypes = new(); private readonly HashSet _knownUnsupportedTypes = new(); @@ -215,6 +219,8 @@ public Parser(Compilation compilation, in JsonSourceGenerationContext sourceGene _dateOnlyType = _metadataLoadContext.Resolve(DateOnlyFullName); _timeOnlyType = _metadataLoadContext.Resolve(TimeOnlyFullName); + _jsonConverterOfTType = _metadataLoadContext.Resolve(JsonConverterOfTFullName); + PopulateKnownTypes(); } @@ -224,8 +230,12 @@ public Parser(Compilation compilation, in JsonSourceGenerationContext sourceGene INamedTypeSymbol jsonSerializerContextSymbol = compilation.GetBestTypeByMetadataName(JsonSerializerContextFullName); INamedTypeSymbol jsonSerializableAttributeSymbol = compilation.GetBestTypeByMetadataName(JsonSerializerAttributeFullName); INamedTypeSymbol jsonSourceGenerationOptionsAttributeSymbol = compilation.GetBestTypeByMetadataName(JsonSourceGenerationOptionsAttributeFullName); + INamedTypeSymbol jsonConverterOfTAttributeSymbol = compilation.GetBestTypeByMetadataName(JsonConverterOfTFullName); - if (jsonSerializerContextSymbol == null || jsonSerializableAttributeSymbol == null || jsonSourceGenerationOptionsAttributeSymbol == null) + if (jsonSerializerContextSymbol == null || + jsonSerializableAttributeSymbol == null || + jsonSourceGenerationOptionsAttributeSymbol == null || + jsonConverterOfTAttributeSymbol == null) { return null; } @@ -1354,7 +1364,14 @@ private static bool PropertyAccessorCanBeReferenced(MethodInfo? accessor) return null; } - if (converterType.GetCompatibleBaseClass(JsonConverterFactoryFullName) != null) + // Validated when creating the source generation spec. + Debug.Assert(_jsonConverterOfTType != null); + + if (converterType.GetCompatibleGenericBaseClass(_jsonConverterOfTType) != null) + { + return $"new {converterType.GetCompilableName()}()"; + } + else if (converterType.GetCompatibleBaseClass(JsonConverterFactoryFullName) != null) { hasFactoryConverter = true; @@ -1368,7 +1385,7 @@ private static bool PropertyAccessorCanBeReferenced(MethodInfo? accessor) } } - return $"new {converterType.GetCompilableName()}()"; + return null; } private static string DetermineRuntimePropName(string clrPropName, string? jsonPropName, JsonKnownNamingPolicy namingPolicy) diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 5063d0f8da85f..9bf231b6e54d5 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -350,7 +350,8 @@ System.Text.Json.Utf8JsonReader - + diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs index 3e25b10c13a23..f820ffbfe3a85 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs @@ -67,10 +67,7 @@ protected sealed override void InitializeConstructorArgumentCaches(ref ReadStack { JsonParameterInfo? parameterInfo = cache[i].Value; Debug.Assert(parameterInfo != null); - - arguments[parameterInfo.ClrInfo.Position] = parameterInfo.ShouldDeserialize - ? parameterInfo.DefaultValue - : parameterInfo.ClrDefaultValue; + arguments[parameterInfo.ClrInfo.Position] = parameterInfo.DefaultValue; } state.Current.CtorArgumentState!.Arguments = arguments; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs index 2d23e7c5c9200..f81025bbc460e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs @@ -600,9 +600,7 @@ internal JsonTypeInfo GetOrAddClass(Type type) { _haveTypesBeenCreated = true; - // todo: for performance and reduced instances, consider using the converters and JsonTypeInfo from s_defaultOptions by cloning (or reference directly if no changes). - // https://github.com/dotnet/runtime/issues/32357 - if (!_classes.TryGetValue(type, out JsonTypeInfo? result)) + if (!TryGetClass(type, out JsonTypeInfo? result)) { result = _classes.GetOrAdd(type, GetClassFromContextOrCreate(type)); } @@ -644,6 +642,20 @@ internal JsonTypeInfo GetOrAddClassForRootType(Type type) return jsonTypeInfo; } + internal bool TryGetClass(Type type, [NotNullWhen(true)] out JsonTypeInfo? jsonTypeInfo) + { + // todo: for performance and reduced instances, consider using the converters and JsonTypeInfo from s_defaultOptions by cloning (or reference directly if no changes). + // https://github.com/dotnet/runtime/issues/32357 + if (!_classes.TryGetValue(type, out JsonTypeInfo? result)) + { + jsonTypeInfo = null; + return false; + } + + jsonTypeInfo = result; + return true; + } + internal bool TypeIsCached(Type type) { return _classes.ContainsKey(type); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/GenericMethodHolder.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/GenericMethodHolder.cs index a144c11d398c9..2c143f95e59cc 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/GenericMethodHolder.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/GenericMethodHolder.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Text.Json.Reflection; @@ -12,10 +13,24 @@ namespace System.Text.Json.Serialization.Metadata /// internal abstract class GenericMethodHolder { + /// + /// Returns the default value for the specified type. + /// + public abstract object? DefaultValue { get; } + /// /// Returns true if contains only default values. /// public abstract bool IsDefaultValue(object value); + + /// + /// Creates a holder instance representing a type. + /// + public static GenericMethodHolder CreateHolder(Type type) + { + Type holderType = typeof(GenericMethodHolder<>).MakeGenericType(type); + return (GenericMethodHolder)Activator.CreateInstance(holderType)!; + } } /// @@ -23,6 +38,8 @@ internal abstract class GenericMethodHolder /// internal sealed class GenericMethodHolder : GenericMethodHolder { + public override object? DefaultValue => default(T); + public override bool IsDefaultValue(object value) { // For performance, we only want to call this method for non-nullable value types. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs index 7b33f3dd97a88..3905c70402024 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs @@ -17,8 +17,6 @@ internal abstract class JsonParameterInfo private protected bool MatchingPropertyCanBeNull { get; private set; } - internal abstract object? ClrDefaultValue { get; } - // The default value of the parameter. This is `DefaultValue` of the `ParameterInfo`, if specified, or the CLR `default` for the `ParameterType`. public object? DefaultValue { get; private protected set; } @@ -74,18 +72,49 @@ public virtual void Initialize(JsonParameterInfoValues parameterInfo, JsonProper MatchingPropertyCanBeNull = matchingProperty.PropertyTypeCanBeNull; } - // Create a parameter that is ignored at run time. It uses the same type (typeof(sbyte)) to help - // prevent issues with unsupported types and helps ensure we don't accidently (de)serialize it. - public static JsonParameterInfo CreateIgnoredParameterPlaceholder(JsonParameterInfoValues parameterInfo, JsonPropertyInfo matchingProperty) + /// + /// Create a parameter that is ignored at run time. It uses the same type (typeof(sbyte)) to help + /// prevent issues with unsupported types and helps ensure we don't accidently (de)serialize it. + /// + public static JsonParameterInfo CreateIgnoredParameterPlaceholder( + JsonParameterInfoValues parameterInfo, + JsonPropertyInfo matchingProperty, + bool sourceGenMode) { - JsonParameterInfo jsonParameterInfo = matchingProperty.ConverterBase.CreateJsonParameterInfo(); + JsonParameterInfo jsonParameterInfo = new JsonParameterInfo(); jsonParameterInfo.ClrInfo = parameterInfo; jsonParameterInfo.RuntimePropertyType = matchingProperty.RuntimePropertyType!; jsonParameterInfo.NameAsUtf8Bytes = matchingProperty.NameAsUtf8Bytes!; - jsonParameterInfo.InitializeDefaultValue(matchingProperty); + + // TODO: https://github.com/dotnet/runtime/issues/60082. + // Default value initialization for params mapping to ignored properties doesn't + // account for the default value of optional parameters. This should be fixed. + + if (sourceGenMode) + { + // The value in the matching JsonPropertyInfo instance matches the parameter type. + jsonParameterInfo.DefaultValue = matchingProperty.DefaultValue; + } + else + { + // The value in the created JsonPropertyInfo instance (sbyte) + // doesn't match the parameter type, use reflection to get the default value. + Type parameterType = parameterInfo.ParameterType; + + GenericMethodHolder holder; + if (matchingProperty.Options.TryGetClass(parameterType, out JsonTypeInfo? typeInfo)) + { + holder = typeInfo.GenericMethods; + } + else + { + holder = GenericMethodHolder.CreateHolder(parameterInfo.ParameterType); + } + + jsonParameterInfo.DefaultValue = holder.DefaultValue; + } + return jsonParameterInfo; } - - protected abstract void InitializeDefaultValue(JsonPropertyInfo matchingProperty); } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfoOfT.cs index 2195426a551ed..b275f01acd095 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfoOfT.cs @@ -11,8 +11,6 @@ namespace System.Text.Json.Serialization.Metadata /// internal sealed class JsonParameterInfo : JsonParameterInfo { - internal override object? ClrDefaultValue => default(T); - public T TypedDefaultValue { get; private set; } = default!; public override void Initialize(JsonParameterInfoValues parameterInfo, JsonPropertyInfo matchingProperty, JsonSerializerOptions options) @@ -21,7 +19,7 @@ public override void Initialize(JsonParameterInfoValues parameterInfo, JsonPrope InitializeDefaultValue(matchingProperty); } - protected override void InitializeDefaultValue(JsonPropertyInfo matchingProperty) + private void InitializeDefaultValue(JsonPropertyInfo matchingProperty) { Debug.Assert(ClrInfo.ParameterType == matchingProperty.DeclaredPropertyType); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs index 3b8c003ac3066..5e2258ec6dde8 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs @@ -42,16 +42,14 @@ internal static JsonPropertyInfo GetPropertyPlaceholder() // Create a property that is ignored at run-time. internal static JsonPropertyInfo CreateIgnoredPropertyPlaceholder( - JsonConverter converter, MemberInfo memberInfo, Type memberType, bool isVirtual, JsonSerializerOptions options) { - JsonPropertyInfo jsonPropertyInfo = converter.CreateJsonPropertyInfo(); + JsonPropertyInfo jsonPropertyInfo = new JsonPropertyInfo(); jsonPropertyInfo.Options = options; - jsonPropertyInfo.ConverterBase = converter; jsonPropertyInfo.MemberInfo = memberInfo; jsonPropertyInfo.IsIgnored = true; jsonPropertyInfo.DeclaredPropertyType = memberType; @@ -525,5 +523,10 @@ internal JsonTypeInfo RuntimeTypeInfo internal string? ClrName { get; set; } internal bool IsVirtual { get; set; } + + /// + /// Default value used for parameterized ctor invocation. + /// + internal abstract object? DefaultValue { get; } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs index f60f0450701b9..e98f08dd54cdc 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs @@ -28,8 +28,11 @@ internal sealed class JsonPropertyInfo : JsonPropertyInfo private bool _propertyTypeEqualsTypeToConvert; internal Func? Get { get; set; } + internal Action? Set { get; set; } + internal override object? DefaultValue => default(T); + public JsonConverter Converter { get; internal set; } = null!; internal override void Initialize( diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.Cache.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.Cache.cs index d3f2c3c9bee6f..f696cefe8f21c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.Cache.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.Cache.cs @@ -58,6 +58,12 @@ internal static JsonPropertyInfo AddProperty( JsonNumberHandling? parentTypeNumberHandling, JsonSerializerOptions options) { + JsonIgnoreCondition? ignoreCondition = JsonPropertyInfo.GetAttribute(memberInfo)?.Condition; + if (ignoreCondition == JsonIgnoreCondition.Always) + { + return JsonPropertyInfo.CreateIgnoredPropertyPlaceholder(memberInfo, memberType, isVirtual, options); + } + JsonConverter converter = GetConverter( memberType, parentClassType, @@ -65,12 +71,6 @@ internal static JsonPropertyInfo AddProperty( out Type runtimeType, options); - JsonIgnoreCondition? ignoreCondition = JsonPropertyInfo.GetAttribute(memberInfo)?.Condition; - if (ignoreCondition == JsonIgnoreCondition.Always) - { - return JsonPropertyInfo.CreateIgnoredPropertyPlaceholder(converter, memberInfo, memberType, isVirtual, options); - } - return CreateProperty( declaredPropertyType: memberType, runtimePropertyType: runtimeType, @@ -646,7 +646,7 @@ internal void InitializeParameterCache() return; } - InitializeConstructorParameters(array); + InitializeConstructorParameters(array, sourceGenMode: true); Debug.Assert(ParameterCache != null); } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs index 4f662c67cd65c..4bd852e447e2b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs @@ -133,12 +133,7 @@ internal GenericMethodHolder GenericMethods { get { - if (_genericMethods == null) - { - Type runtimePropertyClass = typeof(GenericMethodHolder<>).MakeGenericType(new Type[] { Type })!; - _genericMethods = (GenericMethodHolder)Activator.CreateInstance(runtimePropertyClass)!; - } - + _genericMethods ??= GenericMethodHolder.CreateHolder(Type); return _genericMethods; } } @@ -454,7 +449,7 @@ public ParameterLookupValue(JsonPropertyInfo jsonPropertyInfo) public JsonPropertyInfo JsonPropertyInfo { get; } } - private void InitializeConstructorParameters(JsonParameterInfoValues[] jsonParameters) + private void InitializeConstructorParameters(JsonParameterInfoValues[] jsonParameters, bool sourceGenMode = false) { var parameterCache = new JsonPropertyDictionary(Options.PropertyNameCaseInsensitive, jsonParameters.Length); @@ -500,7 +495,7 @@ private void InitializeConstructorParameters(JsonParameterInfoValues[] jsonParam Debug.Assert(matchingEntry.JsonPropertyInfo != null); JsonPropertyInfo jsonPropertyInfo = matchingEntry.JsonPropertyInfo; - JsonParameterInfo jsonParameterInfo = CreateConstructorParameter(parameterInfo, jsonPropertyInfo, Options); + JsonParameterInfo jsonParameterInfo = CreateConstructorParameter(parameterInfo, jsonPropertyInfo, sourceGenMode, Options); parameterCache.Add(jsonPropertyInfo.NameAsString, jsonParameterInfo); } // It is invalid for the extension data property to bind with a constructor argument. @@ -530,7 +525,7 @@ private static JsonParameterInfoValues[] GetParameterInfoArray(ParameterInfo[] p ParameterType = reflectionInfo.ParameterType, Position = reflectionInfo.Position, HasDefaultValue = reflectionInfo.HasDefaultValue, - DefaultValue = reflectionInfo.DefaultValue + DefaultValue = reflectionInfo.GetDefaultValue() }; jsonParameters[i] = jsonInfo; @@ -580,11 +575,12 @@ private bool IsValidDataExtensionProperty(JsonPropertyInfo jsonPropertyInfo) private static JsonParameterInfo CreateConstructorParameter( JsonParameterInfoValues parameterInfo, JsonPropertyInfo jsonPropertyInfo, + bool sourceGenMode, JsonSerializerOptions options) { if (jsonPropertyInfo.IsIgnored) { - return JsonParameterInfo.CreateIgnoredParameterPlaceholder(parameterInfo, jsonPropertyInfo); + return JsonParameterInfo.CreateIgnoredParameterPlaceholder(parameterInfo, jsonPropertyInfo, sourceGenMode); } JsonConverter converter = jsonPropertyInfo.ConverterBase; diff --git a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs index c04815dc85e6a..93aff74c1b4d0 100644 --- a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs +++ b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs @@ -1216,5 +1216,111 @@ public class TypeWithUri public TypeWithUri(Uri myUri = default) => MyUri = myUri; } + + [Fact] + public async Task SmallObject_ClrDefaultParamValueUsed_WhenMatchingPropIgnored() + { + string json = @"{""Prop"":20}"; + var obj1 = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(0, obj1.Prop); + + var obj2 = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(0, obj2.Prop); + } + + public class SmallType_IgnoredProp_Bind_ParamWithDefaultValue + { + [JsonIgnore] + public int Prop { get; set; } + + public SmallType_IgnoredProp_Bind_ParamWithDefaultValue(int prop = 5) + => Prop = prop; + } + + public class SmallType_IgnoredProp_Bind_Param + { + [JsonIgnore] + public int Prop { get; set; } + + public SmallType_IgnoredProp_Bind_Param(int prop) + => Prop = prop; + } + + [Fact] + public async Task LargeObject_ClrDefaultParamValueUsed_WhenMatchingPropIgnored() + { + string json = @"{""Prop"":20}"; + var obj1 = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(0, obj1.Prop); + + var obj2 = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(0, obj2.Prop); + } + + public class LargeType_IgnoredProp_Bind_ParamWithDefaultValue + { + public int W { get; set; } + + public int X { get; set; } + + public int Y { get; set; } + + public int Z { get; set; } + + [JsonIgnore] + public int Prop { get; set; } + + public LargeType_IgnoredProp_Bind_ParamWithDefaultValue(int w, int x, int y, int z, int prop = 5) + => Prop = prop; + } + + public class LargeType_IgnoredProp_Bind_Param + { + public int W { get; set; } + + public int X { get; set; } + + public int Y { get; set; } + + public int Z { get; set; } + + [JsonIgnore] + public int Prop { get; set; } + + public LargeType_IgnoredProp_Bind_Param(int w, int x, int y, int z, int prop) + => Prop = prop; + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/34779")] + public async Task BindingBetweenRefProps() + { + string json = @"{""NameRef"":""John""}"; + await JsonSerializerWrapperForString.DeserializeWrapper(json); + } + + public class TypeWith_RefStringProp_ParamCtor + { + private string _name; + + public ref string NameRef => ref _name; + + public TypeWith_RefStringProp_ParamCtor(ref string nameRef) => _name = nameRef; + } + + [Fact] + public async Task BindToIgnoredPropOfSameType() + { + string json = @"{""Prop"":{}}"; + Assert.NotNull(await JsonSerializerWrapperForString.DeserializeWrapper(json)); + } + + public class ClassWithIgnoredSameType + { + [JsonIgnore] + public ClassWithIgnoredSameType Prop { get; } + + public ClassWithIgnoredSameType(ClassWithIgnoredSameType prop) { } + } } } diff --git a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs index a2b5845ca44dc..a41380e3e60d9 100644 --- a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs @@ -2742,5 +2742,80 @@ public async Task JsonIgnoreCondition_Polymorphic() Assert.Equal(3, obj.Abstract_Property); Assert.Equal(4, obj.Virtual_Property); } + + [Fact] + public async Task SerializationMetadataNotComputedWhenMemberIgnored() + { + string janePayload = @"{""Name"":""Jane Doe""}"; + +#if !BUILDING_SOURCE_GENERATOR_TESTS + // Without [JsonIgnore], serializer throws exceptions due to runtime-reflection-based property metadata inspection. + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(new TypeWith_RefStringProp())); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{}")); + + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(new TypeWith_PropWith_BadConverter())); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{}")); +#else + // Ref returns supported in source-gen mode + string expected = @"{""NameRef"":""John Doe"",""Name"":""John Doe""}"; + JsonTestHelper.AssertJsonEqual(expected, await JsonSerializerWrapperForString.SerializeWrapper(new TypeWith_RefStringProp())); + + var obj = await JsonSerializerWrapperForString.DeserializeWrapper(janePayload); + Assert.Equal("Jane Doe", obj.Name); + Assert.Equal("Jane Doe", obj.NameRef); + + var obj2 = new TypeWith_PropWith_BadConverter(); + obj2.Property = "Hello"; + + // Invalid converter specified, fallback to built-in converter. This should be corrected. + // https://github.com/dotnet/runtime/issues/60020. + + Assert.Equal(@"{""Property"":""Hello""}", await JsonSerializerWrapperForString.SerializeWrapper(obj2)); + + obj2 = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""Property"":""World""}"); + Assert.Equal("World", obj2.Property); +#endif + + // With [JsonIgnore], serializer skips property metadata inspection + Assert.Equal(@"{""Name"":""John Doe""}", await JsonSerializerWrapperForString.SerializeWrapper(new TypeWith_IgnoredRefStringProp())); + Assert.Equal("Jane Doe", (await JsonSerializerWrapperForString.DeserializeWrapper(janePayload)).Name); + + Assert.Equal("{}", await JsonSerializerWrapperForString.SerializeWrapper(new TypeWith_IgnoredPropWith_BadConverter())); + Assert.Null((await JsonSerializerWrapperForString.DeserializeWrapper("{}")).Property); + } + + internal class TypeWith_RefStringProp + { + public ref string NameRef => ref Name; + + [JsonInclude] // This is a field. + public string Name = "John Doe"; + } + + internal class TypeWith_IgnoredRefStringProp + { + [JsonIgnore] + public ref string NameRef => ref Name; + + [JsonInclude] // This is a field. + public string Name = "John Doe"; + } + + public class TypeWith_PropWith_BadConverter + { + [JsonConverter(typeof(BadConverter))] + public string? Property { get; set; } + } + + public class TypeWith_IgnoredPropWith_BadConverter + { + [JsonIgnore] + [JsonConverter(typeof(BadConverter))] + public string? Property { get; set; } + } + + public class BadConverter + { + } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs index f0d1cb897ce2d..deba91529ef37 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs @@ -125,6 +125,11 @@ protected ConstructorTests_Metadata(JsonSerializerWrapperForString stringWrapper [JsonSerializable(typeof(JsonElement))] [JsonSerializable(typeof(Parameterized_Class_With_ComplexTuple))] [JsonSerializable(typeof(Parameterized_Person_Simple))] + [JsonSerializable(typeof(SmallType_IgnoredProp_Bind_ParamWithDefaultValue))] + [JsonSerializable(typeof(SmallType_IgnoredProp_Bind_Param))] + [JsonSerializable(typeof(LargeType_IgnoredProp_Bind_ParamWithDefaultValue))] + [JsonSerializable(typeof(LargeType_IgnoredProp_Bind_Param))] + [JsonSerializable(typeof(ClassWithIgnoredSameType))] internal sealed partial class ConstructorTestsContext_Metadata : JsonSerializerContext { } @@ -241,6 +246,11 @@ public ConstructorTests_Default() [JsonSerializable(typeof(JsonElement))] [JsonSerializable(typeof(Parameterized_Class_With_ComplexTuple))] [JsonSerializable(typeof(Parameterized_Person_Simple))] + [JsonSerializable(typeof(SmallType_IgnoredProp_Bind_ParamWithDefaultValue))] + [JsonSerializable(typeof(SmallType_IgnoredProp_Bind_Param))] + [JsonSerializable(typeof(LargeType_IgnoredProp_Bind_ParamWithDefaultValue))] + [JsonSerializable(typeof(LargeType_IgnoredProp_Bind_Param))] + [JsonSerializable(typeof(ClassWithIgnoredSameType))] internal sealed partial class ConstructorTestsContext_Default : JsonSerializerContext { } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs index f4858804d6012..3b38cefe23e98 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs @@ -264,6 +264,10 @@ public override async Task HonorJsonPropertyName_PrivateSetter() [JsonSerializable(typeof(ClassWithValueAndReferenceTypes))] [JsonSerializable(typeof(ClassWithReadOnlyStringProperty_IgnoreWhenWritingDefault))] [JsonSerializable(typeof(ConcreteDerivedClass))] + [JsonSerializable(typeof(TypeWith_RefStringProp))] + [JsonSerializable(typeof(TypeWith_IgnoredRefStringProp))] + [JsonSerializable(typeof(TypeWith_PropWith_BadConverter))] + [JsonSerializable(typeof(TypeWith_IgnoredPropWith_BadConverter))] internal sealed partial class PropertyVisibilityTestsContext_Metadata : JsonSerializerContext { } @@ -431,6 +435,10 @@ public override async Task JsonIgnoreCondition_WhenWritingNull_OnValueType_Fail_ [JsonSerializable(typeof(ClassWithValueAndReferenceTypes))] [JsonSerializable(typeof(ClassWithReadOnlyStringProperty_IgnoreWhenWritingDefault))] [JsonSerializable(typeof(ConcreteDerivedClass))] + [JsonSerializable(typeof(TypeWith_RefStringProp))] + [JsonSerializable(typeof(TypeWith_IgnoredRefStringProp))] + [JsonSerializable(typeof(TypeWith_PropWith_BadConverter))] + [JsonSerializable(typeof(TypeWith_IgnoredPropWith_BadConverter))] internal sealed partial class PropertyVisibilityTestsContext_Default : JsonSerializerContext { } diff --git a/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs index 5845e04426661..bc4f615b9878f 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/Regex.Match.Tests.cs @@ -1090,10 +1090,10 @@ public async Task Match_SpecialUnicodeCharacters_Invariant(RegexEngine engine) private static bool IsNotArmProcessAndRemoteExecutorSupported => PlatformDetection.IsNotArmProcess && RemoteExecutor.IsSupported; - [ActiveIssue("https://github.com/dotnet/runtime/issues/59541")] [ConditionalTheory(nameof(IsNotArmProcessAndRemoteExecutorSupported))] // times out on ARM [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, ".NET Framework does not have fix for https://github.com/dotnet/runtime/issues/24749")] - [SkipOnCoreClr("Long running tests: https://github.com/dotnet/runtime/issues/10680", RuntimeConfiguration.Checked, RuntimeTestModes.JitMinOpts)] + [SkipOnCoreClr("Long running tests: https://github.com/dotnet/runtime/issues/10680", RuntimeConfiguration.Checked)] + [SkipOnCoreClr("Long running tests: https://github.com/dotnet/runtime/issues/10680", RuntimeTestModes.JitMinOpts)] [MemberData(nameof(RegexHelpers.AvailableEngines_MemberData), MemberType = typeof(RegexHelpers))] public void Match_ExcessPrefix(RegexEngine engine) { diff --git a/src/libraries/src.proj b/src/libraries/src.proj index 8b38ce5b44939..4e0fea066f750 100644 --- a/src/libraries/src.proj +++ b/src/libraries/src.proj @@ -14,6 +14,11 @@ Microsoft.Windows.Compatibility\src\Microsoft.Windows.Compatibility.csproj" Condition="'$(BuildAllConfigurations)' != 'true'" /> + + <_allSrc Remove="Microsoft.Extensions.DependencyInjection.Specification.Tests\src\Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj; + Microsoft.Windows.Compatibility\src\Microsoft.Windows.Compatibility.csproj" + Condition="'$(DotNetBuildFromSource)' == 'true'" /> + + + + @@ -273,6 +276,10 @@ + + + + diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt index 51c5dda0763d6..58a0a18e80bdf 100644 --- a/src/mono/CMakeLists.txt +++ b/src/mono/CMakeLists.txt @@ -234,6 +234,15 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") # sys/random.h exists, but its not found set(HAVE_SYS_RANDOM_H 1) set(INTERNAL_ZLIB 1) +elseif(CMAKE_SYSTEM_NAME STREQUAL "WASI") + set(HOST_WASI 1) + add_definitions(-D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_MMAN) + add_definitions(-DNO_GLOBALIZATION_SHIM) + add_definitions(-D_THREAD_SAFE) + set(DISABLE_SHARED_LIBS 1) + set(INTERNAL_ZLIB 1) + set(DISABLE_EXECUTABLES 1) + set(DISABLE_COMPONENTS 1) elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") set(HOST_WIN32 1) set(EXE_SUFFIX ".exe") @@ -245,6 +254,7 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") add_compile_options(/W3) # set warning level 3 add_compile_options(/EHsc) # set exception handling behavior add_compile_options(/FC) # use full pathnames in diagnostics + add_link_options(/STACK:0x800000) # set stack size to 8MB (default is 1MB) if(CMAKE_BUILD_TYPE STREQUAL "Release") add_compile_options(/Oi) # enable intrinsics add_compile_options(/GF) # enable string pooling @@ -298,6 +308,8 @@ elseif(TARGET_SYSTEM_NAME STREQUAL "Emscripten") if (CMAKE_BUILD_TYPE STREQUAL "Release") add_compile_options(-Os) endif() +elseif(TARGET_SYSTEM_NAME STREQUAL "WASI") + set(TARGET_WASI 1) elseif(TARGET_SYSTEM_NAME STREQUAL "Windows") set(TARGET_WIN32 1) elseif(TARGET_SYSTEM_NAME STREQUAL "SunOS") @@ -350,7 +362,7 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm") set(NO_UNALIGNED_ACCESS 1) elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "s390x") set(HOST_S390X 1) -elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "wasm") +elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "wasm" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "wasm32") set(HOST_WASM 1) else() message(FATAL_ERROR "CMAKE_SYSTEM_PROCESSOR='${CMAKE_SYSTEM_PROCESSOR}' not supported.") @@ -407,7 +419,7 @@ elseif(TARGET_ARCH STREQUAL "s390x") set(MONO_ARCHITECTURE "\"s390x\"") set(TARGET_SIZEOF_VOID_P 8) set(SIZEOF_REGISTER 8) -elseif(TARGET_ARCH STREQUAL "wasm") +elseif(TARGET_ARCH STREQUAL "wasm" OR TARGET_ARCH STREQUAL "wasm32") set(TARGET_WASM 1) set(MONO_ARCHITECTURE "\"wasm\"") set(TARGET_SIZEOF_VOID_P 4) diff --git a/src/mono/Makefile b/src/mono/Makefile index d2cce8e8bda73..e4c6727b00ad4 100644 --- a/src/mono/Makefile +++ b/src/mono/Makefile @@ -30,7 +30,7 @@ run-sample-coreclr: # build System.Private.CoreLib.dll bcl corelib: - ../.././build.sh -c $(MONO_RUNTIME_CONFIG) -subset Mono.CoreLib + ../.././build.sh -c $(MONO_RUNTIME_CONFIG) -subset Mono.CoreLib+Libs.Pretest # build runtime and copy to artifacts runtime: diff --git a/src/mono/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Mono.cs index 2ec69c7393648..f646ccb652f0b 100644 --- a/src/mono/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Mono.cs @@ -80,6 +80,7 @@ internal static Assembly[] GetLoadedAssemblies() // We only support looking up load context for runtime assemblies. if (rtAsm != null) { + var _ = Default; // ensure the default ALC is initialized. RuntimeAssembly runtimeAssembly = rtAsm; IntPtr ptrAssemblyLoadContext = GetLoadContextForAssembly(runtimeAssembly); loadContextForAssembly = GetAssemblyLoadContext(ptrAssemblyLoadContext); diff --git a/src/mono/cmake/config.h.in b/src/mono/cmake/config.h.in index 96aa8939ade7c..136a22bbe1dd5 100644 --- a/src/mono/cmake/config.h.in +++ b/src/mono/cmake/config.h.in @@ -134,6 +134,15 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UNISTD_H 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SETJMP_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYSLOG_H 1 + /* Define to 1 if `major', `minor', and `makedev' are declared in . */ #cmakedefine MAJOR_IN_MKDEV 1 @@ -623,6 +632,12 @@ /* Have access */ #cmakedefine HAVE_ACCESS 1 +/* Have getpid */ +#cmakedefine HAVE_GETPID 1 + +/* Have mktemp */ +#cmakedefine HAVE_MKTEMP 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_ERRNO_H 1 @@ -839,6 +854,12 @@ /* ... */ #cmakedefine HOST_WASM 1 +/* ... */ +#cmakedefine HOST_BROWSER 1 + +/* ... */ +#cmakedefine HOST_WASI 1 + /* ... */ #cmakedefine HOST_X86 1 diff --git a/src/mono/cmake/configure.cmake b/src/mono/cmake/configure.cmake index 438e71783cc81..5bad48a719b85 100644 --- a/src/mono/cmake/configure.cmake +++ b/src/mono/cmake/configure.cmake @@ -20,6 +20,10 @@ if(HOST_SOLARIS) set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -DGC_SOLARIS_THREADS -DGC_SOLARIS_PTHREADS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -DUSE_MMAP -DUSE_MUNMAP -DHOST_SOLARIS -D__EXTENSIONS__ -D_XPG4_2") endif() +if(HOST_WASI) + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_MMAN") +endif() + function(ac_check_headers) foreach(arg ${ARGN}) check_include_file ("${arg}" FOUND_${arg}) @@ -61,8 +65,8 @@ endfunction() ac_check_headers ( sys/types.h sys/stat.h sys/filio.h sys/sockio.h sys/utime.h sys/un.h sys/syscall.h sys/uio.h sys/param.h sys/sysctl.h sys/prctl.h sys/socket.h sys/utsname.h sys/select.h sys/user.h sys/poll.h sys/wait.h sts/auxv.h sys/resource.h - sys/ioctl.h sys/errno.h sys/sendfile.h sys/statvfs.h sys/statfs.h sys/mman.h sys/mount.h sys/time.h sys/random.h sys/mman.h - strings.h stdint.h unistd.h netdb.h utime.h semaphore.h libproc.h alloca.h ucontext.h pwd.h elf.h + sys/ioctl.h sys/errno.h sys/sendfile.h sys/statvfs.h sys/statfs.h sys/mman.h sys/mount.h sys/time.h sys/random.h + strings.h stdint.h unistd.h signal.h setjmp.h syslog.h netdb.h utime.h semaphore.h libproc.h alloca.h ucontext.h pwd.h elf.h gnu/lib-names.h netinet/tcp.h netinet/in.h link.h arpa/inet.h unwind.h poll.h wchar.h linux/magic.h android/legacy_signal_inlines.h android/ndk-version.h execinfo.h pthread.h pthread_np.h net/if.h dirent.h CommonCrypto/CommonDigest.h dlfcn.h getopt.h pwd.h iconv.h alloca.h @@ -77,7 +81,7 @@ ac_check_funcs ( fork execv execve waitpid localtime_r mkdtemp getrandom execvp strlcpy stpcpy strtok_r rewinddir vasprintf strndup getpwuid_r getprotobyname getprotobyname_r getaddrinfo mach_absolute_time gethrtime read_real_time gethostbyname gethostbyname2 getnameinfo getifaddrs - access inet_ntop Qp2getifaddrs) + access inet_ntop Qp2getifaddrs getpid mktemp) if(NOT HOST_DARWIN) # getentropy was introduced in macOS 10.12 / iOS 10.0 @@ -181,3 +185,14 @@ if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") set(HAVE_SYS_SYSCTL_H 1) set(HAVE_SYS_USER_H 1) endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "WASI") + # Redirected to errno.h + set(SYS_ERRNO_H 0) + # Some headers exist, but don't compile (wasi sdk 12.0) + set(HAVE_SYS_SOCKET_H 0) + set(HAVE_SYS_UN_H 0) + set(HAVE_NETINET_IN_H 0) + set(HAVE_NETINET_TCP_H 0) + set(HAVE_ARPA_INET_H 0) +endif() diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index 7eebeb2455808..71c67a7b5d136 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -79,6 +79,7 @@ #include #include #include +#include #include #include "debugger-agent.h" @@ -5022,7 +5023,7 @@ buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain, MonoObject *obj; gboolean boxed_vtype = FALSE; - if (t->byref) { + if (m_type_is_byref (t)) { if (!(*(void**)addr)) { /* This can happen with compiler generated locals */ //PRINT_MSG ("%s\n", mono_type_full_name (t)); @@ -5698,7 +5699,7 @@ set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domai host_mgreg_t v; gboolean is_signed = FALSE; - if (t->byref) { + if (m_type_is_byref (t)) { addr = (guint8 *)mono_arch_context_get_int_reg (ctx, reg); if (addr) { @@ -5708,7 +5709,7 @@ set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domai break; } - if (!t->byref && (t->type == MONO_TYPE_I1 || t->type == MONO_TYPE_I2 || t->type == MONO_TYPE_I4 || t->type == MONO_TYPE_I8)) + if (!m_type_is_byref (t) && (t->type == MONO_TYPE_I1 || t->type == MONO_TYPE_I2 || t->type == MONO_TYPE_I4 || t->type == MONO_TYPE_I8)) is_signed = TRUE; switch (size) { @@ -5753,7 +5754,7 @@ set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domai //PRINT_MSG ("[R%d+%d] = %p\n", reg, var->offset, addr); - if (t->byref) { + if (m_type_is_byref (t)) { addr = *(guint8**)addr; if (!addr) @@ -6102,7 +6103,7 @@ mono_do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, gu if (args [i] && ((MonoObject*)args [i])->vtable->domain != domain) NOT_IMPLEMENTED; - if (sig->params [i]->byref) { + if (m_type_is_byref (sig->params [i])) { arg_buf [i] = g_newa (guint8, sizeof (gpointer)); *(gpointer*)arg_buf [i] = args [i]; args [i] = arg_buf [i]; @@ -6177,7 +6178,7 @@ mono_do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, gu buffer_add_value (buf, mono_get_void_type_dbg (), NULL, domain); } } else if (MONO_TYPE_IS_REFERENCE (sig->ret)) { - if (sig->ret->byref) { + if (m_type_is_byref (sig->ret)) { MonoType* ret_byval = m_class_get_byval_arg (mono_class_from_mono_type_internal (sig->ret)); buffer_add_value (buf, ret_byval, &res, domain); } else { @@ -6194,7 +6195,7 @@ mono_do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, gu } else { g_assert (res); - if (sig->ret->byref) { + if (m_type_is_byref (sig->ret)) { MonoType* ret_byval = m_class_get_byval_arg (mono_class_from_mono_type_internal (sig->ret)); buffer_add_value (buf, ret_byval, mono_object_unbox_internal (res), domain); } else { @@ -6212,7 +6213,7 @@ mono_do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, gu for (i = 0; i < nargs; ++i) { if (MONO_TYPE_IS_REFERENCE (sig->params [i])) buffer_add_value (buf, sig->params [i], &args [i], domain); - else if (sig->params [i]->byref) + else if (m_type_is_byref (sig->params [i])) /* add_value () does an indirection */ buffer_add_value (buf, sig->params [i], &arg_buf [i], domain); else @@ -7891,7 +7892,7 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint b |= (1 << 0); if (type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) b |= (1 << 1); - if (!type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U))) + if (!m_type_is_byref (type) && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U))) b |= (1 << 2); if (type->type == MONO_TYPE_VALUETYPE) b |= (1 << 3); @@ -9513,7 +9514,7 @@ create_file_to_check_memory_address (void) { if (file_check_valid_memory != -1) return; - char *file_name = g_strdup_printf ("debugger_check_valid_memory.%d", getpid()); + char *file_name = g_strdup_printf ("debugger_check_valid_memory.%d", mono_process_current_pid ()); filename_check_valid_memory = g_build_filename (g_get_tmp_dir (), file_name, (const char*)NULL); file_check_valid_memory = open(filename_check_valid_memory, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR); g_free (file_name); diff --git a/src/mono/mono/component/debugger-engine.c b/src/mono/mono/component/debugger-engine.c index 7310283357178..004dddab633c9 100644 --- a/src/mono/mono/component/debugger-engine.c +++ b/src/mono/mono/component/debugger-engine.c @@ -1733,7 +1733,7 @@ mono_de_set_interp_var (MonoType *t, gpointer addr, guint8 *val_buf) { int size; - if (t->byref) { + if (m_type_is_byref (t)) { addr = *(gpointer*)addr; if (!addr) return ERR_INVALID_OBJECT; diff --git a/src/mono/mono/component/debugger-stub.c b/src/mono/mono/component/debugger-stub.c index 1296bd2235247..224f531f79648 100644 --- a/src/mono/mono/component/debugger-stub.c +++ b/src/mono/mono/component/debugger-stub.c @@ -204,7 +204,7 @@ stub_send_enc_delta (MonoImage *image, gconstpointer dmeta_bytes, int32_t dmeta_ { } -#ifdef HOST_WASM +#ifdef HOST_BROWSER #include @@ -229,6 +229,4 @@ mono_wasm_send_dbg_command (int id, int command_set, int command, guint8* data, return false; } -#endif // HOST_WASM - - +#endif // HOST_BROWSER diff --git a/src/mono/mono/component/mini-wasm-debugger.c b/src/mono/mono/component/mini-wasm-debugger.c index f70738d7cb0c1..77ceed873a245 100644 --- a/src/mono/mono/component/mini-wasm-debugger.c +++ b/src/mono/mono/component/mini-wasm-debugger.c @@ -68,8 +68,8 @@ void wasm_debugger_log (int level, const gchar *format, ...) var message = Module.UTF8ToString ($1); var namespace = "Debugger.Debug"; - if (MONO["logging"] && MONO.logging["debugger"]) { - MONO.logging.debugger (level, message); + if (INTERNAL["logging"] && INTERNAL.logging["debugger"]) { + INTERNAL.logging.debugger (level, message); return; } @@ -375,7 +375,7 @@ mono_wasm_send_dbg_command_with_parms (int id, MdbgProtCommandSet command_set, i m_dbgprot_buffer_add_data (&bufWithParms, data, size); if (!write_value_to_buffer(&bufWithParms, valtype, newvalue)) { EM_ASM ({ - MONO.mono_wasm_add_dbg_command_received ($0, $1, $2, $3); + INTERNAL.mono_wasm_add_dbg_command_received ($0, $1, $2, $3); }, 0, id, 0, 0); return TRUE; } @@ -403,7 +403,7 @@ mono_wasm_send_dbg_command (int id, MdbgProtCommandSet command_set, int command, else error = mono_process_dbg_packet (id, command_set, command, &no_reply, data, data + size, &buf); EM_ASM ({ - MONO.mono_wasm_add_dbg_command_received ($0, $1, $2, $3); + INTERNAL.mono_wasm_add_dbg_command_received ($0, $1, $2, $3); }, error == MDBGPROT_ERR_NONE, id, buf.buf, buf.p-buf.buf); buffer_free (&buf); @@ -414,7 +414,7 @@ static gboolean receive_debugger_agent_message (void *data, int len) { EM_ASM ({ - MONO.mono_wasm_add_dbg_command_received (1, -1, $0, $1); + INTERNAL.mono_wasm_add_dbg_command_received (1, -1, $0, $1); }, data, len); mono_wasm_save_thread_context(); mono_wasm_fire_debugger_agent_message (); diff --git a/src/mono/mono/eventpipe/CMakeLists.txt b/src/mono/mono/eventpipe/CMakeLists.txt index 530abd5908667..2aef7f44378ca 100644 --- a/src/mono/mono/eventpipe/CMakeLists.txt +++ b/src/mono/mono/eventpipe/CMakeLists.txt @@ -1,6 +1,6 @@ -if(ENABLE_PERFTRACING) +include(${MONO_EVENTPIPE_SHIM_SOURCE_PATH}/gen-eventing.cmake) - include(${MONO_EVENTPIPE_SHIM_SOURCE_PATH}/gen-eventing.cmake) +if(ENABLE_PERFTRACING) if (FEATURE_PERFTRACING_PAL_TCP) add_definitions(-DENABLE_PERFTRACING_PAL_TCP) diff --git a/src/mono/mono/eventpipe/gen-eventing.cmake b/src/mono/mono/eventpipe/gen-eventing.cmake index ffb92c99cdc7b..71a0520b74099 100644 --- a/src/mono/mono/eventpipe/gen-eventing.cmake +++ b/src/mono/mono/eventpipe/gen-eventing.cmake @@ -94,5 +94,7 @@ if(ENABLE_PERFTRACING) add_custom_target(${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME}-gen-sources DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME}-gen-sources.timestamp ${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME}-gen-headers) - +else(ENABLE_PERFTRACING) + add_custom_target(${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME}-gen-headers) + add_custom_target(${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME}-gen-sources) endif(ENABLE_PERFTRACING) diff --git a/src/mono/mono/metadata/assembly.c b/src/mono/mono/metadata/assembly.c index 235d1645fdcc9..6f14674683a86 100644 --- a/src/mono/mono/metadata/assembly.c +++ b/src/mono/mono/metadata/assembly.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -594,7 +595,7 @@ mono_set_rootdir (void) } /* Solaris 10 style */ - str = g_strdup_printf ("/proc/%d/path/a.out", getpid ()); + str = g_strdup_printf ("/proc/%d/path/a.out", mono_process_current_pid ()); #if defined(HAVE_READLINK) s = readlink (str, buf, sizeof (buf)-1); diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index f591daee162bf..86eadc64a1193 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -493,7 +493,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) { /*WARNING: this must satisfy mono_metadata_type_hash*/ - klass->this_arg.byref = 1; + klass->this_arg.byref__ = 1; klass->this_arg.data.klass = klass; klass->this_arg.type = MONO_TYPE_CLASS; klass->_byval_arg.data.klass = klass; @@ -846,7 +846,7 @@ mono_class_create_generic_inst (MonoGenericClass *gclass) klass->_byval_arg.type = MONO_TYPE_GENERICINST; klass->this_arg.type = m_class_get_byval_arg (klass)->type; klass->this_arg.data.generic_class = klass->_byval_arg.data.generic_class = gclass; - klass->this_arg.byref = TRUE; + klass->this_arg.byref__ = TRUE; klass->enumtype = gklass->enumtype; klass->valuetype = gklass->valuetype; @@ -1148,7 +1148,7 @@ mono_class_create_bounded_array (MonoClass *eclass, guint32 rank, gboolean bound klass->_byval_arg.data.klass = eclass; } klass->this_arg = klass->_byval_arg; - klass->this_arg.byref = 1; + klass->this_arg.byref__ = 1; if (rank > 32) { ERROR_DECL (prepared_error); @@ -1321,7 +1321,7 @@ make_generic_param_class (MonoGenericParam *param) klass->this_arg.type = t; CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param ); CHECKED_METADATA_WRITE_PTR ( klass->_byval_arg.data.generic_param , param ); - klass->this_arg.byref = TRUE; + klass->this_arg.byref__ = TRUE; /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */ klass->sizes.generic_param_token = !is_anonymous ? pinfo->token : 0; @@ -1464,7 +1464,7 @@ mono_class_create_ptr (MonoType *type) result->this_arg.type = result->_byval_arg.type = MONO_TYPE_PTR; result->this_arg.data.type = result->_byval_arg.data.type = m_class_get_byval_arg (el_class); - result->this_arg.byref = TRUE; + result->this_arg.byref__ = TRUE; mono_class_setup_supertypes (result); @@ -1529,7 +1529,7 @@ mono_class_create_fnptr (MonoMethodSignature *sig) result->cast_class = result->element_class = result; result->this_arg.type = result->_byval_arg.type = MONO_TYPE_FNPTR; result->this_arg.data.method = result->_byval_arg.data.method = sig; - result->this_arg.byref = TRUE; + result->this_arg.byref__ = TRUE; result->blittable = TRUE; result->inited = TRUE; @@ -1805,7 +1805,7 @@ type_has_references (MonoClass *klass, MonoType *ftype) { if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type_internal (ftype))))) return TRUE; - if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) { + if (!m_type_is_byref (ftype) && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) { MonoGenericParam *gparam = ftype->data.generic_param; if (gparam->gshared_constraint) @@ -1974,7 +1974,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; if (blittable) { - if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) { + if (m_type_is_byref (field->type) || MONO_TYPE_IS_REFERENCE (field->type)) { blittable = FALSE; } else if (mono_type_is_generic_parameter (field->type) && mono_class_is_gparam_with_nonblittable_parent (mono_class_from_mono_type_internal (field->type))) { @@ -3102,7 +3102,7 @@ mono_class_setup_mono_type (MonoClass *klass) const char *nspace = klass->name_space; gboolean is_corlib = mono_is_corlib_image (klass->image); - klass->this_arg.byref = 1; + klass->this_arg.byref__ = 1; klass->this_arg.data.klass = klass; klass->this_arg.type = MONO_TYPE_CLASS; klass->_byval_arg.data.klass = klass; diff --git a/src/mono/mono/metadata/class-setup-vtable.c b/src/mono/mono/metadata/class-setup-vtable.c index 73015f3753df6..69dea4e592d74 100644 --- a/src/mono/mono/metadata/class-setup-vtable.c +++ b/src/mono/mono/metadata/class-setup-vtable.c @@ -1421,10 +1421,10 @@ vtable_slot_has_preserve_base_overrides_attribute (MonoClass *klass, int slot, M static gboolean is_ok_for_covariant_ret (MonoType *type_impl, MonoType *type_decl) { - if (type_impl->byref ^ type_decl->byref) + if (m_type_is_byref (type_impl) ^ m_type_is_byref (type_decl)) return FALSE; - if (type_impl->byref) { + if (m_type_is_byref (type_impl)) { return mono_byref_type_is_assignable_from (type_decl, type_impl, TRUE); } diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index 6c816c174ab01..9c9ab6be663ef 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -283,7 +283,7 @@ _mono_type_get_assembly_name (MonoClass *klass, GString *str) static void mono_type_name_check_byref (MonoType *type, GString *str) { - if (type->byref) + if (m_type_is_byref (type)) g_string_append_c (str, '&'); } @@ -575,9 +575,9 @@ mono_type_get_name (MonoType *type) MonoType* mono_type_get_underlying_type (MonoType *type) { - if (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (type->data.klass) && !type->byref) + if (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (type->data.klass) && !m_type_is_byref (type)) return mono_class_enum_basetype_internal (type->data.klass); - if (type->type == MONO_TYPE_GENERICINST && m_class_is_enumtype (type->data.generic_class->container_class) && !type->byref) + if (type->type == MONO_TYPE_GENERICINST && m_class_is_enumtype (type->data.generic_class->container_class) && !m_type_is_byref (type)) return mono_class_enum_basetype_internal (type->data.generic_class->container_class); return type; } @@ -708,7 +708,7 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont * ->byref and ->attrs from @type are propagated to the returned type. */ nt = mono_metadata_type_dup_with_cmods (image, inst->type_argv [num], type); - nt->byref = type->byref; + nt->byref__ = type->byref__; nt->attrs = type->attrs; return nt; } @@ -750,7 +750,7 @@ inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *cont #endif nt = mono_metadata_type_dup_with_cmods (image, inst->type_argv [num], type); - nt->byref = type->byref || inst->type_argv[num]->byref; + nt->byref__ = type->byref__ || inst->type_argv[num]->byref__; nt->attrs = type->attrs; #ifdef DEBUG_INFLATE_CMODS if (append_cmods) { @@ -1691,7 +1691,7 @@ MonoType* mono_type_get_basic_type_from_generic (MonoType *type) { /* When we do generic sharing we let type variables stand for reference/primitive types. */ - if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && + if (!m_type_is_byref (type) && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT)) return mono_get_object_type (); return type; @@ -3782,8 +3782,8 @@ mono_type_get_underlying_type_ignore_byref (MonoType *type) gboolean mono_byref_type_is_assignable_from (MonoType *type, MonoType *ctype, gboolean signature_assignment) { - g_assert (type->byref); - g_assert (ctype->byref); + g_assert (m_type_is_byref (type)); + g_assert (m_type_is_byref (ctype)); MonoType *t = mono_type_get_underlying_type_ignore_byref (type); MonoType *ot = mono_type_get_underlying_type_ignore_byref (ctype); diff --git a/src/mono/mono/metadata/debug-helpers.c b/src/mono/mono/metadata/debug-helpers.c index 51a4391bcd1ce..2eddf8a35103a 100644 --- a/src/mono/mono/metadata/debug-helpers.c +++ b/src/mono/mono/metadata/debug-helpers.c @@ -235,7 +235,7 @@ mono_type_get_desc (GString *res, MonoType *type, gboolean include_namespace) if (type->has_cmods) { mono_custom_modifiers_get_desc (res, type, include_namespace); } - if (type->byref) + if (m_type_is_byref (type)) g_string_append_c (res, '&'); } diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index c48f2b1199a0d..8a01903ab30a8 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -160,7 +160,7 @@ type_array_from_modifiers (MonoType *type, int optional, MonoError *error); static inline MonoBoolean is_generic_parameter (MonoType *type) { - return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR); + return !m_type_is_byref (type) && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR); } #ifdef HOST_WIN32 @@ -708,7 +708,7 @@ ves_icall_System_Array_InternalCreate (MonoArray *volatile* result, MonoType* ty goto exit; } - if (type->byref || m_class_is_byreflike (klass)) { + if (m_type_is_byref (type) || m_class_is_byreflike (klass)) { mono_error_set_not_supported (error, NULL); goto exit; } @@ -1092,7 +1092,7 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetUninitializedObjectI return NULL_HANDLE; } - if (mono_class_is_array (klass) || mono_class_is_pointer (klass) || handle->byref) { + if (mono_class_is_array (klass) || mono_class_is_pointer (klass) || m_type_is_byref (handle)) { mono_error_set_argument (error, NULL, NULL); return NULL_HANDLE; } @@ -1709,10 +1709,10 @@ ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionTypeHandle re MonoType *ctype = MONO_HANDLE_GETVAL (ref_c, type); MonoClass *klassc = mono_class_from_mono_type_internal (ctype); - if (type->byref ^ ctype->byref) + if (m_type_is_byref (type) ^ m_type_is_byref (ctype)) return FALSE; - if (type->byref) { + if (m_type_is_byref (type)) { return mono_byref_type_is_assignable_from (type, ctype, FALSE); } @@ -1732,12 +1732,12 @@ ves_icall_RuntimeTypeHandle_is_subclass_of (MonoType *childType, MonoType *baseT childClass = mono_class_from_mono_type_internal (childType); baseClass = mono_class_from_mono_type_internal (baseType); - if (G_UNLIKELY (childType->byref)) { - result = !baseType->byref && baseClass == mono_defaults.object_class; + if (G_UNLIKELY (m_type_is_byref (childType))) { + result = !m_type_is_byref (baseType) && baseClass == mono_defaults.object_class; goto done; } - if (G_UNLIKELY (baseType->byref)) { + if (G_UNLIKELY (m_type_is_byref (baseType))) { result = FALSE; goto done; } @@ -1792,7 +1792,7 @@ ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionTypeHandle ref_type, Mo { MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); - if (type->byref || type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) + if (m_type_is_byref (type) || type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) return TYPE_ATTRIBUTE_NOT_PUBLIC; MonoClass *klass = mono_class_from_mono_type_internal (type); @@ -2022,7 +2022,7 @@ ves_icall_RuntimeFieldInfo_SetValueInternal (MonoReflectionFieldHandle field, Mo gboolean isref = FALSE; MonoGCHandle value_gchandle = 0; gchar *v = NULL; - if (!type->byref) { + if (!m_type_is_byref (type)) { switch (type->type) { case MONO_TYPE_U1: case MONO_TYPE_I1: @@ -2684,7 +2684,7 @@ ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionTypeHandle ref_type, M { MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); - if (!type->byref && type->type == MONO_TYPE_SZARRAY) + if (!m_type_is_byref (type) && type->type == MONO_TYPE_SZARRAY) return mono_type_get_object_handle (m_class_get_byval_arg (type->data.klass), error); MonoClass *klass = mono_class_from_mono_type_internal (type); @@ -2693,7 +2693,7 @@ ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionTypeHandle ref_type, M // GetElementType should only return a type for: // Array Pointer PassedByRef - if (type->byref) + if (m_type_is_byref (type)) return mono_type_get_object_handle (m_class_get_byval_arg (klass), error); else if (m_class_get_element_class (klass) && MONO_CLASS_IS_ARRAY (klass)) return mono_type_get_object_handle (m_class_get_byval_arg (m_class_get_element_class (klass)), error); @@ -2708,7 +2708,7 @@ ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionTypeHandle ref_type, Mono { MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); - if (type->byref) + if (m_type_is_byref (type)) return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE); MonoClass *klass = mono_class_from_mono_type_internal (type); @@ -2723,7 +2723,7 @@ ves_icall_RuntimeTypeHandle_GetCorElementType (MonoReflectionTypeHandle ref_type { MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); - if (type->byref) + if (m_type_is_byref (type)) return MONO_TYPE_BYREF; else return (guint32)type->type; @@ -2745,7 +2745,7 @@ ves_icall_RuntimeTypeHandle_IsByRefLike (MonoReflectionTypeHandle ref_type, Mono { MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); /* .NET Core says byref types are not IsByRefLike */ - if (type->byref) + if (m_type_is_byref (type)) return FALSE; MonoClass *klass = mono_class_from_mono_type_internal (type); return m_class_is_byreflike (klass); @@ -2791,7 +2791,7 @@ ves_icall_RuntimeType_get_DeclaringType (MonoReflectionTypeHandle ref_type, Mono MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); MonoClass *klass; - if (type->byref) + if (m_type_is_byref (type)) return MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE); if (type->type == MONO_TYPE_VAR) { MonoGenericContainer *param = mono_type_get_generic_param_owner (type); @@ -2818,7 +2818,7 @@ ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *err // Determining exactly when to do so is fairly difficult, so for now we don't bother to avoid regressions const char *klass_name = m_class_get_name (klass); - if (type->byref) { + if (m_type_is_byref (type)) { char *n = g_strdup_printf ("%s&", klass_name); MonoStringHandle res = mono_string_new_handle (n, error); @@ -2927,7 +2927,7 @@ ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionTypeHandle re return FALSE; MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); - if (type->byref) + if (m_type_is_byref (type)) return FALSE; MonoClass *klass = mono_class_from_mono_type_internal (type); @@ -2942,7 +2942,7 @@ ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionTypeHan MonoReflectionTypeHandle ret = MONO_HANDLE_NEW (MonoReflectionType, NULL); - if (type->byref) + if (m_type_is_byref (type)) goto leave; MonoClass *klass; @@ -3016,7 +3016,7 @@ ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionTypeHandle ref_type, return FALSE; MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); - if (type->byref) + if (m_type_is_byref (type)) return FALSE; klass = mono_class_from_mono_type_internal (type); @@ -3085,7 +3085,7 @@ ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionTypeHandle ref_type, Mo MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); MonoReflectionMethodHandle ret = MONO_HANDLE_NEW (MonoReflectionMethod, NULL); - if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) { + if (m_type_is_byref (type) || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) { mono_error_set_invalid_operation (error, "DeclaringMethod can only be used on generic arguments"); goto leave; } @@ -3416,7 +3416,7 @@ ves_icall_InternalInvoke (MonoReflectionMethodHandle method_handle, MonoObjectHa goto return_null; } - if (sig->ret->byref) { + if (m_type_is_byref (sig->ret)) { MonoType* ret_byval = m_class_get_byval_arg (mono_class_from_mono_type_internal (sig->ret)); if (ret_byval->type == MONO_TYPE_VOID) { exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "ByRef to void return values are not supported in reflection invocation"); @@ -3749,7 +3749,7 @@ ves_icall_RuntimeType_GetFields_native (MonoReflectionTypeHandle ref_type, char error_init (error); MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); - if (type->byref) { + if (m_type_is_byref (type)) { return g_ptr_array_new (); } @@ -3942,7 +3942,7 @@ ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionTypeHandle ref_type MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); MonoClass *klass = mono_class_from_mono_type_internal (type); - if (type->byref) { + if (m_type_is_byref (type)) { return g_ptr_array_new (); } @@ -3953,7 +3953,7 @@ GPtrArray* ves_icall_RuntimeType_GetConstructors_native (MonoReflectionTypeHandle ref_type, guint32 bflags, MonoError *error) { MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); - if (type->byref) { + if (m_type_is_byref (type)) { return g_ptr_array_new (); } @@ -4072,7 +4072,7 @@ ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionTypeHandle ref_t bflags |= BFLAGS_NonPublic; MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); - if (type->byref) { + if (m_type_is_byref (type)) { return g_ptr_array_new (); } @@ -4182,7 +4182,7 @@ ves_icall_RuntimeType_GetEvents_native (MonoReflectionTypeHandle ref_type, char { MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); - if (type->byref) { + if (m_type_is_byref (type)) { return g_ptr_array_new (); } @@ -4253,7 +4253,7 @@ ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionTypeHandle ref_type, { MonoType *type = MONO_HANDLE_GETVAL (ref_type, type); - if (type->byref) { + if (m_type_is_byref (type)) { return g_ptr_array_new (); } @@ -6047,7 +6047,7 @@ check_for_invalid_array_type (MonoType *type, MonoError *error) error_init (error); - if (type->byref) + if (m_type_is_byref (type)) allowed = FALSE; else if (type->type == MONO_TYPE_TYPEDBYREF) allowed = FALSE; @@ -6293,6 +6293,11 @@ ves_icall_System_Environment_get_TickCount64 (void) gpointer ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method, MonoError *error) { + /* WISH: we should do this in managed */ + if (G_UNLIKELY (mono_method_has_unmanaged_callers_only_attribute (method))) { + method = mono_marshal_get_managed_wrapper (method, NULL, (MonoGCHandle)0, error); + return_val_if_nok (error, NULL); + } return mono_get_runtime_callbacks ()->get_ftnptr (method, error); } diff --git a/src/mono/mono/metadata/marshal-ilgen.c b/src/mono/mono/metadata/marshal-ilgen.c index 7d8e9f0743b52..0741b7ebe1f71 100644 --- a/src/mono/mono/metadata/marshal-ilgen.c +++ b/src/mono/mono/metadata/marshal-ilgen.c @@ -1162,7 +1162,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje int t; //XXX a byref field!?!? that's not allowed! and worse, it might miss a WB - g_assert (!ftype->byref); + g_assert (!m_type_is_byref (ftype)); if (ftype->type == MONO_TYPE_I || ftype->type == MONO_TYPE_U) { mono_mb_emit_ldloc (mb, 1); mono_mb_emit_ldloc (mb, 0); @@ -1442,7 +1442,7 @@ mono_mb_emit_restore_result (MonoMethodBuilder *mb, MonoType *return_type) MonoType *t = mono_type_get_underlying_type (return_type); MonoType *int_type = mono_get_int_type (); - if (return_type->byref) + if (m_type_is_byref (return_type)) return_type = int_type; switch (t->type) { @@ -1542,7 +1542,7 @@ emit_invoke_call (MonoMethodBuilder *mb, MonoMethod *method, mono_mb_emit_byte (mb, CEE_ADD); } - if (t->byref) { + if (m_type_is_byref (t)) { mono_mb_emit_byte (mb, CEE_LDIND_I); /* A Nullable type don't have a boxed form, it's either null or a boxed T. * So to make this work we unbox it to a local variablee and push a reference to that. @@ -1628,7 +1628,7 @@ emit_invoke_call (MonoMethodBuilder *mb, MonoMethod *method, mono_mb_emit_calli (mb, callsig); } - if (sig->ret->byref) { + if (m_type_is_byref (sig->ret)) { /* perform indirect load and return by value */ int pos; mono_mb_emit_byte (mb, CEE_DUP); @@ -1638,7 +1638,7 @@ emit_invoke_call (MonoMethodBuilder *mb, MonoMethod *method, int ldind_op; MonoType* ret_byval = m_class_get_byval_arg (mono_class_from_mono_type_internal (sig->ret)); - g_assert (!ret_byval->byref); + g_assert (!m_type_is_byref (ret_byval)); // TODO: Handle null references ldind_op = mono_type_to_ldind (ret_byval); /* taken from similar code in mini-generic-sharing.c @@ -1701,7 +1701,7 @@ emit_invoke_call (MonoMethodBuilder *mb, MonoMethod *method, * Box the result and put it back into the array, the caller will have * to obtain it from there. */ - if (t->byref && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type_internal (t))) { + if (m_type_is_byref (t) && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type_internal (t))) { mono_mb_emit_ldarg (mb, 1); mono_mb_emit_icon (mb, TARGET_SIZEOF_VOID_P * i); mono_mb_emit_byte (mb, CEE_ADD); @@ -2184,7 +2184,7 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi gc_safe_transition_builder_cleanup (&gc_safe_transition_builder); /* convert the result */ - if (!sig->ret->byref) { + if (!m_type_is_byref (sig->ret)) { MonoMarshalSpec *spec = mspecs [0]; type = sig->ret->type; @@ -2446,7 +2446,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, if (m_class_is_blittable (eklass)) { mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_icall_id (mb, conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY, NULL)); mono_mb_emit_stloc (mb, conv_arg); @@ -2481,7 +2481,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, src_var = mono_mb_add_local (mb, object_type); mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_stloc (mb, src_var); @@ -2584,18 +2584,18 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, param_type = m->sig->params [param_num]; - if (param_type->byref && param_type->type != MONO_TYPE_I4) { + if (m_type_is_byref (param_type) && param_type->type != MONO_TYPE_I4) { char *msg = g_strdup ("Not implemented."); mono_mb_emit_exception_marshal_directive (mb, msg); break; } - if (t->byref ) { + if (m_type_is_byref (t) ) { mono_mb_emit_ldarg (mb, argnum); /* Create the managed array */ mono_mb_emit_ldarg (mb, param_num); - if (m->sig->params [param_num]->byref) + if (m_type_is_byref (m->sig->params [param_num])) // FIXME: Support other types mono_mb_emit_byte (mb, CEE_LDIND_I4); mono_mb_emit_byte (mb, CEE_CONV_OVF_I); @@ -2621,7 +2621,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, /* Check null */ mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I); label1 = mono_mb_emit_branch (mb, CEE_BRFALSE); @@ -2635,7 +2635,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, label2 = mono_mb_get_label (mb); mono_mb_emit_ldloc (mb, index_var); mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_REF); mono_mb_emit_byte (mb, CEE_LDLEN); label3 = mono_mb_emit_branch (mb, CEE_BGE); @@ -2650,7 +2650,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, /* dest */ mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_ldloc (mb, index_var); mono_mb_emit_byte (mb, CEE_LDELEM_REF); @@ -2686,7 +2686,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, /* set dst_ptr */ mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_REF); mono_mb_emit_ldloc (mb, index_var); mono_mb_emit_op (mb, CEE_LDELEMA, eklass); @@ -2718,7 +2718,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, /* free memory allocated (if any) by MONO_MARSHAL_CONV_ARRAY_LPARRAY */ mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_REF); mono_mb_emit_ldloc (mb, conv_arg); mono_mb_emit_icall_id (mb, conv_to_icall (MONO_MARSHAL_FREE_LPARRAY, NULL)); @@ -2728,7 +2728,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } case MARSHAL_ACTION_PUSH: - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_ldloc_addr (mb, conv_arg); else mono_mb_emit_ldloc (mb, conv_arg); @@ -2750,7 +2750,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, conv_arg = mono_mb_add_local (mb, object_type); *conv_arg_type = int_type; - if (t->byref) { + if (m_type_is_byref (t)) { char *msg = g_strdup ("Byref array marshalling to managed code is not implemented."); mono_mb_emit_exception_marshal_directive (mb, msg); return conv_arg; @@ -2952,7 +2952,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, break; /* These are already checked in CONV_IN */ - g_assert (!t->byref); + g_assert (!m_type_is_byref (t)); g_assert (spec->native == MONO_NATIVE_LPARRAY); g_assert (t->attrs & PARAM_ATTRIBUTE_OUT); @@ -3071,7 +3071,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalConv conv = MONO_MARSHAL_CONV_INVALID; gboolean is_string = FALSE; - g_assert (!t->byref); + g_assert (!m_type_is_byref (t)); mono_marshal_load_type_info (eklass); @@ -3239,14 +3239,14 @@ emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, guint8 ldc_op = CEE_LDC_I4_1; local_type = mono_marshal_boolean_conv_in_get_local_type (spec, &ldc_op); - if (t->byref) + if (m_type_is_byref (t)) *conv_arg_type = int_type; else *conv_arg_type = local_type; conv_arg = mono_mb_add_local (mb, local_type); mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I1); label_false = mono_mb_emit_branch (mb, CEE_BRFALSE); mono_mb_emit_byte (mb, ldc_op); @@ -3259,7 +3259,7 @@ emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, case MARSHAL_ACTION_CONV_OUT: { int label_false, label_end; - if (!t->byref) + if (!m_type_is_byref (t)) break; mono_mb_emit_ldarg (mb, argnum); @@ -3278,7 +3278,7 @@ emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } case MARSHAL_ACTION_PUSH: - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_ldloc_addr (mb, conv_arg); else if (conv_arg) mono_mb_emit_ldloc (mb, conv_arg); @@ -3299,7 +3299,7 @@ emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, conv_arg_class = mono_marshal_boolean_managed_conv_in_get_conv_arg_class (spec, &ldop); conv_arg = mono_mb_add_local (mb, boolean_type); - if (t->byref) + if (m_type_is_byref (t)) *conv_arg_type = m_class_get_this_arg (conv_arg_class); else *conv_arg_type = m_class_get_byval_arg (conv_arg_class); @@ -3308,7 +3308,7 @@ emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldarg (mb, argnum); /* Check null */ - if (t->byref) { + if (m_type_is_byref (t)) { label_null = mono_mb_emit_branch (mb, CEE_BRFALSE); mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_byte (mb, ldop); @@ -3320,7 +3320,7 @@ emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_stloc (mb, conv_arg); mono_mb_patch_branch (mb, label_false); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_patch_branch (mb, label_null); break; } @@ -3330,7 +3330,7 @@ emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, guint8 ldc_op = CEE_LDC_I4_1; int label_null,label_false, label_end; - if (!t->byref) + if (!m_type_is_byref (t)) break; if (spec) { switch (spec->native) { @@ -4463,7 +4463,7 @@ emit_thunk_invoke_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *method, Mono /* byref args & and the "this" arg must remain a ptr. Otherwise make a copy of the value type */ - if (!(csig->params [i]->byref || (i == 0 && sig->hasthis))) + if (!(m_type_is_byref (csig->params [i]) || (i == 0 && sig->hasthis))) mono_mb_emit_op (mb, CEE_LDOBJ, klass); csig->params [i] = object_type; @@ -4634,23 +4634,23 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, CEE_LDNULL); mono_mb_emit_stloc (mb, conv_arg); - if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) + if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) break; /* Minic MS.NET behavior */ - if (!t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT) && !(t->attrs & PARAM_ATTRIBUTE_IN)) + if (!m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT) && !(t->attrs & PARAM_ATTRIBUTE_IN)) break; /* Check for null */ mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I); pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE); emit_marshal_custom_get_instance (mb, mklass, spec); mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_REF); if (t->type == MONO_TYPE_VALUETYPE) { @@ -4674,7 +4674,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldloc (mb, conv_arg); pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE); - if (t->byref) { + if (m_type_is_byref (t)) { mono_mb_emit_ldarg (mb, argnum); emit_marshal_custom_get_instance (mb, mklass, spec); @@ -4702,7 +4702,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, break; case MARSHAL_ACTION_PUSH: - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_ldloc_addr (mb, conv_arg); else mono_mb_emit_ldloc (mb, conv_arg); @@ -4739,19 +4739,19 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, CEE_LDNULL); mono_mb_emit_stloc (mb, conv_arg); - if (t->byref && t->attrs & PARAM_ATTRIBUTE_OUT) + if (m_type_is_byref (t) && t->attrs & PARAM_ATTRIBUTE_OUT) break; /* Check for null */ mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I); pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE); emit_marshal_custom_get_instance (mb, mklass, spec); mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed); @@ -4761,7 +4761,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, break; case MARSHAL_ACTION_MANAGED_CONV_RESULT: - g_assert (!t->byref); + g_assert (!m_type_is_byref (t)); loc1 = mono_mb_add_local (mb, object_type); @@ -4793,7 +4793,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldloc (mb, conv_arg); pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE); - if (t->byref) { + if (m_type_is_byref (t)) { mono_mb_emit_ldarg (mb, argnum); emit_marshal_custom_get_instance (mb, mklass, spec); @@ -4832,7 +4832,7 @@ emit_marshal_asany_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalNative encoding = mono_marshal_get_string_encoding (m->piinfo, NULL); g_assert (t->type == MONO_TYPE_OBJECT); - g_assert (!t->byref); + g_assert (!m_type_is_byref (t)); conv_arg = mono_mb_add_local (mb, int_type); mono_mb_emit_ldarg (mb, argnum); @@ -4888,13 +4888,13 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, conv_arg = mono_mb_add_local (mb, double_type); - if (t->byref) { + if (m_type_is_byref (t)) { mono_mb_emit_ldarg (mb, argnum); pos = mono_mb_emit_branch (mb, CEE_BRFALSE); } - if (!(t->byref && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))) { - if (!t->byref) + if (!(m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))) { + if (!m_type_is_byref (t)) m->csig->params [argnum - m->csig->hasthis] = double_type; MONO_STATIC_POINTER_INIT (MonoMethod, to_oadate) @@ -4907,7 +4907,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_stloc (mb, conv_arg); } - if (t->byref) + if (m_type_is_byref (t)) mono_mb_patch_branch (mb, pos); break; } @@ -4918,7 +4918,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, conv_arg = mono_mb_add_local (mb, int_type); /* store the address of the source into local variable 0 */ - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_ldarg (mb, argnum); else mono_mb_emit_ldarg_addr (mb, argnum); @@ -4932,12 +4932,12 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, CEE_LOCALLOC); mono_mb_emit_stloc (mb, conv_arg); - if (t->byref) { + if (m_type_is_byref (t)) { mono_mb_emit_ldloc (mb, 0); pos = mono_mb_emit_branch (mb, CEE_BRFALSE); } - if (!(t->byref && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))) { + if (!(m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))) { /* set dst_ptr */ mono_mb_emit_ldloc (mb, conv_arg); mono_mb_emit_stloc (mb, 1); @@ -4946,14 +4946,14 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, emit_struct_conv (mb, klass, FALSE); } - if (t->byref) + if (m_type_is_byref (t)) mono_mb_patch_branch (mb, pos); break; case MARSHAL_ACTION_PUSH: if (spec && spec->native == MONO_NATIVE_LPSTRUCT) { /* FIXME: */ - g_assert (!t->byref); + g_assert (!m_type_is_byref (t)); /* Have to change the signature since the vtype is passed byref */ m->csig->params [argnum - m->csig->hasthis] = int_type; @@ -4966,7 +4966,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } if (klass == date_time_class) { - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_ldloc_addr (mb, conv_arg); else mono_mb_emit_ldloc (mb, conv_arg); @@ -4978,7 +4978,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, break; } mono_mb_emit_ldloc (mb, conv_arg); - if (!t->byref) { + if (!m_type_is_byref (t)) { mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_op (mb, CEE_MONO_LDNATIVEOBJ, klass); } @@ -4988,7 +4988,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, if (klass == date_time_class) { /* Convert from an OLE DATE type */ - if (!t->byref) + if (!m_type_is_byref (t)) break; if (!((t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))) { @@ -5010,7 +5010,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) break; - if (t->byref) { + if (m_type_is_byref (t)) { /* dst = argument */ mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_stloc (mb, 1); @@ -5030,7 +5030,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, emit_struct_free (mb, klass, conv_arg); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_patch_branch (mb, pos); break; @@ -5064,13 +5064,13 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, if (t->attrs & PARAM_ATTRIBUTE_OUT) break; - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_ldarg (mb, argnum); else mono_mb_emit_ldarg_addr (mb, argnum); mono_mb_emit_stloc (mb, 0); - if (t->byref) { + if (m_type_is_byref (t)) { mono_mb_emit_ldloc (mb, 0); pos = mono_mb_emit_branch (mb, CEE_BRFALSE); } @@ -5081,14 +5081,14 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, /* emit valuetype conversion code */ emit_struct_conv (mb, klass, TRUE); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_patch_branch (mb, pos); break; case MARSHAL_ACTION_MANAGED_CONV_OUT: if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) break; - if (t->byref && (t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT)) + if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT)) break; /* Check for null */ @@ -5171,7 +5171,7 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, *conv_arg_type = int_type; conv_arg = mono_mb_add_local (mb, int_type); - if (t->byref) { + if (m_type_is_byref (t)) { if (t->attrs & PARAM_ATTRIBUTE_OUT) break; @@ -5201,7 +5201,7 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, if (encoding == MONO_NATIVE_VBBYREFSTR) { - if (!t->byref) { + if (!m_type_is_byref (t)) { char *msg = g_strdup ("VBByRefStr marshalling requires a ref parameter."); mono_mb_emit_exception_marshal_directive (mb, msg); break; @@ -5217,7 +5217,7 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, * Have to allocate a new string with the same length as the original, and * copy the contents of the buffer pointed to by CONV_ARG into it. */ - g_assert (t->byref); + g_assert (m_type_is_byref (t)); mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, conv_arg); mono_mb_emit_ldarg (mb, argnum); @@ -5225,7 +5225,7 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_managed_call (mb, m, NULL); mono_mb_emit_icall (mb, mono_string_new_len_wrapper); mono_mb_emit_byte (mb, CEE_STIND_REF); - } else if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { + } else if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { int stind_op; mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, conv_arg); @@ -5241,7 +5241,7 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, break; case MARSHAL_ACTION_PUSH: - if (t->byref && encoding != MONO_NATIVE_VBBYREFSTR) + if (m_type_is_byref (t) && encoding != MONO_NATIVE_VBBYREFSTR) mono_mb_emit_ldloc_addr (mb, conv_arg); else mono_mb_emit_ldloc (mb, conv_arg); @@ -5271,7 +5271,7 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, *conv_arg_type = int_type; - if (t->byref) { + if (m_type_is_byref (t)) { if (t->attrs & PARAM_ATTRIBUTE_OUT) break; } @@ -5284,14 +5284,14 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_icall_id (mb, conv_to_icall (conv, NULL)); mono_mb_emit_stloc (mb, conv_arg); break; case MARSHAL_ACTION_MANAGED_CONV_OUT: - if (t->byref) { + if (m_type_is_byref (t)) { if (conv_arg) { int stind_op; mono_mb_emit_ldarg (mb, argnum); @@ -5350,7 +5350,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_icon (mb, 0); mono_mb_emit_stloc (mb, dar_release_slot); - if (t->byref) { + if (m_type_is_byref (t)) { int old_handle_value_slot = mono_mb_add_local (mb, int_type); if (!is_in (t)) { @@ -5389,7 +5389,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } case MARSHAL_ACTION_PUSH: - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_ldloc_addr (mb, conv_arg); else mono_mb_emit_ldloc (mb, conv_arg); @@ -5403,7 +5403,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, if (!sh_dangerous_release) init_safe_handle (); - if (t->byref){ + if (m_type_is_byref (t)) { /* If there was SafeHandle on input we have to release the reference to it */ if (is_in (t)) { mono_mb_emit_ldloc (mb, dar_release_slot); @@ -5534,7 +5534,7 @@ emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, conv_arg = mono_mb_add_local (mb, int_type); *conv_arg_type = int_type; - if (t->byref){ + if (m_type_is_byref (t)) { char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)"); mono_mb_emit_exception_marshal_directive (mb, msg); break; @@ -5605,7 +5605,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } if (m_class_is_delegate (klass)) { - if (t->byref) { + if (m_type_is_byref (t)) { if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) { char *msg = g_strdup_printf ("Byref marshalling of delegates is not implemented."); mono_mb_emit_exception_marshal_directive (mb, msg); @@ -5622,7 +5622,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalConv conv = mono_marshal_get_stringbuilder_to_ptr_conv (m->piinfo, spec); #if 0 - if (t->byref) { + if (m_type_is_byref (t)) { if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) { char *msg = g_strdup_printf ("Byref marshalling of stringbuilders is not implemented."); mono_mb_emit_exception_marshal_directive (mb, msg); @@ -5631,7 +5631,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } #endif - if (t->byref && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT)) + if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT)) break; if (conv == MONO_MARSHAL_CONV_INVALID) { @@ -5641,7 +5641,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_icall_id (mb, conv_to_icall (conv, NULL)); @@ -5663,7 +5663,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, CEE_LDNULL); mono_mb_emit_stloc (mb, conv_arg); - if (t->byref) { + if (m_type_is_byref (t)) { /* we dont need any conversions for out parameters */ if (t->attrs & PARAM_ATTRIBUTE_OUT) break; @@ -5688,7 +5688,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, CEE_LOCALLOC); mono_mb_emit_stloc (mb, conv_arg); - if (t->byref) { + if (m_type_is_byref (t)) { /* Need to store the original buffer so we can free it later */ m->orig_conv_args [argnum] = mono_mb_add_local (mb, int_type); mono_mb_emit_ldloc (mb, conv_arg); @@ -5722,7 +5722,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, g_assert (encoding != -1); - if (t->byref) { + if (m_type_is_byref (t)) { //g_assert (!(t->attrs & PARAM_ATTRIBUTE_OUT)); need_free = TRUE; @@ -5760,7 +5760,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } if (m_class_is_delegate (klass)) { - if (t->byref) { + if (m_type_is_byref (t)) { mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass); @@ -5771,7 +5771,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, break; } - if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT)) { + if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) { /* allocate a new object */ mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); @@ -5782,7 +5782,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, /* dst = *argument */ mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_stloc (mb, 1); @@ -5790,7 +5790,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_ldloc (mb, 1); pos = mono_mb_emit_branch (mb, CEE_BRFALSE); - if (t->byref || (t->attrs & PARAM_ATTRIBUTE_OUT)) { + if (m_type_is_byref (t) || (t->attrs & PARAM_ATTRIBUTE_OUT)) { mono_mb_emit_ldloc (mb, 1); mono_mb_emit_icon (mb, MONO_ABI_SIZEOF (MonoObject)); mono_mb_emit_byte (mb, CEE_ADD); @@ -5835,7 +5835,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, break; case MARSHAL_ACTION_PUSH: - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_ldloc_addr (mb, conv_arg); else mono_mb_emit_ldloc (mb, conv_arg); @@ -5843,7 +5843,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, case MARSHAL_ACTION_CONV_RESULT: if (m_class_is_delegate (klass)) { - g_assert (!t->byref); + g_assert (!m_type_is_byref (t)); mono_mb_emit_stloc (mb, 0); mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass); @@ -5900,7 +5900,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass); mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte (mb, CEE_LDIND_I); mono_mb_emit_icall_id (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL)); mono_mb_emit_stloc (mb, conv_arg); @@ -5915,7 +5915,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, // FIXME: g_assert (encoding == MONO_NATIVE_LPSTR || encoding == MONO_NATIVE_UTF8STR); - g_assert (!t->byref); + g_assert (!m_type_is_byref (t)); g_assert (encoding != -1); mono_mb_emit_ldarg (mb, argnum); @@ -5938,7 +5938,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, /* Set src */ mono_mb_emit_ldarg (mb, argnum); - if (t->byref) { + if (m_type_is_byref (t)) { int pos2; /* Check for NULL and raise an exception */ @@ -5975,7 +5975,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, case MARSHAL_ACTION_MANAGED_CONV_OUT: if (m_class_is_delegate (klass)) { - if (t->byref) { + if (m_type_is_byref (t)) { int stind_op; mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc (mb, conv_arg); @@ -5985,7 +5985,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } } - if (t->byref) { + if (m_type_is_byref (t)) { /* Check for null */ mono_mb_emit_ldloc (mb, conv_arg); pos = mono_mb_emit_branch (mb, CEE_BRTRUE); @@ -6100,16 +6100,16 @@ emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, case MARSHAL_ACTION_CONV_IN: { conv_arg = mono_mb_add_local (mb, variant_type); - if (t->byref) + if (m_type_is_byref (t)) *conv_arg_type = variant_type_byref; else *conv_arg_type = variant_type; - if (t->byref && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT) + if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT) break; mono_mb_emit_ldarg (mb, argnum); - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_byte(mb, CEE_LDIND_REF); mono_mb_emit_ldloc_addr (mb, conv_arg); mono_mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL); @@ -6117,7 +6117,7 @@ emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } case MARSHAL_ACTION_CONV_OUT: { - if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { + if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_ldloc_addr (mb, conv_arg); mono_mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL); @@ -6130,7 +6130,7 @@ emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } case MARSHAL_ACTION_PUSH: - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_ldloc_addr (mb, conv_arg); else mono_mb_emit_ldloc (mb, conv_arg); @@ -6145,15 +6145,15 @@ emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, case MARSHAL_ACTION_MANAGED_CONV_IN: { conv_arg = mono_mb_add_local (mb, object_type); - if (t->byref) + if (m_type_is_byref (t)) *conv_arg_type = variant_type_byref; else *conv_arg_type = variant_type; - if (t->byref && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT) + if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT) break; - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_ldarg (mb, argnum); else mono_mb_emit_ldarg_addr (mb, argnum); @@ -6163,7 +6163,7 @@ emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t, } case MARSHAL_ACTION_MANAGED_CONV_OUT: { - if (t->byref && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { + if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) { mono_mb_emit_ldloc (mb, conv_arg); mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL); @@ -6297,7 +6297,7 @@ emit_managed_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_s MonoType *t = sig->params [i]; if (tmp_locals [i]) { - if (t->byref) + if (m_type_is_byref (t)) mono_mb_emit_ldloc_addr (mb, tmp_locals [i]); else mono_mb_emit_ldloc (mb, tmp_locals [i]); @@ -6322,7 +6322,7 @@ emit_managed_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_s if (mspecs [0] && mspecs [0]->native == MONO_NATIVE_CUSTOM) { mono_emit_marshal (m, 0, sig->ret, mspecs [0], 0, NULL, MARSHAL_ACTION_MANAGED_CONV_RESULT); - } else if (!sig->ret->byref) { + } else if (!m_type_is_byref (sig->ret)) { switch (sig->ret->type) { case MONO_TYPE_VOID: break; @@ -6369,7 +6369,7 @@ emit_managed_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_s if (spec && spec->native == MONO_NATIVE_CUSTOM) { mono_emit_marshal (m, i, t, mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT); } - else if (t->byref) { + else if (m_type_is_byref (t)) { switch (t->type) { case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: @@ -6552,18 +6552,18 @@ signature_param_uses_handles (MonoMethodSignature *sig, MonoMethodSignature *gen * like string& since the C code for the icall has to work uniformly * for both valuetypes and reference types. */ - if (generic_sig && mono_type_is_byref_internal (generic_sig->params [param]) && + if (generic_sig && m_type_is_byref (generic_sig->params [param]) && (generic_sig->params [param]->type == MONO_TYPE_VAR || generic_sig->params [param]->type == MONO_TYPE_MVAR)) return ICALL_HANDLES_WRAP_VALUETYPE_REF; if (MONO_TYPE_IS_REFERENCE (sig->params [param])) { if (mono_signature_param_is_out (sig, param)) return ICALL_HANDLES_WRAP_OBJ_OUT; - else if (mono_type_is_byref_internal (sig->params [param])) + else if (m_type_is_byref (sig->params [param])) return ICALL_HANDLES_WRAP_OBJ_INOUT; else return ICALL_HANDLES_WRAP_OBJ; - } else if (mono_type_is_byref_internal (sig->params [param])) + } else if (m_type_is_byref (sig->params [param])) return ICALL_HANDLES_WRAP_VALUETYPE_REF; else return ICALL_HANDLES_WRAP_NONE; diff --git a/src/mono/mono/metadata/marshal-noilgen.c b/src/mono/mono/metadata/marshal-noilgen.c index ea0aa2c7e02f4..0cc81a3e5744b 100644 --- a/src/mono/mono/metadata/marshal-noilgen.c +++ b/src/mono/mono/metadata/marshal-noilgen.c @@ -52,7 +52,7 @@ emit_marshal_boolean_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, MonoType *int_type = mono_get_int_type (); switch (action) { case MARSHAL_ACTION_CONV_IN: - if (t->byref) + if (m_type_is_byref (t)) *conv_arg_type = int_type; else *conv_arg_type = mono_marshal_boolean_conv_in_get_local_type (spec, NULL); @@ -60,7 +60,7 @@ emit_marshal_boolean_noilgen (EmitMarshalContext *m, int argnum, MonoType *t, case MARSHAL_ACTION_MANAGED_CONV_IN: { MonoClass* conv_arg_class = mono_marshal_boolean_managed_conv_in_get_conv_arg_class (spec, NULL); - if (t->byref) + if (m_type_is_byref (t)) *conv_arg_type = m_class_get_this_arg (conv_arg_class); else *conv_arg_type = m_class_get_byval_arg (conv_arg_class); @@ -199,7 +199,7 @@ emit_managed_wrapper_noilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke } } - if (!sig->ret->byref) { + if (!m_type_is_byref (sig->ret)) { switch (sig->ret->type) { case MONO_TYPE_STRING: csig->ret = int_type; diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 680286a2ef83a..4a23274cc4a63 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -1158,7 +1158,7 @@ mono_string_new_len_wrapper_impl (const char *text, guint length, MonoError *err guint mono_type_to_ldind (MonoType *type) { - if (type->byref) + if (m_type_is_byref (type)) return CEE_LDIND_I; handle_enum: @@ -1215,7 +1215,7 @@ mono_type_to_ldind (MonoType *type) guint mono_type_to_stind (MonoType *type) { - if (type->byref) + if (m_type_is_byref (type)) return MONO_TYPE_IS_REFERENCE (type) ? CEE_STIND_REF : CEE_STIND_I; handle_enum: @@ -2297,7 +2297,7 @@ mono_marshal_get_string_ctor_signature (MonoMethod *method) static MonoType* get_runtime_invoke_type (MonoType *t, gboolean ret) { - if (t->byref) { + if (m_type_is_byref (t)) { if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type_internal (t))) return t; @@ -3693,7 +3693,7 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i static gboolean type_is_blittable (MonoType *type) { - if (type->byref) + if (m_type_is_byref (type)) return FALSE; type = mono_type_get_underlying_type (type); switch (type->type) { @@ -5441,7 +5441,7 @@ mono_type_native_stack_size (MonoType *t, guint32 *align) if (!align) align = &tmp; - if (t->byref) { + if (m_type_is_byref (t)) { *align = TARGET_SIZEOF_VOID_P; return TARGET_SIZEOF_VOID_P; } @@ -5934,7 +5934,7 @@ mono_marshal_get_thunk_invoke_wrapper (MonoMethod *method) /* setup exception param as byref+[out] */ csig->params [param_count - 1] = mono_metadata_type_dup (image, m_class_get_byval_arg (mono_defaults.exception_class)); - csig->params [param_count - 1]->byref = 1; + csig->params [param_count - 1]->byref__ = 1; csig->params [param_count - 1]->attrs = PARAM_ATTRIBUTE_OUT; /* convert struct return to object */ diff --git a/src/mono/mono/metadata/metadata-internals.h b/src/mono/mono/metadata/metadata-internals.h index 45f8e28cdab21..f750438ac7d33 100644 --- a/src/mono/mono/metadata/metadata-internals.h +++ b/src/mono/mono/metadata/metadata-internals.h @@ -33,7 +33,7 @@ struct _MonoType { unsigned int attrs : 16; /* param attributes or field flags */ MonoTypeEnum type : 8; unsigned int has_cmods : 1; - unsigned int byref : 1; + unsigned int byref__ : 1; /* don't access directly, use m_type_is_byref */ unsigned int pinned : 1; /* valid when included in a local var signature */ }; @@ -1183,15 +1183,15 @@ mono_type_get_signature_internal (MonoType *type) } /** - * mono_type_is_byref_internal: + * m_type_is_byref: * \param type the \c MonoType operated on * \returns TRUE if \p type represents a type passed by reference, * FALSE otherwise. */ -static inline mono_bool -mono_type_is_byref_internal (MonoType *type) +static inline gboolean +m_type_is_byref (const MonoType *type) { - return type->byref; + return type->byref__; } /** diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index 1e3cd55ed2d8f..80fc7f0309653 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -1850,7 +1850,7 @@ mono_type_hash (gconstpointer data) if (type->type == MONO_TYPE_GENERICINST) return mono_generic_class_hash (type->data.generic_class); else - return type->type | (type->byref << 8) | (type->attrs << 9); + return type->type | ((m_type_is_byref (type) ? 1 : 0) << 8) | (type->attrs << 9); } static gint @@ -1859,7 +1859,7 @@ mono_type_equal (gconstpointer ka, gconstpointer kb) const MonoType *a = (const MonoType *) ka; const MonoType *b = (const MonoType *) kb; - if (a->type != b->type || a->byref != b->byref || a->attrs != b->attrs || a->pinned != b->pinned) + if (a->type != b->type || m_type_is_byref (a) != m_type_is_byref (b) || a->attrs != b->attrs || a->pinned != b->pinned) return 0; /* need other checks */ return 1; @@ -2088,7 +2088,7 @@ mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container g_assert (count == 0); type->attrs = opt_attrs; - type->byref = byref; + type->byref__ = byref; type->pinned = pinned ? 1 : 0; if (!do_mono_metadata_parse_type (type, m, container, transient, ptr, &ptr, error)) @@ -2101,7 +2101,7 @@ mono_metadata_parse_type_internal (MonoImage *m, MonoGenericContainer *container if (!type->has_cmods && !transient) { /* no need to free type here, because it is on the stack */ if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) { - MonoType *ret = type->byref ? m_class_get_this_arg (type->data.klass) : m_class_get_byval_arg (type->data.klass); + MonoType *ret = m_type_is_byref (type) ? m_class_get_this_arg (type->data.klass) : m_class_get_byval_arg (type->data.klass); /* Consider the case: @@ -5100,7 +5100,7 @@ mono_type_size (MonoType *t, int *align) *align = 1; return 0; } - if (t->byref) { + if (m_type_is_byref (t)) { *align = MONO_ABI_ALIGNOF (gpointer); return MONO_ABI_SIZEOF (gpointer); } @@ -5215,7 +5215,7 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open) if (!align) align = &tmp; - if (t->byref) { + if (m_type_is_byref (t)) { *align = stack_slot_align; return stack_slot_size; } @@ -5408,7 +5408,7 @@ mono_metadata_type_hash (MonoType *t1) { guint hash = t1->type; - hash |= t1->byref << 6; /* do not collide with t1->type values */ + hash |= (m_type_is_byref (t1) ? 1 : 0) << 6; /* do not collide with t1->type values */ switch (t1->type) { case MONO_TYPE_VALUETYPE: case MONO_TYPE_CLASS: @@ -5423,7 +5423,7 @@ mono_metadata_type_hash (MonoType *t1) * inserted in a bunch of hash tables before been finished. */ if (image_is_dynamic (m_class_get_image (klass))) - return (t1->byref << 6) | mono_metadata_str_hash (m_class_get_name (klass)); + return ((m_type_is_byref (t1) ? 1 : 0) << 6) | mono_metadata_str_hash (m_class_get_name (klass)); return ((hash << 5) - hash) ^ mono_metadata_str_hash (m_class_get_name (klass)); } case MONO_TYPE_PTR: @@ -5598,7 +5598,7 @@ mono_metadata_custom_modifiers_equal (MonoType *t1, MonoType *t2, gboolean signa static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only) { - if (t1->type != t2->type || t1->byref != t2->byref) + if (t1->type != t2->type || m_type_is_byref (t1) != m_type_is_byref (t2)) return FALSE; gboolean cmod_reject = FALSE; @@ -6552,7 +6552,7 @@ mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_fiel *conv = MONO_MARSHAL_CONV_NONE; - if (type->byref) + if (m_type_is_byref (type)) return MONO_NATIVE_UINT; handle_enum: @@ -7147,7 +7147,7 @@ mono_type_is_byref (MonoType *type) { mono_bool result; MONO_ENTER_GC_UNSAFE; // FIXME slow - result = mono_type_is_byref_internal (type); + result = m_type_is_byref (type); MONO_EXIT_GC_UNSAFE; return result; } @@ -7239,7 +7239,7 @@ mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter) mono_bool mono_type_is_struct (MonoType *type) { - return (!type->byref && ((type->type == MONO_TYPE_VALUETYPE && + return (!m_type_is_byref (type) && ((type->type == MONO_TYPE_VALUETYPE && !m_class_is_enumtype (type->data.klass)) || (type->type == MONO_TYPE_TYPEDBYREF) || ((type->type == MONO_TYPE_GENERICINST) && mono_metadata_generic_class_is_valuetype (type->data.generic_class) && @@ -7254,7 +7254,7 @@ mono_type_is_struct (MonoType *type) mono_bool mono_type_is_void (MonoType *type) { - return (type && (type->type == MONO_TYPE_VOID) && !type->byref); + return (type && (type->type == MONO_TYPE_VOID) && !m_type_is_byref (type)); } /** @@ -7265,7 +7265,7 @@ mono_type_is_void (MonoType *type) mono_bool mono_type_is_pointer (MonoType *type) { - return (type && ((type->byref || (type->type == MONO_TYPE_I) || type->type == MONO_TYPE_STRING) + return (type && ((m_type_is_byref (type) || (type->type == MONO_TYPE_I) || type->type == MONO_TYPE_STRING) || (type->type == MONO_TYPE_SZARRAY) || (type->type == MONO_TYPE_CLASS) || (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_OBJECT) || (type->type == MONO_TYPE_ARRAY) || (type->type == MONO_TYPE_PTR) || @@ -7295,7 +7295,7 @@ mono_type_is_reference (MonoType *type) mono_bool mono_type_is_generic_parameter (MonoType *type) { - return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR); + return !m_type_is_byref (type) && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR); } /** @@ -7736,7 +7736,7 @@ mono_guid_signature_append_type (GString *res, MonoType *type) default: break; } - if (type->byref) g_string_append_c (res, '&'); + if (m_type_is_byref (type)) g_string_append_c (res, '&'); } static void diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c index eae091bc6c15c..e5d4503684f8b 100644 --- a/src/mono/mono/metadata/native-library.c +++ b/src/mono/mono/metadata/native-library.c @@ -526,7 +526,8 @@ netcore_probe_for_module (MonoImage *image, const char *file_name, int flags) module = netcore_probe_for_module_variations (pinvoke_search_directories[i], file_name, lflags); // Check the assembly directory if the search flag is set and the image exists - if (flags & DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY && image != NULL && module == NULL) { + if ((flags & DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY) != 0 && image != NULL && + module == NULL && (image->filename != NULL)) { char *mdirname = g_path_get_dirname (image->filename); if (mdirname) module = netcore_probe_for_module_variations (mdirname, file_name, lflags); diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 70c967df384b5..af53f4d8694df 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -848,7 +848,7 @@ compute_class_bitmap (MonoClass *klass, gsize *bitmap, int size, int offset, int continue; } /* FIXME: should not happen, flag as type load error */ - if (field->type->byref) + if (m_type_is_byref (field->type)) break; if (static_fields && field->offset == -1) @@ -2654,7 +2654,7 @@ mono_copy_value (MonoType *type, void *dest, void *value, int deref_pointer) MONO_REQ_GC_UNSAFE_MODE; int t; - if (type->byref) { + if (m_type_is_byref (type)) { /* object fields cannot be byref, so we don't need a wbarrier here */ gpointer *p = (gpointer*)dest; @@ -2997,7 +2997,7 @@ mono_field_get_value_object_checked (MonoClassField *field, MonoObject *obj, Mon case MONO_TYPE_I8: case MONO_TYPE_R8: case MONO_TYPE_VALUETYPE: - is_ref = type->byref; + is_ref = m_type_is_byref (type); break; case MONO_TYPE_GENERICINST: is_ref = !mono_type_generic_inst_is_valuetype (type); @@ -4556,7 +4556,7 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, MonoObject /* The runtime invoke wrapper needs the original boxed vtype, it does handle byref values as well. */ *pa_obj = mono_array_get_internal (params, MonoObject*, i); result = *pa_obj; - if (t->byref) + if (m_type_is_byref (t)) *has_byref_nullables = TRUE; } else { /* MS seems to create the objects if a null is passed in */ @@ -4568,7 +4568,7 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, MonoObject was_null = TRUE; } - if (t->byref) { + if (m_type_is_byref (t)) { /* * We can't pass the unboxed vtype byref to the callee, since * that would mean the callee would be able to modify boxed @@ -4583,7 +4583,7 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, MonoObject } *pa_obj = mono_array_get_internal (params, MonoObject*, i); result = mono_object_unbox_internal (*pa_obj); - if (!t->byref && was_null) + if (!m_type_is_byref (t) && was_null) mono_array_setref_internal (params, i, NULL); } break; @@ -4592,7 +4592,7 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, MonoObject case MONO_TYPE_CLASS: case MONO_TYPE_ARRAY: case MONO_TYPE_SZARRAY: - if (t->byref) { + if (m_type_is_byref (t)) { result = mono_array_addr_internal (params, MonoObject*, i); // FIXME: I need to check this code path } else { @@ -4601,7 +4601,7 @@ invoke_array_extract_argument (MonoArray *params, int i, MonoType *t, MonoObject } break; case MONO_TYPE_GENERICINST: - if (t->byref) + if (m_type_is_byref (t)) t = m_class_get_this_arg (t->data.generic_class->container_class); else t = m_class_get_byval_arg (t->data.generic_class->container_class); @@ -4875,10 +4875,10 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params, } else { box_args [0] = NULL; } - if (sig->ret->byref) { + if (m_type_is_byref (sig->ret)) { // byref is already unboxed by the invoke code MonoType *tmpret = mono_metadata_type_dup (NULL, sig->ret); - tmpret->byref = FALSE; + tmpret->byref__ = FALSE; MonoReflectionTypeHandle type_h = mono_type_get_object_handle (tmpret, error); box_args [1] = MONO_HANDLE_RAW (type_h); mono_metadata_free_type (tmpret); @@ -4902,7 +4902,7 @@ mono_runtime_try_invoke_array (MonoMethod *method, void *obj, MonoArray *params, for (i = 0; i < mono_array_length_internal (params); i++) { MonoType *t = sig->params [i]; - if (t->byref && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type_internal (t))) + if (m_type_is_byref (t) && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type_internal (t))) mono_array_setref_internal (params, i, pa [i]); } } @@ -7851,7 +7851,7 @@ format_cmd_line (int argc, char **argv, gboolean add_host) GString *cmd_line = NULL; if (add_host) { -#if !defined(HOST_WIN32) && defined(HAVE_UNISTD_H) +#if !defined(HOST_WIN32) && defined(HAVE_GETPID) host_path = mono_w32process_get_path (getpid ()); #elif defined(HOST_WIN32) gunichar2 *host_path_ucs2 = NULL; diff --git a/src/mono/mono/metadata/reflection.c b/src/mono/mono/metadata/reflection.c index f7d0ef0fad017..5501a50befdda 100644 --- a/src/mono/mono/metadata/reflection.c +++ b/src/mono/mono/metadata/reflection.c @@ -403,11 +403,11 @@ mono_type_normalize (MonoType *type) } if (is_denorm_gtd) - return type->byref == m_class_get_byval_arg (gtd)->byref ? m_class_get_byval_arg (gtd) : m_class_get_this_arg (gtd); + return m_type_is_byref (type) == m_type_is_byref (m_class_get_byval_arg (gtd)) ? m_class_get_byval_arg (gtd) : m_class_get_this_arg (gtd); if (requires_rebind) { MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic); - return type->byref == m_class_get_byval_arg (klass)->byref ? m_class_get_byval_arg (klass) : m_class_get_this_arg (klass); + return m_type_is_byref (type) == m_type_is_byref (m_class_get_byval_arg (klass)) ? m_class_get_byval_arg (klass) : m_class_get_this_arg (klass); } return type; @@ -450,7 +450,7 @@ mono_type_get_object_checked (MonoType *type, MonoError *error) * expects that is can be freed. * Using the right type from */ - type = m_class_get_byval_arg (klass)->byref == type->byref ? m_class_get_byval_arg (klass) : m_class_get_this_arg (klass); + type = m_type_is_byref (m_class_get_byval_arg (klass)) == m_type_is_byref (type) ? m_class_get_byval_arg (klass) : m_class_get_this_arg (klass); /* We don't want to return types with custom modifiers to the managed * world since they're hard to distinguish from plain types using the @@ -463,7 +463,7 @@ mono_type_get_object_checked (MonoType *type, MonoError *error) g_assert (!type->has_cmods); /* void is very common */ - if (!type->byref && type->type == MONO_TYPE_VOID && domain->typeof_void) + if (!m_type_is_byref (type) && type->type == MONO_TYPE_VOID && domain->typeof_void) return (MonoReflectionType*)domain->typeof_void; /* @@ -531,7 +531,7 @@ mono_type_get_object_checked (MonoType *type, MonoError *error) goto leave; } - if (mono_class_has_ref_info (klass) && !m_class_was_typebuilder (klass) && !type->byref) { + if (mono_class_has_ref_info (klass) && !m_class_was_typebuilder (klass) && !m_type_is_byref (type)) { res = &mono_class_get_ref_info_raw (klass)->type; /* FIXME use handles */ goto leave; } @@ -547,7 +547,7 @@ mono_type_get_object_checked (MonoType *type, MonoError *error) res = cached; } else { mono_g_hash_table_insert_internal (memory_manager->type_hash, type, res); - if (type->type == MONO_TYPE_VOID && !type->byref) + if (type->type == MONO_TYPE_VOID && !m_type_is_byref (type)) domain->typeof_void = (MonoObject*)res; } mono_mem_manager_unlock (memory_manager); diff --git a/src/mono/mono/metadata/sre-encode.c b/src/mono/mono/metadata/sre-encode.c index bc14aae023117..c44a6efc89b04 100644 --- a/src/mono/mono/metadata/sre-encode.c +++ b/src/mono/mono/metadata/sre-encode.c @@ -162,7 +162,7 @@ encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf) return; } - if (type->byref) + if (m_type_is_byref (type)) sigbuffer_add_value (buf, MONO_TYPE_BYREF); switch (type->type){ diff --git a/src/mono/mono/metadata/w32file-unix.c b/src/mono/mono/metadata/w32file-unix.c index e11bfb335dac5..50da28bf8468b 100644 --- a/src/mono/mono/metadata/w32file-unix.c +++ b/src/mono/mono/metadata/w32file-unix.c @@ -277,93 +277,6 @@ _wapi_dirname (const gchar *filename) return ret; } -static gboolean -_wapi_lock_file_region (gint fd, off_t offset, off_t length) -{ - struct flock lock_data; - gint ret; - - if (offset < 0 || length < 0) { - mono_w32error_set_last (ERROR_INVALID_PARAMETER); - return FALSE; - } - - lock_data.l_type = F_WRLCK; - lock_data.l_whence = SEEK_SET; - lock_data.l_start = offset; - lock_data.l_len = length; - - do { - ret = fcntl (fd, F_SETLK, &lock_data); - } while(ret == -1 && errno == EINTR); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: fcntl returns %d", __func__, ret); - - if (ret == -1) { - /* - * if locks are not available (NFS for example), - * ignore the error - */ - if (errno == ENOLCK -#ifdef EOPNOTSUPP - || errno == EOPNOTSUPP -#endif -#ifdef ENOTSUP - || errno == ENOTSUP -#endif - ) { - return TRUE; - } - - mono_w32error_set_last (ERROR_LOCK_VIOLATION); - return FALSE; - } - - return TRUE; -} - -static gboolean -_wapi_unlock_file_region (gint fd, off_t offset, off_t length) -{ - struct flock lock_data; - gint ret; - - lock_data.l_type = F_UNLCK; - lock_data.l_whence = SEEK_SET; - lock_data.l_start = offset; - lock_data.l_len = length; - - do { - ret = fcntl (fd, F_SETLK, &lock_data); - } while(ret == -1 && errno == EINTR); - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: fcntl returns %d", __func__, ret); - - if (ret == -1) { - /* - * if locks are not available (NFS for example), - * ignore the error - */ - if (errno == ENOLCK -#ifdef EOPNOTSUPP - || errno == EOPNOTSUPP -#endif -#ifdef ENOTSUP - || errno == ENOTSUP -#endif - ) { - return TRUE; - } - - mono_w32error_set_last (ERROR_LOCK_VIOLATION); - return FALSE; - } - - return TRUE; -} - -static gboolean lock_while_writing = FALSE; - static void _wapi_set_last_error_from_errno (void) { @@ -402,7 +315,6 @@ static gboolean file_write (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *byteswritten) { gint ret; - off_t current_pos = 0; MonoThreadInfo *info = mono_thread_info_current (); if(byteswritten!=NULL) { @@ -415,26 +327,6 @@ file_write (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 * mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } - - if (lock_while_writing) { - /* Need to lock the region we're about to write to, - * because we only do advisory locking on POSIX - * systems - */ - MONO_ENTER_GC_SAFE; - current_pos = lseek (((MonoFDHandle*) filehandle)->fd, (off_t)0, SEEK_CUR); - MONO_EXIT_GC_SAFE; - if (current_pos == -1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: fd %d lseek failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror (errno)); - _wapi_set_last_error_from_errno (); - return(FALSE); - } - - if (_wapi_lock_file_region (((MonoFDHandle*) filehandle)->fd, current_pos, numbytes) == FALSE) { - /* The error has already been set */ - return(FALSE); - } - } do { MONO_ENTER_GC_SAFE; @@ -442,10 +334,6 @@ file_write (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 * MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); - - if (lock_while_writing) { - _wapi_unlock_file_region (((MonoFDHandle*) filehandle)->fd, current_pos, numbytes); - } if (ret == -1) { if (errno == EINTR) { @@ -650,9 +538,6 @@ mono_w32file_init (void) mono_fdhandle_register (MONO_FDTYPE_PIPE, &file_data_callbacks); mono_coop_mutex_init (&file_share_mutex); - - if (g_hasenv ("MONO_STRICT_IO_EMULATION")) - lock_while_writing = TRUE; } gpointer diff --git a/src/mono/mono/mini/abcremoval.c b/src/mono/mono/mini/abcremoval.c index 44317cdac6c5c..ec87d201c06ee 100644 --- a/src/mono/mono/mini/abcremoval.c +++ b/src/mono/mono/mini/abcremoval.c @@ -1245,7 +1245,7 @@ process_block (MonoCompile *cfg, MonoBasicBlock *bb, MonoVariableRelationsEvalua static MonoIntegerValueKind type_to_value_kind (MonoType *type) { - if (type->byref) + if (m_type_is_byref (type)) return MONO_UNKNOWN_INTEGER_VALUE; switch (type->type) { case MONO_TYPE_I1: diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index a5da9c638b47e..cd1b153379d9d 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -3581,7 +3581,7 @@ encode_type (MonoAotCompile *acfg, MonoType *t, guint8 *buf, guint8 **endbuf) *p = MONO_TYPE_PINNED; ++p; } - if (t->byref) { + if (m_type_is_byref (t)) { *p = MONO_TYPE_BYREF; ++p; } @@ -8765,14 +8765,14 @@ get_concrete_sig (MonoMethodSignature *sig) //printf ("%s\n", mono_signature_full_name (sig)); - if (sig->ret->byref) + if (m_type_is_byref (sig->ret)) copy->ret = m_class_get_this_arg (mono_defaults.int_class); else copy->ret = mini_get_underlying_type (sig->ret); if (!is_concrete_type (copy->ret)) concrete = FALSE; for (i = 0; i < sig->param_count; ++i) { - if (sig->params [i]->byref) { + if (m_type_is_byref (sig->params [i])) { MonoType *t = m_class_get_byval_arg (mono_class_from_mono_type_internal (sig->params [i])); t = mini_get_underlying_type (t); copy->params [i] = m_class_get_this_arg (mono_class_from_mono_type_internal (t)); @@ -9342,7 +9342,7 @@ mono_aot_get_method_name (MonoCompile *cfg) static gboolean append_mangled_type (GString *s, MonoType *t) { - if (t->byref) + if (m_type_is_byref (t)) g_string_append_printf (s, "b"); switch (t->type) { case MONO_TYPE_VOID: @@ -10612,7 +10612,7 @@ mono_aot_type_hash (MonoType *t1) { guint hash = t1->type; - hash |= t1->byref << 6; /* do not collide with t1->type values */ + hash |= m_type_is_byref (t1) << 6; /* do not collide with t1->type values */ switch (t1->type) { case MONO_TYPE_VALUETYPE: case MONO_TYPE_CLASS: diff --git a/src/mono/mono/mini/aot-runtime-wasm.c b/src/mono/mono/mini/aot-runtime-wasm.c index f2d70e4e8bbd8..875f765e8b095 100644 --- a/src/mono/mono/mini/aot-runtime-wasm.c +++ b/src/mono/mono/mini/aot-runtime-wasm.c @@ -16,7 +16,7 @@ static char type_to_c (MonoType *t) { - if (t->byref) + if (m_type_is_byref (t)) return 'I'; handle_enum: diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 4525bbf40622d..a04e272b9aac1 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -710,7 +710,7 @@ decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf, MonoError *err t->pinned = TRUE; ++p; } else if (*p == MONO_TYPE_BYREF) { - t->byref = TRUE; + t->byref__ = TRUE; ++p; } else { break; diff --git a/src/mono/mono/mini/dwarfwriter.c b/src/mono/mono/mini/dwarfwriter.c index d23074199bc65..febfef0fc416c 100644 --- a/src/mono/mono/mini/dwarfwriter.c +++ b/src/mono/mono/mini/dwarfwriter.c @@ -1144,7 +1144,7 @@ get_type_die (MonoDwarfWriter *w, MonoType *t) int j; const char *tdie; - if (t->byref) { + if (m_type_is_byref (t)) { if (t->type == MONO_TYPE_VALUETYPE) { tdie = (const char *)g_hash_table_lookup (w->class_to_pointer_die, klass); } @@ -1203,7 +1203,7 @@ emit_type (MonoDwarfWriter *w, MonoType *t) int j; const char *tdie; - if (t->byref) { + if (m_type_is_byref (t)) { if (t->type == MONO_TYPE_VALUETYPE) { tdie = emit_class_dwarf_info (w, klass, TRUE); if (tdie) diff --git a/src/mono/mono/mini/interp/interp-internals.h b/src/mono/mono/mini/interp/interp-internals.h index 465fd20240fa4..8925d870c73f1 100644 --- a/src/mono/mono/mini/interp/interp-internals.h +++ b/src/mono/mono/mini/interp/interp-internals.h @@ -97,6 +97,10 @@ typedef enum { #define PROFILE_INTERP 0 +#define INTERP_IMETHOD_TAG_UNBOX(im) ((gpointer)((mono_u)(im) | 1)) +#define INTERP_IMETHOD_IS_TAGGED_UNBOX(im) ((mono_u)(im) & 1) +#define INTERP_IMETHOD_UNTAG_UNBOX(im) ((InterpMethod*)((mono_u)(im) & ~1)) + /* * Structure representing a method transformed for the interpreter */ @@ -125,6 +129,7 @@ struct InterpMethod { MonoType **param_types; MonoJitInfo *jinfo; MonoFtnDesc *ftndesc; + MonoFtnDesc *ftndesc_unbox; guint32 locals_size; guint32 alloca_size; @@ -274,7 +279,7 @@ static inline int mint_type(MonoType *type_) { MonoType *type = mini_native_type_replace_type (type_); - if (type->byref) + if (m_type_is_byref (type)) return MINT_TYPE_I; enum_type: switch (type->type) { diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 61b685cb307c8..3aa46e135b007 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -694,11 +694,12 @@ static InterpMethod* // Inlining causes additional stack use in caller. get_virtual_method_fast (InterpMethod *imethod, MonoVTable *vtable, int offset) { gpointer *table; - MonoMemoryManager *memory_manager = m_class_get_mem_manager (vtable->klass); + MonoMemoryManager *memory_manager = NULL; table = get_method_table (vtable, offset); - if (!table) { + if (G_UNLIKELY (!table)) { + memory_manager = m_class_get_mem_manager (vtable->klass); /* Lazily allocate method table */ mono_mem_manager_lock (memory_manager); table = get_method_table (vtable, offset); @@ -707,8 +708,10 @@ get_virtual_method_fast (InterpMethod *imethod, MonoVTable *vtable, int offset) mono_mem_manager_unlock (memory_manager); } - if (!table [offset]) { + if (G_UNLIKELY (!table [offset])) { InterpMethod *target_imethod = get_virtual_method (imethod, vtable); + if (!memory_manager) + memory_manager = m_class_get_mem_manager (vtable->klass); /* Lazily initialize the method table slot */ mono_mem_manager_lock (memory_manager); if (!table [offset]) { @@ -727,8 +730,10 @@ get_virtual_method_fast (InterpMethod *imethod, MonoVTable *vtable, int offset) /* Virtual generic or interface call. Multiple methods in slot */ InterpMethod *target_imethod = get_target_imethod ((GSList*)table [offset], imethod); - if (!target_imethod) { + if (G_UNLIKELY (!target_imethod)) { target_imethod = get_virtual_method (imethod, vtable); + if (!memory_manager) + memory_manager = m_class_get_mem_manager (vtable->klass); mono_mem_manager_lock (memory_manager); if (!get_target_imethod ((GSList*)table [offset], imethod)) table [offset] = append_imethod (memory_manager, (GSList*)table [offset], imethod, target_imethod); @@ -743,7 +748,7 @@ static int stackval_from_data (MonoType *type, stackval *result, const void *data, gboolean pinvoke) { type = mini_native_type_replace_type (type); - if (type->byref) { + if (m_type_is_byref (type)) { result->data.p = *(gpointer*)data; return MINT_STACK_SLOT_SIZE; } @@ -830,7 +835,7 @@ static int stackval_to_data (MonoType *type, stackval *val, void *data, gboolean pinvoke) { type = mini_native_type_replace_type (type); - if (type->byref) { + if (m_type_is_byref (type)) { gpointer *p = (gpointer*)data; *p = val->data.p; return MINT_STACK_SLOT_SIZE; @@ -1032,16 +1037,6 @@ interp_throw (ThreadContext *context, MonoException *ex, InterpFrame *frame, con } \ } while (0) -/* Don't throw exception if thread is in GC Safe mode. Should only happen in managed-to-native wrapper. */ -#define EXCEPTION_CHECKPOINT_GC_UNSAFE \ - do { \ - if (mono_thread_interruption_request_flag && !mono_threads_is_critical_method (frame->imethod->method) && mono_thread_is_gc_unsafe_mode ()) { \ - MonoException *exc = mono_thread_interruption_checkpoint (); \ - if (exc) \ - THROW_EX_GENERAL (exc, ip, TRUE); \ - } \ - } while (0) - // Reduce duplicate code in interp_exec_method static void do_safepoint (InterpFrame *frame, ThreadContext *context) @@ -1253,7 +1248,7 @@ static InterpMethodArguments* build_args_from_sig (MonoMethodSignature *sig, Int margs->ilen++; for (int i = 0; i < sig->param_count; i++) { - guint32 ptype = sig->params [i]->byref ? MONO_TYPE_PTR : sig->params [i]->type; + guint32 ptype = m_type_is_byref (sig->params [i]) ? MONO_TYPE_PTR : sig->params [i]->type; switch (ptype) { case MONO_TYPE_BOOLEAN: case MONO_TYPE_CHAR: @@ -1327,7 +1322,7 @@ static InterpMethodArguments* build_args_from_sig (MonoMethodSignature *sig, Int MonoType *type = sig->params [i]; guint32 ptype; retry: - ptype = type->byref ? MONO_TYPE_PTR : type->type; + ptype = m_type_is_byref (type) ? MONO_TYPE_PTR : type->type; switch (ptype) { case MONO_TYPE_BOOLEAN: case MONO_TYPE_CHAR: @@ -1525,7 +1520,8 @@ ves_pinvoke_method ( stackval *ret_sp, stackval *sp, gboolean save_last_error, - gpointer *cache) + gpointer *cache, + gboolean *gc_transitions) { InterpFrame frame = {0}; frame.parent = parent_frame; @@ -1536,14 +1532,7 @@ ves_pinvoke_method ( MonoLMFExt ext; gpointer args; - /* - * When there's a calli in a pinvoke wrapper, we're in GC Safe mode. - * When we're called for some other calli, we may be in GC Unsafe mode. - * - * On any code path where we call anything other than the entry_func, - * we need to switch back to GC Unsafe before calling the runtime. - */ - MONO_REQ_GC_NEUTRAL_MODE; + MONO_REQ_GC_UNSAFE_MODE; #ifdef HOST_WASM /* @@ -1579,9 +1568,7 @@ ves_pinvoke_method ( #ifdef MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP CallContext ccontext; - MONO_ENTER_GC_UNSAFE; mono_arch_set_native_call_context_args (&ccontext, &frame, sig); - MONO_EXIT_GC_UNSAFE; args = &ccontext; #else InterpMethodArguments *margs = build_args_from_sig (sig, &frame); @@ -1589,16 +1576,23 @@ ves_pinvoke_method ( #endif INTERP_PUSH_LMF_WITH_CTX (&frame, ext, exit_pinvoke); - entry_func ((gpointer) addr, args); + + if (*gc_transitions) { + MONO_ENTER_GC_SAFE; + entry_func ((gpointer) addr, args); + MONO_EXIT_GC_SAFE; + *gc_transitions = FALSE; + } else { + entry_func ((gpointer) addr, args); + } + if (save_last_error) mono_marshal_set_last_error (); interp_pop_lmf (&ext); #ifdef MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP if (!context->has_resume_state) { - MONO_ENTER_GC_UNSAFE; mono_arch_get_native_call_context_ret (&ccontext, &frame, sig); - MONO_EXIT_GC_UNSAFE; } g_free (ccontext.stack); @@ -1632,7 +1626,7 @@ interp_init_delegate (MonoDelegate *del, MonoError *error) if (del->interp_method) { /* Delegate created by a call to ves_icall_mono_delegate_ctor_interp () */ del->method = ((InterpMethod *)del->interp_method)->method; - } if (del->method_ptr && !del->method) { + } else if (del->method_ptr && !del->method) { /* Delegate created from methodInfo.MethodHandle.GetFunctionPointer() */ del->interp_method = (InterpMethod *)del->method_ptr; if (mono_llvm_only) @@ -1679,7 +1673,7 @@ interp_init_delegate (MonoDelegate *del, MonoError *error) /* Convert a function pointer for a managed method to an InterpMethod* */ static InterpMethod* -ftnptr_to_imethod (gpointer addr) +ftnptr_to_imethod (gpointer addr, gboolean *need_unbox) { InterpMethod *imethod; @@ -1690,44 +1684,59 @@ ftnptr_to_imethod (gpointer addr) g_assert (ftndesc); g_assert (ftndesc->method); - imethod = ftndesc->interp_method; - if (!imethod) { + if (!ftndesc->interp_method) { imethod = mono_interp_get_imethod (ftndesc->method, error); mono_error_assert_ok (error); mono_memory_barrier (); + // FIXME Handle unboxing here ? ftndesc->interp_method = imethod; } + *need_unbox = INTERP_IMETHOD_IS_TAGGED_UNBOX (ftndesc->interp_method); + imethod = INTERP_IMETHOD_UNTAG_UNBOX (ftndesc->interp_method); } else { /* Function pointers are represented by their InterpMethod */ - imethod = (InterpMethod*)addr; + *need_unbox = INTERP_IMETHOD_IS_TAGGED_UNBOX (addr); + imethod = INTERP_IMETHOD_UNTAG_UNBOX (addr); } return imethod; } static gpointer -imethod_to_ftnptr (InterpMethod *imethod) +imethod_to_ftnptr (InterpMethod *imethod, gboolean need_unbox) { if (mono_llvm_only) { ERROR_DECL (error); /* Function pointers are represented by a MonoFtnDesc structure */ - MonoFtnDesc *ftndesc = imethod->ftndesc; - if (!ftndesc) { - ftndesc = mini_llvmonly_load_method_ftndesc (imethod->method, FALSE, FALSE, error); + MonoFtnDesc **ftndesc_p; + if (need_unbox) + ftndesc_p = &imethod->ftndesc_unbox; + else + ftndesc_p = &imethod->ftndesc; + if (!*ftndesc_p) { + MonoFtnDesc *ftndesc = mini_llvmonly_load_method_ftndesc (imethod->method, FALSE, need_unbox, error); mono_error_assert_ok (error); + if (need_unbox) + ftndesc->interp_method = INTERP_IMETHOD_TAG_UNBOX (imethod); + else + ftndesc->interp_method = imethod; mono_memory_barrier (); - imethod->ftndesc = ftndesc; + *ftndesc_p = ftndesc; } - return ftndesc; + return *ftndesc_p; } else { - return imethod; + if (need_unbox) + return INTERP_IMETHOD_TAG_UNBOX (imethod); + else + return imethod; } } static void interp_delegate_ctor (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoError *error) { + gboolean need_unbox; /* addr is the result of an LDFTN opcode */ - InterpMethod *imethod = ftnptr_to_imethod (addr); + InterpMethod *imethod = ftnptr_to_imethod (addr, &need_unbox); if (!(imethod->method->flags & METHOD_ATTRIBUTE_STATIC)) { MonoMethod *invoke = mono_get_delegate_invoke_internal (mono_handle_class (this_obj)); @@ -1945,7 +1954,9 @@ interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject // method is transformed. context->stack_pointer = (guchar*)(sp + 4); + MONO_ENTER_GC_UNSAFE; interp_exec_method (&frame, context, NULL); + MONO_EXIT_GC_UNSAFE; context->stack_pointer = (guchar*)sp; @@ -2011,7 +2022,7 @@ interp_entry (InterpEntryData *data) else params = data->args; for (i = 0; i < sig->param_count; ++i) { - if (sig->params [i]->byref) { + if (m_type_is_byref (sig->params [i])) { sp_args->data.p = params [i]; sp_args++; } else { @@ -2027,7 +2038,9 @@ interp_entry (InterpEntryData *data) context->stack_pointer = (guchar*)sp_args; + MONO_ENTER_GC_UNSAFE; interp_exec_method (&frame, context, NULL); + MONO_EXIT_GC_UNSAFE; context->stack_pointer = (guchar*)sp; @@ -2159,12 +2172,19 @@ do_icall (MonoMethodSignature *sig, int op, stackval *ret_sp, stackval *sp, gpoi #endif // Do not inline in case order of frame addresses matters, and maybe other reasons. static MONO_NO_OPTIMIZATION MONO_NEVER_INLINE gpointer -do_icall_wrapper (InterpFrame *frame, MonoMethodSignature *sig, int op, stackval *ret_sp, stackval *sp, gpointer ptr, gboolean save_last_error) +do_icall_wrapper (InterpFrame *frame, MonoMethodSignature *sig, int op, stackval *ret_sp, stackval *sp, gpointer ptr, gboolean save_last_error, gboolean *gc_transitions) { MonoLMFExt ext; INTERP_PUSH_LMF_WITH_CTX (frame, ext, exit_icall); - do_icall (sig, op, ret_sp, sp, ptr, save_last_error); + if (*gc_transitions) { + MONO_ENTER_GC_SAFE; + do_icall (sig, op, ret_sp, sp, ptr, save_last_error); + MONO_EXIT_GC_SAFE; + *gc_transitions = FALSE; + } else { + do_icall (sig, op, ret_sp, sp, ptr, save_last_error); + } interp_pop_lmf (&ext); @@ -2346,7 +2366,7 @@ init_jit_call_info (InterpMethod *rmethod, MonoError *error) for (int i = 0; i < rmethod->param_count; ++i) { MonoType *t = rmethod->param_types [i]; int mt = mint_type (t); - if (sig->params [i]->byref) { + if (m_type_is_byref (sig->params [i])) { cinfo->arginfo [i] = JIT_ARG_BYVAL; } else if (mt == MINT_TYPE_O) { cinfo->arginfo [i] = JIT_ARG_BYREF; @@ -2725,7 +2745,9 @@ interp_entry_from_trampoline (gpointer ccontext_untyped, gpointer rmethod_untype } context->stack_pointer = (guchar*)newsp; + MONO_ENTER_GC_UNSAFE; interp_exec_method (&frame, context, NULL); + MONO_EXIT_GC_UNSAFE; context->stack_pointer = (guchar*)sp; g_assert (!context->has_resume_state); @@ -3109,14 +3131,14 @@ static MONO_NEVER_INLINE MonoException* mono_interp_leave (InterpFrame* parent_frame) { InterpFrame frame = {parent_frame}; - + gboolean gc_transitions = FALSE; stackval tmp_sp; /* * We need for mono_thread_get_undeniable_exception to be able to unwind * to check the abort threshold. For this to work we use frame as a * dummy frame that is stored in the lmf and serves as the transition frame */ - do_icall_wrapper (&frame, NULL, MINT_ICALL_V_P, &tmp_sp, &tmp_sp, (gpointer)mono_thread_get_undeniable_exception, FALSE); + do_icall_wrapper (&frame, NULL, MINT_ICALL_V_P, &tmp_sp, &tmp_sp, (gpointer)mono_thread_get_undeniable_exception, FALSE, &gc_transitions); return (MonoException*)tmp_sp.data.p; } @@ -3224,6 +3246,7 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs unsigned char *locals = NULL; int call_args_offset; int return_offset; + gboolean gc_transitions = FALSE; #if DEBUG_INTERP int tracing = global_tracing; @@ -3484,12 +3507,10 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs goto call; } MINT_IN_CASE(MINT_CALLI) { - MonoMethodSignature *csignature; - - csignature = (MonoMethodSignature*)frame->imethod->data_items [ip [4]]; + gboolean need_unbox; /* In mixed mode, stay in the interpreter for simplicity even if there is an AOT version of the callee */ - cmethod = ftnptr_to_imethod (LOCAL_VAR (ip [2], gpointer)); + cmethod = ftnptr_to_imethod (LOCAL_VAR (ip [2], gpointer), &need_unbox); if (cmethod->method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) { cmethod = mono_interp_get_imethod (mono_marshal_get_native_wrapper (cmethod->method, FALSE, FALSE), error); @@ -3499,15 +3520,11 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs return_offset = ip [1]; call_args_offset = ip [3]; - if (csignature->hasthis) { + if (need_unbox) { MonoObject *this_arg = LOCAL_VAR (call_args_offset, MonoObject*); - - if (m_class_is_valuetype (this_arg->vtable->klass)) { - gpointer unboxed = mono_object_unbox_internal (this_arg); - LOCAL_VAR (call_args_offset, gpointer) = unboxed; - } + LOCAL_VAR (call_args_offset, gpointer) = mono_object_unbox_internal (this_arg); } - ip += 5; + ip += 4; goto call; } @@ -3522,8 +3539,8 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs /* for calls, have ip pointing at the start of next instruction */ frame->state.ip = ip + 7; - do_icall_wrapper (frame, csignature, opcode, ret, args, target_ip, save_last_error); - EXCEPTION_CHECKPOINT_GC_UNSAFE; + do_icall_wrapper (frame, csignature, opcode, ret, args, target_ip, save_last_error, &gc_transitions); + EXCEPTION_CHECKPOINT; CHECK_RESUME_STATE (context); ip += 7; MINT_IN_BREAK; @@ -3550,9 +3567,9 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs gpointer *cache = (gpointer*)&frame->imethod->data_items [ip [7]]; /* for calls, have ip pointing at the start of next instruction */ frame->state.ip = ip + 8; - ves_pinvoke_method (imethod, csignature, (MonoFuncV)code, context, frame, (stackval*)(locals + ip [1]), (stackval*)(locals + ip [3]), save_last_error, cache); + ves_pinvoke_method (imethod, csignature, (MonoFuncV)code, context, frame, (stackval*)(locals + ip [1]), (stackval*)(locals + ip [3]), save_last_error, cache, &gc_transitions); - EXCEPTION_CHECKPOINT_GC_UNSAFE; + EXCEPTION_CHECKPOINT; CHECK_RESUME_STATE (context); ip += 8; @@ -6242,8 +6259,8 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_ICALL_PPPPP_V) MINT_IN_CASE(MINT_ICALL_PPPPPP_V) frame->state.ip = ip + 3; - do_icall_wrapper (frame, NULL, *ip, NULL, (stackval*)(locals + ip [1]), frame->imethod->data_items [ip [2]], FALSE); - EXCEPTION_CHECKPOINT_GC_UNSAFE; + do_icall_wrapper (frame, NULL, *ip, NULL, (stackval*)(locals + ip [1]), frame->imethod->data_items [ip [2]], FALSE, &gc_transitions); + EXCEPTION_CHECKPOINT; CHECK_RESUME_STATE (context); ip += 3; MINT_IN_BREAK; @@ -6255,8 +6272,8 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_ICALL_PPPPP_P) MINT_IN_CASE(MINT_ICALL_PPPPPP_P) frame->state.ip = ip + 4; - do_icall_wrapper (frame, NULL, *ip, (stackval*)(locals + ip [1]), (stackval*)(locals + ip [2]), frame->imethod->data_items [ip [3]], FALSE); - EXCEPTION_CHECKPOINT_GC_UNSAFE; + do_icall_wrapper (frame, NULL, *ip, (stackval*)(locals + ip [1]), (stackval*)(locals + ip [2]), frame->imethod->data_items [ip [3]], FALSE, &gc_transitions); + EXCEPTION_CHECKPOINT; CHECK_RESUME_STATE (context); ip += 4; MINT_IN_BREAK; @@ -6306,9 +6323,9 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; LOCAL_VAR (ip [1], gpointer) = mono_domain_get (); ip += 2; MINT_IN_BREAK; - MINT_IN_CASE(MINT_MONO_GET_SP) - LOCAL_VAR (ip [1], gpointer) = frame; - ip += 2; + MINT_IN_CASE(MINT_MONO_ENABLE_GCTRANS) + gc_transitions = TRUE; + ip++; MINT_IN_BREAK; MINT_IN_CASE(MINT_SDB_INTR_LOC) if (G_UNLIKELY (ss_enabled)) { @@ -6508,17 +6525,18 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_CASE(MINT_LDFTN) { InterpMethod *m = (InterpMethod*)frame->imethod->data_items [ip [2]]; - LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (m); + LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (m, FALSE); ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_LDVIRTFTN) { - InterpMethod *m = (InterpMethod*)frame->imethod->data_items [ip [3]]; + InterpMethod *virtual_method = (InterpMethod*)frame->imethod->data_items [ip [3]]; MonoObject *o = LOCAL_VAR (ip [2], MonoObject*); NULL_CHECK (o); - m = get_virtual_method (m, o->vtable); - LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (m); + InterpMethod *res_method = get_virtual_method (virtual_method, o->vtable); + gboolean need_unbox = m_class_is_valuetype (res_method->method->klass) && !m_class_is_valuetype (virtual_method->method->klass); + LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (res_method, need_unbox); ip += 4; MINT_IN_BREAK; } @@ -6527,9 +6545,16 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MonoMethod *cmethod = LOCAL_VAR (ip [2], MonoMethod*); - InterpMethod *m = mono_interp_get_imethod (cmethod, error); - mono_error_assert_ok (error); - LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (m); + if (G_UNLIKELY (mono_method_has_unmanaged_callers_only_attribute (cmethod))) { + cmethod = mono_marshal_get_managed_wrapper (cmethod, NULL, (MonoGCHandle)0, error); + mono_error_assert_ok (error); + gpointer addr = mini_get_interp_callbacks ()->create_method_pointer (cmethod, TRUE, error); + LOCAL_VAR (ip [1], gpointer) = addr; + } else { + InterpMethod *m = mono_interp_get_imethod (cmethod, error); + mono_error_assert_ok (error); + LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (m, FALSE); + } ip += 3; MINT_IN_BREAK; } @@ -6711,7 +6736,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; mono_error_assert_ok (error); } g_assert (del->interp_method); - LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (del->interp_method); + LOCAL_VAR (ip [1], gpointer) = imethod_to_ftnptr (del->interp_method, FALSE); ip += 3; MINT_IN_BREAK; } diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index 9ef942e9d1b25..3f55869659543 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -664,7 +664,7 @@ OPDEF(MINT_CALL, "call", 4, 1, 1, MintOpMethodToken) OPDEF(MINT_CALLVIRT, "callvirt", 4, 1, 1, MintOpMethodToken) OPDEF(MINT_CALLVIRT_FAST, "callvirt.fast", 5, 1, 1, MintOpMethodToken) OPDEF(MINT_CALL_DELEGATE, "call.delegate", 5, 1, 1, MintOpTwoShorts) -OPDEF(MINT_CALLI, "calli", 5, 1, 2, MintOpMethodToken) +OPDEF(MINT_CALLI, "calli", 4, 1, 2, MintOpNoArgs) OPDEF(MINT_CALLI_NAT, "calli.nat", 8, 1, 2, MintOpMethodToken) OPDEF(MINT_CALLI_NAT_DYNAMIC, "calli.nat.dynamic", 5, 1, 2, MintOpMethodToken) OPDEF(MINT_CALLI_NAT_FAST, "calli.nat.fast", 7, 1, 2, MintOpMethodToken) @@ -697,7 +697,7 @@ OPDEF(MINT_MONO_ATOMIC_STORE_I4, "mono_atomic.store.i4", 3, 0, 2, MintOpNoArgs) OPDEF(MINT_MONO_MEMORY_BARRIER, "mono_memory_barrier", 1, 0, 0, MintOpNoArgs) OPDEF(MINT_MONO_EXCHANGE_I8, "mono_interlocked.xchg.i8", 4, 1, 2, MintOpNoArgs) OPDEF(MINT_MONO_LDDOMAIN, "mono_lddomain", 2, 1, 0, MintOpNoArgs) -OPDEF(MINT_MONO_GET_SP, "mono_get_sp", 2, 1, 0, MintOpNoArgs) +OPDEF(MINT_MONO_ENABLE_GCTRANS, "mono_enable_gctrans", 1, 0, 0, MintOpNoArgs) OPDEF(MINT_SDB_INTR_LOC, "sdb_intr_loc", 1, 0, 0, MintOpNoArgs) OPDEF(MINT_SDB_SEQ_POINT, "sdb_seq_point", 1, 0, 0, MintOpNoArgs) diff --git a/src/mono/mono/mini/interp/mintops.h b/src/mono/mono/mini/interp/mintops.h index 6de5e8c4ec0a0..e1a381f0a5dda 100644 --- a/src/mono/mono/mini/interp/mintops.h +++ b/src/mono/mono/mini/interp/mintops.h @@ -59,10 +59,13 @@ typedef enum { #define MINT_SWITCH_LEN(n) (4 + (n) * 2) +#define MINT_IS_NOP(op) ((op) == MINT_NOP || (op) == MINT_DEF || (op) == MINT_DUMMY_USE || (op) == MINT_IL_SEQ_POINT) #define MINT_IS_MOV(op) ((op) >= MINT_MOV_I1 && (op) <= MINT_MOV_VT) +#define MINT_IS_UNCONDITIONAL_BRANCH(op) ((op) >= MINT_BR && (op) <= MINT_CALL_HANDLER_S) #define MINT_IS_CONDITIONAL_BRANCH(op) ((op) >= MINT_BRFALSE_I4 && (op) <= MINT_BLT_UN_R8_S) #define MINT_IS_UNOP_CONDITIONAL_BRANCH(op) ((op) >= MINT_BRFALSE_I4 && (op) <= MINT_BRTRUE_R8_S) #define MINT_IS_BINOP_CONDITIONAL_BRANCH(op) ((op) >= MINT_BEQ_I4 && (op) <= MINT_BLT_UN_R8_S) +#define MINT_IS_SUPER_BRANCH(op) ((op) >= MINT_BRFALSE_I4_SP && (op) <= MINT_BLT_UN_I8_IMM_SP) #define MINT_IS_CALL(op) ((op) >= MINT_CALL && (op) <= MINT_JIT_CALL) #define MINT_IS_PATCHABLE_CALL(op) ((op) >= MINT_CALL && (op) <= MINT_VCALL) #define MINT_IS_LDC_I4(op) ((op) >= MINT_LDC_I4_M1 && (op) <= MINT_LDC_I4) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 0e71341d852f5..979f7a1b7ffe3 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -582,7 +582,7 @@ interp_merge_bblocks (TransformData *td, InterpBasicBlock *bb, InterpBasicBlock if (bb->last_ins) { InterpInst *last_ins = (bb->last_ins->opcode != MINT_NOP) ? bb->last_ins : interp_prev_ins (bb->last_ins); if (last_ins) { - if (last_ins->opcode == MINT_BR || last_ins->opcode == MINT_BR_S) { + if (last_ins->opcode == MINT_BR) { g_assert (last_ins->info.target_bb == bbadd); interp_clear_ins (last_ins); } else if (last_ins->opcode == MINT_SWITCH) { @@ -779,9 +779,8 @@ init_bb_stack_state (TransformData *td, InterpBasicBlock *bb) } static void -handle_branch (TransformData *td, int short_op, int long_op, int offset) +handle_branch (TransformData *td, int long_op, int offset) { - int shorten_branch = 0; int target = td->ip + offset - td->il_code; if (target < 0 || target >= td->code_size) g_assert_not_reached (); @@ -794,7 +793,7 @@ handle_branch (TransformData *td, int short_op, int long_op, int offset) InterpBasicBlock *target_bb = td->offset_to_bb [target]; g_assert (target_bb); - if (short_op == MINT_LEAVE_S || short_op == MINT_LEAVE_S_CHECK) + if (long_op == MINT_LEAVE || long_op == MINT_LEAVE_CHECK) target_bb->eh_block = TRUE; fixup_newbb_stack_locals (td, target_bb); @@ -803,16 +802,8 @@ handle_branch (TransformData *td, int short_op, int long_op, int offset) interp_link_bblocks (td, td->cbb, target_bb); - if (td->header->code_size <= 25000) /* FIX to be precise somehow? */ - shorten_branch = 1; - - if (shorten_branch) { - interp_add_ins (td, short_op); - td->last_ins->info.target_bb = target_bb; - } else { - interp_add_ins (td, long_op); - td->last_ins->info.target_bb = target_bb; - } + interp_add_ins (td, long_op); + td->last_ins->info.target_bb = target_bb; } static void @@ -820,11 +811,10 @@ one_arg_branch(TransformData *td, int mint_op, int offset, int inst_size) { int type = td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_MP ? STACK_TYPE_I : td->sp [-1].type; int long_op = mint_op + type - STACK_TYPE_I4; - int short_op = long_op + MINT_BRFALSE_I4_S - MINT_BRFALSE_I4; CHECK_STACK(td, 1); --td->sp; if (offset) { - handle_branch (td, short_op, long_op, offset + inst_size); + handle_branch (td, long_op, offset + inst_size); interp_ins_set_sreg (td->last_ins, td->sp->local); } else { interp_add_ins (td, MINT_NOP); @@ -870,10 +860,9 @@ two_arg_branch(TransformData *td, int mint_op, int offset, int inst_size) } int long_op = mint_op + type1 - STACK_TYPE_I4; - int short_op = long_op + MINT_BEQ_I4_S - MINT_BEQ_I4; td->sp -= 2; if (offset) { - handle_branch (td, short_op, long_op, offset + inst_size); + handle_branch (td, long_op, offset + inst_size); interp_ins_set_sregs2 (td->last_ins, td->sp [0].local, td->sp [1].local); } else { interp_add_ins (td, MINT_NOP); @@ -3322,7 +3311,7 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target for (i = csignature->param_count - 1 + !!csignature->hasthis; i >= 0; --i) store_arg (td, i); - interp_add_ins (td, MINT_BR_S); + interp_add_ins (td, MINT_BR); // We are branching to the beginning of the method td->last_ins->info.target_bb = td->entry_bb; int in_offset = td->ip - td->il_code; @@ -3511,7 +3500,6 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target interp_add_ins (td, MINT_CALLI); interp_ins_set_dreg (td->last_ins, dreg); interp_ins_set_sregs2 (td->last_ins, fp_sreg, MINT_CALL_ARGS_SREG); - td->last_ins->data [0] = get_data_item_index (td, (void *)csignature); } } else { InterpMethod *imethod = mono_interp_get_imethod (target_method, error); @@ -4958,7 +4946,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, if (inlining) { td->ip++; fixup_newbb_stack_locals (td, exit_bb); - interp_add_ins (td, MINT_BR_S); + interp_add_ins (td, MINT_BR); td->last_ins->info.target_bb = exit_bb; init_bb_stack_state (td, exit_bb); interp_link_bblocks (td, td->cbb, exit_bb); @@ -5022,7 +5010,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, case CEE_BR: { int offset = read32 (td->ip + 1); if (offset) { - handle_branch (td, MINT_BR_S, MINT_BR, 5 + offset); + handle_branch (td, MINT_BR, 5 + offset); link_bblocks = FALSE; } td->ip += 5; @@ -5031,7 +5019,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, case CEE_BR_S: { int offset = (gint8)td->ip [1]; if (offset) { - handle_branch (td, MINT_BR_S, MINT_BR, 2 + (gint8)td->ip [1]); + handle_branch (td, MINT_BR, 2 + (gint8)td->ip [1]); link_bblocks = FALSE; } td->ip += 2; @@ -6906,20 +6894,16 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, continue; if (MONO_OFFSET_IN_CLAUSE (clause, (td->ip - header->code)) && (!MONO_OFFSET_IN_CLAUSE (clause, (target_offset + in_offset)))) { - handle_branch (td, MINT_CALL_HANDLER_S, MINT_CALL_HANDLER, clause->handler_offset - in_offset); - // FIXME We need new IR to get rid of _S ugliness - if (td->last_ins->opcode == MINT_CALL_HANDLER_S) - td->last_ins->data [1] = i; - else - td->last_ins->data [2] = i; + handle_branch (td, MINT_CALL_HANDLER, clause->handler_offset - in_offset); + td->last_ins->data [2] = i; } } if (td->clause_indexes [in_offset] != -1) { /* LEAVE instructions in catch clauses need to check for abort exceptions */ - handle_branch (td, MINT_LEAVE_S_CHECK, MINT_LEAVE_CHECK, target_offset); + handle_branch (td, MINT_LEAVE_CHECK, target_offset); } else { - handle_branch (td, MINT_LEAVE_S, MINT_LEAVE, target_offset); + handle_branch (td, MINT_LEAVE, target_offset); } if (*td->ip == CEE_LEAVE) @@ -7143,12 +7127,28 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, save_last_error = TRUE; ++td->ip; break; - case CEE_MONO_GET_SP: - interp_add_ins (td, MINT_MONO_GET_SP); - push_simple_type (td, STACK_TYPE_I); - interp_ins_set_dreg (td->last_ins, td->sp [-1].local); + case CEE_MONO_GET_SP: { ++td->ip; + g_assert (*td->ip == MONO_CUSTOM_PREFIX); + ++td->ip; + g_assert (*td->ip == CEE_MONO_ICALL); + // in coop gc transitions we use mono.get.sp + calli to implement enter/exit + // on interpreter we do these transitions explicitly when entering/exiting the + // interpreter so we can ignore them here in the wrappers. + MonoJitICallId const jit_icall_id = (MonoJitICallId)read32 (td->ip + 1); + MonoJitICallInfo const * const info = mono_find_jit_icall_info (jit_icall_id); + + if (info->sig->ret->type != MONO_TYPE_VOID) { + // Push a dummy coop gc var + push_simple_type (td, STACK_TYPE_I); + interp_add_ins (td, MINT_MONO_ENABLE_GCTRANS); + } else { + // Pop the unused gc var + td->sp--; + } + td->ip += 5; break; + } default: g_error ("transform.c: Unimplemented opcode: 0xF0 %02x at 0x%x\n", *td->ip, td->ip-header->code); } @@ -7643,6 +7643,60 @@ get_inst_length (InterpInst *ins) return mono_interp_oplen [ins->opcode]; } +static int +compute_native_offset_estimates (TransformData *td) +{ + InterpBasicBlock *bb; + int noe = 0; + for (bb = td->entry_bb; bb != NULL; bb = bb->next_bb) { + InterpInst *ins; + bb->native_offset_estimate = noe; + for (ins = bb->first_ins; ins != NULL; ins = ins->next) { + int opcode = ins->opcode; + // Skip dummy opcodes for more precise offset computation + if (MINT_IS_NOP (opcode)) + continue; + noe += get_inst_length (ins); + } + } + return noe; +} + +static gboolean +is_short_offset (int src_offset, int dest_offset) +{ + int diff = dest_offset - src_offset; + if (diff >= G_MININT16 && diff <= G_MAXINT16) + return TRUE; + return FALSE; +} + +static int +get_short_brop (int opcode) +{ + if (MINT_IS_UNCONDITIONAL_BRANCH (opcode)) { + if (opcode == MINT_BR) + return MINT_BR_S; + else if (opcode == MINT_LEAVE) + return MINT_LEAVE_S; + else if (opcode == MINT_LEAVE_CHECK) + return MINT_LEAVE_S_CHECK; + else if (opcode == MINT_CALL_HANDLER) + return MINT_CALL_HANDLER_S; + else + return opcode; + } + + if (opcode >= MINT_BRFALSE_I4 && opcode <= MINT_BRTRUE_R8) + return opcode + MINT_BRFALSE_I4_S - MINT_BRFALSE_I4; + + if (opcode >= MINT_BEQ_I4 && opcode <= MINT_BLT_UN_R8) + return opcode + MINT_BEQ_I4_S - MINT_BEQ_I4; + + // Already short branch + return opcode; +} + static guint16* emit_compacted_instruction (TransformData *td, guint16* start_ip, InterpInst *ins) @@ -7682,56 +7736,47 @@ emit_compacted_instruction (TransformData *td, guint16* start_ip, InterpInst *in *ip++ = 0xdead; *ip++ = 0xbeef; } - } else if ((opcode >= MINT_BRFALSE_I4_S && opcode <= MINT_BRTRUE_R8_S) || - (opcode >= MINT_BEQ_I4_S && opcode <= MINT_BLT_UN_R8_S) || - (opcode >= MINT_BRFALSE_I4_SP && opcode <= MINT_BLT_UN_I8_IMM_SP) || - opcode == MINT_BR_S || opcode == MINT_LEAVE_S || opcode == MINT_LEAVE_S_CHECK || opcode == MINT_CALL_HANDLER_S) { + } else if (MINT_IS_UNCONDITIONAL_BRANCH (opcode) || MINT_IS_CONDITIONAL_BRANCH (opcode) || MINT_IS_SUPER_BRANCH (opcode)) { const int br_offset = start_ip - td->new_code; gboolean has_imm = opcode >= MINT_BEQ_I4_IMM_SP && opcode <= MINT_BLT_UN_I8_IMM_SP; for (int i = 0; i < mono_interp_op_sregs [opcode]; i++) *ip++ = td->locals [ins->sregs [i]].offset; if (has_imm) *ip++ = ins->data [0]; + if (ins->info.target_bb->native_offset >= 0) { + int offset = ins->info.target_bb->native_offset - br_offset; // Backwards branch. We can already patch it. - *ip++ = ins->info.target_bb->native_offset - br_offset; - } else if (opcode == MINT_BR_S && ins->info.target_bb == td->cbb->next_bb) { - // Ignore branch to the next basic block. Revert the added MINT_BR_S. + if (is_short_offset (br_offset, ins->info.target_bb->native_offset)) { + // Replace the long opcode we added at the start + *start_ip = get_short_brop (opcode); + *ip++ = ins->info.target_bb->native_offset - br_offset; + } else { + WRITE32 (ip, &offset); + } + } else if (opcode == MINT_BR && ins->info.target_bb == td->cbb->next_bb) { + // Ignore branch to the next basic block. Revert the added MINT_BR. ip--; } else { + // If the estimate offset is short, then surely the real offset is short + gboolean is_short = is_short_offset (br_offset, ins->info.target_bb->native_offset_estimate); + if (is_short) + *start_ip = get_short_brop (opcode); + // We don't know the in_offset of the target, add a reloc Reloc *reloc = (Reloc*)mono_mempool_alloc0 (td->mempool, sizeof (Reloc)); - reloc->type = RELOC_SHORT_BRANCH; + reloc->type = is_short ? RELOC_SHORT_BRANCH : RELOC_LONG_BRANCH; reloc->skip = mono_interp_op_sregs [opcode] + has_imm; reloc->offset = br_offset; reloc->target_bb = ins->info.target_bb; g_ptr_array_add (td->relocs, reloc); *ip++ = 0xdead; - } - if (opcode == MINT_CALL_HANDLER_S) - *ip++ = ins->data [1]; - } else if ((opcode >= MINT_BRFALSE_I4 && opcode <= MINT_BRTRUE_R8) || - (opcode >= MINT_BEQ_I4 && opcode <= MINT_BLT_UN_R8) || - opcode == MINT_BR || opcode == MINT_LEAVE || opcode == MINT_LEAVE_CHECK || opcode == MINT_CALL_HANDLER) { - const int br_offset = start_ip - td->new_code; - for (int i = 0; i < mono_interp_op_sregs [opcode]; i++) - *ip++ = td->locals [ins->sregs [i]].offset; - if (ins->info.target_bb->native_offset >= 0) { - // Backwards branch. We can already patch it - int target_offset = ins->info.target_bb->native_offset - br_offset; - WRITE32 (ip, &target_offset); - } else { - Reloc *reloc = (Reloc*)mono_mempool_alloc0 (td->mempool, sizeof (Reloc)); - reloc->type = RELOC_LONG_BRANCH; - reloc->skip = mono_interp_op_sregs [opcode]; - reloc->offset = br_offset; - reloc->target_bb = ins->info.target_bb; - g_ptr_array_add (td->relocs, reloc); - *ip++ = 0xdead; - *ip++ = 0xbeef; + if (!is_short) + *ip++ = 0xbeef; } if (opcode == MINT_CALL_HANDLER) *ip++ = ins->data [2]; + } else if (opcode == MINT_SDB_SEQ_POINT || opcode == MINT_IL_SEQ_POINT) { SeqPoint *seqp = (SeqPoint*)mono_mempool_alloc0 (td->mempool, sizeof (SeqPoint)); InterpBasicBlock *cbb; @@ -7801,7 +7846,7 @@ emit_compacted_instruction (TransformData *td, guint16* start_ip, InterpInst *in #endif } else if (opcode >= MINT_MOV_8_2 && opcode <= MINT_MOV_8_4) { // This instruction is not marked as operating on any vars, all instruction slots are - // actually vas. Resolve their offset + // actually vars. Resolve their offset int num_vars = mono_interp_oplen [opcode] - 1; for (int i = 0; i < num_vars; i++) *ip++ = td->locals [ins->data [i]].offset; @@ -7835,18 +7880,13 @@ static void generate_compacted_code (TransformData *td) { guint16 *ip; - int size = 0; + int size; td->relocs = g_ptr_array_new (); InterpBasicBlock *bb; - // Iterate once for preliminary computations - for (bb = td->entry_bb; bb != NULL; bb = bb->next_bb) { - InterpInst *ins = bb->first_ins; - while (ins) { - size += get_inst_length (ins); - ins = ins->next; - } - } + // This iteration could be avoided at the cost of less precise size result, following + // super instruction pass + size = compute_native_offset_estimates (td); // Generate the compacted stream of instructions td->new_code = ip = (guint16*)mono_mem_manager_alloc0 (td->mem_manager, size * sizeof (guint16)); @@ -8073,7 +8113,7 @@ interp_fold_unop (TransformData *td, LocalValue *local_defs, InterpInst *ins) #define INTERP_FOLD_UNOP_BR(_opcode,_local_type,_cond) \ case _opcode: \ if (_cond) { \ - ins->opcode = MINT_BR_S; \ + ins->opcode = MINT_BR; \ if (cbb->next_bb != ins->info.target_bb) \ interp_unlink_bblocks (cbb, cbb->next_bb); \ for (InterpInst *it = ins->next; it != NULL; it = it->next) \ @@ -8097,10 +8137,10 @@ interp_fold_unop_cond_br (TransformData *td, InterpBasicBlock *cbb, LocalValue * // Top of the stack is a constant switch (ins->opcode) { - INTERP_FOLD_UNOP_BR (MINT_BRFALSE_I4_S, LOCAL_VALUE_I4, val->i == 0); - INTERP_FOLD_UNOP_BR (MINT_BRFALSE_I8_S, LOCAL_VALUE_I8, val->l == 0); - INTERP_FOLD_UNOP_BR (MINT_BRTRUE_I4_S, LOCAL_VALUE_I4, val->i != 0); - INTERP_FOLD_UNOP_BR (MINT_BRTRUE_I8_S, LOCAL_VALUE_I8, val->l != 0); + INTERP_FOLD_UNOP_BR (MINT_BRFALSE_I4, LOCAL_VALUE_I4, val->i == 0); + INTERP_FOLD_UNOP_BR (MINT_BRFALSE_I8, LOCAL_VALUE_I8, val->l == 0); + INTERP_FOLD_UNOP_BR (MINT_BRTRUE_I4, LOCAL_VALUE_I4, val->i != 0); + INTERP_FOLD_UNOP_BR (MINT_BRTRUE_I8, LOCAL_VALUE_I8, val->l != 0); default: return ins; @@ -8249,11 +8289,11 @@ interp_fold_binop (TransformData *td, LocalValue *local_defs, InterpInst *ins, g // Due to poor current design, the branch op might not be the last instruction in the bblock // (in case we fallthrough and need to have the stack locals match the ones from next_bb, done // in fixup_newbb_stack_locals). If that's the case, clear all these mov's. This helps bblock -// merging quickly find the MINT_BR_S opcode. +// merging quickly find the MINT_BR opcode. #define INTERP_FOLD_BINOP_BR(_opcode,_local_type,_cond) \ case _opcode: \ if (_cond) { \ - ins->opcode = MINT_BR_S; \ + ins->opcode = MINT_BR; \ if (cbb->next_bb != ins->info.target_bb) \ interp_unlink_bblocks (cbb, cbb->next_bb); \ for (InterpInst *it = ins->next; it != NULL; it = it->next) \ @@ -8280,27 +8320,27 @@ interp_fold_binop_cond_br (TransformData *td, InterpBasicBlock *cbb, LocalValue return ins; switch (ins->opcode) { - INTERP_FOLD_BINOP_BR (MINT_BEQ_I4_S, LOCAL_VALUE_I4, val1->i == val2->i); - INTERP_FOLD_BINOP_BR (MINT_BEQ_I8_S, LOCAL_VALUE_I8, val1->l == val2->l); - INTERP_FOLD_BINOP_BR (MINT_BGE_I4_S, LOCAL_VALUE_I4, val1->i >= val2->i); - INTERP_FOLD_BINOP_BR (MINT_BGE_I8_S, LOCAL_VALUE_I8, val1->l >= val2->l); - INTERP_FOLD_BINOP_BR (MINT_BGT_I4_S, LOCAL_VALUE_I4, val1->i > val2->i); - INTERP_FOLD_BINOP_BR (MINT_BGT_I8_S, LOCAL_VALUE_I8, val1->l > val2->l); - INTERP_FOLD_BINOP_BR (MINT_BLT_I4_S, LOCAL_VALUE_I4, val1->i < val2->i); - INTERP_FOLD_BINOP_BR (MINT_BLT_I8_S, LOCAL_VALUE_I8, val1->l < val2->l); - INTERP_FOLD_BINOP_BR (MINT_BLE_I4_S, LOCAL_VALUE_I4, val1->i <= val2->i); - INTERP_FOLD_BINOP_BR (MINT_BLE_I8_S, LOCAL_VALUE_I8, val1->l <= val2->l); - - INTERP_FOLD_BINOP_BR (MINT_BNE_UN_I4_S, LOCAL_VALUE_I4, val1->i != val2->i); - INTERP_FOLD_BINOP_BR (MINT_BNE_UN_I8_S, LOCAL_VALUE_I8, val1->l != val2->l); - INTERP_FOLD_BINOP_BR (MINT_BGE_UN_I4_S, LOCAL_VALUE_I4, (guint32)val1->i >= (guint32)val2->i); - INTERP_FOLD_BINOP_BR (MINT_BGE_UN_I8_S, LOCAL_VALUE_I8, (guint64)val1->l >= (guint64)val2->l); - INTERP_FOLD_BINOP_BR (MINT_BGT_UN_I4_S, LOCAL_VALUE_I4, (guint32)val1->i > (guint32)val2->i); - INTERP_FOLD_BINOP_BR (MINT_BGT_UN_I8_S, LOCAL_VALUE_I8, (guint64)val1->l > (guint64)val2->l); - INTERP_FOLD_BINOP_BR (MINT_BLE_UN_I4_S, LOCAL_VALUE_I4, (guint32)val1->i <= (guint32)val2->i); - INTERP_FOLD_BINOP_BR (MINT_BLE_UN_I8_S, LOCAL_VALUE_I8, (guint64)val1->l <= (guint64)val2->l); - INTERP_FOLD_BINOP_BR (MINT_BLT_UN_I4_S, LOCAL_VALUE_I4, (guint32)val1->i < (guint32)val2->i); - INTERP_FOLD_BINOP_BR (MINT_BLT_UN_I8_S, LOCAL_VALUE_I8, (guint64)val1->l < (guint64)val2->l); + INTERP_FOLD_BINOP_BR (MINT_BEQ_I4, LOCAL_VALUE_I4, val1->i == val2->i); + INTERP_FOLD_BINOP_BR (MINT_BEQ_I8, LOCAL_VALUE_I8, val1->l == val2->l); + INTERP_FOLD_BINOP_BR (MINT_BGE_I4, LOCAL_VALUE_I4, val1->i >= val2->i); + INTERP_FOLD_BINOP_BR (MINT_BGE_I8, LOCAL_VALUE_I8, val1->l >= val2->l); + INTERP_FOLD_BINOP_BR (MINT_BGT_I4, LOCAL_VALUE_I4, val1->i > val2->i); + INTERP_FOLD_BINOP_BR (MINT_BGT_I8, LOCAL_VALUE_I8, val1->l > val2->l); + INTERP_FOLD_BINOP_BR (MINT_BLT_I4, LOCAL_VALUE_I4, val1->i < val2->i); + INTERP_FOLD_BINOP_BR (MINT_BLT_I8, LOCAL_VALUE_I8, val1->l < val2->l); + INTERP_FOLD_BINOP_BR (MINT_BLE_I4, LOCAL_VALUE_I4, val1->i <= val2->i); + INTERP_FOLD_BINOP_BR (MINT_BLE_I8, LOCAL_VALUE_I8, val1->l <= val2->l); + + INTERP_FOLD_BINOP_BR (MINT_BNE_UN_I4, LOCAL_VALUE_I4, val1->i != val2->i); + INTERP_FOLD_BINOP_BR (MINT_BNE_UN_I8, LOCAL_VALUE_I8, val1->l != val2->l); + INTERP_FOLD_BINOP_BR (MINT_BGE_UN_I4, LOCAL_VALUE_I4, (guint32)val1->i >= (guint32)val2->i); + INTERP_FOLD_BINOP_BR (MINT_BGE_UN_I8, LOCAL_VALUE_I8, (guint64)val1->l >= (guint64)val2->l); + INTERP_FOLD_BINOP_BR (MINT_BGT_UN_I4, LOCAL_VALUE_I4, (guint32)val1->i > (guint32)val2->i); + INTERP_FOLD_BINOP_BR (MINT_BGT_UN_I8, LOCAL_VALUE_I8, (guint64)val1->l > (guint64)val2->l); + INTERP_FOLD_BINOP_BR (MINT_BLE_UN_I4, LOCAL_VALUE_I4, (guint32)val1->i <= (guint32)val2->i); + INTERP_FOLD_BINOP_BR (MINT_BLE_UN_I8, LOCAL_VALUE_I8, (guint64)val1->l <= (guint64)val2->l); + INTERP_FOLD_BINOP_BR (MINT_BLT_UN_I4, LOCAL_VALUE_I4, (guint32)val1->i < (guint32)val2->i); + INTERP_FOLD_BINOP_BR (MINT_BLT_UN_I8, LOCAL_VALUE_I8, (guint64)val1->l < (guint64)val2->l); default: return ins; @@ -8710,26 +8750,26 @@ static int get_binop_condbr_imm_sp (int opcode) { switch (opcode) { - case MINT_BEQ_I4_S: return MINT_BEQ_I4_IMM_SP; - case MINT_BEQ_I8_S: return MINT_BEQ_I8_IMM_SP; - case MINT_BGE_I4_S: return MINT_BGE_I4_IMM_SP; - case MINT_BGE_I8_S: return MINT_BGE_I8_IMM_SP; - case MINT_BGT_I4_S: return MINT_BGT_I4_IMM_SP; - case MINT_BGT_I8_S: return MINT_BGT_I8_IMM_SP; - case MINT_BLT_I4_S: return MINT_BLT_I4_IMM_SP; - case MINT_BLT_I8_S: return MINT_BLT_I8_IMM_SP; - case MINT_BLE_I4_S: return MINT_BLE_I4_IMM_SP; - case MINT_BLE_I8_S: return MINT_BLE_I8_IMM_SP; - case MINT_BNE_UN_I4_S: return MINT_BNE_UN_I4_IMM_SP; - case MINT_BNE_UN_I8_S: return MINT_BNE_UN_I8_IMM_SP; - case MINT_BGE_UN_I4_S: return MINT_BGE_UN_I4_IMM_SP; - case MINT_BGE_UN_I8_S: return MINT_BGE_UN_I8_IMM_SP; - case MINT_BGT_UN_I4_S: return MINT_BGT_UN_I4_IMM_SP; - case MINT_BGT_UN_I8_S: return MINT_BGT_UN_I8_IMM_SP; - case MINT_BLE_UN_I4_S: return MINT_BLE_UN_I4_IMM_SP; - case MINT_BLE_UN_I8_S: return MINT_BLE_UN_I8_IMM_SP; - case MINT_BLT_UN_I4_S: return MINT_BLT_UN_I4_IMM_SP; - case MINT_BLT_UN_I8_S: return MINT_BLT_UN_I8_IMM_SP; + case MINT_BEQ_I4: return MINT_BEQ_I4_IMM_SP; + case MINT_BEQ_I8: return MINT_BEQ_I8_IMM_SP; + case MINT_BGE_I4: return MINT_BGE_I4_IMM_SP; + case MINT_BGE_I8: return MINT_BGE_I8_IMM_SP; + case MINT_BGT_I4: return MINT_BGT_I4_IMM_SP; + case MINT_BGT_I8: return MINT_BGT_I8_IMM_SP; + case MINT_BLT_I4: return MINT_BLT_I4_IMM_SP; + case MINT_BLT_I8: return MINT_BLT_I8_IMM_SP; + case MINT_BLE_I4: return MINT_BLE_I4_IMM_SP; + case MINT_BLE_I8: return MINT_BLE_I8_IMM_SP; + case MINT_BNE_UN_I4: return MINT_BNE_UN_I4_IMM_SP; + case MINT_BNE_UN_I8: return MINT_BNE_UN_I8_IMM_SP; + case MINT_BGE_UN_I4: return MINT_BGE_UN_I4_IMM_SP; + case MINT_BGE_UN_I8: return MINT_BGE_UN_I8_IMM_SP; + case MINT_BGT_UN_I4: return MINT_BGT_UN_I4_IMM_SP; + case MINT_BGT_UN_I8: return MINT_BGT_UN_I8_IMM_SP; + case MINT_BLE_UN_I4: return MINT_BLE_UN_I4_IMM_SP; + case MINT_BLE_UN_I8: return MINT_BLE_UN_I8_IMM_SP; + case MINT_BLT_UN_I4: return MINT_BLT_UN_I4_IMM_SP; + case MINT_BLT_UN_I8: return MINT_BLT_UN_I8_IMM_SP; default: return MINT_NOP; } } @@ -8738,26 +8778,26 @@ static int get_binop_condbr_sp (int opcode) { switch (opcode) { - case MINT_BEQ_I4_S: return MINT_BEQ_I4_SP; - case MINT_BEQ_I8_S: return MINT_BEQ_I8_SP; - case MINT_BGE_I4_S: return MINT_BGE_I4_SP; - case MINT_BGE_I8_S: return MINT_BGE_I8_SP; - case MINT_BGT_I4_S: return MINT_BGT_I4_SP; - case MINT_BGT_I8_S: return MINT_BGT_I8_SP; - case MINT_BLT_I4_S: return MINT_BLT_I4_SP; - case MINT_BLT_I8_S: return MINT_BLT_I8_SP; - case MINT_BLE_I4_S: return MINT_BLE_I4_SP; - case MINT_BLE_I8_S: return MINT_BLE_I8_SP; - case MINT_BNE_UN_I4_S: return MINT_BNE_UN_I4_SP; - case MINT_BNE_UN_I8_S: return MINT_BNE_UN_I8_SP; - case MINT_BGE_UN_I4_S: return MINT_BGE_UN_I4_SP; - case MINT_BGE_UN_I8_S: return MINT_BGE_UN_I8_SP; - case MINT_BGT_UN_I4_S: return MINT_BGT_UN_I4_SP; - case MINT_BGT_UN_I8_S: return MINT_BGT_UN_I8_SP; - case MINT_BLE_UN_I4_S: return MINT_BLE_UN_I4_SP; - case MINT_BLE_UN_I8_S: return MINT_BLE_UN_I8_SP; - case MINT_BLT_UN_I4_S: return MINT_BLT_UN_I4_SP; - case MINT_BLT_UN_I8_S: return MINT_BLT_UN_I8_SP; + case MINT_BEQ_I4: return MINT_BEQ_I4_SP; + case MINT_BEQ_I8: return MINT_BEQ_I8_SP; + case MINT_BGE_I4: return MINT_BGE_I4_SP; + case MINT_BGE_I8: return MINT_BGE_I8_SP; + case MINT_BGT_I4: return MINT_BGT_I4_SP; + case MINT_BGT_I8: return MINT_BGT_I8_SP; + case MINT_BLT_I4: return MINT_BLT_I4_SP; + case MINT_BLT_I8: return MINT_BLT_I8_SP; + case MINT_BLE_I4: return MINT_BLE_I4_SP; + case MINT_BLE_I8: return MINT_BLE_I8_SP; + case MINT_BNE_UN_I4: return MINT_BNE_UN_I4_SP; + case MINT_BNE_UN_I8: return MINT_BNE_UN_I8_SP; + case MINT_BGE_UN_I4: return MINT_BGE_UN_I4_SP; + case MINT_BGE_UN_I8: return MINT_BGE_UN_I8_SP; + case MINT_BGT_UN_I4: return MINT_BGT_UN_I4_SP; + case MINT_BGT_UN_I8: return MINT_BGT_UN_I8_SP; + case MINT_BLE_UN_I4: return MINT_BLE_UN_I4_SP; + case MINT_BLE_UN_I8: return MINT_BLE_UN_I8_SP; + case MINT_BLT_UN_I4: return MINT_BLT_UN_I4_SP; + case MINT_BLT_UN_I8: return MINT_BLT_UN_I8_SP; default: return MINT_NOP; } } @@ -8766,10 +8806,10 @@ static int get_unop_condbr_sp (int opcode) { switch (opcode) { - case MINT_BRFALSE_I4_S: return MINT_BRFALSE_I4_SP; - case MINT_BRFALSE_I8_S: return MINT_BRFALSE_I8_SP; - case MINT_BRTRUE_I4_S: return MINT_BRTRUE_I4_SP; - case MINT_BRTRUE_I8_S: return MINT_BRTRUE_I8_SP; + case MINT_BRFALSE_I4: return MINT_BRFALSE_I4_SP; + case MINT_BRFALSE_I8: return MINT_BRFALSE_I8_SP; + case MINT_BRTRUE_I4: return MINT_BRTRUE_I4_SP; + case MINT_BRTRUE_I8: return MINT_BRTRUE_I8_SP; default: return MINT_NOP; } } @@ -8779,16 +8819,20 @@ interp_super_instructions (TransformData *td) { InterpBasicBlock *bb; int *local_ref_count = td->local_ref_count; + + compute_native_offset_estimates (td); + // Add some actual super instructions for (bb = td->entry_bb; bb != NULL; bb = bb->next_bb) { InterpInst *ins; + int noe; // Set cbb since we do some instruction inserting below td->cbb = bb; - + noe = bb->native_offset_estimate; for (ins = bb->first_ins; ins != NULL; ins = ins->next) { int opcode = ins->opcode; - if (opcode == MINT_NOP) + if (MINT_IS_NOP (opcode)) continue; if (mono_interp_op_dregs [opcode] && !(td->locals [ins->dreg].flags & INTERP_LOCAL_FLAG_GLOBAL)) td->locals [ins->dreg].def = ins; @@ -8956,7 +9000,7 @@ interp_super_instructions (TransformData *td) local_ref_count [obj_sreg]--; mono_interp_stats.super_instructions++; } - } else if (MINT_IS_BINOP_CONDITIONAL_BRANCH (opcode)) { + } else if (MINT_IS_BINOP_CONDITIONAL_BRANCH (opcode) && is_short_offset (noe, ins->info.target_bb->native_offset_estimate)) { gint16 imm; int sreg_imm = ins->sregs [1]; if (get_sreg_imm (td, sreg_imm, &imm)) { @@ -8992,7 +9036,7 @@ interp_super_instructions (TransformData *td) } } } - } else if (MINT_IS_UNOP_CONDITIONAL_BRANCH (opcode)) { + } else if (MINT_IS_UNOP_CONDITIONAL_BRANCH (opcode) && is_short_offset (noe, ins->info.target_bb->native_offset_estimate)) { InterpInst *prev_ins = interp_prev_ins (ins); if (prev_ins && prev_ins->opcode == MINT_SAFEPOINT) { int condbr_op = get_unop_condbr_sp (opcode); @@ -9007,6 +9051,7 @@ interp_super_instructions (TransformData *td) } } + noe += get_inst_length (ins); } } } diff --git a/src/mono/mono/mini/interp/transform.h b/src/mono/mono/mini/interp/transform.h index c57b0981d1b1d..80a2eae7486a4 100644 --- a/src/mono/mono/mini/interp/transform.h +++ b/src/mono/mono/mini/interp/transform.h @@ -99,7 +99,16 @@ struct _InterpBasicBlock { gint16 out_count; InterpBasicBlock **out_bb; + /* The real native offset of this bblock, computed when emitting the instructions in the code stream */ int native_offset; + /* + * Estimated native offset computed before the final code stream is generated. These offsets are used + * to determine whether we will use a long or short branch when branching to this bblock. Native offset + * estimates must respect the following condition: |bb1->n_o_e - bb2->n_o_e| >= |bb1->n_o - bb2->n_o|. + * The real native offset between two instructions is always smaller or equal to the estimate, allowing + * us to safely insert short branches based on the estimated offset. + */ + int native_offset_estimate; /* * The state of the stack when entering this basic block. By default, the stack height is diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index e0e699c588059..4e89ab2d0f1a4 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -658,7 +658,7 @@ emit_jit_helpers_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSi static gboolean byref_arg_is_reference (MonoType *t) { - g_assert (t->byref); + g_assert (m_type_is_byref (t)); return mini_type_is_reference (m_class_get_byval_arg (mono_class_from_mono_type_internal (t))); } @@ -1019,7 +1019,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign gboolean is_enter = FALSE; gboolean is_v4 = FALSE; - if (!strcmp (cmethod->name, "Enter") && fsig->param_count == 2 && fsig->params [1]->byref) { + if (!strcmp (cmethod->name, "Enter") && fsig->param_count == 2 && m_type_is_byref (fsig->params [1])) { is_enter = TRUE; is_v4 = TRUE; } @@ -1058,7 +1058,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign return ins; } else if (strcmp (cmethod->name, "MemoryBarrier") == 0 && fsig->param_count == 0) { return mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ); - } else if (!strcmp (cmethod->name, "VolatileRead") && fsig->param_count == 1 && fsig->params [0]->byref) { + } else if (!strcmp (cmethod->name, "VolatileRead") && fsig->param_count == 1 && m_type_is_byref (fsig->params [0])) { guint32 opcode = 0; gboolean is_ref = byref_arg_is_reference (fsig->params [0]); @@ -1132,7 +1132,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign return ins; } - } else if (!strcmp (cmethod->name, "VolatileWrite") && fsig->param_count == 2 && fsig->params [0]->byref) { + } else if (!strcmp (cmethod->name, "VolatileWrite") && fsig->param_count == 2 && m_type_is_byref (fsig->params [0])) { guint32 opcode = 0; gboolean is_ref = byref_arg_is_reference (fsig->params [0]); @@ -1295,7 +1295,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign MONO_ADD_INS (cfg->cbb, ins); } } - else if (strcmp (cmethod->name, "Exchange") == 0 && fsig->param_count == 2 && fsig->params [0]->byref) { + else if (strcmp (cmethod->name, "Exchange") == 0 && fsig->param_count == 2 && m_type_is_byref (fsig->params [0])) { MonoInst *f2i = NULL, *i2f; guint32 opcode, f2i_opcode, i2f_opcode; gboolean is_ref = byref_arg_is_reference (fsig->params [0]); @@ -1545,7 +1545,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign gboolean is_ref; gboolean is_float = t->type == MONO_TYPE_R4 || t->type == MONO_TYPE_R8; - g_assert (t->byref); + g_assert (m_type_is_byref (t)); is_ref = byref_arg_is_reference (t); if (t->type == MONO_TYPE_I1) opcode = OP_ATOMIC_LOAD_I1; @@ -1626,7 +1626,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign MonoType *t = fsig->params [0]; gboolean is_ref; - g_assert (t->byref); + g_assert (m_type_is_byref (t)); is_ref = byref_arg_is_reference (t); if (t->type == MONO_TYPE_I1) opcode = OP_ATOMIC_STORE_I1; diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index 730ce1e90ffe9..d309d441661d9 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -301,7 +301,7 @@ mono_alloc_ireg_copy (MonoCompile *cfg, guint32 vreg) guint mono_type_to_regmove (MonoCompile *cfg, MonoType *type) { - if (type->byref) + if (m_type_is_byref (type)) return OP_MOVE; type = mini_get_underlying_type (type); @@ -806,7 +806,7 @@ mini_type_to_eval_stack_type (MonoCompile *cfg, MonoType *type, MonoInst *inst) type = mini_get_underlying_type (type); inst->klass = klass = mono_class_from_mono_type_internal (type); - if (type->byref) { + if (m_type_is_byref (type)) { inst->type = STACK_MP; return; } @@ -1307,13 +1307,13 @@ check_values_to_signature (MonoInst *args, MonoType *this_ins, MonoMethodSignatu case STACK_INV: return 0; case STACK_MP: - if (!sig->params [i]->byref) + if (m_type_is_byref (!sig->params [i])) return 0; continue; case STACK_OBJ: - if (sig->params [i]->byref) + if (m_type_is_byref (sig->params [i])) return 0; - switch (sig->params [i]->type) { + switch (m_type_is_byref (sig->params [i])) { case MONO_TYPE_CLASS: case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: @@ -1325,7 +1325,7 @@ check_values_to_signature (MonoInst *args, MonoType *this_ins, MonoMethodSignatu } continue; case STACK_R8: - if (sig->params [i]->byref) + if (m_type_is_byref (sig->params [i])) return 0; if (sig->params [i]->type != MONO_TYPE_R4 && sig->params [i]->type != MONO_TYPE_R8) return 0; @@ -1842,7 +1842,7 @@ target_type_is_incompatible (MonoCompile *cfg, MonoType *target, MonoInst *arg) MonoType *simple_type; MonoClass *klass; - if (target->byref) { + if (m_type_is_byref (target)) { /* FIXME: check that the pointed to types match */ if (arg->type == STACK_MP) { /* This is needed to handle gshared types + ldaddr. We lower the types so we can handle enums and other typedef-like types. */ @@ -2025,7 +2025,7 @@ check_call_signature (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **arg args++; } for (i = 0; i < sig->param_count; ++i) { - if (sig->params [i]->byref) { + if (m_type_is_byref (sig->params [i])) { if (args [i]->type != STACK_MP && args [i]->type != STACK_PTR) return TRUE; continue; @@ -2237,7 +2237,7 @@ static MonoInst* mono_emit_widen_call_res (MonoCompile *cfg, MonoInst *ins, MonoMethodSignature *fsig) { if (!MONO_TYPE_IS_VOID (fsig->ret)) { - if ((fsig->pinvoke || LLVM_ENABLED) && !fsig->ret->byref) { + if ((fsig->pinvoke || LLVM_ENABLED) && !m_type_is_byref (fsig->ret)) { int widen_op = -1; /* @@ -3678,7 +3678,7 @@ handle_constrained_gsharedvt_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMe } else { supported = TRUE; for (int i = 0; i < fsig->param_count; ++i) { - if (!(fsig->params [i]->byref || MONO_TYPE_IS_PRIMITIVE (fsig->params [i]) || MONO_TYPE_IS_REFERENCE (fsig->params [i]) || MONO_TYPE_ISSTRUCT (fsig->params [i]) || mini_is_gsharedvt_type (fsig->params [i]))) + if (!(m_type_is_byref (fsig->params [i]) || MONO_TYPE_IS_PRIMITIVE (fsig->params [i]) || MONO_TYPE_IS_REFERENCE (fsig->params [i]) || MONO_TYPE_ISSTRUCT (fsig->params [i]) || mini_is_gsharedvt_type (fsig->params [i]))) supported = FALSE; } } @@ -3998,7 +3998,7 @@ mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method) if (sig->ret && sig->ret->type == MONO_TYPE_R4) return FALSE; for (i = 0; i < sig->param_count; ++i) - if (!sig->params [i]->byref && sig->params [i]->type == MONO_TYPE_R4) + if (!m_type_is_byref (sig->params [i]) && sig->params [i]->type == MONO_TYPE_R4) return FALSE; } #endif @@ -4469,7 +4469,7 @@ mini_emit_init_rvar (MonoCompile *cfg, int dreg, MonoType *rtype) rtype = mini_get_underlying_type (rtype); t = rtype->type; - if (rtype->byref) { + if (m_type_is_byref (rtype)) { MONO_EMIT_NEW_PCONST (cfg, dreg, NULL); } else if (t >= MONO_TYPE_BOOLEAN && t <= MONO_TYPE_U4) { MONO_EMIT_NEW_ICONST (cfg, dreg, 0); @@ -4505,7 +4505,7 @@ emit_dummy_init_rvar (MonoCompile *cfg, int dreg, MonoType *rtype) rtype = mini_get_underlying_type (rtype); t = rtype->type; - if (rtype->byref) { + if (m_type_is_byref (rtype)) { MONO_EMIT_NEW_DUMMY_INIT (cfg, dreg, OP_DUMMY_PCONST); } else if (t >= MONO_TYPE_BOOLEAN && t <= MONO_TYPE_U4) { MONO_EMIT_NEW_DUMMY_INIT (cfg, dreg, OP_DUMMY_ICONST); @@ -5149,7 +5149,7 @@ set_exception_type_from_invalid_il (MonoCompile *cfg, MonoMethod *method, guchar guint32 mono_type_to_stloc_coerce (MonoType *type) { - if (type->byref) + if (m_type_is_byref (type)) return 0; type = mini_get_underlying_type (type); @@ -5478,7 +5478,7 @@ is_supported_tailcall (MonoCompile *cfg, const guint8 *ip, MonoMethod *method, M } for (int i = 0; i < fsig->param_count; ++i) { - if (IS_NOT_SUPPORTED_TAILCALL (fsig->params [i]->byref || fsig->params [i]->type == MONO_TYPE_PTR || fsig->params [i]->type == MONO_TYPE_FNPTR)) { + if (IS_NOT_SUPPORTED_TAILCALL (m_type_is_byref (fsig->params [i]) || fsig->params [i]->type == MONO_TYPE_PTR || fsig->params [i]->type == MONO_TYPE_FNPTR)) { tailcall_calli = FALSE; tailcall = FALSE; // These can point to the current method's stack. Emit range check? goto exit; @@ -5822,7 +5822,7 @@ emit_setret (MonoCompile *cfg, MonoInst *val) } } else { #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK - if (COMPILE_SOFT_FLOAT (cfg) && !ret_type->byref && ret_type->type == MONO_TYPE_R4) { + if (COMPILE_SOFT_FLOAT (cfg) && !m_type_is_byref (ret_type) && ret_type->type == MONO_TYPE_R4) { MonoInst *conv; MonoInst *iargs [ ] = { val }; @@ -6453,7 +6453,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b mono_debug_init_method (cfg, cfg->cbb, breakpoint_id); for (n = 0; n < header->num_locals; ++n) { - if (header->locals [n]->type == MONO_TYPE_VOID && !header->locals [n]->byref) + if (header->locals [n]->type == MONO_TYPE_VOID && !m_type_is_byref (header->locals [n])) UNVERIFIED; } class_inits = NULL; @@ -8747,8 +8747,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b */ if (cfg->cbb->out_of_line && m_class_get_image (cmethod->klass) == mono_defaults.corlib && is_exception_class (cmethod->klass) && n <= 2 && - ((n < 1) || (!fsig->params [0]->byref && fsig->params [0]->type == MONO_TYPE_STRING)) && - ((n < 2) || (!fsig->params [1]->byref && fsig->params [1]->type == MONO_TYPE_STRING))) { + ((n < 1) || (!m_type_is_byref (fsig->params [0]) && fsig->params [0]->type == MONO_TYPE_STRING)) && + ((n < 2) || (!m_type_is_byref (fsig->params [1]) && fsig->params [1]->type == MONO_TYPE_STRING))) { MonoInst *iargs [3]; sp -= n; diff --git a/src/mono/mono/mini/mini-amd64-gsharedvt.c b/src/mono/mono/mini/mini-amd64-gsharedvt.c index 3a7d769e58994..77fc0e3b89189 100644 --- a/src/mono/mono/mini/mini-amd64-gsharedvt.c +++ b/src/mono/mono/mini/mini-amd64-gsharedvt.c @@ -450,7 +450,7 @@ mono_arch_get_gsharedvt_call_info (MonoMemoryManager *mem_manager, gpointer addr /* Compute return value marshalling */ switch (cinfo->ret.storage) { case ArgInIReg: - if (!gsharedvt_in || sig->ret->byref) { + if (!gsharedvt_in || m_type_is_byref (sig->ret)) { info->ret_marshal = GSHAREDVT_RET_IREGS_1; } else { MonoType *ret = sig->ret; diff --git a/src/mono/mono/mini/mini-amd64.c b/src/mono/mono/mini/mini-amd64.c index 1404f5e29837f..7b5c36779f1b0 100644 --- a/src/mono/mono/mini/mini-amd64.c +++ b/src/mono/mono/mini/mini-amd64.c @@ -2246,7 +2246,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) t = mini_get_underlying_type (t); //XXX what about ArgGSharedVtOnStack here? if (ainfo->storage == ArgOnStack && !MONO_TYPE_ISSTRUCT (t)) { - if (!t->byref) { + if (!m_type_is_byref (t)) { if (t->type == MONO_TYPE_R4) MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, AMD64_RSP, ainfo->offset, in->dreg); else if (t->type == MONO_TYPE_R8) @@ -2632,7 +2632,7 @@ mono_arch_dyn_call_prepare (MonoMethodSignature *sig) MonoType *t = sig->params [aindex]; ArgInfo *ainfo = &cinfo->args [aindex + sig->hasthis]; - if (t->byref) + if (m_type_is_byref (t)) continue; switch (t->type) { @@ -2764,7 +2764,7 @@ mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret, g slot = general_param_reg_to_index [ainfo->reg]; } - if (t->byref) { + if (m_type_is_byref (t)) { p->regs [slot] = PTR_TO_GREG (*(arg)); continue; } diff --git a/src/mono/mono/mini/mini-arm-gsharedvt.c b/src/mono/mono/mini/mini-arm-gsharedvt.c index f03551d61eeca..89eaf7715bb40 100644 --- a/src/mono/mono/mini/mini-arm-gsharedvt.c +++ b/src/mono/mono/mini/mini-arm-gsharedvt.c @@ -287,13 +287,13 @@ mono_arch_get_gsharedvt_call_info (MonoMemoryManager *mem_manager, gpointer addr if (var_ret) { switch (cinfo->ret.storage) { case RegTypeGeneral: - if (gsharedvt_in && !sig->ret->byref && sig->ret->type == MONO_TYPE_I1) + if (gsharedvt_in && !m_type_is_byref (sig->ret) && sig->ret->type == MONO_TYPE_I1) info->ret_marshal = GSHAREDVT_RET_I1; - else if (gsharedvt_in && !sig->ret->byref && (sig->ret->type == MONO_TYPE_U1 || sig->ret->type == MONO_TYPE_BOOLEAN)) + else if (gsharedvt_in && !m_type_is_byref (sig->ret) && (sig->ret->type == MONO_TYPE_U1 || sig->ret->type == MONO_TYPE_BOOLEAN)) info->ret_marshal = GSHAREDVT_RET_U1; - else if (gsharedvt_in && !sig->ret->byref && sig->ret->type == MONO_TYPE_I2) + else if (gsharedvt_in && !m_type_is_byref (sig->ret) && sig->ret->type == MONO_TYPE_I2) info->ret_marshal = GSHAREDVT_RET_I2; - else if (gsharedvt_in && !sig->ret->byref && (sig->ret->type == MONO_TYPE_U2 || sig->ret->type == MONO_TYPE_CHAR)) + else if (gsharedvt_in && !m_type_is_byref (sig->ret) && (sig->ret->type == MONO_TYPE_U2 || sig->ret->type == MONO_TYPE_CHAR)) info->ret_marshal = GSHAREDVT_RET_U2; else info->ret_marshal = GSHAREDVT_RET_IREG; diff --git a/src/mono/mono/mini/mini-arm.c b/src/mono/mono/mini/mini-arm.c index fe6d2984256b9..3f3b4a9bc88b3 100644 --- a/src/mono/mono/mini/mini-arm.c +++ b/src/mono/mono/mini/mini-arm.c @@ -954,7 +954,7 @@ mono_arch_is_soft_float (void) static gboolean is_regsize_var (MonoType *t) { - if (t->byref) + if (m_type_is_byref (t)) return TRUE; t = mini_get_underlying_type (t); switch (t->type) { @@ -1239,7 +1239,7 @@ is_hfa (MonoType *t, int *out_nfields, int *out_esize) prev_ftype = ftype; nfields += nested_nfields; } else { - if (!(!ftype->byref && (ftype->type == MONO_TYPE_R4 || ftype->type == MONO_TYPE_R8))) + if (!(!m_type_is_byref (ftype) && (ftype->type == MONO_TYPE_R4 || ftype->type == MONO_TYPE_R8))) return FALSE; if (prev_ftype && prev_ftype->type != ftype->type) return FALSE; @@ -1412,7 +1412,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) add_general (&gr, &stack_size, &cinfo->sig_cookie, TRUE); } DEBUG(g_print("param %d: ", i)); - if (sig->params [i]->byref) { + if (m_type_is_byref (sig->params [i])) { DEBUG(g_print("byref\n")); add_general (&gr, &stack_size, ainfo, TRUE); n++; @@ -2463,7 +2463,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) switch (ainfo->storage) { case RegTypeGeneral: case RegTypeIRegPair: - if (!t->byref && ((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) { + if (!m_type_is_byref (t) && ((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) { MONO_INST_NEW (cfg, ins, OP_MOVE); ins->dreg = mono_alloc_ireg (cfg); ins->sreg1 = MONO_LVREG_LS (in->dreg); @@ -2475,7 +2475,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) ins->sreg1 = MONO_LVREG_MS (in->dreg); MONO_ADD_INS (cfg->cbb, ins); mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg + 1, FALSE); - } else if (!t->byref && ((t->type == MONO_TYPE_R8) || (t->type == MONO_TYPE_R4))) { + } else if (!m_type_is_byref (t) && ((t->type == MONO_TYPE_R8) || (t->type == MONO_TYPE_R4))) { if (ainfo->size == 4) { if (IS_SOFT_FLOAT) { /* mono_emit_call_args () have already done the r8->r4 conversion */ @@ -2547,9 +2547,9 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) MONO_ADD_INS (cfg->cbb, ins); break; case RegTypeBase: - if (!t->byref && ((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) { + if (!m_type_is_byref (t) && ((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) { MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, ARMREG_SP, ainfo->offset, in->dreg); - } else if (!t->byref && ((t->type == MONO_TYPE_R4) || (t->type == MONO_TYPE_R8))) { + } else if (!m_type_is_byref (t) && ((t->type == MONO_TYPE_R4) || (t->type == MONO_TYPE_R8))) { if (t->type == MONO_TYPE_R8) { MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, ARMREG_SP, ainfo->offset, in->dreg); } else { @@ -2563,14 +2563,14 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) } break; case RegTypeBaseGen: - if (!t->byref && ((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) { + if (!m_type_is_byref (t) && ((t->type == MONO_TYPE_I8) || (t->type == MONO_TYPE_U8))) { MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, ARMREG_SP, ainfo->offset, (G_BYTE_ORDER == G_BIG_ENDIAN) ? MONO_LVREG_LS (in->dreg) : MONO_LVREG_MS (in->dreg)); MONO_INST_NEW (cfg, ins, OP_MOVE); ins->dreg = mono_alloc_ireg (cfg); ins->sreg1 = G_BYTE_ORDER == G_BIG_ENDIAN ? MONO_LVREG_MS (in->dreg) : MONO_LVREG_LS (in->dreg); MONO_ADD_INS (cfg->cbb, ins); mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ARMREG_R3, FALSE); - } else if (!t->byref && (t->type == MONO_TYPE_R8)) { + } else if (!m_type_is_byref (t) && (t->type == MONO_TYPE_R8)) { int creg; /* This should work for soft-float as well */ @@ -2760,7 +2760,7 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val) { MonoType *ret = mini_get_underlying_type (mono_method_signature_internal (method)->ret); - if (!ret->byref) { + if (!m_type_is_byref (ret)) { if (ret->type == MONO_TYPE_I8 || ret->type == MONO_TYPE_U8) { MonoInst *ins; @@ -2873,7 +2873,7 @@ dyn_call_supported (CallInfo *cinfo, MonoMethodSignature *sig) for (i = 0; i < sig->param_count; ++i) { MonoType *t = sig->params [i]; - if (t->byref) + if (m_type_is_byref (t)) continue; t = mini_get_underlying_type (t); @@ -2987,7 +2987,7 @@ mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret, g g_assert_not_reached (); } - if (t->byref) { + if (m_type_is_byref (t)) { p->regs [slot] = (host_mgreg_t)(gsize)*arg; continue; } diff --git a/src/mono/mono/mini/mini-arm64-gsharedvt.c b/src/mono/mono/mini/mini-arm64-gsharedvt.c index 44ac04e0da179..4353d5c7000b4 100644 --- a/src/mono/mono/mini/mini-arm64-gsharedvt.c +++ b/src/mono/mono/mini/mini-arm64-gsharedvt.c @@ -345,7 +345,7 @@ mono_arch_get_gsharedvt_call_info (MonoMemoryManager *mem_manager, gpointer addr if (var_ret) { switch (cinfo->ret.storage) { case ArgInIReg: - if (!gsharedvt_in || sig->ret->byref) { + if (!gsharedvt_in || m_type_is_byref (sig->ret)) { info->ret_marshal = GSHAREDVT_RET_I8; } else { MonoType *rtype = mini_get_underlying_type (sig->ret); diff --git a/src/mono/mono/mini/mini-arm64.c b/src/mono/mono/mini/mini-arm64.c index 217c9d08d32ae..b93b4aa6a8567 100644 --- a/src/mono/mono/mini/mini-arm64.c +++ b/src/mono/mono/mini/mini-arm64.c @@ -1182,7 +1182,7 @@ is_hfa (MonoType *t, int *out_nfields, int *out_esize, int *field_offsets) } nfields += nested_nfields; } else { - if (!(!ftype->byref && (ftype->type == MONO_TYPE_R4 || ftype->type == MONO_TYPE_R8))) + if (!(!m_type_is_byref (ftype) && (ftype->type == MONO_TYPE_R4 || ftype->type == MONO_TYPE_R8))) return FALSE; if (prev_ftype && prev_ftype->type != ftype->type) return FALSE; @@ -1720,7 +1720,7 @@ mono_arch_dyn_call_prepare (MonoMethodSignature *sig) for (aindex = 0; aindex < sig->param_count; aindex++) { MonoType *t = info->param_types [aindex]; - if (t->byref) + if (m_type_is_byref (t)) continue; switch (t->type) { @@ -1819,7 +1819,7 @@ mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret, g slot = ainfo->reg; } - if (t->byref) { + if (m_type_is_byref (t)) { p->regs [slot] = (host_mgreg_t)*arg; continue; } diff --git a/src/mono/mono/mini/mini-codegen.c b/src/mono/mono/mini/mini-codegen.c index 40dedf8aff368..44a60604b9406 100644 --- a/src/mono/mono/mini/mini-codegen.c +++ b/src/mono/mono/mini/mini-codegen.c @@ -2751,7 +2751,7 @@ mini_type_is_hfa (MonoType *t, int *out_nfields, int *out_esize) prev_ftype = ftype; nfields += nested_nfields; } else { - if (!(!ftype->byref && (ftype->type == MONO_TYPE_R4 || ftype->type == MONO_TYPE_R8))) + if (!(!m_type_is_byref (ftype) && (ftype->type == MONO_TYPE_R4 || ftype->type == MONO_TYPE_R8))) return FALSE; if (prev_ftype && prev_ftype->type != ftype->type) return FALSE; diff --git a/src/mono/mono/mini/mini-generic-sharing.c b/src/mono/mono/mini/mini-generic-sharing.c index a596cf3e6cd47..9201708118120 100644 --- a/src/mono/mono/mini/mini-generic-sharing.c +++ b/src/mono/mono/mini/mini-generic-sharing.c @@ -1260,7 +1260,7 @@ get_wrapper_shared_vtype (MonoType *t) static MonoType* get_wrapper_shared_type_full (MonoType *t, gboolean is_field) { - if (t->byref) + if (m_type_is_byref (t)) return m_class_get_this_arg (mono_defaults.int_class); t = mini_get_underlying_type (t); @@ -1381,7 +1381,7 @@ get_wrapper_shared_type_reg (MonoType *t, gboolean pinvoke) MonoType *orig_t = t; t = get_wrapper_shared_type (t); - if (t->byref) + if (m_type_is_byref (t)) return t; switch (t->type) { @@ -1507,9 +1507,9 @@ mini_get_gsharedvt_in_sig_wrapper (MonoMethodSignature *sig) } for (i = 0; i < sig->param_count; i++) { gsharedvt_sig->params [pindex] = sig->params [i]; - if (!sig->params [i]->byref) { + if (!m_type_is_byref (sig->params [i])) { gsharedvt_sig->params [pindex] = mono_metadata_type_dup (NULL, gsharedvt_sig->params [pindex]); - gsharedvt_sig->params [pindex]->byref = 1; + gsharedvt_sig->params [pindex]->byref__ = 1; } pindex ++; } @@ -1534,7 +1534,7 @@ mini_get_gsharedvt_in_sig_wrapper (MonoMethodSignature *sig) if (sig->ret->type != MONO_TYPE_VOID) mono_mb_emit_ldloc_addr (mb, retval_var); for (i = 0; i < sig->param_count; i++) { - if (sig->params [i]->byref) + if (m_type_is_byref (sig->params [i])) mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE)); else mono_mb_emit_ldarg_addr (mb, i + (sig->hasthis == TRUE)); @@ -1621,9 +1621,9 @@ mini_get_gsharedvt_out_sig_wrapper (MonoMethodSignature *sig) for (i = 0; i < sig->param_count; i++) { csig->params [pindex] = sig->params [i]; param_names [pindex] = g_strdup_printf ("%d", i); - if (!sig->params [i]->byref) { + if (!m_type_is_byref (sig->params [i])) { csig->params [pindex] = mono_metadata_type_dup (NULL, csig->params [pindex]); - csig->params [pindex]->byref = 1; + csig->params [pindex]->byref__ = 1; } pindex ++; } @@ -1655,7 +1655,7 @@ mini_get_gsharedvt_out_sig_wrapper (MonoMethodSignature *sig) if (sig->hasthis) mono_mb_emit_ldarg (mb, 0); for (i = 0; i < sig->param_count; i++) { - if (sig->params [i]->byref) { + if (m_type_is_byref (sig->params [i])) { mono_mb_emit_ldarg (mb, args_start + i); } else { ldind_op = mono_type_to_ldind (sig->params [i]); @@ -1769,7 +1769,7 @@ mini_get_interp_in_wrapper (MonoMethodSignature *sig) memcpy (csig, sig, mono_metadata_signature_size (sig)); for (i = 0; i < sig->param_count; i++) { - if (sig->params [i]->byref) + if (m_type_is_byref (sig->params [i])) csig->params [i] = m_class_get_this_arg (mono_defaults.int_class); } @@ -1804,9 +1804,9 @@ mini_get_interp_in_wrapper (MonoMethodSignature *sig) } for (i = 0; i < sig->param_count; i++) { entry_sig->params [pindex] = sig->params [i]; - if (!sig->params [i]->byref) { + if (!m_type_is_byref (sig->params [i])) { entry_sig->params [pindex] = mono_metadata_type_dup (NULL, entry_sig->params [pindex]); - entry_sig->params [pindex]->byref = 1; + entry_sig->params [pindex]->byref__ = 1; } pindex ++; } @@ -1852,7 +1852,7 @@ mini_get_interp_in_wrapper (MonoMethodSignature *sig) mono_mb_emit_ldloc (mb, args_var); mono_mb_emit_icon (mb, TARGET_SIZEOF_VOID_P * i); mono_mb_emit_byte (mb, CEE_ADD); - if (sig->params [i]->byref) + if (m_type_is_byref (sig->params [i])) mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE)); else mono_mb_emit_ldarg_addr (mb, i + (sig->hasthis == TRUE)); @@ -1878,7 +1878,7 @@ mini_get_interp_in_wrapper (MonoMethodSignature *sig) else if (sig->ret->type != MONO_TYPE_VOID) mono_mb_emit_ldloc_addr (mb, retval_var); for (i = 0; i < sig->param_count; i++) { - if (sig->params [i]->byref) + if (m_type_is_byref (sig->params [i])) mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE)); else mono_mb_emit_ldarg_addr (mb, i + (sig->hasthis == TRUE)); @@ -3218,10 +3218,10 @@ type_is_sharable (MonoType *type, gboolean allow_type_vars, gboolean allow_parti return TRUE; /* Allow non ref arguments if they are primitive types or enums (partial sharing). */ - if (allow_partial && !type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (type->data.klass)))) + if (allow_partial && !m_type_is_byref (type) && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U) || (type->type == MONO_TYPE_VALUETYPE && m_class_is_enumtype (type->data.klass)))) return TRUE; - if (allow_partial && !type->byref && type->type == MONO_TYPE_GENERICINST && MONO_TYPE_ISSTRUCT (type)) { + if (allow_partial && !m_type_is_byref (type) && type->type == MONO_TYPE_GENERICINST && MONO_TYPE_ISSTRUCT (type)) { MonoGenericClass *gclass = type->data.generic_class; if (gclass->context.class_inst && !mini_generic_inst_is_sharable (gclass->context.class_inst, allow_type_vars, allow_partial)) @@ -3723,9 +3723,9 @@ mini_class_get_context (MonoClass *klass) static MonoType* mini_get_basic_type_from_generic (MonoType *type) { - if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && mini_is_gsharedvt_type (type)) + if (!m_type_is_byref (type) && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && mini_is_gsharedvt_type (type)) return type; - else if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) { + else if (!m_type_is_byref (type) && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) { MonoType *constraint = type->data.generic_param->gshared_constraint; /* The gparam constraint encodes the type this gparam can represent */ if (!constraint) { @@ -3753,9 +3753,9 @@ mini_type_get_underlying_type (MonoType *type) { type = mini_native_type_replace_type (type); - if (type->byref) + if (m_type_is_byref (type)) return mono_get_int_type (); - if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && mini_is_gsharedvt_type (type)) + if (!m_type_is_byref (type) && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && mini_is_gsharedvt_type (type)) return type; type = mini_get_basic_type_from_generic (mono_type_get_underlying_type (type)); switch (type->type) { @@ -4054,7 +4054,7 @@ get_shared_type (MonoType *t, MonoType *type) { MonoTypeEnum ttype; - if (!type->byref && type->type == MONO_TYPE_GENERICINST && MONO_TYPE_ISSTRUCT (type)) { + if (!m_type_is_byref (type) && type->type == MONO_TYPE_GENERICINST && MONO_TYPE_ISSTRUCT (type)) { ERROR_DECL (error); MonoGenericClass *gclass = type->data.generic_class; MonoGenericContext context; @@ -4356,7 +4356,7 @@ mini_is_gsharedvt_type (MonoType *t) { int i; - if (t->byref) + if (m_type_is_byref (t)) return FALSE; if ((t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) && t->data.generic_param->gshared_constraint && t->data.generic_param->gshared_constraint->type == MONO_TYPE_VALUETYPE) return TRUE; @@ -4446,7 +4446,7 @@ is_variable_size (MonoType *t) { int i; - if (t->byref) + if (m_type_is_byref (t)) return FALSE; if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) { diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 97218672adcc2..2b8e07dfb3745 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -751,7 +751,7 @@ inst_c1_type (const MonoInst *ins) static LLVMTypeRef type_to_llvm_type (EmitContext *ctx, MonoType *t) { - if (t->byref) + if (m_type_is_byref (t)) return ThisType (); t = mini_get_underlying_type (t); @@ -845,7 +845,7 @@ static gboolean type_is_unsigned (EmitContext *ctx, MonoType *t) { t = mini_get_underlying_type (t); - if (t->byref) + if (m_type_is_byref (t)) return FALSE; return primitive_type_is_unsigned (t->type); } @@ -1414,7 +1414,7 @@ emit_volatile_load (EmitContext *ctx, int vreg) v = mono_llvm_build_load (ctx->builder, ctx->addresses [vreg], "", TRUE); t = ctx->vreg_cli_types [vreg]; - if (t && !t->byref) { + if (t && !m_type_is_byref (t)) { /* * Might have to zero extend since llvm doesn't have * unsigned types. @@ -3912,7 +3912,7 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder) default: { LLVMTypeRef t; /* Needed to avoid phi argument mismatch errors since operations on pointers produce i32/i64 */ - if (ainfo->type->byref) + if (m_type_is_byref (ainfo->type)) t = IntPtrType (); else t = type_to_llvm_type (ctx, ainfo->type); @@ -11126,7 +11126,7 @@ get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig) } for (i = 0; i < sig->param_count; ++i) { - if (sig->params [i]->byref) + if (m_type_is_byref (sig->params [i])) linfo->args [pindex].storage = LLVMArgNormal; else if (mini_is_gsharedvt_variable_type (sig->params [i])) linfo->args [pindex].storage = LLVMArgGsharedvtVariable; diff --git a/src/mono/mono/mini/mini-native-types.c b/src/mono/mono/mini/mini-native-types.c index 08f72acafe684..ee331120a5620 100644 --- a/src/mono/mono/mini/mini-native-types.c +++ b/src/mono/mono/mini/mini-native-types.c @@ -95,9 +95,9 @@ mini_magic_type_size (MonoCompile *cfg, MonoType *type) return 4; else if (type->type == MONO_TYPE_I8 || type->type == MONO_TYPE_U8) return 8; - else if (type->type == MONO_TYPE_R4 && !type->byref && (!cfg || cfg->r4fp)) + else if (type->type == MONO_TYPE_R4 && !m_type_is_byref (type) && (!cfg || cfg->r4fp)) return 4; - else if (type->type == MONO_TYPE_R8 && !type->byref) + else if (type->type == MONO_TYPE_R8 && !m_type_is_byref (type)) return 8; return TARGET_SIZEOF_VOID_P; } @@ -471,12 +471,12 @@ mini_native_type_replace_type (MonoType *type) klass = type->data.klass; if (mono_class_is_magic_int (klass)) - return type->byref ? m_class_get_this_arg (mono_defaults.int_class) : mono_get_int_type (); + return m_type_is_byref (type) ? m_class_get_this_arg (mono_defaults.int_class) : mono_get_int_type (); if (mono_class_is_magic_float (klass)) #if TARGET_SIZEOF_VOID_P == 8 - return type->byref ? m_class_get_this_arg (mono_defaults.double_class) : m_class_get_byval_arg (mono_defaults.double_class); + return m_type_is_byref (type) ? m_class_get_this_arg (mono_defaults.double_class) : m_class_get_byval_arg (mono_defaults.double_class); #else - return type->byref ? m_class_get_this_arg (mono_defaults.single_class) : m_class_get_byval_arg (mono_defaults.single_class); + return m_type_is_byref (type) ? m_class_get_this_arg (mono_defaults.single_class) : m_class_get_byval_arg (mono_defaults.single_class); #endif return type; } diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 5ad5a916421b2..de06752a54ec5 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -3039,7 +3039,7 @@ create_runtime_invoke_info (MonoMethod *method, gpointer compiled_method, gboole for (i = 0; i < sig->param_count; ++i) { MonoType *t = sig->params [i]; - if (t->byref && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type_internal (t))) + if (m_type_is_byref (t) && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type_internal (t))) supported = FALSE; } @@ -3186,7 +3186,7 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void if (sig->hasthis) args [pindex ++] = &obj; if (sig->ret->type != MONO_TYPE_VOID) { - if (info->ret_box_class && !sig->ret->byref && + if (info->ret_box_class && !m_type_is_byref (sig->ret) && (sig->ret->type == MONO_TYPE_VALUETYPE || (sig->ret->type == MONO_TYPE_GENERICINST && !MONO_TYPE_IS_REFERENCE (sig->ret)))) { // if the return type is a struct, allocate enough stack space to hold it @@ -3219,7 +3219,7 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void params [i] = nullable_buf; } - if (!t->byref && (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR)) { + if (!m_type_is_byref (t) && (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR)) { param_refs [i] = params [i]; params [i] = &(param_refs [i]); } @@ -3234,7 +3234,7 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void if (exc && *exc) return NULL; - if (sig->ret->byref) { + if (m_type_is_byref (sig->ret)) { if (*(gpointer*)retval == NULL) { MonoClass *klass = mono_class_get_nullbyrefreturn_ex_class (); MonoObject *ex = mono_object_new_checked (klass, error); @@ -3246,14 +3246,14 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void if (sig->ret->type != MONO_TYPE_VOID) { if (info->ret_box_class) { - if (sig->ret->byref) { + if (m_type_is_byref (sig->ret)) { return mono_value_box_checked (info->ret_box_class, *(gpointer*)retval, error); } else { MonoObject *ret = mono_value_box_checked (info->ret_box_class, retval, error); return ret; } } else { - if (sig->ret->byref) + if (m_type_is_byref (sig->ret)) return **(MonoObject***)retval; else return *(MonoObject**)retval; @@ -3417,7 +3417,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec guint8 *retval = NULL; /* if the return type is a struct and it's too big, allocate more space for it */ - if (info->ret_box_class && !sig->ret->byref && + if (info->ret_box_class && !m_type_is_byref (sig->ret) && (sig->ret->type == MONO_TYPE_VALUETYPE || (sig->ret->type == MONO_TYPE_GENERICINST && !MONO_TYPE_IS_REFERENCE (sig->ret)))) { MonoClass *ret_klass = mono_class_from_mono_type_internal (sig->ret); @@ -3438,7 +3438,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec for (i = 0; i < sig->param_count; ++i) { MonoType *t = sig->params [i]; - if (t->byref) { + if (m_type_is_byref (t)) { args [pindex ++] = ¶ms [i]; } else if (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR) { args [pindex ++] = ¶ms [i]; @@ -3464,7 +3464,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec return NULL; } - if (sig->ret->byref) { + if (m_type_is_byref (sig->ret)) { if (*(gpointer*)retval == NULL) { MonoClass *klass = mono_class_get_nullbyrefreturn_ex_class (); MonoObject *ex = mono_object_new_checked (klass, error); @@ -3475,14 +3475,14 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec } if (info->ret_box_class) { - if (sig->ret->byref) { + if (m_type_is_byref (sig->ret)) { return mono_value_box_checked (info->ret_box_class, *(gpointer*)retval, error); } else { MonoObject *boxed_ret = mono_value_box_checked (info->ret_box_class, retval, error); return boxed_ret; } } else { - if (sig->ret->byref) + if (m_type_is_byref (sig->ret)) return **(MonoObject***)retval; else return *(MonoObject**)retval; diff --git a/src/mono/mono/mini/mini-trampolines.c b/src/mono/mono/mini/mini-trampolines.c index 07a50524a0feb..316b92fd58377 100644 --- a/src/mono/mono/mini/mini-trampolines.c +++ b/src/mono/mono/mini/mini-trampolines.c @@ -1024,7 +1024,7 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint if (sig->hasthis && m_class_is_valuetype (method->klass)) { gboolean need_unbox = TRUE; - if (tramp_info->invoke_sig->param_count > sig->param_count && tramp_info->invoke_sig->params [0]->byref) + if (tramp_info->invoke_sig->param_count > sig->param_count && m_type_is_byref (tramp_info->invoke_sig->params [0])) need_unbox = FALSE; if (need_unbox) { diff --git a/src/mono/mono/mini/mini-wasm.c b/src/mono/mono/mini/mini-wasm.c index 56d58e1c6a0d2..45910e1c2b002 100644 --- a/src/mono/mono/mini/mini-wasm.c +++ b/src/mono/mono/mini/mini-wasm.c @@ -11,9 +11,6 @@ #include #include -//XXX This is dirty, extend ee.h to support extracting info from MonoInterpFrameHandle -#include - static int mono_wasm_debug_level = 0; #ifndef DISABLE_JIT @@ -275,7 +272,7 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val) { MonoType *ret = mini_get_underlying_type (mono_method_signature_internal (method)->ret); - if (!ret->byref) { + if (!m_type_is_byref (ret)) { if (ret->type == MONO_TYPE_R4) { MONO_EMIT_NEW_UNALU (cfg, cfg->r4fp ? OP_RMOVE : OP_FMOVE, cfg->ret->dreg, val->dreg); return; @@ -383,7 +380,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe g_error ("mono_arch_get_delegate_invoke_impl"); } -#ifdef HOST_WASM +#ifdef HOST_BROWSER #include @@ -398,7 +395,7 @@ G_END_DECLS void mono_background_exec (void); -#endif // HOST_WASM +#endif // HOST_BROWSER gpointer mono_arch_get_this_arg_from_call (host_mgreg_t *regs, guint8 *code) @@ -496,7 +493,7 @@ mono_arch_context_get_int_reg_address (MonoContext *ctx, int reg) return 0; } -#ifdef HOST_WASM +#ifdef HOST_BROWSER void mono_runtime_setup_stat_profiler (void) @@ -566,7 +563,7 @@ mono_set_timeout_exec (int id) void mono_wasm_set_timeout (int timeout, int id) { -#ifdef HOST_WASM +#ifdef HOST_BROWSER mono_set_timeout (timeout, id); #endif } @@ -599,7 +596,7 @@ tp_cb (void) } } -#ifdef HOST_WASM +#ifdef HOST_BROWSER void mono_wasm_queue_tp_cb (void) { @@ -610,7 +607,7 @@ mono_wasm_queue_tp_cb (void) void mono_arch_register_icall (void) { -#ifdef HOST_WASM +#ifdef HOST_BROWSER mono_add_internal_call_internal ("System.Threading.TimerQueue::SetTimeout", mono_wasm_set_timeout); mono_add_internal_call_internal ("System.Threading.ThreadPool::QueueCallback", mono_wasm_queue_tp_cb); #endif @@ -622,7 +619,7 @@ mono_arch_patch_code_new (MonoCompile *cfg, guint8 *code, MonoJumpInfo *ji, gpoi g_error ("mono_arch_patch_code_new"); } -#ifdef HOST_WASM +#ifdef HOST_BROWSER G_BEGIN_DECLS @@ -755,7 +752,7 @@ mono_wasm_print_stack_trace (void) ); } -#endif // HOST_WASM +#endif // HOST_BROWSER gpointer mono_arch_load_function (MonoJitICallId jit_icall_id) diff --git a/src/mono/mono/mini/mini-x86-gsharedvt.c b/src/mono/mono/mini/mini-x86-gsharedvt.c index d4b5e39da3a27..d2d4b09d29834 100644 --- a/src/mono/mono/mini/mini-x86-gsharedvt.c +++ b/src/mono/mono/mini/mini-x86-gsharedvt.c @@ -160,13 +160,13 @@ mono_arch_get_gsharedvt_call_info (MonoMemoryManager *mem_manager, gpointer addr if (var_ret) { switch (cinfo->ret.storage) { case ArgInIReg: - if (gsharedvt_in && !sig->ret->byref && sig->ret->type == MONO_TYPE_I1) + if (gsharedvt_in && !m_type_is_byref (sig->ret) && sig->ret->type == MONO_TYPE_I1) info->ret_marshal = GSHAREDVT_RET_I1; - else if (gsharedvt_in && !sig->ret->byref && (sig->ret->type == MONO_TYPE_U1 || sig->ret->type == MONO_TYPE_BOOLEAN)) + else if (gsharedvt_in && !m_type_is_byref (sig->ret) && (sig->ret->type == MONO_TYPE_U1 || sig->ret->type == MONO_TYPE_BOOLEAN)) info->ret_marshal = GSHAREDVT_RET_U1; - else if (gsharedvt_in && !sig->ret->byref && sig->ret->type == MONO_TYPE_I2) + else if (gsharedvt_in && !m_type_is_byref (sig->ret) && sig->ret->type == MONO_TYPE_I2) info->ret_marshal = GSHAREDVT_RET_I2; - else if (gsharedvt_in && !sig->ret->byref && (sig->ret->type == MONO_TYPE_U2 || sig->ret->type == MONO_TYPE_CHAR)) + else if (gsharedvt_in && !m_type_is_byref (sig->ret) && (sig->ret->type == MONO_TYPE_U2 || sig->ret->type == MONO_TYPE_CHAR)) info->ret_marshal = GSHAREDVT_RET_U2; else if (cinfo->ret.is_pair) info->ret_marshal = GSHAREDVT_RET_IREGS; diff --git a/src/mono/mono/mini/mini-x86.c b/src/mono/mono/mini/mini-x86.c index ea338d4a3b866..bfd2746149fed 100644 --- a/src/mono/mono/mini/mini-x86.c +++ b/src/mono/mono/mini/mini-x86.c @@ -456,7 +456,7 @@ get_call_info_internal (CallInfo *cinfo, MonoMethodSignature *sig) add_general (&gr, param_regs, &stack_size, &cinfo->sig_cookie); } - if (sig->params [i]->byref) { + if (m_type_is_byref (sig->params [i])) { add_general (&gr, param_regs, &stack_size, ainfo); continue; } @@ -1331,7 +1331,7 @@ collect_fp_stack_space (MonoMethodSignature *sig, int start_arg, int *fp_arg_set for (; start_arg < sig->param_count; ++start_arg) { t = mini_get_underlying_type (sig->params [start_arg]); - if (!t->byref && t->type == MONO_TYPE_R8) { + if (!m_type_is_byref (t) && t->type == MONO_TYPE_R8) { fp_space += sizeof (double); *fp_arg_setup = start_arg; } else { @@ -1612,7 +1612,7 @@ mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call) } else { switch (ainfo->storage) { case ArgOnStack: - if (!t->byref) { + if (!m_type_is_byref (t)) { if (t->type == MONO_TYPE_R4) { MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, X86_ESP, ainfo->offset, in->dreg); argsize = 4; @@ -1747,7 +1747,7 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val) { MonoType *ret = mini_get_underlying_type (mono_method_signature_internal (method)->ret); - if (!ret->byref) { + if (!m_type_is_byref (ret)) { if (ret->type == MONO_TYPE_R4) { if (COMPILE_LLVM (cfg)) MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg); diff --git a/src/mono/mono/mini/mini.c b/src/mono/mono/mini/mini.c index 30bbff456cfeb..5634422f479ca 100644 --- a/src/mono/mono/mini/mini.c +++ b/src/mono/mono/mini/mini.c @@ -440,7 +440,7 @@ guint mini_type_to_stind (MonoCompile* cfg, MonoType *type) { type = mini_get_underlying_type (type); - if (cfg->gshared && !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) { + if (cfg->gshared && !m_type_is_byref (type) && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) { g_assert (mini_type_var_is_vt (type)); return CEE_STOBJ; } @@ -625,8 +625,8 @@ set_vreg_to_inst (MonoCompile *cfg, int vreg, MonoInst *inst) cfg->vreg_to_inst [vreg] = inst; } -#define mono_type_is_long(type) (!(type)->byref && ((mono_type_get_underlying_type (type)->type == MONO_TYPE_I8) || (mono_type_get_underlying_type (type)->type == MONO_TYPE_U8))) -#define mono_type_is_float(type) (!(type)->byref && (((type)->type == MONO_TYPE_R8) || ((type)->type == MONO_TYPE_R4))) +#define mono_type_is_long(type) (!m_type_is_byref (type) && ((mono_type_get_underlying_type (type)->type == MONO_TYPE_I8) || (mono_type_get_underlying_type (type)->type == MONO_TYPE_U8))) +#define mono_type_is_float(type) (!m_type_is_byref (type) && (((type)->type == MONO_TYPE_R8) || ((type)->type == MONO_TYPE_R4))) MonoInst* mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode, int vreg) @@ -660,7 +660,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode, mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD); if (cfg->compute_gc_maps) { - if (type->byref) { + if (m_type_is_byref (type)) { mono_mark_vreg_as_mp (cfg, vreg); } else { if ((MONO_TYPE_ISSTRUCT (type) && m_class_has_references (inst->klass)) || mini_type_is_reference (type)) { @@ -753,7 +753,7 @@ mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode) { int dreg; - if (type->type == MONO_TYPE_VALUETYPE && !type->byref) { + if (type->type == MONO_TYPE_VALUETYPE && !m_type_is_byref (type)) { MonoClass *klass = mono_class_from_mono_type_internal (type); if (m_class_is_enumtype (klass) && m_class_get_image (klass) == mono_get_corlib () && !strcmp (m_class_get_name (klass), "StackCrawlMark")) { if (!(cfg->method->flags & METHOD_ATTRIBUTE_REQSECOBJ)) diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index c4bd7def1cbcb..cd49dc45b9963 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -138,8 +138,8 @@ typedef struct SeqPointInfo SeqPointInfo; #define printf g_print #endif -#define MONO_TYPE_IS_PRIMITIVE(t) ((!(t)->byref && ((((t)->type >= MONO_TYPE_BOOLEAN && (t)->type <= MONO_TYPE_R8) || ((t)->type >= MONO_TYPE_I && (t)->type <= MONO_TYPE_U))))) -#define MONO_TYPE_IS_VECTOR_PRIMITIVE(t) ((!(t)->byref && ((((t)->type >= MONO_TYPE_I1 && (t)->type <= MONO_TYPE_R8) || ((t)->type >= MONO_TYPE_I && (t)->type <= MONO_TYPE_U))))) +#define MONO_TYPE_IS_PRIMITIVE(t) ((!m_type_is_byref ((t)) && ((((t)->type >= MONO_TYPE_BOOLEAN && (t)->type <= MONO_TYPE_R8) || ((t)->type >= MONO_TYPE_I && (t)->type <= MONO_TYPE_U))))) +#define MONO_TYPE_IS_VECTOR_PRIMITIVE(t) ((!m_type_is_byref ((t)) && ((((t)->type >= MONO_TYPE_I1 && (t)->type <= MONO_TYPE_R8) || ((t)->type >= MONO_TYPE_I && (t)->type <= MONO_TYPE_U))))) //XXX this ignores if t is byref #define MONO_TYPE_IS_PRIMITIVE_SCALAR(t) ((((((t)->type >= MONO_TYPE_BOOLEAN && (t)->type <= MONO_TYPE_U8) || ((t)->type >= MONO_TYPE_I && (t)->type <= MONO_TYPE_U))))) @@ -1144,7 +1144,7 @@ typedef struct gpointer addr; gpointer arg; MonoMethod *method; - /* InterpMethod* */ + /* Tagged InterpMethod* */ gpointer interp_method; } MonoFtnDesc; diff --git a/src/mono/mono/mini/ssa.c b/src/mono/mono/mini/ssa.c index fa6ec5bb53d9c..c91851baee597 100644 --- a/src/mono/mono/mini/ssa.c +++ b/src/mono/mono/mini/ssa.c @@ -437,7 +437,7 @@ mono_ssa_compute (MonoCompile *cfg) break; } - if (var->inst_vtype->byref) + if (m_type_is_byref (var->inst_vtype)) ins->klass = mono_defaults.int_class; else ins->klass = var->klass; diff --git a/src/mono/mono/mini/trace.c b/src/mono/mono/mini/trace.c index 72c5602870402..2f1a4fd7c35be 100644 --- a/src/mono/mono/mini/trace.c +++ b/src/mono/mono/mini/trace.c @@ -213,7 +213,7 @@ mono_trace_enter_method (MonoMethod *method, MonoJitInfo *ji, MonoProfilerCallCo MonoType *type = sig->params [i]; - if (type->byref) { + if (m_type_is_byref (type)) { printf ("[BYREF:%p]", *(gpointer*)buf); mini_profiler_context_free_buffer (buf); break; diff --git a/src/mono/mono/profiler/aot.c b/src/mono/mono/profiler/aot.c index 8509a6e7d81d8..71be9f1fdcaaa 100644 --- a/src/mono/mono/profiler/aot.c +++ b/src/mono/mono/profiler/aot.c @@ -673,7 +673,7 @@ prof_save (MonoProfiler *prof, FILE* file) sig = mono_method_signature_checked (send_method, error); mono_error_assert_ok (error); - if (sig->param_count != 3 || !sig->params [0]->byref || sig->params [0]->type != MONO_TYPE_U1 || sig->params [1]->type != MONO_TYPE_I4 || sig->params [2]->type != MONO_TYPE_STRING) { + if (sig->param_count != 3 || !m_type_is_byref (sig->params [0]) || sig->params [0]->type != MONO_TYPE_U1 || sig->params [1]->type != MONO_TYPE_I4 || sig->params [2]->type != MONO_TYPE_STRING) { mono_profiler_printf_err ("Method '%s' should have signature void (byte&,int,string).", prof->send_to_str); exit (1); } diff --git a/src/mono/mono/sgen/sgen-gc.c b/src/mono/mono/sgen/sgen-gc.c index d5b31e753179c..08f192c49e7c2 100644 --- a/src/mono/mono/sgen/sgen-gc.c +++ b/src/mono/mono/sgen/sgen-gc.c @@ -2719,7 +2719,7 @@ sgen_perform_collection_inner (size_t requested_size, int generation_to_collect, sgen_restart_world (oldest_generation_collected, forced_serial || !sgen_major_collector.is_concurrent); } -#ifdef HOST_WASM +#ifdef HOST_BROWSER typedef struct { size_t requested_size; @@ -2737,16 +2737,14 @@ gc_pump_callback (void) sgen_perform_collection_inner (gc_request.requested_size, gc_request.generation_to_collect, gc_request.reason, TRUE, TRUE); gc_request.generation_to_collect = 0; } -#endif -#ifdef HOST_WASM extern gboolean mono_wasm_enable_gc; #endif void sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason, gboolean forced_serial, gboolean stw) { -#ifdef HOST_WASM +#ifdef HOST_BROWSER if (!mono_wasm_enable_gc) { g_assert (stw); //can't handle non-stw mode (IE, domain unload) //we ignore forced_serial diff --git a/src/mono/mono/utils/mono-mmap-wasm.c b/src/mono/mono/utils/mono-mmap-wasm.c index e8cada0137b92..b04d69ab1b5e2 100644 --- a/src/mono/mono/utils/mono-mmap-wasm.c +++ b/src/mono/mono/utils/mono-mmap-wasm.c @@ -233,7 +233,7 @@ void* mono_shared_area (void) { if (!malloced_shared_area) - malloced_shared_area = mono_malloc_shared_area (getpid ()); + malloced_shared_area = mono_malloc_shared_area (mono_process_current_pid ()); /* get the pid here */ return malloced_shared_area; } diff --git a/src/mono/mono/utils/mono-proclib.c b/src/mono/mono/utils/mono-proclib.c index 1b19cdec49fb5..1fe731d9fe0f5 100644 --- a/src/mono/mono/utils/mono-proclib.c +++ b/src/mono/mono/utils/mono-proclib.c @@ -742,8 +742,10 @@ mono_process_get_data (gpointer pid, MonoProcessData data) int mono_process_current_pid () { -#if defined(HAVE_UNISTD_H) +#if defined(HAVE_GETPID) return (int) getpid (); +#elif defined(HOST_WASI) + return 0; #else #error getpid #endif diff --git a/src/mono/mono/utils/mono-signal-handler.h b/src/mono/mono/utils/mono-signal-handler.h index 0b2b38482b257..151c729928508 100644 --- a/src/mono/mono/utils/mono-signal-handler.h +++ b/src/mono/mono/utils/mono-signal-handler.h @@ -89,6 +89,8 @@ typedef struct { EXCEPTION_POINTERS* ep; } MonoWindowsSigHandlerInfo; /* seh_vectored_exception_handler () passes in a CONTEXT* */ +#elif defined(HOST_WASM) +#define MONO_SIG_HANDLER_INFO_TYPE int #else /* sigaction */ #define MONO_SIG_HANDLER_INFO_TYPE siginfo_t diff --git a/src/mono/mono/utils/mono-threads-wasm.c b/src/mono/mono/utils/mono-threads-wasm.c index dc792e8158e00..fae0193050b9c 100644 --- a/src/mono/mono/utils/mono-threads-wasm.c +++ b/src/mono/mono/utils/mono-threads-wasm.c @@ -9,9 +9,12 @@ #include #include +#include + +#ifdef HOST_BROWSER + #include #include -#include #define round_down(addr, val) ((void*)((addr) & ~((val) - 1))) @@ -29,6 +32,24 @@ wasm_get_stack_size (void) return (guint8*)emscripten_stack_get_base () - (guint8*)emscripten_stack_get_end (); } +#else /* WASI */ + +static int +wasm_get_stack_base (void) +{ + g_assert_not_reached (); + return 0; +} + +static int +wasm_get_stack_size (void) +{ + g_assert_not_reached (); + return 0; +} + +#endif + int mono_thread_info_get_system_max_stack_size (void) { @@ -277,6 +298,13 @@ mono_threads_platform_in_critical_region (THREAD_INFO_TYPE *info) return FALSE; } +void +mono_memory_barrier_process_wide (void) +{ +} + +#ifdef HOST_BROWSER + G_EXTERN_C extern void schedule_background_exec (void); @@ -310,10 +338,7 @@ mono_background_exec (void) g_slist_free (j); } -void -mono_memory_barrier_process_wide (void) -{ -} +#endif /* HOST_BROWSER */ #else diff --git a/src/mono/sample/mbr/browser/index.html b/src/mono/sample/mbr/browser/index.html index eb19b7bb2f595..6122370dd9d65 100644 --- a/src/mono/sample/mbr/browser/index.html +++ b/src/mono/sample/mbr/browser/index.html @@ -18,12 +18,12 @@ init: function () { var outElement = document.getElementById("out"); document.getElementById("update").addEventListener("click", function () { - BINDING.call_static_method("[WasmDelta] Sample.Test:Update", []); + INTERNAL.call_static_method("[WasmDelta] Sample.Test:Update", []); console.log ("applied update"); - var ret = BINDING.call_static_method("[WasmDelta] Sample.Test:TestMeaning", []); + var ret = INTERNAL.call_static_method("[WasmDelta] Sample.Test:TestMeaning", []); outElement.innerHTML = ret; }) - var ret = BINDING.call_static_method("[WasmDelta] Sample.Test:TestMeaning", []); + var ret = INTERNAL.call_static_method("[WasmDelta] Sample.Test:TestMeaning", []); outElement.innerHTML = ret; console.log ("ready"); }, diff --git a/src/mono/sample/mbr/browser/runtime.js b/src/mono/sample/mbr/browser/runtime.js index 41989feb6a547..0252041eff5ac 100644 --- a/src/mono/sample/mbr/browser/runtime.js +++ b/src/mono/sample/mbr/browser/runtime.js @@ -2,30 +2,30 @@ // The .NET Foundation licenses this file to you under the MIT license. "use strict"; -var Module = { +var Module = { config: null, - preInit: async function() { - await MONO.mono_wasm_load_config("./mono-config.json"); // sets Module.config implicitly + preInit: async function () { + await MONO.mono_wasm_load_config("./mono-config.json"); // sets MONO.config implicitly }, // Called when the runtime is initialized and wasm is ready onRuntimeInitialized: function () { - if (!Module.config || Module.config.error) { + if (!MONO.config || MONO.config.error) { console.log("An error occured while loading the config file"); return; } - Module.config.loaded_cb = function () { - App.init (); + MONO.config.loaded_cb = function () { + App.init(); }; - Module.config.environment_variables = { + MONO.config.environment_variables = { "DOTNET_MODIFIABLE_ASSEMBLIES": "debug" }; - Module.config.fetch_file_cb = function (asset) { - return fetch (asset, { credentials: 'same-origin' }); + MONO.config.fetch_file_cb = function (asset) { + return fetch(asset, { credentials: 'same-origin' }); } - MONO.mono_load_runtime_and_bcl_args (Module.config); + MONO.mono_load_runtime_and_bcl_args(MONO.config); }, }; diff --git a/src/mono/sample/wasm/browser-bench/index.html b/src/mono/sample/wasm/browser-bench/index.html index 6b26090c6dddf..136e400e70c2a 100644 --- a/src/mono/sample/wasm/browser-bench/index.html +++ b/src/mono/sample/wasm/browser-bench/index.html @@ -37,7 +37,7 @@ }; function yieldBench () { - let promise = BINDING.call_static_method("[Wasm.Browser.Bench.Sample] Sample.Test:RunBenchmark", []); + let promise = INTERNAL.call_static_method("[Wasm.Browser.Bench.Sample] Sample.Test:RunBenchmark", []); promise.then(ret => { document.getElementById("out").innerHTML += ret; if (ret.length > 0) { @@ -52,7 +52,7 @@ var App = { init: function () { if (tasks != '') - BINDING.call_static_method("[Wasm.Browser.Bench.Sample] Sample.Test:SetTasks", tasks); + INTERNAL.call_static_method("[Wasm.Browser.Bench.Sample] Sample.Test:SetTasks", tasks); yieldBench (); } }; diff --git a/src/mono/sample/wasm/browser-bench/runtime.js b/src/mono/sample/wasm/browser-bench/runtime.js index 87fb6436dbc1d..2d934c659ea13 100644 --- a/src/mono/sample/wasm/browser-bench/runtime.js +++ b/src/mono/sample/wasm/browser-bench/runtime.js @@ -2,46 +2,44 @@ // The .NET Foundation licenses this file to you under the MIT license. "use strict"; -var Module = { +var Module = { config: null, - preInit: async function() { - await MONO.mono_wasm_load_config("./mono-config.json"); // sets Module.config implicitly + preInit: async function () { + await MONO.mono_wasm_load_config("./mono-config.json"); // sets MONO.config implicitly }, // Called when the runtime is initialized and wasm is ready onRuntimeInitialized: function () { - if (!Module.config || Module.config.error) { + if (!MONO.config || MONO.config.error) { console.log("An error occured while loading the config file"); return; } - Module.config.loaded_cb = function () { + MONO.config.loaded_cb = function () { try { - App.init (); + App.init(); } catch (error) { test_exit(1); throw (error); } }; - Module.config.fetch_file_cb = function (asset) { - return fetch (asset, { credentials: 'same-origin' }); + MONO.config.fetch_file_cb = function (asset) { + return fetch(asset, { credentials: 'same-origin' }); } - if (Module.config.enable_profiler) - { - Module.config.aot_profiler_options = { - write_at:"Sample.Test::StopProfile", + if (MONO.config.enable_profiler) { + MONO.config.aot_profiler_options = { + write_at: "Sample.Test::StopProfile", send_to: "System.Runtime.InteropServices.JavaScript.Runtime::DumpAotProfileData" } } - try - { - MONO.mono_load_runtime_and_bcl_args (Module.config); + try { + MONO.mono_load_runtime_and_bcl_args(MONO.config); } catch (error) { test_exit(1); - throw(error); + throw (error); } }, }; diff --git a/src/mono/sample/wasm/browser-profile/README.md b/src/mono/sample/wasm/browser-profile/README.md index 1e2981be112f7..26afb1386711b 100644 --- a/src/mono/sample/wasm/browser-profile/README.md +++ b/src/mono/sample/wasm/browser-profile/README.md @@ -27,16 +27,16 @@ var Module = { 3. Call the `write_at` method at the end of the app, either in C# or in JS. To call the `write_at` method in JS, make use of bindings: -`BINDING.call_static_method("<[ProjectName] Namespace.Class::StopProfile">, []);` +`INTERNAL.call_static_method("<[ProjectName] Namespace.Class::StopProfile">, []);` -When the `write_at` method is called, the `send_to` method `DumpAotProfileData` stores the profile data into `Module.aot_profile_data` +When the `write_at` method is called, the `send_to` method `DumpAotProfileData` stores the profile data into `INTERNAL.aot_profile_data` -4. Download `Module.aot_profile_data` in JS, using something similar to: +4. Download `INTERNAL.aot_profile_data` in JS, using something similar to: ``` function saveProfile() { var a = document.createElement('a'); - var blob = new Blob([Module.aot_profile_data]); + var blob = new Blob([INTERNAL.aot_profile_data]); a.href = URL.createObjectURL(blob); a.download = "data.aotprofile"; // Append anchor to body. diff --git a/src/mono/sample/wasm/browser-profile/runtime.js b/src/mono/sample/wasm/browser-profile/runtime.js index cd0dd0cb9ed32..69b84d002bb8d 100644 --- a/src/mono/sample/wasm/browser-profile/runtime.js +++ b/src/mono/sample/wasm/browser-profile/runtime.js @@ -2,22 +2,22 @@ // The .NET Foundation licenses this file to you under the MIT license. "use strict"; -var Module = { +var Module = { is_testing: false, config: null, - preInit: async function() { - await MONO.mono_wasm_load_config("./mono-config.json"); // sets Module.config implicitly + preInit: async function () { + await MONO.mono_wasm_load_config("./mono-config.json"); // sets MONO.config implicitly }, // Called when the runtime is initialized and wasm is ready onRuntimeInitialized: function () { - if (!Module.config || Module.config.error) { + if (!MONO.config || MONO.config.error) { console.log("An error occured while loading the config file"); return; } - Module.config.loaded_cb = function () { + MONO.config.loaded_cb = function () { try { Module.init(); } catch (error) { @@ -25,70 +25,67 @@ var Module = { throw (error); } }; - Module.config.fetch_file_cb = function (asset) { - return fetch (asset, { credentials: 'same-origin' }); + MONO.config.fetch_file_cb = function (asset) { + return fetch(asset, { credentials: 'same-origin' }); } - if (Module.config.enable_profiler) - { - Module.config.aot_profiler_options = { - write_at:"Sample.Test::StopProfile", + if (MONO.config.enable_profiler) { + MONO.config.aot_profiler_options = { + write_at: "Sample.Test::StopProfile", send_to: "System.Runtime.InteropServices.JavaScript.Runtime::DumpAotProfileData" } } - try - { - MONO.mono_load_runtime_and_bcl_args (Module.config); + try { + MONO.mono_load_runtime_and_bcl_args(MONO.config); } catch (error) { Module.test_exit(1); - throw(error); + throw (error); } }, init: function () { console.log("not ready yet") - var ret = BINDING.call_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:TestMeaning", []); + const ret = INTERNAL.call_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:TestMeaning", []); document.getElementById("out").innerHTML = ret; - console.log ("ready"); + console.log("ready"); - if (Module.is_testing) - { - console.debug(`ret: ${ret}`); - let exit_code = ret == 42 ? 0 : 1; - Module.test_exit(exit_code); + if (Module.is_testing) { + console.debug(`ret: ${ret}`); + let exit_code = ret == 42 ? 0 : 1; + Module.test_exit(exit_code); } - if (Module.config.enable_profiler) { - BINDING.call_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:StopProfile", []); - Module.saveProfile(); + if (MONO.config.enable_profiler) { + INTERNAL.call_static_method("[Wasm.BrowserProfile.Sample] Sample.Test:StopProfile", []); + Module.saveProfile(); } }, - onLoad: function() { - var url = new URL(decodeURI(window.location)); - let args = url.searchParams.getAll('arg'); + onLoad: function () { + const url = new URL(decodeURI(window.location)); + const args = url.searchParams.getAll('arg'); Module.is_testing = args !== undefined && (args.find(arg => arg == '--testing') !== undefined); }, - - test_exit: function(exit_code) { + + test_exit: function (exit_code) { if (!Module.is_testing) { console.log(`test_exit: ${exit_code}`); return; } /* Set result in a tests_done element, to be read by xharness */ - var tests_done_elem = document.createElement("label"); + const tests_done_elem = document.createElement("label"); tests_done_elem.id = "tests_done"; tests_done_elem.innerHTML = exit_code.toString(); document.body.appendChild(tests_done_elem); console.log(`WASM EXIT ${exit_code}`); }, - + saveProfile: function () { - var a = document.createElement('a'); - var blob = new Blob([Module.aot_profile_data]); + const a = document.createElement('a'); + const blob = new Blob([INTERNAL.aot_profile_data]); a.href = URL.createObjectURL(blob); a.download = "data.aotprofile"; // Append anchor to body. diff --git a/src/mono/sample/wasm/browser/index.html b/src/mono/sample/wasm/browser/index.html index 5f170bb38e7bc..cedcae5715afb 100644 --- a/src/mono/sample/wasm/browser/index.html +++ b/src/mono/sample/wasm/browser/index.html @@ -36,7 +36,7 @@ var App = { init: function () { - var ret = BINDING.call_static_method("[Wasm.Browser.Sample] Sample.Test:TestMeaning", []); + var ret = INTERNAL.call_static_method("[Wasm.Browser.Sample] Sample.Test:TestMeaning", []); document.getElementById("out").innerHTML = ret; if (is_testing) diff --git a/src/mono/sample/wasm/browser/runtime.js b/src/mono/sample/wasm/browser/runtime.js index 904ca19958f76..8b14c3637e6b4 100644 --- a/src/mono/sample/wasm/browser/runtime.js +++ b/src/mono/sample/wasm/browser/runtime.js @@ -2,39 +2,38 @@ // The .NET Foundation licenses this file to you under the MIT license. "use strict"; -var Module = { +var Module = { config: null, - preInit: async function() { - await MONO.mono_wasm_load_config("./mono-config.json"); // sets Module.config implicitly + preInit: async function () { + await MONO.mono_wasm_load_config("./mono-config.json"); // sets MONO.config implicitly }, // Called when the runtime is initialized and wasm is ready onRuntimeInitialized: function () { - if (!Module.config || Module.config.error) { + if (!MONO.config || MONO.config.error) { console.log("No config found"); return; } - Module.config.loaded_cb = function () { + MONO.config.loaded_cb = function () { try { - App.init (); + App.init(); } catch (error) { test_exit(1); throw (error); } }; - Module.config.fetch_file_cb = function (asset) { - return fetch (asset, { credentials: 'same-origin' }); + MONO.config.fetch_file_cb = function (asset) { + return fetch(asset, { credentials: 'same-origin' }); } - try - { - MONO.mono_load_runtime_and_bcl_args (Module.config); + try { + MONO.mono_load_runtime_and_bcl_args(MONO.config); } catch (error) { test_exit(1); - throw(error); + throw (error); } }, }; diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs index 950acbb2dcf91..97acfe9517d4e 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs @@ -172,33 +172,31 @@ internal class MonoCommands public MonoCommands(string expression) => this.expression = expression; - public static MonoCommands GetExceptionObject() => new MonoCommands("MONO.mono_wasm_get_exception_object()"); + public static MonoCommands GetDebuggerAgentBufferReceived() => new MonoCommands("INTERNAL.mono_wasm_get_dbg_command_info()"); - public static MonoCommands GetDebuggerAgentBufferReceived() => new MonoCommands("MONO.mono_wasm_get_dbg_command_info()"); + public static MonoCommands IsRuntimeReady() => new MonoCommands("INTERNAL.mono_wasm_runtime_is_ready"); - public static MonoCommands IsRuntimeReady() => new MonoCommands("MONO.mono_wasm_runtime_is_ready"); - - public static MonoCommands GetLoadedFiles() => new MonoCommands("MONO.mono_wasm_get_loaded_files()"); + public static MonoCommands GetLoadedFiles() => new MonoCommands("INTERNAL.mono_wasm_get_loaded_files()"); public static MonoCommands SendDebuggerAgentCommand(int id, int command_set, int command, string command_parameters) { - return new MonoCommands($"MONO.mono_wasm_send_dbg_command ({id}, {command_set}, {command},'{command_parameters}')"); + return new MonoCommands($"INTERNAL.mono_wasm_send_dbg_command ({id}, {command_set}, {command},'{command_parameters}')"); } public static MonoCommands SendDebuggerAgentCommandWithParms(int id, int command_set, int command, string command_parameters, int len, int type, string parm) { - return new MonoCommands($"MONO.mono_wasm_send_dbg_command_with_parms ({id}, {command_set}, {command},'{command_parameters}', {len}, {type}, '{parm}')"); + return new MonoCommands($"INTERNAL.mono_wasm_send_dbg_command_with_parms ({id}, {command_set}, {command},'{command_parameters}', {len}, {type}, '{parm}')"); } - public static MonoCommands CallFunctionOn(JToken args) => new MonoCommands($"MONO.mono_wasm_call_function_on ({args.ToString()})"); + public static MonoCommands CallFunctionOn(JToken args) => new MonoCommands($"INTERNAL.mono_wasm_call_function_on ({args})"); - public static MonoCommands GetDetails(int objectId, JToken args = null) => new MonoCommands($"MONO.mono_wasm_get_details ({objectId}, {(args ?? "{ }")})"); + public static MonoCommands GetDetails(int objectId, JToken args = null) => new MonoCommands($"INTERNAL.mono_wasm_get_details ({objectId}, {(args ?? "{ }")})"); - public static MonoCommands Resume() => new MonoCommands($"MONO.mono_wasm_debugger_resume ()"); + public static MonoCommands Resume() => new MonoCommands($"INTERNAL.mono_wasm_debugger_resume ()"); - public static MonoCommands DetachDebugger() => new MonoCommands($"MONO.mono_wasm_detach_debugger()"); + public static MonoCommands DetachDebugger() => new MonoCommands($"INTERNAL.mono_wasm_detach_debugger()"); - public static MonoCommands ReleaseObject(DotnetObjectId objectId) => new MonoCommands($"MONO.mono_wasm_release_object('{objectId}')"); + public static MonoCommands ReleaseObject(DotnetObjectId objectId) => new MonoCommands($"INTERNAL.mono_wasm_release_object('{objectId}')"); } internal enum MonoErrorCodes diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index 6e9d420801dd9..ecd9070a8e21d 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -35,7 +35,7 @@ public async Task CreateJSBreakpoint() { // Test that js breakpoints get set correctly // 13 24 - // 13 31 + // 13 33 var bp1_res = await SetBreakpoint("/debugger-driver.html", 13, 24); Assert.EndsWith("debugger-driver.html", bp1_res.Value["breakpointId"].ToString()); @@ -47,7 +47,7 @@ public async Task CreateJSBreakpoint() Assert.Equal(13, loc["lineNumber"]); Assert.Equal(24, loc["columnNumber"]); - var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 31); + var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 33); Assert.EndsWith("debugger-driver.html", bp2_res.Value["breakpointId"].ToString()); Assert.Equal(1, bp2_res.Value["locations"]?.Value()?.Count); @@ -56,14 +56,14 @@ public async Task CreateJSBreakpoint() Assert.NotNull(loc2["scriptId"]); Assert.Equal(13, loc2["lineNumber"]); - Assert.Equal(31, loc2["columnNumber"]); + Assert.Equal(33, loc2["columnNumber"]); } [Fact] public async Task CreateJS0Breakpoint() { // 13 24 - // 13 31 + // 13 33 var bp1_res = await SetBreakpoint("/debugger-driver.html", 13, 0); Assert.EndsWith("debugger-driver.html", bp1_res.Value["breakpointId"].ToString()); @@ -75,7 +75,7 @@ public async Task CreateJS0Breakpoint() Assert.Equal(13, loc["lineNumber"]); Assert.Equal(24, loc["columnNumber"]); - var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 31); + var bp2_res = await SetBreakpoint("/debugger-driver.html", 13, 33); Assert.EndsWith("debugger-driver.html", bp2_res.Value["breakpointId"].ToString()); Assert.Equal(1, bp2_res.Value["locations"]?.Value()?.Count); @@ -84,7 +84,7 @@ public async Task CreateJS0Breakpoint() Assert.NotNull(loc2["scriptId"]); Assert.Equal(13, loc2["lineNumber"]); - Assert.Equal(31, loc2["columnNumber"]); + Assert.Equal(33, loc2["columnNumber"]); } [Theory] diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs index 7e78bc0e2b64c..bd92af72637ad 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs @@ -41,7 +41,12 @@ protected static string DebuggerTestAppPath static protected string FindTestPath() { var asm_dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var test_app_path = Path.Combine(asm_dir, "..", "..", "..", "debugger-test", "Debug", "publish"); +#if DEBUG + var config="Debug"; +#else + var config="Release"; +#endif + var test_app_path = Path.Combine(asm_dir, "..", "..", "..", "debugger-test", config, "publish"); if (File.Exists(Path.Combine(test_app_path, "debugger-driver.html"))) return test_app_path; diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs index b45825acfcbd8..38742d8d36330 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/MonoJsTests.cs @@ -13,41 +13,17 @@ namespace DebuggerTests { public class MonoJsTests : DebuggerTestBase { - [Fact] - public async Task InvalidScopeId() - { - var bp1_res = await SetBreakpointInMethod("debugger-test.dll", "Math", "IntAdd", 3); - await EvaluateAndCheck( - "window.setTimeout(function() { invoke_static_method('[debugger-test] Math:IntAdd', 1, 2); })", - null, -1, -1, "IntAdd"); - - var varIds = new[] - { - new { index = 0, name = "one" }, - }; - - var scopeId = "-12"; - var expression = $"MONO.mono_wasm_get_variables({scopeId}, {JsonConvert.SerializeObject(varIds)})"; - var res = await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression, returnByValue = true }), token); - Assert.False(res.IsOk); - - scopeId = "30000"; - expression = $"MONO.mono_wasm_get_variables({scopeId}, {JsonConvert.SerializeObject(varIds)})"; - res = await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression, returnByValue = true }), token); - Assert.False(res.IsOk); - } - [Fact] public async Task BadRaiseDebugEventsTest() { var bad_expressions = new[] { - "MONO.mono_wasm_raise_debug_event('')", - "MONO.mono_wasm_raise_debug_event(undefined)", - "MONO.mono_wasm_raise_debug_event({})", + "INTERNAL.mono_wasm_raise_debug_event('')", + "INTERNAL.mono_wasm_raise_debug_event(undefined)", + "INTERNAL.mono_wasm_raise_debug_event({})", - "MONO.mono_wasm_raise_debug_event({eventName:'foo'}, '')", - "MONO.mono_wasm_raise_debug_event({eventName:'foo'}, 12)" + "INTERNAL.mono_wasm_raise_debug_event({eventName:'foo'}, '')", + "INTERNAL.mono_wasm_raise_debug_event({eventName:'foo'}, 12)" }; foreach (var expression in bad_expressions) @@ -82,7 +58,7 @@ public async Task RaiseDebugEventTraceTest(bool? trace) }); var trace_str = trace.HasValue ? $"trace: {trace.ToString().ToLower()}" : String.Empty; - var expression = $"MONO.mono_wasm_raise_debug_event({{ eventName:'qwe' }}, {{ {trace_str} }})"; + var expression = $"INTERNAL.mono_wasm_raise_debug_event({{ eventName:'qwe' }}, {{ {trace_str} }})"; var res = await cli.SendCommand($"Runtime.evaluate", JObject.FromObject(new { expression }), token); Assert.True(res.IsOk, $"Expected to pass for {expression}"); @@ -163,7 +139,7 @@ async Task AssemblyLoadedEventTest(string asm_name, string asm_path, string pdb_ pdb_base64 = Convert.ToBase64String(bytes); } - var expression = $@"MONO.mono_wasm_raise_debug_event({{ + var expression = $@"INTERNAL.mono_wasm_raise_debug_event({{ eventName: 'AssemblyLoaded', assembly_name: '{asm_name}', assembly_b64: '{asm_base64}', diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html b/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html index b1bfcd859d064..8f6902ca0f0de 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html @@ -6,14 +6,14 @@